86
dp_order = [ u'm', u'd', u'y' ]
88
# this will be added to re_consts later
89
units = { 'seconds': [ 'second', 'sec' ],
90
'minutes': [ 'minute', 'min' ],
91
'hours': [ 'hour', 'hr' ],
92
'days': [ 'day', 'dy' ],
93
'weeks': [ 'week', 'wk' ],
94
'months': [ 'month', 'mth' ],
95
'years': [ 'year', 'yr' ],
98
# text constants to be used by regex's later
99
re_consts = { 'specials': 'in|on|of|at',
100
'timeseperator': ':',
101
'rangeseperator': '-',
102
'daysuffix': 'rd|st|nd|th',
103
'meridian': 'am|pm|a.m.|p.m.|a|p',
104
'qunits': 'h|m|s|d|w|m|y',
108
# Used to adjust the returned date before/after the source
109
modifiers = { 'from': 1,
124
dayoffsets = { 'tomorrow': 1,
129
# special day and/or times, i.e. lunch, noon, evening
130
# each element in the dictionary is a dictionary that is used
131
# to fill in any value to be replace - the current date/time will
132
# already have been populated by the method buildSources
133
re_sources = { 'noon': { 'hr': 12, 'mn': 0, 'sec': 0 },
134
'lunch': { 'hr': 12, 'mn': 0, 'sec': 0 },
135
'morning': { 'hr': 6, 'mn': 0, 'sec': 0 },
136
'breakfast': { 'hr': 8, 'mn': 0, 'sec': 0 },
137
'dinner': { 'hr': 19, 'mn': 0, 'sec': 0 },
138
'evening': { 'hr': 18, 'mn': 0, 'sec': 0 },
139
'midnight': { 'hr': 0, 'mn': 0, 'sec': 0 },
140
'night': { 'hr': 21, 'mn': 0, 'sec': 0 },
141
'tonight': { 'hr': 21, 'mn': 0, 'sec': 0 },
142
'eod': { 'hr': 17, 'mn': 0, 'sec': 0 },
148
en_AU Locale constants
150
This class will be used to initialize L{Constants} if PyICU is not located.
152
Defined as class variables are the lists and strings needed by parsedatetime
153
to evaluate strings for Australia
156
localeID = 'en_AU' # don't use a unicode string
157
dateSep = [ u'-', u'/' ]
159
meridian = [ u'AM', u'PM' ]
163
Weekdays = [ u'monday', u'tuesday', u'wednesday',
164
u'thursday', u'friday', u'saturday', u'sunday',
166
shortWeekdays = [ u'mon', u'tues', u'wed',
167
u'thu', u'fri', u'sat', u'sun',
169
Months = [ u'january', u'february', u'march',
170
u'april', u'may', u'june',
171
u'july', u'august', u'september',
172
u'october', u'november', u'december',
174
shortMonths = [ u'jan', u'feb', u'mar',
175
u'apr', u'may', u'jun',
176
u'jul', u'aug', u'sep',
177
u'oct', u'nov', u'dec',
179
dateFormats = { 'full': 'EEEE, d MMMM yyyy',
180
'long': 'd MMMM yyyy',
181
'medium': 'dd/MM/yyyy',
184
timeFormats = { 'full': 'h:mm:ss a z',
186
'medium': 'h:mm:ss a',
190
dp_order = [ u'd', u'm', u'y' ]
192
# this will be added to re_consts later
193
units = { 'seconds': [ 'second', 'sec' ],
194
'minutes': [ 'minute', 'min' ],
195
'hours': [ 'hour', 'hr' ],
196
'days': [ 'day', 'dy' ],
197
'weeks': [ 'week', 'wk' ],
198
'months': [ 'month', 'mth' ],
199
'years': [ 'year', 'yr' ],
202
# text constants to be used by regex's later
203
re_consts = { 'specials': 'in|on|of|at',
204
'timeseperator': ':',
205
'rangeseperator': '-',
206
'daysuffix': 'rd|st|nd|th',
207
'meridian': 'am|pm|a.m.|p.m.|a|p',
208
'qunits': 'h|m|s|d|w|m|y',
80
# this will be added to re_consts later
81
units = { 'seconds': [ 'second', 'sec' ],
82
'minutes': [ 'minute', 'min' ],
83
'hours': [ 'hour', 'hr' ],
84
'days': [ 'day', 'dy' ],
85
'weeks': [ 'week', 'wk' ],
86
'months': [ 'month', 'mth' ],
87
'years': [ 'year', 'yr' ],
90
# text constants to be used by regex's later
91
re_consts = { 'specials': 'in|on|of|at',
93
'daysuffix': 'rd|st|nd|th',
94
'meridian': 'am|pm|a.m.|p.m.|a|p',
95
'qunits': 'h|m|s|d|w|m|y',
212
99
# Used to adjust the returned date before/after the source
338
223
# each element in the dictionary is a dictionary that is used
339
224
# to fill in any value to be replace - the current date/time will
340
225
# already have been populated by the method buildSources
341
re_sources = { 'noon': { 'hr': 12, 'mn': 0, 'sec': 0 },
342
'lunch': { 'hr': 12, 'mn': 0, 'sec': 0 },
343
'morning': { 'hr': 6, 'mn': 0, 'sec': 0 },
344
'breakfast': { 'hr': 8, 'mn': 0, 'sec': 0 },
345
'dinner': { 'hr': 19, 'mn': 0, 'sec': 0 },
346
'evening': { 'hr': 18, 'mn': 0, 'sec': 0 },
347
'midnight': { 'hr': 0, 'mn': 0, 'sec': 0 },
348
'night': { 'hr': 21, 'mn': 0, 'sec': 0 },
349
'tonight': { 'hr': 21, 'mn': 0, 'sec': 0 },
350
'eod': { 'hr': 17, 'mn': 0, 'sec': 0 },
356
de_DE Locale constants
358
This class will be used to initialize L{Constants} if PyICU is not located.
360
Contributed by Debian parsedatetime package maintainer Bernd Zeimetz <bzed@debian.org>
362
Defined as class variables are the lists and strings needed by parsedatetime
363
to evaluate strings for German
366
localeID = 'de_DE' # don't use a unicode string
373
Weekdays = [ u'montag', u'dienstag', u'mittwoch',
374
u'donnerstag', u'freitag', u'samstag', u'sonntag',
376
shortWeekdays = [ u'mo', u'di', u'mi',
377
u'do', u'fr', u'sa', u'so',
379
Months = [ u'januar', u'februar', u'm\xe4rz',
380
u'april', u'mai', u'juni',
381
u'juli', u'august', u'september',
382
u'oktober', u'november', u'dezember',
384
shortMonths = [ u'jan', u'feb', u'mrz',
385
u'apr', u'mai', u'jun',
386
u'jul', u'aug', u'sep',
387
u'okt', u'nov', u'dez',
389
dateFormats = { 'full': u'EEEE, d. MMMM yyyy',
390
'long': u'd. MMMM yyyy',
391
'medium': u'dd.MM.yyyy',
395
timeFormats = { 'full': u'HH:mm:ss v',
396
'long': u'HH:mm:ss z',
397
'medium': u'HH:mm:ss',
401
dp_order = [ u'd', u'm', u'y' ]
403
# this will be added to re_consts later
404
units = { 'seconds': [ 'sekunden', 'sek', 's' ],
405
'minutes': [ 'minuten', 'min' , 'm' ],
406
'hours': [ 'stunden', 'std', 'h' ],
407
'days': [ 'tage', 't' ],
408
'weeks': [ 'wochen', 'w' ],
409
'months': [ 'monate' ], #the short version would be a capital M,
410
#as I understand it we can't distinguis
411
#between m for minutes and M for months.
412
'years': [ 'jahre', 'j' ],
415
# text constants to be used by regex's later
416
re_consts = { 'specials': 'am|dem|der|im|in|den|zum',
417
'timeseperator': ':',
418
'rangeseperator': '-',
420
'qunits': 'h|m|s|t|w|m|j',
424
# Used to adjust the returned date before/after the source
425
#still looking for insight on how to translate all of them to german.
426
modifiers = { u'from': 1,
442
#morgen/abermorgen does not work, see http://code.google.com/p/parsedatetime/issues/detail?id=19
443
dayoffsets = { u'morgen': 1,
450
# special day and/or times, i.e. lunch, noon, evening
451
# each element in the dictionary is a dictionary that is used
452
# to fill in any value to be replace - the current date/time will
453
# already have been populated by the method buildSources
454
re_sources = { u'mittag': { 'hr': 12, 'mn': 0, 'sec': 0 },
455
u'mittags': { 'hr': 12, 'mn': 0, 'sec': 0 },
456
u'mittagessen': { 'hr': 12, 'mn': 0, 'sec': 0 },
457
u'morgen': { 'hr': 6, 'mn': 0, 'sec': 0 },
458
u'morgens': { 'hr': 6, 'mn': 0, 'sec': 0 },
459
u'fr\e4hst\xe4ck': { 'hr': 8, 'mn': 0, 'sec': 0 },
460
u'abendessen': { 'hr': 19, 'mn': 0, 'sec': 0 },
461
u'abend': { 'hr': 18, 'mn': 0, 'sec': 0 },
462
u'abends': { 'hr': 18, 'mn': 0, 'sec': 0 },
463
u'mitternacht': { 'hr': 0, 'mn': 0, 'sec': 0 },
464
u'nacht': { 'hr': 21, 'mn': 0, 'sec': 0 },
465
u'nachts': { 'hr': 21, 'mn': 0, 'sec': 0 },
466
u'heute abend': { 'hr': 21, 'mn': 0, 'sec': 0 },
467
u'heute nacht': { 'hr': 21, 'mn': 0, 'sec': 0 },
468
u'feierabend': { 'hr': 17, 'mn': 0, 'sec': 0 },
226
re_sources = { 'noon': { 'hr': 12, 'mn': 0, 'sec': 0 },
227
'lunch': { 'hr': 12, 'mn': 0, 'sec': 0 },
228
'morning': { 'hr': 6, 'mn': 0, 'sec': 0 },
229
'breakfast': { 'hr': 8, 'mn': 0, 'sec': 0 },
230
'dinner': { 'hr': 19, 'mn': 0, 'sec': 0 },
231
'evening': { 'hr': 18, 'mn': 0, 'sec': 0 },
232
'midnight': { 'hr': 0, 'mn': 0, 'sec': 0 },
233
'night': { 'hr': 21, 'mn': 0, 'sec': 0 },
234
'tonight': { 'hr': 21, 'mn': 0, 'sec': 0 },
472
238
pdtLocales = { 'en_US': pdtLocale_en,
473
'en_AU': pdtLocale_au,
474
'es_ES': pdtLocale_es,
475
'de_DE': pdtLocale_de,
479
243
def _initLocale(ptc):
481
245
Helper function to initialize the different lists and strings
482
from either PyICU or one of the internal pdt Locales and store
246
from either PyICU or one of the locale pdt Locales and store
489
249
if pyicu and ptc.usePyICU:
492
if ptc.localeID is not None:
493
ptc.icuLocale = pyicu.Locale(ptc.localeID)
495
if ptc.icuLocale is None:
496
for id in range(0, len(ptc.fallbackLocales)):
497
ptc.localeID = ptc.fallbackLocales[id]
498
ptc.icuLocale = pyicu.Locale(ptc.localeID)
500
if ptc.icuLocale is not None:
503
ptc.icuSymbols = pyicu.DateFormatSymbols(ptc.icuLocale)
505
# grab ICU list of weekdays, skipping first entry which
507
wd = map(lcase, ptc.icuSymbols.getWeekdays()[1:])
508
swd = map(lcase, ptc.icuSymbols.getShortWeekdays()[1:])
510
# store them in our list with Monday first (ICU puts Sunday first)
511
ptc.Weekdays = wd[1:] + wd[0:1]
512
ptc.shortWeekdays = swd[1:] + swd[0:1]
513
ptc.Months = map(lcase, ptc.icuSymbols.getMonths())
514
ptc.shortMonths = map(lcase, ptc.icuSymbols.getShortMonths())
250
ptc.icuLocale = pyicu.Locale(ptc.localeID)
252
if not ptc.icuLocale:
253
ptc.icuLocale = pyicu.Locale('en_US')
255
ptc.icuSymbols = pyicu.DateFormatSymbols(ptc.icuLocale)
257
ptc.Weekdays = map(string.lower, ptc.icuSymbols.getWeekdays()[1:])
258
ptc.shortWeekdays = map(string.lower, ptc.icuSymbols.getShortWeekdays()[1:])
259
ptc.Months = map(string.lower, ptc.icuSymbols.getMonths())
260
ptc.shortMonths = map(string.lower, ptc.icuSymbols.getShortMonths())
516
262
# not quite sure how to init this so for now
517
263
# set it to none so it will be set to the en_US defaults for now
519
ptc.icu_df = { 'full': pyicu.DateFormat.createDateInstance(pyicu.DateFormat.kFull, ptc.icuLocale),
520
'long': pyicu.DateFormat.createDateInstance(pyicu.DateFormat.kLong, ptc.icuLocale),
521
'medium': pyicu.DateFormat.createDateInstance(pyicu.DateFormat.kMedium, ptc.icuLocale),
522
'short': pyicu.DateFormat.createDateInstance(pyicu.DateFormat.kShort, ptc.icuLocale),
524
ptc.icu_tf = { 'full': pyicu.DateFormat.createTimeInstance(pyicu.DateFormat.kFull, ptc.icuLocale),
525
'long': pyicu.DateFormat.createTimeInstance(pyicu.DateFormat.kLong, ptc.icuLocale),
526
'medium': pyicu.DateFormat.createTimeInstance(pyicu.DateFormat.kMedium, ptc.icuLocale),
527
'short': pyicu.DateFormat.createTimeInstance(pyicu.DateFormat.kShort, ptc.icuLocale),
529
ptc.dateFormats = { 'full': ptc.icu_df['full'].toPattern(),
530
'long': ptc.icu_df['long'].toPattern(),
531
'medium': ptc.icu_df['medium'].toPattern(),
532
'short': ptc.icu_df['short'].toPattern(),
534
ptc.timeFormats = { 'full': ptc.icu_tf['full'].toPattern(),
535
'long': ptc.icu_tf['long'].toPattern(),
536
'medium': ptc.icu_tf['medium'].toPattern(),
537
'short': ptc.icu_tf['short'].toPattern(),
266
ptc.icu_df = { 'full': pyicu.DateFormat.createDateInstance(pyicu.DateFormat.kFull, ptc.icuLocale),
267
'long': pyicu.DateFormat.createDateInstance(pyicu.DateFormat.kLong, ptc.icuLocale),
268
'medium': pyicu.DateFormat.createDateInstance(pyicu.DateFormat.kMedium, ptc.icuLocale),
269
'short': pyicu.DateFormat.createDateInstance(pyicu.DateFormat.kShort, ptc.icuLocale),
271
ptc.icu_tf = { 'full': pyicu.DateFormat.createTimeInstance(pyicu.DateFormat.kFull, ptc.icuLocale),
272
'long': pyicu.DateFormat.createTimeInstance(pyicu.DateFormat.kLong, ptc.icuLocale),
273
'medium': pyicu.DateFormat.createTimeInstance(pyicu.DateFormat.kMedium, ptc.icuLocale),
274
'short': pyicu.DateFormat.createTimeInstance(pyicu.DateFormat.kShort, ptc.icuLocale),
277
ptc.dateFormats = { 'full': ptc.icu_df['full'].toPattern(),
278
'long': ptc.icu_df['long'].toPattern(),
279
'medium': ptc.icu_df['medium'].toPattern(),
280
'short': ptc.icu_df['short'].toPattern(),
282
ptc.timeFormats = { 'full': ptc.icu_tf['full'].toPattern(),
283
'long': ptc.icu_tf['long'].toPattern(),
284
'medium': ptc.icu_tf['medium'].toPattern(),
285
'short': ptc.icu_tf['short'].toPattern(),
540
288
if not ptc.localeID in pdtLocales:
541
for id in range(0, len(ptc.fallbackLocales)):
542
ptc.localeID = ptc.fallbackLocales[id]
544
if ptc.localeID in pdtLocales:
547
ptc.locale = pdtLocales[ptc.localeID]
289
ptc.localeID = 'en_US'
291
ptc.locale = pdtLocales[ptc.localeID]
550
293
ptc.Weekdays = ptc.locale.Weekdays
551
294
ptc.shortWeekdays = ptc.locale.shortWeekdays
603
341
Helper function to initialize the single character constants
604
342
and other symbols needed.
606
ptc.timeSep = [ u':' ]
607
ptc.dateSep = [ u'/' ]
608
346
ptc.meridian = [ u'AM', u'PM' ]
610
348
ptc.usesMeridian = True
611
349
ptc.uses24 = False
613
if pyicu and ptc.usePyICU:
618
# ICU doesn't seem to provide directly the
619
# date or time seperator - so we have to
355
# ICU doesn't seem to provide directly the
356
# date or time seperator - so we have to
359
p = pyicu.FieldPosition(pyicu.DateFormat.AM_PM_FIELD)
621
360
o = ptc.icu_tf['short']
622
362
s = ptc.timeFormats['short']
624
364
ptc.usesMeridian = u'a' in s
625
365
ptc.uses24 = u'H' in s
627
# '11:45 AM' or '11:45'
628
s = o.format(datetime.datetime(2003, 10, 30, 11, 45))
367
s = o.format(datetime.datetime(2003, 10, 30, 11, 45)) # '11:45 AM' or '11:45'
631
s = s.replace('11', '').replace('45', '')
369
s = s.replace('11', '').replace('45', '') # ': AM' or ':'
636
374
if ptc.usesMeridian:
637
# '23:45 AM' or '23:45'
639
s = o.format(datetime.datetime(2003, 10, 30, 23, 45))
375
am = s[1:].strip() # 'AM'
377
s = o.format(datetime.datetime(2003, 10, 30, 23, 45)) # '23:45 AM' or '23:45'
642
380
s = s.replace('23', '')
644
382
s = s.replace('11', '')
647
pm = s.replace('45', '').replace(ts, '').strip()
384
pm = s.replace('45', '').replace(ptc.timeSep, '').strip() # 'PM' or ''
650
386
ptc.meridian = [ am, pm ]
652
o = ptc.icu_df['short']
653
s = o.format(datetime.datetime(2003, 10, 30, 11, 45))
654
s = s.replace('10', '').replace('30', '').replace('03', '').replace('2003', '')
662
s = ptc.dateFormats['short']
663
l = s.lower().split(ds)
668
dp_order.append(s[:1])
670
ptc.dp_order = dp_order
672
389
ptc.timeSep = ptc.locale.timeSep
673
390
ptc.dateSep = ptc.locale.dateSep
674
391
ptc.meridian = ptc.locale.meridian
675
392
ptc.usesMeridian = ptc.locale.usesMeridian
676
393
ptc.uses24 = ptc.locale.uses24
677
ptc.dp_order = ptc.locale.dp_order
679
395
# build am and pm lists to contain
680
396
# original case, lowercase and first-char
715
431
# TODO add code to parse the date formats and build the regexes up from sub-parts
716
432
# TODO find all hard-coded uses of date/time seperators
718
ptc.RE_DATE4 = r'''(?P<date>(((?P<day>\d\d?)(?P<suffix>%(daysuffix)s)?(,)?(\s)?)
719
(?P<mthname>(%(months)s|%(shortmonths)s))\s?
720
(?P<year>\d\d(\d\d)?)?
724
# I refactored DATE3 to fix Issue 16 http://code.google.com/p/parsedatetime/issues/detail?id=16
725
# I suspect the final line was for a trailing time - but testing shows it's not needed
726
# ptc.RE_DATE3 = r'''(?P<date>((?P<mthname>(%(months)s|%(shortmonths)s))\s?
727
# ((?P<day>\d\d?)(\s?|%(daysuffix)s|$)+)?
728
# (,\s?(?P<year>\d\d(\d\d)?))?))
729
# (\s?|$|[^0-9a-zA-Z])''' % ptc.re_values
730
ptc.RE_DATE3 = r'''(?P<date>(
731
(((?P<mthname>(%(months)s|%(shortmonths)s))|
732
((?P<day>\d\d?)(?P<suffix>%(daysuffix)s)?))(\s)?){1,2}
733
((,)?(\s)?(?P<year>\d\d(\d\d)?))?
736
ptc.RE_MONTH = r'''(\s?|^)
738
(?P<mthname>(%(months)s|%(shortmonths)s))
739
(\s?(?P<year>(\d\d\d\d)))?
741
(\s?|$|[^0-9a-zA-Z])''' % ptc.re_values
742
ptc.RE_WEEKDAY = r'''(\s?|^)
743
(?P<weekday>(%(days)s|%(shortdays)s))
744
(\s?|$|[^0-9a-zA-Z])''' % ptc.re_values
434
ptc.RE_DATE3 = r'(?P<date>((?P<mthname>(%(months)s|%(shortmonths)s))\s?((?P<day>\d\d?)(\s|%(daysuffix)s|,|$)+)?(?P<year>\d\d\d\d)?))' % ptc.re_values
435
ptc.RE_MONTH = r'(?P<month>((?P<mthname>(%(months)s|%(shortmonths)s))(\s?(?P<year>(\d\d\d\d)))?))' % ptc.re_values
436
ptc.RE_WEEKDAY = r'(?P<weekday>(%(days)s|%(shortdays)s))' % ptc.re_values
746
438
ptc.RE_SPECIAL = r'(?P<special>^[%(specials)s]+)\s+' % ptc.re_values
747
ptc.RE_UNITS = r'''(?P<qty>(-?\d+\s*
748
(?P<units>((%(units)s)s?))
749
))''' % ptc.re_values
750
ptc.RE_QUNITS = r'''(?P<qty>(-?\d+\s?
751
(?P<qunits>%(qunits)s)
753
))''' % ptc.re_values
754
ptc.RE_MODIFIER = r'''(\s?|^)
756
(previous|prev|last|next|eod|eo|(end\sof)|(in\sa)))''' % ptc.re_values
757
ptc.RE_MODIFIER2 = r'''(\s?|^)
759
(from|before|after|ago|prior))
760
(\s?|$|[^0-9a-zA-Z])''' % ptc.re_values
761
ptc.RE_TIMEHMS = r'''(\s?|^)
763
(?P<tsep>%(timeseperator)s|)
765
(?:(?P=tsep)(?P<seconds>\d\d(?:[.,]\d+)?))?''' % ptc.re_values
766
ptc.RE_TIMEHMS2 = r'''(?P<hours>(\d\d?))
767
((?P<tsep>%(timeseperator)s|)
771
(?:[.,]\d+)?))?)?''' % ptc.re_values
439
ptc.RE_UNITS = r'(?P<qty>(-?\d+\s*(?P<units>((%(units)s)s?))))' % ptc.re_values
440
ptc.RE_QUNITS = r'(?P<qty>(-?\d+\s?(?P<qunits>%(qunits)s)(\s|,|$)))' % ptc.re_values
441
ptc.RE_MODIFIER = r'(?P<modifier>(previous|prev|last|next|this|eo|(end\sof)|(in\sa)))' % ptc.re_values
442
ptc.RE_MODIFIER2 = r'(?P<modifier>(from|before|after|ago|prior))' % ptc.re_values
443
ptc.RE_TIMEHMS = r'(?P<hours>\d\d?)(?P<tsep>%(timeseperator)s|)(?P<minutes>\d\d)(?:(?P=tsep)(?P<seconds>\d\d(?:[.,]\d+)?))?' % ptc.re_values
445
ptc.RE_TIMEHMS2 = r'(?P<hours>(\d\d?))((?P<tsep>%(timeseperator)s|)(?P<minutes>(\d\d?))(?:(?P=tsep)(?P<seconds>\d\d?(?:[.,]\d+)?))?)?' % ptc.re_values
773
447
if 'meridian' in ptc.re_values:
774
448
ptc.RE_TIMEHMS2 += r'\s?(?P<meridian>(%(meridian)s))' % ptc.re_values
776
dateSeps = ''.join(ptc.dateSep) + '.'
778
ptc.RE_DATE = r'''(\s?|^)
779
(?P<date>(\d\d?[%s]\d\d?([%s]\d\d(\d\d)?)?))
780
(\s?|$|[^0-9a-zA-Z])''' % (dateSeps, dateSeps)
781
ptc.RE_DATE2 = r'[%s]' % dateSeps
782
ptc.RE_DAY = r'''(\s?|^)
783
(?P<day>(today|tomorrow|yesterday))
784
(\s?|$|[^0-9a-zA-Z])''' % ptc.re_values
785
ptc.RE_DAY2 = r'''(?P<day>\d\d?)|(?P<suffix>%(daysuffix)s)
787
ptc.RE_TIME = r'''(\s?|^)
788
(?P<time>(morning|breakfast|noon|lunch|evening|midnight|tonight|dinner|night|now))
789
(\s?|$|[^0-9a-zA-Z])''' % ptc.re_values
450
ptc.RE_DATE = r'(?P<date>\d+([/.\\]\d+)+)'
451
ptc.RE_DATE2 = r'[/.\\]'
452
ptc.RE_DAY = r'(?P<day>(today|tomorrow|yesterday))' % ptc.re_values
453
ptc.RE_TIME = r'\s*(?P<time>(morning|breakfast|noon|lunch|evening|midnight|tonight|dinner|night|now))' % ptc.re_values
790
454
ptc.RE_REMAINING = r'\s+'
792
# Regex for date/time ranges
793
ptc.RE_RTIMEHMS = r'''(\s?|^)
794
(\d\d?)%(timeseperator)s
796
(%(timeseperator)s(\d\d))?
797
(\s?|$)''' % ptc.re_values
798
ptc.RE_RTIMEHMS2 = r'''(\s?|^)
800
(%(timeseperator)s(\d\d?))?
801
(%(timeseperator)s(\d\d?))?''' % ptc.re_values
456
# Regex for date/time ranges
458
ptc.RE_RTIMEHMS = r'(\d\d?)%(timeseperator)s(\d\d)(%(timeseperator)s(\d\d))?' % ptc.re_values
460
ptc.RE_RTIMEHMS2 = r'(\d\d?)(%(timeseperator)s(\d\d?))?(%(timeseperator)s(\d\d?))?' % ptc.re_values
803
462
if 'meridian' in ptc.re_values:
804
463
ptc.RE_RTIMEHMS2 += r'\s?(%(meridian)s)' % ptc.re_values
806
ptc.RE_RDATE = r'(\d+([%s]\d+)+)' % dateSeps
807
ptc.RE_RDATE3 = r'''((((%(months)s))\s?
809
(\s?|%(daysuffix)s|$)+)?
810
(,\s?\d\d\d\d)?))''' % ptc.re_values
812
# "06/07/06 - 08/09/06"
813
ptc.DATERNG1 = ptc.RE_RDATE + r'\s?%(rangeseperator)s\s?' + ptc.RE_RDATE
814
ptc.DATERNG1 = ptc.DATERNG1 % ptc.re_values
816
# "march 31 - june 1st, 2006"
817
ptc.DATERNG2 = ptc.RE_RDATE3 + r'\s?%(rangeseperator)s\s?' + ptc.RE_RDATE3
818
ptc.DATERNG2 = ptc.DATERNG2 % ptc.re_values
821
ptc.DATERNG3 = ptc.RE_RDATE3 + r'\s?%(rangeseperator)s\s?(\d\d?)\s?(rd|st|nd|th)?'
822
ptc.DATERNG3 = ptc.DATERNG3 % ptc.re_values
824
# "4:00:55 pm - 5:90:44 am", '4p-5p'
825
ptc.TIMERNG1 = ptc.RE_RTIMEHMS2 + r'\s?%(rangeseperator)s\s?' + ptc.RE_RTIMEHMS2
826
ptc.TIMERNG1 = ptc.TIMERNG1 % ptc.re_values
828
# "4:00 - 5:90 ", "4:55:55-3:44:55"
829
ptc.TIMERNG2 = ptc.RE_RTIMEHMS + r'\s?%(rangeseperator)s\s?' + ptc.RE_RTIMEHMS
830
ptc.TIMERNG2 = ptc.TIMERNG2 % ptc.re_values
833
ptc.TIMERNG3 = r'\d\d?\s?%(rangeseperator)s\s?' + ptc.RE_RTIMEHMS2
834
ptc.TIMERNG3 = ptc.TIMERNG3 % ptc.re_values
837
ptc.TIMERNG4 = ptc.RE_RTIMEHMS + r'\s?%(rangeseperator)s\s?' + ptc.RE_RTIMEHMS2
838
ptc.TIMERNG4 = ptc.TIMERNG4 % ptc.re_values
465
ptc.RE_RDATE = r'(\d+([/.\\]\d+)+)'
466
ptc.RE_RDATE3 = r'((((%(months)s))\s?((\d\d?)(\s|%(daysuffix)s|,|$)+)?(\d\d\d\d)?))' % ptc.re_values
467
ptc.DATERNG1 = ptc.RE_RDATE + r'\s?-\s?' + ptc.RE_RDATE # "06/07/06 - 08/09/06"
468
ptc.DATERNG2 = ptc.RE_RDATE3 + r'\s?-\s?' + ptc.RE_RDATE3 # "march 31 - june 1st, 2006"
469
ptc.DATERNG3 = ptc.RE_RDATE3 + r'\s?' + r'-' + r'\s?(\d\d?)\s?(rd|st|nd|th)?' % ptc.re_values # "march 1rd -13th"
470
ptc.TIMERNG1 = ptc.RE_RTIMEHMS2 + r'\s?-\s?'+ ptc.RE_RTIMEHMS2 # "4:00:55 pm - 5:90:44 am",'4p-5p'
471
ptc.TIMERNG2 = ptc.RE_RTIMEHMS + r'\s?-\s?'+ ptc.RE_RTIMEHMS # "4:00 - 5:90 ","4:55:55-3:44:55"
472
ptc.TIMERNG3 = r'\d\d?\s?-\s?'+ ptc.RE_RTIMEHMS2 # "4-5pm "
841
475
def _initConstants(ptc):
858
492
# build month offsets - yes, it assumes the Months and shortMonths
859
493
# lists are in the same order and Jan..Dec
860
494
ptc.MonthOffsets = {}
863
498
for key in ptc.Months:
864
499
ptc.MonthOffsets[key] = o
500
ptc.DaysInMonth[key] = ptc.DaysInMonthList[o - 1]
867
503
for key in ptc.shortMonths:
868
504
ptc.MonthOffsets[key] = o
505
ptc.DaysInMonth[key] = ptc.DaysInMonthList[o - 1]
871
# ptc.DaySuffixes = ptc.re_consts['daysuffix'].split('|')
876
511
Default set of constants for parsedatetime.
878
If PyICU is present, then the class will first try to get PyICU
879
to return a locale specified by C{localeID}. If either C{localeID} is
880
None or if the locale does not exist within PyICU, then each of the
881
locales defined in C{fallbackLocales} is tried in order.
883
If PyICU is not present or none of the specified locales can be used,
884
then the class will initialize itself to the en_US locale.
886
if PyICU is not present or not requested, only the locales defined by
887
C{pdtLocales} will be searched.
513
If PyICU is present, then the class will initialize itself to
514
the current default locale or to the locale specified by C{localeID}.
516
If PyICU is not present then the class will initialize itself to
517
en_US locale or if C{localeID} is passed in and the value matches one
518
of the defined pdtLocales then that will be used.
889
def __init__(self, localeID=None, usePyICU=True, fallbackLocales=['en_US']):
890
self.localeID = localeID
891
self.fallbackLocales = fallbackLocales
893
if 'en_US' not in self.fallbackLocales:
894
self.fallbackLocales.append('en_US')
520
def __init__(self, localeID=None, usePyICU=True):
522
self.localeID = 'en_US'
524
self.localeID = localeID
896
526
# define non-locale specific constants
898
528
self.locale = None
899
529
self.usePyICU = usePyICU
901
# starting cache of leap years
902
# daysInMonth will add to this if during
903
# runtime it gets a request for a year not found
904
self._leapYears = [ 1904, 1908, 1912, 1916, 1920, 1924, 1928, 1932, 1936, 1940, 1944,
905
1948, 1952, 1956, 1960, 1964, 1968, 1972, 1976, 1980, 1984, 1988,
906
1992, 1996, 2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028, 2032,
907
2036, 2040, 2044, 2048, 2052, 2056, 2060, 2064, 2068, 2072, 2076,
908
2080, 2084, 2088, 2092, 2096 ]
911
532
self.Minute = 60 * self.Second
912
533
self.Hour = 60 * self.Minute
915
536
self.Month = 30 * self.Day
916
537
self.Year = 365 * self.Day
920
self._DaysInMonthList = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
922
self.BirthdayEpoch = 50
924
# DOWParseStyle controls how we parse "Tuesday"
925
# If the current day was Thursday and the text to parse is "Tuesday"
926
# then the following table shows how each style would be returned
929
# Current day marked as ***
931
# Sun Mon Tue Wed Thu Fri Sat
936
# If the current day was Monday and the text to parse is "Tuesday"
937
# then the following table shows how each style would be returned
940
# Sun Mon Tue Wed Thu Fri Sat
945
self.DOWParseStyle = 1
947
# CurrentDOWParseStyle controls how we parse "Friday"
948
# If the current day was Friday and the text to parse is "Friday"
949
# then the following table shows how each style would be returned
950
# True/False. This also depends on DOWParseStyle.
952
# Current day marked as ***
955
# Sun Mon Tue Wed Thu Fri Sat
961
# Sun Mon Tue Wed Thu Fri Sat
968
# Sun Mon Tue Wed Thu Fri Sat
973
self.CurrentDOWParseStyle = False
975
# initalize attributes to empty values to ensure
977
self.re_sources = None
978
self.re_values = None
979
self.Modifiers = None
980
self.dayOffsets = None
981
self.WeekdayOffsets = None
982
self.MonthOffsets = None
988
self.usesMeridian = None
995
self.RE_WEEKDAY = r''
996
self.RE_SPECIAL = r''
999
self.RE_MODIFIER = r''
1000
self.RE_MODIFIER2 = r''
1001
self.RE_TIMEHMS = r''
1002
self.RE_TIMEHMS2 = r''
1008
self.RE_REMAINING = r''
1009
self.RE_RTIMEHMS = r''
1010
self.RE_RTIMEHMS2 = r''
1012
self.RE_RDATE3 = r''
539
self.DaysInMonthList = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
1021
541
_initLocale(self)
1022
542
_initConstants(self)
1023
543
_initSymbols(self)
1024
544
_initPatterns(self)
1026
self.re_option = re.IGNORECASE + re.VERBOSE
1027
self.cre_source = { 'CRE_SPECIAL': self.RE_SPECIAL,
1028
'CRE_UNITS': self.RE_UNITS,
1029
'CRE_QUNITS': self.RE_QUNITS,
1030
'CRE_MODIFIER': self.RE_MODIFIER,
1031
'CRE_MODIFIER2': self.RE_MODIFIER2,
1032
'CRE_TIMEHMS': self.RE_TIMEHMS,
1033
'CRE_TIMEHMS2': self.RE_TIMEHMS2,
1034
'CRE_DATE': self.RE_DATE,
1035
'CRE_DATE2': self.RE_DATE2,
1036
'CRE_DATE3': self.RE_DATE3,
1037
'CRE_DATE4': self.RE_DATE4,
1038
'CRE_MONTH': self.RE_MONTH,
1039
'CRE_WEEKDAY': self.RE_WEEKDAY,
1040
'CRE_DAY': self.RE_DAY,
1041
'CRE_DAY2': self.RE_DAY2,
1042
'CRE_TIME': self.RE_TIME,
1043
'CRE_REMAINING': self.RE_REMAINING,
1044
'CRE_RTIMEHMS': self.RE_RTIMEHMS,
1045
'CRE_RTIMEHMS2': self.RE_RTIMEHMS2,
1046
'CRE_RDATE': self.RE_RDATE,
1047
'CRE_RDATE3': self.RE_RDATE3,
1048
'CRE_TIMERNG1': self.TIMERNG1,
1049
'CRE_TIMERNG2': self.TIMERNG2,
1050
'CRE_TIMERNG3': self.TIMERNG3,
1051
'CRE_TIMERNG4': self.TIMERNG4,
1052
'CRE_DATERNG1': self.DATERNG1,
1053
'CRE_DATERNG2': self.DATERNG2,
1054
'CRE_DATERNG3': self.DATERNG3,
1056
self.cre_keys = self.cre_source.keys()
1059
def __getattr__(self, name):
1060
if name in self.cre_keys:
1061
value = re.compile(self.cre_source[name], self.re_option)
1062
setattr(self, name, value)
1065
raise AttributeError, name
1067
def daysInMonth(self, month, year):
1069
Take the given month (1-12) and a given year (4 digit) return
1070
the number of days in the month adjusting for leap year as needed
1074
if month > 0 and month <= 12:
1075
result = self._DaysInMonthList[month - 1]
1078
if year in self._leapYears:
1081
if calendar.isleap(year):
1082
self._leapYears.append(year)
1087
547
def buildSources(self, sourceTime=None):