Back to index

moin  1.9.0~rc2
parsedatetime_consts.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 """
00004 parsedatetime constants and helper functions to determine
00005 regex values from Locale information if present.
00006 
00007 Also contains the internal Locale classes to give some sane
00008 defaults if PyICU is not found.
00009 """
00010 
00011 __license__ = """
00012 Copyright (c) 2004-2008 Mike Taylor
00013 Copyright (c) 2006-2008 Darshana Chhajed
00014 Copyright (c)      2007 Bernd Zeimetz <bzed@debian.org>
00015 All rights reserved.
00016 
00017 Licensed under the Apache License, Version 2.0 (the "License");
00018 you may not use this file except in compliance with the License.
00019 You may obtain a copy of the License at
00020 
00021    http://www.apache.org/licenses/LICENSE-2.0
00022 
00023 Unless required by applicable law or agreed to in writing, software
00024 distributed under the License is distributed on an "AS IS" BASIS,
00025 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00026 See the License for the specific language governing permissions and
00027 limitations under the License.
00028 """
00029 
00030 try:
00031     import PyICU as pyicu
00032 except:
00033     pyicu = None
00034 
00035 
00036 import datetime
00037 import calendar
00038 import time
00039 import re
00040 
00041 
00042 class pdtLocale_en:
00043     """
00044     en_US Locale constants
00045 
00046     This class will be used to initialize L{Constants} if PyICU is not located.
00047 
00048     Defined as class variables are the lists and strings needed by parsedatetime
00049     to evaluate strings for USA
00050     """
00051 
00052     localeID      = 'en_US'   # don't use a unicode string
00053     dateSep       = [ u'/', u'.' ]
00054     timeSep       = [ u':' ]
00055     meridian      = [ u'AM', u'PM' ]
00056     usesMeridian  = True
00057     uses24        = False
00058 
00059     Weekdays      = [ u'monday', u'tuesday', u'wednesday',
00060                       u'thursday', u'friday', u'saturday', u'sunday',
00061                     ]
00062     shortWeekdays = [ u'mon', u'tues', u'wed',
00063                       u'thu', u'fri', u'sat', u'sun',
00064                     ]
00065     Months        = [ u'january', u'february', u'march',
00066                       u'april',   u'may',      u'june',
00067                       u'july',    u'august',   u'september',
00068                       u'october', u'november', u'december',
00069                     ]
00070     shortMonths   = [ u'jan', u'feb', u'mar',
00071                       u'apr', u'may', u'jun',
00072                       u'jul', u'aug', u'sep',
00073                       u'oct', u'nov', u'dec',
00074                     ]
00075     dateFormats   = { 'full':   'EEEE, MMMM d, yyyy',
00076                       'long':   'MMMM d, yyyy',
00077                       'medium': 'MMM d, yyyy',
00078                       'short':  'M/d/yy',
00079                     }
00080     timeFormats   = { 'full':   'h:mm:ss a z',
00081                       'long':   'h:mm:ss a z',
00082                       'medium': 'h:mm:ss a',
00083                       'short':  'h:mm a',
00084                     }
00085 
00086     dp_order = [ u'm', u'd', u'y' ]
00087 
00088       # this will be added to re_consts later
00089     units = { 'seconds': [ 'second', 'sec' ],
00090               'minutes': [ 'minute', 'min' ],
00091               'hours':   [ 'hour',   'hr'  ],
00092               'days':    [ 'day',    'dy'  ],
00093               'weeks':   [ 'week',   'wk'  ],
00094               'months':  [ 'month',  'mth' ],
00095               'years':   [ 'year',   'yr'  ],
00096             }
00097 
00098       # text constants to be used by regex's later
00099     re_consts     = { 'specials':       'in|on|of|at',
00100                       'timeseperator':  ':',
00101                       'rangeseperator': '-',
00102                       'daysuffix':      'rd|st|nd|th',
00103                       'meridian':       'am|pm|a.m.|p.m.|a|p',
00104                       'qunits':         'h|m|s|d|w|m|y',
00105                       'now':            [ 'now' ],
00106                     }
00107 
00108       # Used to adjust the returned date before/after the source
00109     modifiers = { 'from':       1,
00110                   'before':    -1,
00111                   'after':      1,
00112                   'ago':       -1,
00113                   'prior':     -1,
00114                   'prev':      -1,
00115                   'last':      -1,
00116                   'next':       1,
00117                   'previous':  -1,
00118                   'in a':       2,
00119                   'end of':     0,
00120                   'eod':        0,
00121                   'eo':         0
00122                 }
00123 
00124     dayoffsets = { 'tomorrow':   1,
00125                    'today':      0,
00126                    'yesterday': -1,
00127                  }
00128 
00129       # special day and/or times, i.e. lunch, noon, evening
00130       # each element in the dictionary is a dictionary that is used
00131       # to fill in any value to be replace - the current date/time will
00132       # already have been populated by the method buildSources
00133     re_sources    = { 'noon':      { 'hr': 12, 'mn': 0, 'sec': 0 },
00134                       'lunch':     { 'hr': 12, 'mn': 0, 'sec': 0 },
00135                       'morning':   { 'hr':  6, 'mn': 0, 'sec': 0 },
00136                       'breakfast': { 'hr':  8, 'mn': 0, 'sec': 0 },
00137                       'dinner':    { 'hr': 19, 'mn': 0, 'sec': 0 },
00138                       'evening':   { 'hr': 18, 'mn': 0, 'sec': 0 },
00139                       'midnight':  { 'hr':  0, 'mn': 0, 'sec': 0 },
00140                       'night':     { 'hr': 21, 'mn': 0, 'sec': 0 },
00141                       'tonight':   { 'hr': 21, 'mn': 0, 'sec': 0 },
00142                       'eod':       { 'hr': 17, 'mn': 0, 'sec': 0 },
00143                     }
00144 
00145 
00146 class pdtLocale_au:
00147     """
00148     en_AU Locale constants
00149 
00150     This class will be used to initialize L{Constants} if PyICU is not located.
00151 
00152     Defined as class variables are the lists and strings needed by parsedatetime
00153     to evaluate strings for Australia
00154     """
00155 
00156     localeID      = 'en_AU'   # don't use a unicode string
00157     dateSep       = [ u'-', u'/' ]
00158     timeSep       = [ u':' ]
00159     meridian      = [ u'AM', u'PM' ]
00160     usesMeridian  = True
00161     uses24        = False
00162 
00163     Weekdays      = [ u'monday', u'tuesday', u'wednesday',
00164                       u'thursday', u'friday', u'saturday', u'sunday',
00165                     ]
00166     shortWeekdays = [ u'mon', u'tues', u'wed',
00167                       u'thu', u'fri', u'sat', u'sun',
00168                     ]
00169     Months        = [ u'january', u'february', u'march',
00170                       u'april',   u'may',      u'june',
00171                       u'july',    u'august',   u'september',
00172                       u'october', u'november', u'december',
00173                     ]
00174     shortMonths   = [ u'jan', u'feb', u'mar',
00175                       u'apr', u'may', u'jun',
00176                       u'jul', u'aug', u'sep',
00177                       u'oct', u'nov', u'dec',
00178                     ]
00179     dateFormats   = { 'full':   'EEEE, d MMMM yyyy',
00180                       'long':   'd MMMM yyyy',
00181                       'medium': 'dd/MM/yyyy',
00182                       'short':  'd/MM/yy',
00183                     }
00184     timeFormats   = { 'full':   'h:mm:ss a z',
00185                       'long':   'h:mm:ss a',
00186                       'medium': 'h:mm:ss a',
00187                       'short':  'h:mm a',
00188                     }
00189 
00190     dp_order = [ u'd', u'm', u'y' ]
00191 
00192       # this will be added to re_consts later
00193     units = { 'seconds': [ 'second', 'sec' ],
00194               'minutes': [ 'minute', 'min' ],
00195               'hours':   [ 'hour',   'hr'  ],
00196               'days':    [ 'day',    'dy'  ],
00197               'weeks':   [ 'week',   'wk'  ],
00198               'months':  [ 'month',  'mth' ],
00199               'years':   [ 'year',   'yr'  ],
00200             }
00201 
00202       # text constants to be used by regex's later
00203     re_consts     = { 'specials':       'in|on|of|at',
00204                       'timeseperator':  ':',
00205                       'rangeseperator': '-',
00206                       'daysuffix':      'rd|st|nd|th',
00207                       'meridian':       'am|pm|a.m.|p.m.|a|p',
00208                       'qunits':         'h|m|s|d|w|m|y',
00209                       'now':            [ 'now' ],
00210                     }
00211 
00212       # Used to adjust the returned date before/after the source
00213     modifiers = { 'from':       1,
00214                   'before':    -1,
00215                   'after':      1,
00216                   'ago':        1,
00217                   'prior':     -1,
00218                   'prev':      -1,
00219                   'last':      -1,
00220                   'next':       1,
00221                   'previous':  -1,
00222                   'in a':       2,
00223                   'end of':     0,
00224                   'eo':         0,
00225                 }
00226 
00227     dayoffsets = { 'tomorrow':   1,
00228                    'today':      0,
00229                    'yesterday': -1,
00230                  }
00231 
00232       # special day and/or times, i.e. lunch, noon, evening
00233       # each element in the dictionary is a dictionary that is used
00234       # to fill in any value to be replace - the current date/time will
00235       # already have been populated by the method buildSources
00236     re_sources    = { 'noon':      { 'hr': 12, 'mn': 0, 'sec': 0 },
00237                       'lunch':     { 'hr': 12, 'mn': 0, 'sec': 0 },
00238                       'morning':   { 'hr':  6, 'mn': 0, 'sec': 0 },
00239                       'breakfast': { 'hr':  8, 'mn': 0, 'sec': 0 },
00240                       'dinner':    { 'hr': 19, 'mn': 0, 'sec': 0 },
00241                       'evening':   { 'hr': 18, 'mn': 0, 'sec': 0 },
00242                       'midnight':  { 'hr':  0, 'mn': 0, 'sec': 0 },
00243                       'night':     { 'hr': 21, 'mn': 0, 'sec': 0 },
00244                       'tonight':   { 'hr': 21, 'mn': 0, 'sec': 0 },
00245                       'eod':       { 'hr': 17, 'mn': 0, 'sec': 0 },
00246                     }
00247 
00248 
00249 class pdtLocale_es:
00250     """
00251     es Locale constants
00252 
00253     This class will be used to initialize L{Constants} if PyICU is not located.
00254 
00255     Defined as class variables are the lists and strings needed by parsedatetime
00256     to evaluate strings in Spanish
00257 
00258     Note that I don't speak Spanish so many of the items below are still in English
00259     """
00260 
00261     localeID      = 'es'   # don't use a unicode string
00262     dateSep       = [ u'/' ]
00263     timeSep       = [ u':' ]
00264     meridian      = []
00265     usesMeridian  = False
00266     uses24        = True
00267 
00268     Weekdays      = [ u'lunes', u'martes', u'mi\xe9rcoles',
00269                       u'jueves', u'viernes', u's\xe1bado', u'domingo',
00270                     ]
00271     shortWeekdays = [ u'lun', u'mar', u'mi\xe9',
00272                       u'jue', u'vie', u's\xe1b', u'dom',
00273                     ]
00274     Months        = [ u'enero', u'febrero', u'marzo',
00275                       u'abril', u'mayo', u'junio',
00276                       u'julio', u'agosto', u'septiembre',
00277                       u'octubre', u'noviembre', u'diciembre'
00278                     ]
00279     shortMonths   = [ u'ene', u'feb', u'mar',
00280                       u'abr', u'may', u'jun',
00281                       u'jul', u'ago', u'sep',
00282                       u'oct', u'nov', u'dic'
00283                     ]
00284     dateFormats   = { 'full':   "EEEE d' de 'MMMM' de 'yyyy",
00285                       'long':   "d' de 'MMMM' de 'yyyy",
00286                       'medium': "dd-MMM-yy",
00287                       'short':  "d/MM/yy",
00288                     }
00289     timeFormats   = { 'full':   "HH'H'mm' 'ss z",
00290                       'long':   "HH:mm:ss z",
00291                       'medium': "HH:mm:ss",
00292                       'short':  "HH:mm",
00293                     }
00294 
00295     dp_order = [ u'd', u'm', u'y' ]
00296 
00297       # this will be added to re_consts later
00298     units = { 'seconds': [ 'second', 'sec' ],
00299               'minutes': [ 'minute', 'min' ],
00300               'hours':   [ 'hour',   'hr'  ],
00301               'days':    [ 'day',    'dy'  ],
00302               'weeks':   [ 'week',   'wk'  ],
00303               'months':  [ 'month',  'mth' ],
00304               'years':   [ 'year',   'yr'  ],
00305             }
00306 
00307       # text constants to be used by regex's later
00308     re_consts     = { 'specials':       'in|on|of|at',
00309                       'timeseperator':  timeSep,
00310                       'dateseperator':  dateSep,
00311                       'rangeseperator': '-',
00312                       'daysuffix':      'rd|st|nd|th',
00313                       'qunits':         'h|m|s|d|w|m|y',
00314                       'now':            [ 'now' ],
00315                     }
00316 
00317       # Used to adjust the returned date before/after the source
00318     modifiers = { 'from':      1,
00319                   'before':   -1,
00320                   'after':     1,
00321                   'ago':       1,
00322                   'prior':    -1,
00323                   'prev':     -1,
00324                   'last':     -1,
00325                   'next':      1,
00326                   'previous': -1,
00327                   'in a':      2,
00328                   'end of':    0,
00329                   'eo':        0,
00330                 }
00331 
00332     dayoffsets = { 'tomorrow':   1,
00333                    'today':      0,
00334                    'yesterday': -1,
00335                  }
00336 
00337       # special day and/or times, i.e. lunch, noon, evening
00338       # each element in the dictionary is a dictionary that is used
00339       # to fill in any value to be replace - the current date/time will
00340       # already have been populated by the method buildSources
00341     re_sources    = { 'noon':      { 'hr': 12, 'mn': 0, 'sec': 0 },
00342                       'lunch':     { 'hr': 12, 'mn': 0, 'sec': 0 },
00343                       'morning':   { 'hr':  6, 'mn': 0, 'sec': 0 },
00344                       'breakfast': { 'hr':  8, 'mn': 0, 'sec': 0 },
00345                       'dinner':    { 'hr': 19, 'mn': 0, 'sec': 0 },
00346                       'evening':   { 'hr': 18, 'mn': 0, 'sec': 0 },
00347                       'midnight':  { 'hr':  0, 'mn': 0, 'sec': 0 },
00348                       'night':     { 'hr': 21, 'mn': 0, 'sec': 0 },
00349                       'tonight':   { 'hr': 21, 'mn': 0, 'sec': 0 },
00350                       'eod':       { 'hr': 17, 'mn': 0, 'sec': 0 },
00351                     }
00352 
00353 
00354 class pdtLocale_de:
00355     """
00356     de_DE Locale constants
00357 
00358     This class will be used to initialize L{Constants} if PyICU is not located.
00359 
00360     Contributed by Debian parsedatetime package maintainer Bernd Zeimetz <bzed@debian.org>
00361 
00362     Defined as class variables are the lists and strings needed by parsedatetime
00363     to evaluate strings for German
00364     """
00365 
00366     localeID      = 'de_DE'   # don't use a unicode string
00367     dateSep       = [ u'.' ]
00368     timeSep       = [ u':' ]
00369     meridian      = [ ]
00370     usesMeridian  = False
00371     uses24        = True
00372 
00373     Weekdays      = [ u'montag', u'dienstag', u'mittwoch',
00374                       u'donnerstag', u'freitag', u'samstag', u'sonntag',
00375                     ]
00376     shortWeekdays = [ u'mo', u'di', u'mi',
00377                       u'do', u'fr', u'sa', u'so',
00378                     ]
00379     Months        = [ u'januar',  u'februar',  u'm\xe4rz',
00380                       u'april',   u'mai',      u'juni',
00381                       u'juli',    u'august',   u'september',
00382                       u'oktober', u'november', u'dezember',
00383                     ]
00384     shortMonths   = [ u'jan', u'feb', u'mrz',
00385                       u'apr', u'mai', u'jun',
00386                       u'jul', u'aug', u'sep',
00387                       u'okt', u'nov', u'dez',
00388                     ]
00389     dateFormats   = { 'full':   u'EEEE, d. MMMM yyyy',
00390                       'long':   u'd. MMMM yyyy',
00391                       'medium': u'dd.MM.yyyy',
00392                       'short':  u'dd.MM.yy'
00393                     }
00394 
00395     timeFormats   = { 'full':   u'HH:mm:ss v',
00396                       'long':   u'HH:mm:ss z',
00397                       'medium': u'HH:mm:ss',
00398                       'short':  u'HH:mm'
00399                     }
00400 
00401     dp_order = [ u'd', u'm', u'y' ]
00402 
00403       # this will be added to re_consts later
00404     units = { 'seconds': [ 'sekunden', 'sek',  's' ],
00405               'minutes': [ 'minuten',  'min' , 'm' ],
00406               'hours':   [ 'stunden',  'std',  'h' ],
00407               'days':    [ 'tage',     't' ],
00408               'weeks':   [ 'wochen',   'w' ],
00409               'months':  [ 'monate' ], #the short version would be a capital M,
00410                                        #as I understand it we can't distinguis
00411                                        #between m for minutes and M for months.
00412               'years':   [ 'jahre',    'j' ],
00413             }
00414 
00415       # text constants to be used by regex's later
00416     re_consts     = { 'specials':       'am|dem|der|im|in|den|zum',
00417                       'timeseperator':  ':',
00418                       'rangeseperator': '-',
00419                       'daysuffix':      '',
00420                       'qunits':         'h|m|s|t|w|m|j',
00421                       'now':            [ 'jetzt' ],
00422                     }
00423 
00424       # Used to adjust the returned date before/after the source
00425       #still looking for insight on how to translate all of them to german.
00426     modifiers = { u'from':         1,
00427                   u'before':      -1,
00428                   u'after':        1,
00429                   u'vergangener': -1,
00430                   u'vorheriger':  -1,
00431                   u'prev':        -1,
00432                   u'letzter':     -1,
00433                   u'n\xe4chster':  1,
00434                   u'dieser':       0,
00435                   u'previous':    -1,
00436                   u'in a':         2,
00437                   u'end of':       0,
00438                   u'eod':          0,
00439                   u'eo':           0,
00440                 }
00441 
00442      #morgen/abermorgen does not work, see http://code.google.com/p/parsedatetime/issues/detail?id=19
00443     dayoffsets = { u'morgen':        1,
00444                    u'heute':         0,
00445                    u'gestern':      -1,
00446                    u'vorgestern':   -2,
00447                    u'\xfcbermorgen': 2,
00448                  }
00449 
00450       # special day and/or times, i.e. lunch, noon, evening
00451       # each element in the dictionary is a dictionary that is used
00452       # to fill in any value to be replace - the current date/time will
00453       # already have been populated by the method buildSources
00454     re_sources    = { u'mittag':      { 'hr': 12, 'mn': 0, 'sec': 0 },
00455                       u'mittags':     { 'hr': 12, 'mn': 0, 'sec': 0 },
00456                       u'mittagessen': { 'hr': 12, 'mn': 0, 'sec': 0 },
00457                       u'morgen':      { 'hr':  6, 'mn': 0, 'sec': 0 },
00458                       u'morgens':     { 'hr':  6, 'mn': 0, 'sec': 0 },
00459                       u'fr\e4hst\xe4ck': { 'hr':  8, 'mn': 0, 'sec': 0 },
00460                       u'abendessen':  { 'hr': 19, 'mn': 0, 'sec': 0 },
00461                       u'abend':       { 'hr': 18, 'mn': 0, 'sec': 0 },
00462                       u'abends':      { 'hr': 18, 'mn': 0, 'sec': 0 },
00463                       u'mitternacht': { 'hr':  0, 'mn': 0, 'sec': 0 },
00464                       u'nacht':       { 'hr': 21, 'mn': 0, 'sec': 0 },
00465                       u'nachts':      { 'hr': 21, 'mn': 0, 'sec': 0 },
00466                       u'heute abend': { 'hr': 21, 'mn': 0, 'sec': 0 },
00467                       u'heute nacht': { 'hr': 21, 'mn': 0, 'sec': 0 },
00468                       u'feierabend':  { 'hr': 17, 'mn': 0, 'sec': 0 },
00469                     }
00470 
00471 
00472 pdtLocales = { 'en_US': pdtLocale_en,
00473                'en_AU': pdtLocale_au,
00474                'es_ES': pdtLocale_es,
00475                'de_DE': pdtLocale_de,
00476              }
00477 
00478 
00479 def _initLocale(ptc):
00480     """
00481     Helper function to initialize the different lists and strings
00482     from either PyICU or one of the internal pdt Locales and store
00483     them into ptc.
00484     """
00485 
00486     def lcase(x):
00487         return x.lower()
00488 
00489     if pyicu and ptc.usePyICU:
00490         ptc.icuLocale = None
00491 
00492         if ptc.localeID is not None:
00493             ptc.icuLocale = pyicu.Locale(ptc.localeID)
00494 
00495         if ptc.icuLocale is None:
00496             for id in range(0, len(ptc.fallbackLocales)):
00497                 ptc.localeID  = ptc.fallbackLocales[id]
00498                 ptc.icuLocale = pyicu.Locale(ptc.localeID)
00499 
00500                 if ptc.icuLocale is not None:
00501                     break
00502 
00503         ptc.icuSymbols = pyicu.DateFormatSymbols(ptc.icuLocale)
00504 
00505           # grab ICU list of weekdays, skipping first entry which
00506           # is always blank
00507         wd  = map(lcase, ptc.icuSymbols.getWeekdays()[1:])
00508         swd = map(lcase, ptc.icuSymbols.getShortWeekdays()[1:])
00509 
00510           # store them in our list with Monday first (ICU puts Sunday first)
00511         ptc.Weekdays      = wd[1:] + wd[0:1]
00512         ptc.shortWeekdays = swd[1:] + swd[0:1]
00513         ptc.Months        = map(lcase, ptc.icuSymbols.getMonths())
00514         ptc.shortMonths   = map(lcase, ptc.icuSymbols.getShortMonths())
00515 
00516           # not quite sure how to init this so for now
00517           # set it to none so it will be set to the en_US defaults for now
00518         ptc.re_consts   = None
00519         ptc.icu_df      = { 'full':   pyicu.DateFormat.createDateInstance(pyicu.DateFormat.kFull,   ptc.icuLocale),
00520                             'long':   pyicu.DateFormat.createDateInstance(pyicu.DateFormat.kLong,   ptc.icuLocale),
00521                             'medium': pyicu.DateFormat.createDateInstance(pyicu.DateFormat.kMedium, ptc.icuLocale),
00522                             'short':  pyicu.DateFormat.createDateInstance(pyicu.DateFormat.kShort,  ptc.icuLocale),
00523                           }
00524         ptc.icu_tf      = { 'full':   pyicu.DateFormat.createTimeInstance(pyicu.DateFormat.kFull,   ptc.icuLocale),
00525                             'long':   pyicu.DateFormat.createTimeInstance(pyicu.DateFormat.kLong,   ptc.icuLocale),
00526                             'medium': pyicu.DateFormat.createTimeInstance(pyicu.DateFormat.kMedium, ptc.icuLocale),
00527                             'short':  pyicu.DateFormat.createTimeInstance(pyicu.DateFormat.kShort,  ptc.icuLocale),
00528                           }
00529         ptc.dateFormats = { 'full':   ptc.icu_df['full'].toPattern(),
00530                             'long':   ptc.icu_df['long'].toPattern(),
00531                             'medium': ptc.icu_df['medium'].toPattern(),
00532                             'short':  ptc.icu_df['short'].toPattern(),
00533                           }
00534         ptc.timeFormats = { 'full':   ptc.icu_tf['full'].toPattern(),
00535                             'long':   ptc.icu_tf['long'].toPattern(),
00536                             'medium': ptc.icu_tf['medium'].toPattern(),
00537                             'short':  ptc.icu_tf['short'].toPattern(),
00538                           }
00539     else:
00540         if not ptc.localeID in pdtLocales:
00541             for id in range(0, len(ptc.fallbackLocales)):
00542                 ptc.localeID  = ptc.fallbackLocales[id]
00543 
00544                 if ptc.localeID in pdtLocales:
00545                     break
00546 
00547         ptc.locale   = pdtLocales[ptc.localeID]
00548         ptc.usePyICU = False
00549 
00550         ptc.Weekdays      = ptc.locale.Weekdays
00551         ptc.shortWeekdays = ptc.locale.shortWeekdays
00552         ptc.Months        = ptc.locale.Months
00553         ptc.shortMonths   = ptc.locale.shortMonths
00554         ptc.dateFormats   = ptc.locale.dateFormats
00555         ptc.timeFormats   = ptc.locale.timeFormats
00556 
00557       # these values are used to setup the various bits 
00558       # of the regex values used to parse
00559       #
00560       # check if a local set of constants has been
00561       # provided, if not use en_US as the default
00562     if ptc.localeID in pdtLocales:
00563         ptc.re_sources = pdtLocales[ptc.localeID].re_sources
00564         ptc.re_values  = pdtLocales[ptc.localeID].re_consts
00565 
00566         units = pdtLocales[ptc.localeID].units
00567 
00568         ptc.Modifiers  = pdtLocales[ptc.localeID].modifiers
00569         ptc.dayOffsets = pdtLocales[ptc.localeID].dayoffsets
00570 
00571           # for now, pull over any missing keys from the US set
00572         for key in pdtLocales['en_US'].re_consts:
00573             if not key in ptc.re_values:
00574                 ptc.re_values[key] = pdtLocales['en_US'].re_consts[key]
00575     else:
00576         ptc.re_sources = pdtLocales['en_US'].re_sources
00577         ptc.re_values  = pdtLocales['en_US'].re_consts
00578         ptc.Modifiers  = pdtLocales['en_US'].modifiers
00579         ptc.dayOffsets = pdtLocales['en_US'].dayoffsets
00580         units          = pdtLocales['en_US'].units
00581 
00582       # escape any regex special characters that may be found
00583     wd   = tuple(map(re.escape, ptc.Weekdays))
00584     swd  = tuple(map(re.escape, ptc.shortWeekdays))
00585     mth  = tuple(map(re.escape, ptc.Months))
00586     smth = tuple(map(re.escape, ptc.shortMonths))
00587 
00588     ptc.re_values['months']      = '%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s' % mth
00589     ptc.re_values['shortmonths'] = '%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s' % smth
00590     ptc.re_values['days']        = '%s|%s|%s|%s|%s|%s|%s' % wd
00591     ptc.re_values['shortdays']   = '%s|%s|%s|%s|%s|%s|%s' % swd
00592 
00593     l = []
00594     for unit in units:
00595         l.append('|'.join(units[unit]))
00596 
00597     ptc.re_values['units'] = '|'.join(l)
00598     ptc.Units              = ptc.re_values['units'].split('|')
00599 
00600 
00601 def _initSymbols(ptc):
00602     """
00603     Helper function to initialize the single character constants
00604     and other symbols needed.
00605     """
00606     ptc.timeSep  = [ u':' ]
00607     ptc.dateSep  = [ u'/' ]
00608     ptc.meridian = [ u'AM', u'PM' ]
00609 
00610     ptc.usesMeridian = True
00611     ptc.uses24       = False
00612 
00613     if pyicu and ptc.usePyICU:
00614         am = u''
00615         pm = u''
00616         ts = ''
00617 
00618         # ICU doesn't seem to provide directly the
00619         # date or time seperator - so we have to
00620         # figure it out
00621         o = ptc.icu_tf['short']
00622         s = ptc.timeFormats['short']
00623 
00624         ptc.usesMeridian = u'a' in s
00625         ptc.uses24       = u'H' in s
00626 
00627         # '11:45 AM' or '11:45'
00628         s = o.format(datetime.datetime(2003, 10, 30, 11, 45))
00629 
00630         # ': AM' or ':'
00631         s = s.replace('11', '').replace('45', '')
00632 
00633         if len(s) > 0:
00634             ts = s[0]
00635 
00636         if ptc.usesMeridian:
00637             # '23:45 AM' or '23:45'
00638             am = s[1:].strip()
00639             s  = o.format(datetime.datetime(2003, 10, 30, 23, 45))
00640 
00641             if ptc.uses24:
00642                 s = s.replace('23', '')
00643             else:
00644                 s = s.replace('11', '')
00645 
00646             # 'PM' or ''
00647             pm = s.replace('45', '').replace(ts, '').strip()
00648 
00649         ptc.timeSep  = [ ts ]
00650         ptc.meridian = [ am, pm ]
00651 
00652         o = ptc.icu_df['short']
00653         s = o.format(datetime.datetime(2003, 10, 30, 11, 45))
00654         s = s.replace('10', '').replace('30', '').replace('03', '').replace('2003', '')
00655 
00656         if len(s) > 0:
00657             ds = s[0]
00658         else:
00659             ds = '/'
00660 
00661         ptc.dateSep = [ ds ]
00662         s           = ptc.dateFormats['short']
00663         l           = s.lower().split(ds)
00664         dp_order    = []
00665 
00666         for s in l:
00667             if len(s) > 0:
00668                 dp_order.append(s[:1])
00669 
00670         ptc.dp_order = dp_order
00671     else:
00672         ptc.timeSep      = ptc.locale.timeSep
00673         ptc.dateSep      = ptc.locale.dateSep
00674         ptc.meridian     = ptc.locale.meridian
00675         ptc.usesMeridian = ptc.locale.usesMeridian
00676         ptc.uses24       = ptc.locale.uses24
00677         ptc.dp_order     = ptc.locale.dp_order
00678 
00679       # build am and pm lists to contain
00680       # original case, lowercase and first-char
00681       # versions of the meridian text
00682 
00683     if len(ptc.meridian) > 0:
00684         am     = ptc.meridian[0]
00685         ptc.am = [ am ]
00686 
00687         if len(am) > 0:
00688             ptc.am.append(am[0])
00689             am = am.lower()
00690             ptc.am.append(am)
00691             ptc.am.append(am[0])
00692     else:
00693         am     = ''
00694         ptc.am = [ '', '' ]
00695 
00696     if len(ptc.meridian) > 1:
00697         pm     = ptc.meridian[1]
00698         ptc.pm = [ pm ]
00699 
00700         if len(pm) > 0:
00701             ptc.pm.append(pm[0])
00702             pm = pm.lower()
00703             ptc.pm.append(pm)
00704             ptc.pm.append(pm[0])
00705     else:
00706         pm     = ''
00707         ptc.pm = [ '', '' ]
00708 
00709 
00710 def _initPatterns(ptc):
00711     """
00712     Helper function to take the different localized bits from ptc and
00713     create the regex strings.
00714     """
00715     # TODO add code to parse the date formats and build the regexes up from sub-parts
00716     # TODO find all hard-coded uses of date/time seperators
00717 
00718     ptc.RE_DATE4     = r'''(?P<date>(((?P<day>\d\d?)(?P<suffix>%(daysuffix)s)?(,)?(\s)?)
00719                                       (?P<mthname>(%(months)s|%(shortmonths)s))\s?
00720                                       (?P<year>\d\d(\d\d)?)?
00721                                     )
00722                            )''' % ptc.re_values
00723 
00724     # I refactored DATE3 to fix Issue 16 http://code.google.com/p/parsedatetime/issues/detail?id=16
00725     # I suspect the final line was for a trailing time - but testing shows it's not needed
00726     # ptc.RE_DATE3     = r'''(?P<date>((?P<mthname>(%(months)s|%(shortmonths)s))\s?
00727     #                                  ((?P<day>\d\d?)(\s?|%(daysuffix)s|$)+)?
00728     #                                  (,\s?(?P<year>\d\d(\d\d)?))?))
00729     #                        (\s?|$|[^0-9a-zA-Z])''' % ptc.re_values
00730     ptc.RE_DATE3     = r'''(?P<date>(
00731                                      (((?P<mthname>(%(months)s|%(shortmonths)s))|
00732                                      ((?P<day>\d\d?)(?P<suffix>%(daysuffix)s)?))(\s)?){1,2}
00733                                      ((,)?(\s)?(?P<year>\d\d(\d\d)?))?
00734                                     )
00735                            )''' % ptc.re_values
00736     ptc.RE_MONTH     = r'''(\s?|^)
00737                            (?P<month>(
00738                                       (?P<mthname>(%(months)s|%(shortmonths)s))
00739                                       (\s?(?P<year>(\d\d\d\d)))?
00740                                      ))
00741                            (\s?|$|[^0-9a-zA-Z])''' % ptc.re_values
00742     ptc.RE_WEEKDAY   = r'''(\s?|^)
00743                            (?P<weekday>(%(days)s|%(shortdays)s))
00744                            (\s?|$|[^0-9a-zA-Z])''' % ptc.re_values
00745 
00746     ptc.RE_SPECIAL   = r'(?P<special>^[%(specials)s]+)\s+' % ptc.re_values
00747     ptc.RE_UNITS     = r'''(?P<qty>(-?\d+\s*
00748                                     (?P<units>((%(units)s)s?))
00749                                    ))''' % ptc.re_values
00750     ptc.RE_QUNITS    = r'''(?P<qty>(-?\d+\s?
00751                                     (?P<qunits>%(qunits)s)
00752                                     (\s?|,|$)
00753                                    ))''' % ptc.re_values
00754     ptc.RE_MODIFIER  = r'''(\s?|^)
00755                            (?P<modifier>
00756                             (previous|prev|last|next|eod|eo|(end\sof)|(in\sa)))''' % ptc.re_values
00757     ptc.RE_MODIFIER2 = r'''(\s?|^)
00758                            (?P<modifier>
00759                             (from|before|after|ago|prior))
00760                            (\s?|$|[^0-9a-zA-Z])''' % ptc.re_values
00761     ptc.RE_TIMEHMS   = r'''(\s?|^)
00762                            (?P<hours>\d\d?)
00763                            (?P<tsep>%(timeseperator)s|)
00764                            (?P<minutes>\d\d)
00765                            (?:(?P=tsep)(?P<seconds>\d\d(?:[.,]\d+)?))?''' % ptc.re_values
00766     ptc.RE_TIMEHMS2  = r'''(?P<hours>(\d\d?))
00767                            ((?P<tsep>%(timeseperator)s|)
00768                             (?P<minutes>(\d\d?))
00769                             (?:(?P=tsep)
00770                                (?P<seconds>\d\d?
00771                                 (?:[.,]\d+)?))?)?''' % ptc.re_values
00772 
00773     if 'meridian' in ptc.re_values:
00774         ptc.RE_TIMEHMS2 += r'\s?(?P<meridian>(%(meridian)s))' % ptc.re_values
00775 
00776     dateSeps = ''.join(ptc.dateSep) + '.'
00777 
00778     ptc.RE_DATE      = r'''(\s?|^)
00779                            (?P<date>(\d\d?[%s]\d\d?([%s]\d\d(\d\d)?)?))
00780                            (\s?|$|[^0-9a-zA-Z])''' % (dateSeps, dateSeps)
00781     ptc.RE_DATE2     = r'[%s]' % dateSeps
00782     ptc.RE_DAY       = r'''(\s?|^)
00783                            (?P<day>(today|tomorrow|yesterday))
00784                            (\s?|$|[^0-9a-zA-Z])''' % ptc.re_values
00785     ptc.RE_DAY2      = r'''(?P<day>\d\d?)|(?P<suffix>%(daysuffix)s)
00786                         ''' % ptc.re_values
00787     ptc.RE_TIME      = r'''(\s?|^)
00788                            (?P<time>(morning|breakfast|noon|lunch|evening|midnight|tonight|dinner|night|now))
00789                            (\s?|$|[^0-9a-zA-Z])''' % ptc.re_values
00790     ptc.RE_REMAINING = r'\s+'
00791 
00792     # Regex for date/time ranges
00793     ptc.RE_RTIMEHMS  = r'''(\s?|^)
00794                            (\d\d?)%(timeseperator)s
00795                            (\d\d)
00796                            (%(timeseperator)s(\d\d))?
00797                            (\s?|$)''' % ptc.re_values
00798     ptc.RE_RTIMEHMS2 = r'''(\s?|^)
00799                            (\d\d?)
00800                            (%(timeseperator)s(\d\d?))?
00801                            (%(timeseperator)s(\d\d?))?''' % ptc.re_values
00802 
00803     if 'meridian' in ptc.re_values:
00804         ptc.RE_RTIMEHMS2 += r'\s?(%(meridian)s)' % ptc.re_values
00805 
00806     ptc.RE_RDATE  = r'(\d+([%s]\d+)+)' % dateSeps
00807     ptc.RE_RDATE3 = r'''((((%(months)s))\s?
00808                          ((\d\d?)
00809                           (\s?|%(daysuffix)s|$)+)?
00810                          (,\s?\d\d\d\d)?))''' % ptc.re_values
00811 
00812     # "06/07/06 - 08/09/06"
00813     ptc.DATERNG1 = ptc.RE_RDATE + r'\s?%(rangeseperator)s\s?' + ptc.RE_RDATE
00814     ptc.DATERNG1 = ptc.DATERNG1 % ptc.re_values
00815 
00816     # "march 31 - june 1st, 2006"
00817     ptc.DATERNG2 = ptc.RE_RDATE3 + r'\s?%(rangeseperator)s\s?' + ptc.RE_RDATE3
00818     ptc.DATERNG2 = ptc.DATERNG2 % ptc.re_values
00819 
00820     # "march 1rd -13th"
00821     ptc.DATERNG3 = ptc.RE_RDATE3 + r'\s?%(rangeseperator)s\s?(\d\d?)\s?(rd|st|nd|th)?'
00822     ptc.DATERNG3 = ptc.DATERNG3 % ptc.re_values
00823 
00824     # "4:00:55 pm - 5:90:44 am", '4p-5p'
00825     ptc.TIMERNG1 = ptc.RE_RTIMEHMS2 + r'\s?%(rangeseperator)s\s?' + ptc.RE_RTIMEHMS2
00826     ptc.TIMERNG1 = ptc.TIMERNG1 % ptc.re_values
00827 
00828     # "4:00 - 5:90 ", "4:55:55-3:44:55"
00829     ptc.TIMERNG2 = ptc.RE_RTIMEHMS + r'\s?%(rangeseperator)s\s?' + ptc.RE_RTIMEHMS
00830     ptc.TIMERNG2 = ptc.TIMERNG2 % ptc.re_values
00831 
00832     # "4-5pm "
00833     ptc.TIMERNG3 = r'\d\d?\s?%(rangeseperator)s\s?' + ptc.RE_RTIMEHMS2
00834     ptc.TIMERNG3 = ptc.TIMERNG3 % ptc.re_values
00835 
00836     # "4:30-5pm "
00837     ptc.TIMERNG4 = ptc.RE_RTIMEHMS + r'\s?%(rangeseperator)s\s?' + ptc.RE_RTIMEHMS2
00838     ptc.TIMERNG4 = ptc.TIMERNG4 % ptc.re_values
00839 
00840 
00841 def _initConstants(ptc):
00842     """
00843     Create localized versions of the units, week and month names
00844     """
00845       # build weekday offsets - yes, it assumes the Weekday and shortWeekday
00846       # lists are in the same order and Mon..Sun (Python style)
00847     ptc.WeekdayOffsets = {}
00848 
00849     o = 0
00850     for key in ptc.Weekdays:
00851         ptc.WeekdayOffsets[key] = o
00852         o += 1
00853     o = 0
00854     for key in ptc.shortWeekdays:
00855         ptc.WeekdayOffsets[key] = o
00856         o += 1
00857 
00858       # build month offsets - yes, it assumes the Months and shortMonths
00859       # lists are in the same order and Jan..Dec
00860     ptc.MonthOffsets = {}
00861 
00862     o = 1
00863     for key in ptc.Months:
00864         ptc.MonthOffsets[key] = o
00865         o += 1
00866     o = 1
00867     for key in ptc.shortMonths:
00868         ptc.MonthOffsets[key] = o
00869         o += 1
00870 
00871     # ptc.DaySuffixes = ptc.re_consts['daysuffix'].split('|')
00872 
00873 
00874 class Constants:
00875     """
00876     Default set of constants for parsedatetime.
00877 
00878     If PyICU is present, then the class will first try to get PyICU
00879     to return a locale specified by C{localeID}.  If either C{localeID} is
00880     None or if the locale does not exist within PyICU, then each of the
00881     locales defined in C{fallbackLocales} is tried in order.
00882 
00883     If PyICU is not present or none of the specified locales can be used,
00884     then the class will initialize itself to the en_US locale.
00885 
00886     if PyICU is not present or not requested, only the locales defined by
00887     C{pdtLocales} will be searched.
00888     """
00889     def __init__(self, localeID=None, usePyICU=True, fallbackLocales=['en_US']):
00890         self.localeID        = localeID
00891         self.fallbackLocales = fallbackLocales
00892 
00893         if 'en_US' not in self.fallbackLocales:
00894             self.fallbackLocales.append('en_US')
00895 
00896           # define non-locale specific constants
00897 
00898         self.locale   = None
00899         self.usePyICU = usePyICU
00900 
00901         # starting cache of leap years
00902         # daysInMonth will add to this if during
00903         # runtime it gets a request for a year not found
00904         self._leapYears = [ 1904, 1908, 1912, 1916, 1920, 1924, 1928, 1932, 1936, 1940, 1944,
00905                             1948, 1952, 1956, 1960, 1964, 1968, 1972, 1976, 1980, 1984, 1988,
00906                             1992, 1996, 2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028, 2032,
00907                             2036, 2040, 2044, 2048, 2052, 2056, 2060, 2064, 2068, 2072, 2076,
00908                             2080, 2084, 2088, 2092, 2096 ]
00909 
00910         self.Second =   1
00911         self.Minute =  60 * self.Second
00912         self.Hour   =  60 * self.Minute
00913         self.Day    =  24 * self.Hour
00914         self.Week   =   7 * self.Day
00915         self.Month  =  30 * self.Day
00916         self.Year   = 365 * self.Day
00917 
00918         self.rangeSep = u'-'
00919 
00920         self._DaysInMonthList = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
00921 
00922         self.BirthdayEpoch = 50
00923 
00924         # DOWParseStyle controls how we parse "Tuesday"
00925         # If the current day was Thursday and the text to parse is "Tuesday"
00926         # then the following table shows how each style would be returned
00927         # -1, 0, +1
00928         #
00929         # Current day marked as ***
00930         #
00931         #          Sun Mon Tue Wed Thu Fri Sat
00932         # week -1
00933         # current         -1,0     ***
00934         # week +1          +1
00935         #
00936         # If the current day was Monday and the text to parse is "Tuesday"
00937         # then the following table shows how each style would be returned
00938         # -1, 0, +1
00939         #
00940         #          Sun Mon Tue Wed Thu Fri Sat
00941         # week -1           -1
00942         # current      *** 0,+1
00943         # week +1
00944 
00945         self.DOWParseStyle = 1
00946 
00947         # CurrentDOWParseStyle controls how we parse "Friday"
00948         # If the current day was Friday and the text to parse is "Friday"
00949         # then the following table shows how each style would be returned
00950         # True/False. This also depends on DOWParseStyle.
00951         #
00952         # Current day marked as ***
00953         #
00954         # DOWParseStyle = 0
00955         #          Sun Mon Tue Wed Thu Fri Sat
00956         # week -1
00957         # current                      T,F
00958         # week +1
00959         #
00960         # DOWParseStyle = -1
00961         #          Sun Mon Tue Wed Thu Fri Sat
00962         # week -1                       F
00963         # current                       T
00964         # week +1
00965         #
00966         # DOWParseStyle = +1
00967         #
00968         #          Sun Mon Tue Wed Thu Fri Sat
00969         # week -1
00970         # current                       T
00971         # week +1                       F
00972 
00973         self.CurrentDOWParseStyle = False
00974 
00975         # initalize attributes to empty values to ensure
00976         # they are defined
00977         self.re_sources     = None
00978         self.re_values      = None
00979         self.Modifiers      = None
00980         self.dayOffsets     = None
00981         self.WeekdayOffsets = None
00982         self.MonthOffsets   = None
00983         self.dateSep        = None
00984         self.timeSep        = None
00985         self.am             = None
00986         self.pm             = None
00987         self.meridian       = None
00988         self.usesMeridian   = None
00989         self.uses24         = None
00990         self.dp_order       = None
00991 
00992         self.RE_DATE4     = r''
00993         self.RE_DATE3     = r''
00994         self.RE_MONTH     = r''
00995         self.RE_WEEKDAY   = r''
00996         self.RE_SPECIAL   = r''
00997         self.RE_UNITS     = r''
00998         self.RE_QUNITS    = r''
00999         self.RE_MODIFIER  = r''
01000         self.RE_MODIFIER2 = r''
01001         self.RE_TIMEHMS   = r''
01002         self.RE_TIMEHMS2  = r''
01003         self.RE_DATE      = r''
01004         self.RE_DATE2     = r''
01005         self.RE_DAY       = r''
01006         self.RE_DAY2      = r''
01007         self.RE_TIME      = r''
01008         self.RE_REMAINING = r''
01009         self.RE_RTIMEHMS  = r''
01010         self.RE_RTIMEHMS2 = r''
01011         self.RE_RDATE     = r''
01012         self.RE_RDATE3    = r''
01013         self.DATERNG1     = r''
01014         self.DATERNG2     = r''
01015         self.DATERNG3     = r''
01016         self.TIMERNG1     = r''
01017         self.TIMERNG2     = r''
01018         self.TIMERNG3     = r''
01019         self.TIMERNG4     = r''
01020 
01021         _initLocale(self)
01022         _initConstants(self)
01023         _initSymbols(self)
01024         _initPatterns(self)
01025 
01026         self.re_option = re.IGNORECASE + re.VERBOSE
01027         self.cre_source = { 'CRE_SPECIAL':   self.RE_SPECIAL,
01028                             'CRE_UNITS':     self.RE_UNITS,
01029                             'CRE_QUNITS':    self.RE_QUNITS,
01030                             'CRE_MODIFIER':  self.RE_MODIFIER,
01031                             'CRE_MODIFIER2': self.RE_MODIFIER2,
01032                             'CRE_TIMEHMS':   self.RE_TIMEHMS,
01033                             'CRE_TIMEHMS2':  self.RE_TIMEHMS2,
01034                             'CRE_DATE':      self.RE_DATE,
01035                             'CRE_DATE2':     self.RE_DATE2,
01036                             'CRE_DATE3':     self.RE_DATE3,
01037                             'CRE_DATE4':     self.RE_DATE4,
01038                             'CRE_MONTH':     self.RE_MONTH,
01039                             'CRE_WEEKDAY':   self.RE_WEEKDAY,
01040                             'CRE_DAY':       self.RE_DAY,
01041                             'CRE_DAY2':      self.RE_DAY2,
01042                             'CRE_TIME':      self.RE_TIME,
01043                             'CRE_REMAINING': self.RE_REMAINING,
01044                             'CRE_RTIMEHMS':  self.RE_RTIMEHMS,
01045                             'CRE_RTIMEHMS2': self.RE_RTIMEHMS2,
01046                             'CRE_RDATE':     self.RE_RDATE,
01047                             'CRE_RDATE3':    self.RE_RDATE3,
01048                             'CRE_TIMERNG1':  self.TIMERNG1,
01049                             'CRE_TIMERNG2':  self.TIMERNG2,
01050                             'CRE_TIMERNG3':  self.TIMERNG3,
01051                             'CRE_TIMERNG4':  self.TIMERNG4,
01052                             'CRE_DATERNG1':  self.DATERNG1,
01053                             'CRE_DATERNG2':  self.DATERNG2,
01054                             'CRE_DATERNG3':  self.DATERNG3,
01055                           }
01056         self.cre_keys = self.cre_source.keys()
01057 
01058 
01059     def __getattr__(self, name):
01060         if name in self.cre_keys:
01061             value = re.compile(self.cre_source[name], self.re_option)
01062             setattr(self, name, value)
01063             return value
01064         else:
01065             raise AttributeError, name
01066 
01067     def daysInMonth(self, month, year):
01068         """
01069         Take the given month (1-12) and a given year (4 digit) return
01070         the number of days in the month adjusting for leap year as needed
01071         """
01072         result = None
01073 
01074         if month > 0 and month <= 12:
01075             result = self._DaysInMonthList[month - 1]
01076 
01077             if month == 2:
01078                 if year in self._leapYears:
01079                     result += 1
01080                 else:
01081                     if calendar.isleap(year):
01082                         self._leapYears.append(year)
01083                         result += 1
01084 
01085         return result
01086 
01087     def buildSources(self, sourceTime=None):
01088         """
01089         Return a dictionary of date/time tuples based on the keys
01090         found in self.re_sources.
01091 
01092         The current time is used as the default and any specified
01093         item found in self.re_sources is inserted into the value
01094         and the generated dictionary is returned.
01095         """
01096         if sourceTime is None:
01097             (yr, mth, dy, hr, mn, sec, wd, yd, isdst) = time.localtime()
01098         else:
01099             (yr, mth, dy, hr, mn, sec, wd, yd, isdst) = sourceTime
01100 
01101         sources  = {}
01102         defaults = { 'yr': yr, 'mth': mth, 'dy':  dy,
01103                      'hr': hr, 'mn':  mn,  'sec': sec, }
01104 
01105         for item in self.re_sources:
01106             values = {}
01107             source = self.re_sources[item]
01108 
01109             for key in defaults.keys():
01110                 if key in source:
01111                     values[key] = source[key]
01112                 else:
01113                     values[key] = defaults[key]
01114 
01115             sources[item] = ( values['yr'], values['mth'], values['dy'],
01116                               values['hr'], values['mn'], values['sec'], wd, yd, isdst )
01117 
01118         return sources
01119