1
2
3 """
4 parsedatetime constants and helper functions to determine
5 regex values from Locale information if present.
6
7 Also contains the internal Locale classes to give some sane
8 defaults if PyICU is not found.
9 """
10
11 __license__ = """
12 Copyright (c) 2004-2007 Mike Taylor
13 Copyright (c) 2006-2007 Darshana Chhajed
14 All rights reserved.
15
16 Licensed under the Apache License, Version 2.0 (the "License");
17 you may not use this file except in compliance with the License.
18 You may obtain a copy of the License at
19
20 http://www.apache.org/licenses/LICENSE-2.0
21
22 Unless required by applicable law or agreed to in writing, software
23 distributed under the License is distributed on an "AS IS" BASIS,
24 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25 See the License for the specific language governing permissions and
26 limitations under the License.
27 """
28
29 try:
30 import PyICU as pyicu
31 except:
32 pyicu = None
33
34
35 import datetime
36 import time
37 import re
38
39
41 """
42 en_US Locale constants
43
44 This class will be used to initialize L{Constants} if PyICU is not located.
45
46 Defined as class variables are the lists and strings needed by parsedatetime
47 to evaluate strings for USA
48 """
49
50 localeID = 'en_US'
51 dateSep = [ u'/', u'.' ]
52 timeSep = [ u':' ]
53 meridian = [ u'AM', u'PM' ]
54 usesMeridian = True
55 uses24 = False
56
57 Weekdays = [ u'monday', u'tuesday', u'wednesday',
58 u'thursday', u'friday', u'saturday', u'sunday',
59 ]
60 shortWeekdays = [ u'mon', u'tues', u'wed',
61 u'thu', u'fri', u'sat', u'sun',
62 ]
63 Months = [ u'january', u'february', u'march',
64 u'april', u'may', u'june',
65 u'july', u'august', u'september',
66 u'october', u'november', u'december',
67 ]
68 shortMonths = [ u'jan', u'feb', u'mar',
69 u'apr', u'may', u'jun',
70 u'jul', u'aug', u'sep',
71 u'oct', u'nov', u'dec',
72 ]
73 dateFormats = { 'full': 'EEEE, MMMM d, yyyy',
74 'long': 'MMMM d, yyyy',
75 'medium': 'MMM d, yyyy',
76 'short': 'M/d/yy',
77 }
78 timeFormats = { 'full': 'h:mm:ss a z',
79 'long': 'h:mm:ss a z',
80 'medium': 'h:mm:ss a',
81 'short': 'h:mm a',
82 }
83
84 dp_order = [ u'm', u'd', u'y' ]
85
86
87 units = { 'seconds': [ 'second', 'sec' ],
88 'minutes': [ 'minute', 'min' ],
89 'hours': [ 'hour', 'hr' ],
90 'days': [ 'day', 'dy' ],
91 'weeks': [ 'week', 'wk' ],
92 'months': [ 'month', 'mth' ],
93 'years': [ 'year', 'yr' ],
94 }
95
96
97 re_consts = { 'specials': 'in|on|of|at',
98 'timeseperator': ':',
99 'rangeseperator': '-',
100 'daysuffix': 'rd|st|nd|th',
101 'meridian': 'am|pm|a.m.|p.m.|a|p',
102 'qunits': 'h|m|s|d|w|m|y',
103 'now': [ 'now' ],
104 }
105
106
107 modifiers = { 'from': 1,
108 'before': -1,
109 'after': 1,
110 'ago': -1,
111 'prior': -1,
112 'prev': -1,
113 'last': -1,
114 'next': 1,
115 'this': 0,
116 'previous': -1,
117 'in a': 2,
118 'end of': 0,
119 'eod': 0,
120 'eo': 0
121 }
122
123 dayoffsets = { 'tomorrow': 1,
124 'today': 0,
125 'yesterday': -1,
126 }
127
128
129
130
131
132 re_sources = { 'noon': { 'hr': 12, 'mn': 0, 'sec': 0 },
133 'lunch': { 'hr': 12, 'mn': 0, 'sec': 0 },
134 'morning': { 'hr': 6, 'mn': 0, 'sec': 0 },
135 'breakfast': { 'hr': 8, 'mn': 0, 'sec': 0 },
136 'dinner': { 'hr': 19, 'mn': 0, 'sec': 0 },
137 'evening': { 'hr': 18, 'mn': 0, 'sec': 0 },
138 'midnight': { 'hr': 0, 'mn': 0, 'sec': 0 },
139 'night': { 'hr': 21, 'mn': 0, 'sec': 0 },
140 'tonight': { 'hr': 21, 'mn': 0, 'sec': 0 },
141 'eod': { 'hr': 17, 'mn': 0, 'sec': 0 },
142 }
143
144
146 """
147 en_AU Locale constants
148
149 This class will be used to initialize L{Constants} if PyICU is not located.
150
151 Defined as class variables are the lists and strings needed by parsedatetime
152 to evaluate strings for Australia
153 """
154
155 localeID = 'en_AU'
156 dateSep = [ u'-', u'/' ]
157 timeSep = [ u':' ]
158 meridian = [ u'AM', u'PM' ]
159 usesMeridian = True
160 uses24 = False
161
162 Weekdays = [ u'monday', u'tuesday', u'wednesday',
163 u'thursday', u'friday', u'saturday', u'sunday',
164 ]
165 shortWeekdays = [ u'mon', u'tues', u'wed',
166 u'thu', u'fri', u'sat', u'sun',
167 ]
168 Months = [ u'january', u'february', u'march',
169 u'april', u'may', u'june',
170 u'july', u'august', u'september',
171 u'october', u'november', u'december',
172 ]
173 shortMonths = [ u'jan', u'feb', u'mar',
174 u'apr', u'may', u'jun',
175 u'jul', u'aug', u'sep',
176 u'oct', u'nov', u'dec',
177 ]
178 dateFormats = { 'full': 'EEEE, d MMMM yyyy',
179 'long': 'd MMMM yyyy',
180 'medium': 'dd/MM/yyyy',
181 'short': 'd/MM/yy',
182 }
183 timeFormats = { 'full': 'h:mm:ss a z',
184 'long': 'h:mm:ss a',
185 'medium': 'h:mm:ss a',
186 'short': 'h:mm a',
187 }
188
189 dp_order = [ u'd', u'm', u'y' ]
190
191
192 units = { 'seconds': [ 'second', 'sec' ],
193 'minutes': [ 'minute', 'min' ],
194 'hours': [ 'hour', 'hr' ],
195 'days': [ 'day', 'dy' ],
196 'weeks': [ 'week', 'wk' ],
197 'months': [ 'month', 'mth' ],
198 'years': [ 'year', 'yr' ],
199 }
200
201
202 re_consts = { 'specials': 'in|on|of|at',
203 'timeseperator': ':',
204 'rangeseperator': '-',
205 'daysuffix': 'rd|st|nd|th',
206 'meridian': 'am|pm|a.m.|p.m.|a|p',
207 'qunits': 'h|m|s|d|w|m|y',
208 'now': [ 'now' ],
209 }
210
211
212 modifiers = { 'from': 1,
213 'before': -1,
214 'after': 1,
215 'ago': 1,
216 'prior': -1,
217 'prev': -1,
218 'last': -1,
219 'next': 1,
220 'this': 0,
221 'previous': -1,
222 'in a': 2,
223 'end of': 0,
224 'eo': 0,
225 }
226
227 dayoffsets = { 'tomorrow': 1,
228 'today': 0,
229 'yesterday': -1,
230 }
231
232
233
234
235
236 re_sources = { 'noon': { 'hr': 12, 'mn': 0, 'sec': 0 },
237 'lunch': { 'hr': 12, 'mn': 0, 'sec': 0 },
238 'morning': { 'hr': 6, 'mn': 0, 'sec': 0 },
239 'breakfast': { 'hr': 8, 'mn': 0, 'sec': 0 },
240 'dinner': { 'hr': 19, 'mn': 0, 'sec': 0 },
241 'evening': { 'hr': 18, 'mn': 0, 'sec': 0 },
242 'midnight': { 'hr': 0, 'mn': 0, 'sec': 0 },
243 'night': { 'hr': 21, 'mn': 0, 'sec': 0 },
244 'tonight': { 'hr': 21, 'mn': 0, 'sec': 0 },
245 'eod': { 'hr': 17, 'mn': 0, 'sec': 0 },
246 }
247
248
250 """
251 es Locale constants
252
253 This class will be used to initialize L{Constants} if PyICU is not located.
254
255 Defined as class variables are the lists and strings needed by parsedatetime
256 to evaluate strings in Spanish
257
258 Note that I don't speak Spanish so many of the items below are still in English
259 """
260
261 localeID = 'es'
262 dateSep = [ u'/' ]
263 timeSep = [ u':' ]
264 meridian = []
265 usesMeridian = False
266 uses24 = True
267
268 Weekdays = [ u'lunes', u'martes', u'mi\xe9rcoles',
269 u'jueves', u'viernes', u's\xe1bado', u'domingo',
270 ]
271 shortWeekdays = [ u'lun', u'mar', u'mi\xe9',
272 u'jue', u'vie', u's\xe1b', u'dom',
273 ]
274 Months = [ u'enero', u'febrero', u'marzo',
275 u'abril', u'mayo', u'junio',
276 u'julio', u'agosto', u'septiembre',
277 u'octubre', u'noviembre', u'diciembre'
278 ]
279 shortMonths = [ u'ene', u'feb', u'mar',
280 u'abr', u'may', u'jun',
281 u'jul', u'ago', u'sep',
282 u'oct', u'nov', u'dic'
283 ]
284 dateFormats = { 'full': "EEEE d' de 'MMMM' de 'yyyy",
285 'long': "d' de 'MMMM' de 'yyyy",
286 'medium': "dd-MMM-yy",
287 'short': "d/MM/yy",
288 }
289 timeFormats = { 'full': "HH'H'mm' 'ss z",
290 'long': "HH:mm:ss z",
291 'medium': "HH:mm:ss",
292 'short': "HH:mm",
293 }
294
295 dp_order = [ u'd', u'm', u'y' ]
296
297
298 units = { 'seconds': [ 'second', 'sec' ],
299 'minutes': [ 'minute', 'min' ],
300 'hours': [ 'hour', 'hr' ],
301 'days': [ 'day', 'dy' ],
302 'weeks': [ 'week', 'wk' ],
303 'months': [ 'month', 'mth' ],
304 'years': [ 'year', 'yr' ],
305 }
306
307
308 re_consts = { 'specials': 'in|on|of|at',
309 'timeseperator': timeSep,
310 'dateseperator': dateSep,
311 'rangeseperator': '-',
312 'daysuffix': 'rd|st|nd|th',
313 'qunits': 'h|m|s|d|w|m|y',
314 'now': [ 'now' ],
315 }
316
317
318 modifiers = { 'from': 1,
319 'before': -1,
320 'after': 1,
321 'ago': 1,
322 'prior': -1,
323 'prev': -1,
324 'last': -1,
325 'next': 1,
326 'this': 0,
327 'previous': -1,
328 'in a': 2,
329 'end of': 0,
330 'eo': 0,
331 }
332
333 dayoffsets = { 'tomorrow': 1,
334 'today': 0,
335 'yesterday': -1,
336 }
337
338
339
340
341
342 re_sources = { 'noon': { 'hr': 12, 'mn': 0, 'sec': 0 },
343 'lunch': { 'hr': 12, 'mn': 0, 'sec': 0 },
344 'morning': { 'hr': 6, 'mn': 0, 'sec': 0 },
345 'breakfast': { 'hr': 8, 'mn': 0, 'sec': 0 },
346 'dinner': { 'hr': 19, 'mn': 0, 'sec': 0 },
347 'evening': { 'hr': 18, 'mn': 0, 'sec': 0 },
348 'midnight': { 'hr': 0, 'mn': 0, 'sec': 0 },
349 'night': { 'hr': 21, 'mn': 0, 'sec': 0 },
350 'tonight': { 'hr': 21, 'mn': 0, 'sec': 0 },
351 'eod': { 'hr': 17, 'mn': 0, 'sec': 0 },
352 }
353
354
355 pdtLocales = { 'en_US': pdtLocale_en,
356 'en_AU': pdtLocale_au,
357 'es': pdtLocale_es,
358 }
359
360
362 """
363 Helper function to initialize the different lists and strings
364 from either PyICU or one of the internal pdt Locales and store
365 them into ptc.
366 """
367
368 def lcase(x):
369 return x.lower()
370
371 if pyicu and ptc.usePyICU:
372 ptc.icuLocale = None
373
374 if ptc.localeID is not None:
375 ptc.icuLocale = pyicu.Locale(ptc.localeID)
376
377 if ptc.icuLocale is None:
378 for id in range(0, len(ptc.fallbackLocales)):
379 ptc.localeID = ptc.fallbackLocales[id]
380 ptc.icuLocale = pyicu.Locale(ptc.localeID)
381
382 if ptc.icuLocale is not None:
383 break
384
385 ptc.icuSymbols = pyicu.DateFormatSymbols(ptc.icuLocale)
386
387
388
389 wd = map(lcase, ptc.icuSymbols.getWeekdays()[1:])
390 swd = map(lcase, ptc.icuSymbols.getShortWeekdays()[1:])
391
392
393 ptc.Weekdays = wd[1:] + wd[0:1]
394 ptc.shortWeekdays = swd[1:] + swd[0:1]
395 ptc.Months = map(lcase, ptc.icuSymbols.getMonths())
396 ptc.shortMonths = map(lcase, ptc.icuSymbols.getShortMonths())
397
398
399
400 ptc.re_consts = None
401 ptc.icu_df = { 'full': pyicu.DateFormat.createDateInstance(pyicu.DateFormat.kFull, ptc.icuLocale),
402 'long': pyicu.DateFormat.createDateInstance(pyicu.DateFormat.kLong, ptc.icuLocale),
403 'medium': pyicu.DateFormat.createDateInstance(pyicu.DateFormat.kMedium, ptc.icuLocale),
404 'short': pyicu.DateFormat.createDateInstance(pyicu.DateFormat.kShort, ptc.icuLocale),
405 }
406 ptc.icu_tf = { 'full': pyicu.DateFormat.createTimeInstance(pyicu.DateFormat.kFull, ptc.icuLocale),
407 'long': pyicu.DateFormat.createTimeInstance(pyicu.DateFormat.kLong, ptc.icuLocale),
408 'medium': pyicu.DateFormat.createTimeInstance(pyicu.DateFormat.kMedium, ptc.icuLocale),
409 'short': pyicu.DateFormat.createTimeInstance(pyicu.DateFormat.kShort, ptc.icuLocale),
410 }
411 ptc.dateFormats = { 'full': ptc.icu_df['full'].toPattern(),
412 'long': ptc.icu_df['long'].toPattern(),
413 'medium': ptc.icu_df['medium'].toPattern(),
414 'short': ptc.icu_df['short'].toPattern(),
415 }
416 ptc.timeFormats = { 'full': ptc.icu_tf['full'].toPattern(),
417 'long': ptc.icu_tf['long'].toPattern(),
418 'medium': ptc.icu_tf['medium'].toPattern(),
419 'short': ptc.icu_tf['short'].toPattern(),
420 }
421 else:
422 if not ptc.localeID in pdtLocales:
423 for id in range(0, len(ptc.fallbackLocales)):
424 ptc.localeID = ptc.fallbackLocales[id]
425
426 if ptc.localeID in pdtLocales:
427 break
428
429 ptc.locale = pdtLocales[ptc.localeID]
430 ptc.usePyICU = False
431
432 ptc.Weekdays = ptc.locale.Weekdays
433 ptc.shortWeekdays = ptc.locale.shortWeekdays
434 ptc.Months = ptc.locale.Months
435 ptc.shortMonths = ptc.locale.shortMonths
436 ptc.dateFormats = ptc.locale.dateFormats
437 ptc.timeFormats = ptc.locale.timeFormats
438
439
440
441
442
443
444 if ptc.localeID in pdtLocales:
445 ptc.re_sources = pdtLocales[ptc.localeID].re_sources
446 ptc.re_values = pdtLocales[ptc.localeID].re_consts
447
448 units = pdtLocales[ptc.localeID].units
449
450 ptc.Modifiers = pdtLocales[ptc.localeID].modifiers
451 ptc.dayOffsets = pdtLocales[ptc.localeID].dayoffsets
452
453
454 for key in pdtLocales['en_US'].re_consts:
455 if not key in ptc.re_values:
456 ptc.re_values[key] = pdtLocales['en_US'].re_consts[key]
457 else:
458 ptc.re_sources = pdtLocales['en_US'].re_sources
459 ptc.re_values = pdtLocales['en_US'].re_consts
460 ptc.Modifiers = pdtLocales['en_US'].modifiers
461 ptc.dayOffsets = pdtLocales['en_US'].dayoffsets
462 units = pdtLocales['en_US'].units
463
464 ptc.re_values['months'] = '%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s' % tuple(ptc.Months)
465 ptc.re_values['shortmonths'] = '%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s' % tuple(ptc.shortMonths)
466 ptc.re_values['days'] = '%s|%s|%s|%s|%s|%s|%s' % tuple(ptc.Weekdays)
467 ptc.re_values['shortdays'] = '%s|%s|%s|%s|%s|%s|%s' % tuple(ptc.shortWeekdays)
468
469 l = []
470 for unit in units:
471 l.append('|'.join(units[unit]))
472
473 ptc.re_values['units'] = '|'.join(l)
474 ptc.Units = ptc.re_values['units'].split('|')
475
476
478 """
479 Helper function to initialize the single character constants
480 and other symbols needed.
481 """
482 ptc.timeSep = [ u':' ]
483 ptc.dateSep = [ u'/' ]
484 ptc.meridian = [ u'AM', u'PM' ]
485
486 ptc.usesMeridian = True
487 ptc.uses24 = False
488
489 if pyicu and ptc.usePyICU:
490 am = u''
491 pm = u''
492 ts = ''
493
494
495
496
497 o = ptc.icu_tf['short']
498 s = ptc.timeFormats['short']
499
500 ptc.usesMeridian = u'a' in s
501 ptc.uses24 = u'H' in s
502
503
504 s = o.format(datetime.datetime(2003, 10, 30, 11, 45))
505
506
507 s = s.replace('11', '').replace('45', '')
508
509 if len(s) > 0:
510 ts = s[0]
511
512 if ptc.usesMeridian:
513
514 am = s[1:].strip()
515 s = o.format(datetime.datetime(2003, 10, 30, 23, 45))
516
517 if ptc.uses24:
518 s = s.replace('23', '')
519 else:
520 s = s.replace('11', '')
521
522
523 pm = s.replace('45', '').replace(ts, '').strip()
524
525 ptc.timeSep = [ ts ]
526 ptc.meridian = [ am, pm ]
527
528 o = ptc.icu_df['short']
529 s = o.format(datetime.datetime(2003, 10, 30, 11, 45))
530 s = s.replace('10', '').replace('30', '').replace('03', '').replace('2003', '')
531
532 if len(s) > 0:
533 ds = s[0]
534 else:
535 ds = '/'
536
537 ptc.dateSep = [ ds ]
538 s = ptc.dateFormats['short']
539 l = s.lower().split(ds)
540 dp_order = []
541
542 for s in l:
543 if len(s) > 0:
544 dp_order.append(s[:1])
545
546 ptc.dp_order = dp_order
547 else:
548 ptc.timeSep = ptc.locale.timeSep
549 ptc.dateSep = ptc.locale.dateSep
550 ptc.meridian = ptc.locale.meridian
551 ptc.usesMeridian = ptc.locale.usesMeridian
552 ptc.uses24 = ptc.locale.uses24
553 ptc.dp_order = ptc.locale.dp_order
554
555
556
557
558
559 if len(ptc.meridian) > 0:
560 am = ptc.meridian[0]
561 ptc.am = [ am ]
562
563 if len(am) > 0:
564 ptc.am.append(am[0])
565 am = am.lower()
566 ptc.am.append(am)
567 ptc.am.append(am[0])
568 else:
569 am = ''
570 ptc.am = [ '', '' ]
571
572 if len(ptc.meridian) > 1:
573 pm = ptc.meridian[1]
574 ptc.pm = [ pm ]
575
576 if len(pm) > 0:
577 ptc.pm.append(pm[0])
578 pm = pm.lower()
579 ptc.pm.append(pm)
580 ptc.pm.append(pm[0])
581 else:
582 pm = ''
583 ptc.pm = [ '', '' ]
584
585
587 """
588 Helper function to take the different localized bits from ptc and
589 create the regex strings.
590 """
591
592
593
594 ptc.RE_DATE3 = r'''(?P<date>((?P<mthname>(%(months)s|%(shortmonths)s))\s?
595 ((?P<day>\d\d?)(\s?|%(daysuffix)s|$)+)?
596 (,\s?(?P<year>\d\d(\d\d)?))?))
597 (\s?|$|[^0-9a-zA-Z])''' % ptc.re_values
598 ptc.RE_MONTH = r'''(\s?|^)
599 (?P<month>(
600 (?P<mthname>(%(months)s|%(shortmonths)s))
601 (\s?(?P<year>(\d\d\d\d)))?
602 ))
603 (\s?|$|[^0-9a-zA-Z])''' % ptc.re_values
604 ptc.RE_WEEKDAY = r'''(\s?|^)
605 (?P<weekday>(%(days)s|%(shortdays)s))
606 (\s?|$|[^0-9a-zA-Z])''' % ptc.re_values
607
608 ptc.RE_SPECIAL = r'(?P<special>^[%(specials)s]+)\s+' % ptc.re_values
609 ptc.RE_UNITS = r'''(?P<qty>(-?\d+\s*
610 (?P<units>((%(units)s)s?))
611 ))''' % ptc.re_values
612 ptc.RE_QUNITS = r'''(?P<qty>(-?\d+\s?
613 (?P<qunits>%(qunits)s)
614 (\s?|,|$)
615 ))''' % ptc.re_values
616 ptc.RE_MODIFIER = r'''(\s?|^)
617 (?P<modifier>
618 (previous|prev|last|next|this|eod|eo|(end\sof)|(in\sa)))''' % ptc.re_values
619 ptc.RE_MODIFIER2 = r'''(\s?|^)
620 (?P<modifier>
621 (from|before|after|ago|prior))
622 (\s?|$|[^0-9a-zA-Z])''' % ptc.re_values
623 ptc.RE_TIMEHMS = r'''(\s?|^)
624 (?P<hours>\d\d?)
625 (?P<tsep>%(timeseperator)s|)
626 (?P<minutes>\d\d)
627 (?:(?P=tsep)(?P<seconds>\d\d(?:[.,]\d+)?))?''' % ptc.re_values
628 ptc.RE_TIMEHMS2 = r'''(?P<hours>(\d\d?))
629 ((?P<tsep>%(timeseperator)s|)
630 (?P<minutes>(\d\d?))
631 (?:(?P=tsep)
632 (?P<seconds>\d\d?
633 (?:[.,]\d+)?))?)?''' % ptc.re_values
634
635 if 'meridian' in ptc.re_values:
636 ptc.RE_TIMEHMS2 += r'\s?(?P<meridian>(%(meridian)s))' % ptc.re_values
637
638 dateSeps = ''.join(ptc.dateSep) + '.'
639
640 ptc.RE_DATE = r'''(\s?|^)
641 (?P<date>(\d\d?[%s]\d\d?([%s]\d\d(\d\d)?)?))
642 (\s?|$|[^0-9a-zA-Z])''' % (dateSeps, dateSeps)
643 ptc.RE_DATE2 = r'[%s]' % dateSeps
644 ptc.RE_DAY = r'''(\s?|^)
645 (?P<day>(today|tomorrow|yesterday))
646 (\s?|$|[^0-9a-zA-Z])''' % ptc.re_values
647 ptc.RE_TIME = r'''(\s?|^)
648 (?P<time>(morning|breakfast|noon|lunch|evening|midnight|tonight|dinner|night|now))
649 (\s?|$|[^0-9a-zA-Z])''' % ptc.re_values
650 ptc.RE_REMAINING = r'\s+'
651
652
653 ptc.RE_RTIMEHMS = r'''(\s?|^)
654 (\d\d?)%(timeseperator)s
655 (\d\d)
656 (%(timeseperator)s(\d\d))?
657 (\s?|$)''' % ptc.re_values
658 ptc.RE_RTIMEHMS2 = r'''(\s?|^)
659 (\d\d?)
660 (%(timeseperator)s(\d\d?))?
661 (%(timeseperator)s(\d\d?))?''' % ptc.re_values
662
663 if 'meridian' in ptc.re_values:
664 ptc.RE_RTIMEHMS2 += r'\s?(%(meridian)s)' % ptc.re_values
665
666 ptc.RE_RDATE = r'(\d+([%s]\d+)+)' % dateSeps
667 ptc.RE_RDATE3 = r'''((((%(months)s))\s?
668 ((\d\d?)
669 (\s?|%(daysuffix)s|$)+)?
670 (,\s?\d\d\d\d)?))''' % ptc.re_values
671
672
673 ptc.DATERNG1 = ptc.RE_RDATE + r'\s?%(rangeseperator)s\s?' + ptc.RE_RDATE
674 ptc.DATERNG1 = ptc.DATERNG1 % ptc.re_values
675
676
677 ptc.DATERNG2 = ptc.RE_RDATE3 + r'\s?%(rangeseperator)s\s?' + ptc.RE_RDATE3
678 ptc.DATERNG2 = ptc.DATERNG2 % ptc.re_values
679
680
681 ptc.DATERNG3 = ptc.RE_RDATE3 + r'\s?%(rangeseperator)s\s?(\d\d?)\s?(rd|st|nd|th)?'
682 ptc.DATERNG3 = ptc.DATERNG3 % ptc.re_values
683
684
685 ptc.TIMERNG1 = ptc.RE_RTIMEHMS2 + r'\s?%(rangeseperator)s\s?' + ptc.RE_RTIMEHMS2
686 ptc.TIMERNG1 = ptc.TIMERNG1 % ptc.re_values
687
688
689 ptc.TIMERNG2 = ptc.RE_RTIMEHMS + r'\s?%(rangeseperator)s\s?' + ptc.RE_RTIMEHMS
690 ptc.TIMERNG2 = ptc.TIMERNG2 % ptc.re_values
691
692
693 ptc.TIMERNG3 = r'\d\d?\s?%(rangeseperator)s\s?' + ptc.RE_RTIMEHMS2
694 ptc.TIMERNG3 = ptc.TIMERNG3 % ptc.re_values
695
696
698 """
699 Create localized versions of the units, week and month names
700 """
701
702
703 ptc.WeekdayOffsets = {}
704
705 o = 0
706 for key in ptc.Weekdays:
707 ptc.WeekdayOffsets[key] = o
708 o += 1
709 o = 0
710 for key in ptc.shortWeekdays:
711 ptc.WeekdayOffsets[key] = o
712 o += 1
713
714
715
716 ptc.MonthOffsets = {}
717 ptc.DaysInMonth = {}
718
719 o = 1
720 for key in ptc.Months:
721 ptc.MonthOffsets[key] = o
722 ptc.DaysInMonth[key] = ptc.DaysInMonthList[o - 1]
723 o += 1
724 o = 1
725 for key in ptc.shortMonths:
726 ptc.MonthOffsets[key] = o
727 ptc.DaysInMonth[key] = ptc.DaysInMonthList[o - 1]
728 o += 1
729
730
732 """
733 Default set of constants for parsedatetime.
734
735 If PyICU is present, then the class will first try to get PyICU
736 to return a locale specified by C{localeID}. If either C{localeID} is
737 None or if the locale does not exist within PyICU, then each of the
738 locales defined in C{fallbackLocales} is tried in order.
739
740 If PyICU is not present or none of the specified locales can be used,
741 then the class will initialize itself to the en_US locale.
742
743 if PyICU is not present or not requested, only the locales defined by
744 C{pdtLocales} will be searched.
745 """
746 - def __init__(self, localeID=None, usePyICU=True, fallbackLocales=['en_US']):
747 self.localeID = localeID
748 self.fallbackLocales = fallbackLocales
749
750 if 'en_US' not in self.fallbackLocales:
751 self.fallbackLocales.append('en_US')
752
753
754
755 self.locale = None
756 self.usePyICU = usePyICU
757
758 self.Second = 1
759 self.Minute = 60 * self.Second
760 self.Hour = 60 * self.Minute
761 self.Day = 24 * self.Hour
762 self.Week = 7 * self.Day
763 self.Month = 30 * self.Day
764 self.Year = 365 * self.Day
765
766 self.rangeSep = u'-'
767
768 self.DaysInMonthList = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
769
770 self.BirthdayEpoch = 50
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793 self.DOWParseStyle = 1
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821 self.CurrentDOWParseStyle = False
822
823
824
825 self.re_sources = None
826 self.re_values = None
827 self.Modifiers = None
828 self.dayOffsets = None
829 self.WeekdayOffsets = None
830 self.MonthOffsets = None
831 self.DaysInMonth = None
832 self.dateSep = None
833 self.timeSep = None
834 self.am = None
835 self.pm = None
836 self.meridian = None
837 self.usesMeridian = None
838 self.uses24 = None
839 self.dp_order = None
840
841 self.RE_DATE3 = r''
842 self.RE_MONTH = r''
843 self.RE_WEEKDAY = r''
844 self.RE_SPECIAL = r''
845 self.RE_UNITS = r''
846 self.RE_QUNITS = r''
847 self.RE_MODIFIER = r''
848 self.RE_MODIFIER2 = r''
849 self.RE_TIMEHMS = r''
850 self.RE_TIMEHMS2 = r''
851 self.RE_DATE = r''
852 self.RE_DATE2 = r''
853 self.RE_DAY = r''
854 self.RE_TIME = r''
855 self.RE_REMAINING = r''
856 self.RE_RTIMEHMS = r''
857 self.RE_RTIMEHMS2 = r''
858 self.RE_RDATE = r''
859 self.RE_RDATE3 = r''
860 self.DATERNG1 = r''
861 self.DATERNG2 = r''
862 self.DATERNG3 = r''
863 self.TIMERNG1 = r''
864 self.TIMERNG2 = r''
865 self.TIMERNG3 = r''
866
867 _initLocale(self)
868 _initConstants(self)
869 _initSymbols(self)
870 _initPatterns(self)
871
872 self.re_option = re.IGNORECASE + re.VERBOSE
873 self.cre_source = { 'CRE_SPECIAL': self.RE_SPECIAL,
874 'CRE_UNITS': self.RE_UNITS,
875 'CRE_QUNITS': self.RE_QUNITS,
876 'CRE_MODIFIER': self.RE_MODIFIER,
877 'CRE_MODIFIER2': self.RE_MODIFIER2,
878 'CRE_TIMEHMS': self.RE_TIMEHMS,
879 'CRE_TIMEHMS2': self.RE_TIMEHMS2,
880 'CRE_DATE': self.RE_DATE,
881 'CRE_DATE2': self.RE_DATE2,
882 'CRE_DATE3': self.RE_DATE3,
883 'CRE_MONTH': self.RE_MONTH,
884 'CRE_WEEKDAY': self.RE_WEEKDAY,
885 'CRE_DAY': self.RE_DAY,
886 'CRE_TIME': self.RE_TIME,
887 'CRE_REMAINING': self.RE_REMAINING,
888 'CRE_RTIMEHMS': self.RE_RTIMEHMS,
889 'CRE_RTIMEHMS2': self.RE_RTIMEHMS2,
890 'CRE_RDATE': self.RE_RDATE,
891 'CRE_RDATE3': self.RE_RDATE3,
892 'CRE_TIMERNG1': self.TIMERNG1,
893 'CRE_TIMERNG2': self.TIMERNG2,
894 'CRE_TIMERNG3': self.TIMERNG3,
895 'CRE_DATERNG1': self.DATERNG1,
896 'CRE_DATERNG2': self.DATERNG2,
897 'CRE_DATERNG3': self.DATERNG3,
898 }
899 self.cre_keys = self.cre_source.keys()
900
901
903 if name in self.cre_keys:
904 value = re.compile(self.cre_source[name], self.re_option)
905 setattr(self, name, value)
906 return value
907 else:
908 raise AttributeError, name
909
910
912 """
913 Return a dictionary of date/time tuples based on the keys
914 found in self.re_sources.
915
916 The current time is used as the default and any specified
917 item found in self.re_sources is inserted into the value
918 and the generated dictionary is returned.
919 """
920 if sourceTime is None:
921 (yr, mth, dy, hr, mn, sec, wd, yd, isdst) = time.localtime()
922 else:
923 (yr, mth, dy, hr, mn, sec, wd, yd, isdst) = sourceTime
924
925 sources = {}
926 defaults = { 'yr': yr, 'mth': mth, 'dy': dy,
927 'hr': hr, 'mn': mn, 'sec': sec, }
928
929 for item in self.re_sources:
930 values = {}
931 source = self.re_sources[item]
932
933 for key in defaults.keys():
934 if key in source:
935 values[key] = source[key]
936 else:
937 values[key] = defaults[key]
938
939 sources[item] = ( values['yr'], values['mth'], values['dy'],
940 values['hr'], values['mn'], values['sec'], wd, yd, isdst )
941
942 return sources
943