~ubuntu-branches/ubuntu/natty/moin/natty-updates

« back to all changes in this revision

Viewing changes to MoinMoin/support/parsedatetime/parsedatetime_consts.py

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Smedegaard
  • Date: 2008-06-22 21:17:13 UTC
  • mto: This revision was merged to the branch mainline in revision 18.
  • Revision ID: james.westby@ubuntu.com-20080622211713-inlv5k4eifxckelr
ImportĀ upstreamĀ versionĀ 1.7.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!/usr/bin/env python
2
2
 
3
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.
 
4
The Constants class defines all constants used by parsedatetime.py.
9
5
"""
10
6
 
11
 
__license__ = """
12
 
Copyright (c) 2004-2008 Mike Taylor
13
 
Copyright (c) 2006-2008 Darshana Chhajed
14
 
Copyright (c)      2007 Bernd Zeimetz <bzed@debian.org>
15
 
All rights reserved.
 
7
__license__ = """Copyright (c) 2004-2006 Mike Taylor, All rights reserved.
16
8
 
17
9
Licensed under the Apache License, Version 2.0 (the "License");
18
10
you may not use this file except in compliance with the License.
26
18
See the License for the specific language governing permissions and
27
19
limitations under the License.
28
20
"""
 
21
__author__       = 'Mike Taylor <http://code-bear.com>'
 
22
__contributors__ = [ 'Darshana Chhajed <mailto://darshana@osafoundation.org>',
 
23
                   ]
 
24
 
29
25
 
30
26
try:
31
27
    import PyICU as pyicu
33
29
    pyicu = None
34
30
 
35
31
 
36
 
import datetime
37
 
import calendar
38
 
import time
39
 
import re
 
32
import string
 
33
import datetime, time
40
34
 
41
35
 
42
36
class pdtLocale_en:
43
37
    """
44
38
    en_US Locale constants
45
39
 
46
 
    This class will be used to initialize L{Constants} if PyICU is not located.
 
40
    This class will be used to initialize C{Constants} if PyICU is not located.
47
41
 
48
42
    Defined as class variables are the lists and strings needed by parsedatetime
49
 
    to evaluate strings for USA
 
43
    to evaluate strings in English (US)
50
44
    """
51
45
 
52
46
    localeID      = 'en_US'   # don't use a unicode string
53
 
    dateSep       = [ u'/', u'.' ]
54
 
    timeSep       = [ u':' ]
 
47
    dateSep       = u'/'
 
48
    timeSep       = u':'
55
49
    meridian      = [ u'AM', u'PM' ]
56
50
    usesMeridian  = True
57
51
    uses24        = False
58
52
 
59
 
    Weekdays      = [ u'monday', u'tuesday', u'wednesday',
60
 
                      u'thursday', u'friday', u'saturday', u'sunday',
 
53
    Weekdays      = [ u'sunday', u'monday', u'tuesday',
 
54
                      u'wednesday', u'thursday', u'friday', u'saturday',
61
55
                    ]
62
 
    shortWeekdays = [ u'mon', u'tues', u'wed',
63
 
                      u'thu', u'fri', u'sat', u'sun',
 
56
    shortWeekdays = [ u'sun', u'mon', u'tues',
 
57
                      u'wed', u'thu', u'fri', u'sat',
64
58
                    ]
65
59
    Months        = [ u'january', u'february', u'march',
66
60
                      u'april',   u'may',      u'june',
83
77
                      'short':  'h:mm a',
84
78
                    }
85
79
 
86
 
    dp_order = [ u'm', u'd', u'y' ]
87
 
 
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'  ],
96
 
            }
97
 
 
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',
105
 
                      'now':            [ 'now' ],
106
 
                    }
107
 
 
108
 
      # Used to adjust the returned date before/after the source
109
 
    modifiers = { 'from':       1,
110
 
                  'before':    -1,
111
 
                  'after':      1,
112
 
                  'ago':       -1,
113
 
                  'prior':     -1,
114
 
                  'prev':      -1,
115
 
                  'last':      -1,
116
 
                  'next':       1,
117
 
                  'previous':  -1,
118
 
                  'in a':       2,
119
 
                  'end of':     0,
120
 
                  'eod':        0,
121
 
                  'eo':         0
122
 
                }
123
 
 
124
 
    dayoffsets = { 'tomorrow':   1,
125
 
                   'today':      0,
126
 
                   'yesterday': -1,
127
 
                 }
128
 
 
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 },
143
 
                    }
144
 
 
145
 
 
146
 
class pdtLocale_au:
147
 
    """
148
 
    en_AU Locale constants
149
 
 
150
 
    This class will be used to initialize L{Constants} if PyICU is not located.
151
 
 
152
 
    Defined as class variables are the lists and strings needed by parsedatetime
153
 
    to evaluate strings for Australia
154
 
    """
155
 
 
156
 
    localeID      = 'en_AU'   # don't use a unicode string
157
 
    dateSep       = [ u'-', u'/' ]
158
 
    timeSep       = [ u':' ]
159
 
    meridian      = [ u'AM', u'PM' ]
160
 
    usesMeridian  = True
161
 
    uses24        = False
162
 
 
163
 
    Weekdays      = [ u'monday', u'tuesday', u'wednesday',
164
 
                      u'thursday', u'friday', u'saturday', u'sunday',
165
 
                    ]
166
 
    shortWeekdays = [ u'mon', u'tues', u'wed',
167
 
                      u'thu', u'fri', u'sat', u'sun',
168
 
                    ]
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',
173
 
                    ]
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',
178
 
                    ]
179
 
    dateFormats   = { 'full':   'EEEE, d MMMM yyyy',
180
 
                      'long':   'd MMMM yyyy',
181
 
                      'medium': 'dd/MM/yyyy',
182
 
                      'short':  'd/MM/yy',
183
 
                    }
184
 
    timeFormats   = { 'full':   'h:mm:ss a z',
185
 
                      'long':   'h:mm:ss a',
186
 
                      'medium': 'h:mm:ss a',
187
 
                      'short':  'h:mm a',
188
 
                    }
189
 
 
190
 
    dp_order = [ u'd', u'm', u'y' ]
191
 
 
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'  ],
200
 
            }
201
 
 
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',
209
 
                      'now':            [ 'now' ],
 
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'  ],
 
88
            }
 
89
 
 
90
      # text constants to be used by regex's later
 
91
    re_consts     = { 'specials':      'in|on|of|at',
 
92
                      'timeseperator': ':',
 
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',
 
96
                      'now':           [ 'now' ],
210
97
                    }
211
98
 
212
99
      # Used to adjust the returned date before/after the source
218
105
                  'prev':      -1,
219
106
                  'last':      -1,
220
107
                  'next':       1,
 
108
                  'this':       0,
221
109
                  'previous':  -1,
222
110
                  'in a':       2,
223
111
                  'end of':     0,
242
130
                      'midnight':  { 'hr':  0, 'mn': 0, 'sec': 0 },
243
131
                      'night':     { 'hr': 21, 'mn': 0, 'sec': 0 },
244
132
                      'tonight':   { 'hr': 21, 'mn': 0, 'sec': 0 },
245
 
                      'eod':       { 'hr': 17, 'mn': 0, 'sec': 0 },
246
133
                    }
247
134
 
248
135
 
250
137
    """
251
138
    es Locale constants
252
139
 
253
 
    This class will be used to initialize L{Constants} if PyICU is not located.
 
140
    This class will be used to initialize C{Constants} if PyICU is not located.
254
141
 
255
142
    Defined as class variables are the lists and strings needed by parsedatetime
256
143
    to evaluate strings in Spanish
259
146
    """
260
147
 
261
148
    localeID      = 'es'   # don't use a unicode string
262
 
    dateSep       = [ u'/' ]
263
 
    timeSep       = [ u':' ]
 
149
    dateSep       = u'/'
 
150
    timeSep       = u':'
264
151
    meridian      = []
265
152
    usesMeridian  = False
266
153
    uses24        = True
267
154
 
268
 
    Weekdays      = [ u'lunes', u'martes', u'mi\xe9rcoles',
269
 
                      u'jueves', u'viernes', u's\xe1bado', u'domingo',
 
155
    Weekdays      = [ u'domingo', u'lunes', u'martes',
 
156
                      u'mi\xe9rcoles', u'jueves', u'viernes', u's\xe1bado',
270
157
                    ]
271
 
    shortWeekdays = [ u'lun', u'mar', u'mi\xe9',
272
 
                      u'jue', u'vie', u's\xe1b', u'dom',
 
158
    shortWeekdays = [ 'dom', u'lun', u'mar',
 
159
                      u'mi\xe9', u'jue', u'vie', u's\xe1b',
273
160
                    ]
274
161
    Months        = [ u'enero', u'febrero', u'marzo',
275
162
                      u'abril', u'mayo', u'junio',
292
179
                      'short':  "HH:mm",
293
180
                    }
294
181
 
295
 
    dp_order = [ u'd', u'm', u'y' ]
296
 
 
297
182
      # this will be added to re_consts later
298
183
    units = { 'seconds': [ 'second', 'sec' ],
299
184
              'minutes': [ 'minute', 'min' ],
305
190
            }
306
191
 
307
192
      # text constants to be used by regex's later
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' ],
 
193
    re_consts     = { 'specials':      'in|on|of|at',
 
194
                      'timeseperator': timeSep,
 
195
                      'dateseperator': dateSep,
 
196
                      'daysuffix':     'rd|st|nd|th',
 
197
                      'qunits':        'h|m|s|d|w|m|y',
 
198
                      'now':           [ 'now' ],
315
199
                    }
316
200
 
317
201
      # Used to adjust the returned date before/after the source
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
 
                  'previous': -1,
327
 
                  'in a':      2,
328
 
                  'end of':    0,
329
 
                  'eo':        0,
 
202
    modifiers = { 'from':       1,
 
203
                  'before':    -1,
 
204
                  'after':      1,
 
205
                  'ago':        1,
 
206
                  'prior':     -1,
 
207
                  'prev':      -1,
 
208
                  'last':      -1,
 
209
                  'next':       1,
 
210
                  'this':       0,
 
211
                  'previous':  -1,
 
212
                  'in a':       2,
 
213
                  'end of':     0,
 
214
                  'eo':         0,
330
215
                }
331
216
 
332
217
    dayoffsets = { 'tomorrow':   1,
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 },
351
 
                    }
352
 
 
353
 
 
354
 
class pdtLocale_de:
355
 
    """
356
 
    de_DE Locale constants
357
 
 
358
 
    This class will be used to initialize L{Constants} if PyICU is not located.
359
 
 
360
 
    Contributed by Debian parsedatetime package maintainer Bernd Zeimetz <bzed@debian.org>
361
 
 
362
 
    Defined as class variables are the lists and strings needed by parsedatetime
363
 
    to evaluate strings for German
364
 
    """
365
 
 
366
 
    localeID      = 'de_DE'   # don't use a unicode string
367
 
    dateSep       = [ u'.' ]
368
 
    timeSep       = [ u':' ]
369
 
    meridian      = [ ]
370
 
    usesMeridian  = False
371
 
    uses24        = True
372
 
 
373
 
    Weekdays      = [ u'montag', u'dienstag', u'mittwoch',
374
 
                      u'donnerstag', u'freitag', u'samstag', u'sonntag',
375
 
                    ]
376
 
    shortWeekdays = [ u'mo', u'di', u'mi',
377
 
                      u'do', u'fr', u'sa', u'so',
378
 
                    ]
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',
383
 
                    ]
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',
388
 
                    ]
389
 
    dateFormats   = { 'full':   u'EEEE, d. MMMM yyyy',
390
 
                      'long':   u'd. MMMM yyyy',
391
 
                      'medium': u'dd.MM.yyyy',
392
 
                      'short':  u'dd.MM.yy'
393
 
                    }
394
 
 
395
 
    timeFormats   = { 'full':   u'HH:mm:ss v',
396
 
                      'long':   u'HH:mm:ss z',
397
 
                      'medium': u'HH:mm:ss',
398
 
                      'short':  u'HH:mm'
399
 
                    }
400
 
 
401
 
    dp_order = [ u'd', u'm', u'y' ]
402
 
 
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' ],
413
 
            }
414
 
 
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': '-',
419
 
                      'daysuffix':      '',
420
 
                      'qunits':         'h|m|s|t|w|m|j',
421
 
                      'now':            [ 'jetzt' ],
422
 
                    }
423
 
 
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,
427
 
                  u'before':      -1,
428
 
                  u'after':        1,
429
 
                  u'vergangener': -1,
430
 
                  u'vorheriger':  -1,
431
 
                  u'prev':        -1,
432
 
                  u'letzter':     -1,
433
 
                  u'n\xe4chster':  1,
434
 
                  u'dieser':       0,
435
 
                  u'previous':    -1,
436
 
                  u'in a':         2,
437
 
                  u'end of':       0,
438
 
                  u'eod':          0,
439
 
                  u'eo':           0,
440
 
                }
441
 
 
442
 
     #morgen/abermorgen does not work, see http://code.google.com/p/parsedatetime/issues/detail?id=19
443
 
    dayoffsets = { u'morgen':        1,
444
 
                   u'heute':         0,
445
 
                   u'gestern':      -1,
446
 
                   u'vorgestern':   -2,
447
 
                   u'\xfcbermorgen': 2,
448
 
                 }
449
 
 
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 },
469
235
                    }
470
236
 
471
237
 
472
238
pdtLocales = { 'en_US': pdtLocale_en,
473
 
               'en_AU': pdtLocale_au,
474
 
               'es_ES': pdtLocale_es,
475
 
               'de_DE': pdtLocale_de,
 
239
               'es':    pdtLocale_es,
476
240
             }
477
241
 
478
242
 
479
243
def _initLocale(ptc):
480
244
    """
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
483
247
    them into ptc.
484
248
    """
485
 
 
486
 
    def lcase(x):
487
 
        return x.lower()
488
 
 
489
249
    if pyicu and ptc.usePyICU:
490
 
        ptc.icuLocale = None
491
 
 
492
 
        if ptc.localeID is not None:
493
 
            ptc.icuLocale = pyicu.Locale(ptc.localeID)
494
 
 
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)
499
 
 
500
 
                if ptc.icuLocale is not None:
501
 
                    break
502
 
 
503
 
        ptc.icuSymbols = pyicu.DateFormatSymbols(ptc.icuLocale)
504
 
 
505
 
          # grab ICU list of weekdays, skipping first entry which
506
 
          # is always blank
507
 
        wd  = map(lcase, ptc.icuSymbols.getWeekdays()[1:])
508
 
        swd = map(lcase, ptc.icuSymbols.getShortWeekdays()[1:])
509
 
 
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)
 
251
 
 
252
        if not ptc.icuLocale:
 
253
            ptc.icuLocale = pyicu.Locale('en_US')
 
254
 
 
255
        ptc.icuSymbols    = pyicu.DateFormatSymbols(ptc.icuLocale)
 
256
 
 
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())
515
261
 
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
518
 
        ptc.re_consts   = None
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),
523
 
                          }
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),
528
 
                          }
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(),
533
 
                          }
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(),
538
 
                          }
 
264
        ptc.re_consts     = None
 
265
 
 
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),
 
270
                            }
 
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),
 
275
                            }
 
276
 
 
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(),
 
281
                            }
 
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(),
 
286
                            }
539
287
    else:
540
288
        if not ptc.localeID in pdtLocales:
541
 
            for id in range(0, len(ptc.fallbackLocales)):
542
 
                ptc.localeID  = ptc.fallbackLocales[id]
543
 
 
544
 
                if ptc.localeID in pdtLocales:
545
 
                    break
546
 
 
547
 
        ptc.locale   = pdtLocales[ptc.localeID]
548
 
        ptc.usePyICU = False
 
289
            ptc.localeID = 'en_US'
 
290
 
 
291
        ptc.locale = pdtLocales[ptc.localeID]
549
292
 
550
293
        ptc.Weekdays      = ptc.locale.Weekdays
551
294
        ptc.shortWeekdays = ptc.locale.shortWeekdays
554
297
        ptc.dateFormats   = ptc.locale.dateFormats
555
298
        ptc.timeFormats   = ptc.locale.timeFormats
556
299
 
 
300
 
557
301
      # these values are used to setup the various bits 
558
302
      # of the regex values used to parse
559
303
      #
579
323
        ptc.dayOffsets = pdtLocales['en_US'].dayoffsets
580
324
        units          = pdtLocales['en_US'].units
581
325
 
582
 
      # escape any regex special characters that may be found
583
 
    wd   = tuple(map(re.escape, ptc.Weekdays))
584
 
    swd  = tuple(map(re.escape, ptc.shortWeekdays))
585
 
    mth  = tuple(map(re.escape, ptc.Months))
586
 
    smth = tuple(map(re.escape, ptc.shortMonths))
587
 
 
588
 
    ptc.re_values['months']      = '%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s' % mth
589
 
    ptc.re_values['shortmonths'] = '%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s' % smth
590
 
    ptc.re_values['days']        = '%s|%s|%s|%s|%s|%s|%s' % wd
591
 
    ptc.re_values['shortdays']   = '%s|%s|%s|%s|%s|%s|%s' % swd
 
326
    ptc.re_values['months']      = '%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s' % tuple(ptc.Months)
 
327
    ptc.re_values['shortmonths'] = '%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s' % tuple(ptc.shortMonths)
 
328
    ptc.re_values['days']        = '%s|%s|%s|%s|%s|%s|%s' % tuple(ptc.Weekdays)
 
329
    ptc.re_values['shortdays']   = '%s|%s|%s|%s|%s|%s|%s' % tuple(ptc.shortWeekdays)
592
330
 
593
331
    l = []
594
332
    for unit in units:
603
341
    Helper function to initialize the single character constants
604
342
    and other symbols needed.
605
343
    """
606
 
    ptc.timeSep  = [ u':' ]
607
 
    ptc.dateSep  = [ u'/' ]
 
344
    ptc.timeSep  = u':'
 
345
    ptc.dateSep  = u'/'
608
346
    ptc.meridian = [ u'AM', u'PM' ]
609
347
 
610
348
    ptc.usesMeridian = True
611
349
    ptc.uses24       = False
612
350
 
613
 
    if pyicu and ptc.usePyICU:
 
351
    if pyicu:
614
352
        am = u''
615
353
        pm = u''
616
 
        ts = ''
617
 
 
618
 
        # ICU doesn't seem to provide directly the
619
 
        # date or time seperator - so we have to
620
 
        # figure it out
 
354
 
 
355
          # ICU doesn't seem to provide directly the
 
356
          # date or time seperator - so we have to
 
357
          # figure it out
 
358
 
 
359
        p = pyicu.FieldPosition(pyicu.DateFormat.AM_PM_FIELD)
621
360
        o = ptc.icu_tf['short']
 
361
 
622
362
        s = ptc.timeFormats['short']
623
363
 
624
364
        ptc.usesMeridian = u'a' in s
625
365
        ptc.uses24       = u'H' in s
626
366
 
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'
629
368
 
630
 
        # ': AM' or ':'
631
 
        s = s.replace('11', '').replace('45', '')
 
369
        s = s.replace('11', '').replace('45', '')                   # ': AM' or ':'
632
370
 
633
371
        if len(s) > 0:
634
 
            ts = s[0]
 
372
            ptc.timeSep = s[0]
635
373
 
636
374
        if ptc.usesMeridian:
637
 
            # '23:45 AM' or '23:45'
638
 
            am = s[1:].strip()
639
 
            s  = o.format(datetime.datetime(2003, 10, 30, 23, 45))
 
375
            am = s[1:].strip()                                      # 'AM'
 
376
 
 
377
            s = o.format(datetime.datetime(2003, 10, 30, 23, 45))   # '23:45 AM' or '23:45'
640
378
 
641
379
            if ptc.uses24:
642
380
                s = s.replace('23', '')
643
381
            else:
644
382
                s = s.replace('11', '')
645
383
 
646
 
            # 'PM' or ''
647
 
            pm = s.replace('45', '').replace(ts, '').strip()
 
384
            pm = s.replace('45', '').replace(ptc.timeSep, '').strip()  # 'PM' or ''
648
385
 
649
 
        ptc.timeSep  = [ ts ]
650
386
        ptc.meridian = [ am, pm ]
651
387
 
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', '')
655
 
 
656
 
        if len(s) > 0:
657
 
            ds = s[0]
658
 
        else:
659
 
            ds = '/'
660
 
 
661
 
        ptc.dateSep = [ ds ]
662
 
        s           = ptc.dateFormats['short']
663
 
        l           = s.lower().split(ds)
664
 
        dp_order    = []
665
 
 
666
 
        for s in l:
667
 
            if len(s) > 0:
668
 
                dp_order.append(s[:1])
669
 
 
670
 
        ptc.dp_order = dp_order
671
388
    else:
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
678
394
 
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
717
433
 
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)?)?
721
 
                                    )
722
 
                           )''' % ptc.re_values
723
 
 
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)?))?
734
 
                                    )
735
 
                           )''' % ptc.re_values
736
 
    ptc.RE_MONTH     = r'''(\s?|^)
737
 
                           (?P<month>(
738
 
                                      (?P<mthname>(%(months)s|%(shortmonths)s))
739
 
                                      (\s?(?P<year>(\d\d\d\d)))?
740
 
                                     ))
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
745
437
 
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)
752
 
                                    (\s?|,|$)
753
 
                                   ))''' % ptc.re_values
754
 
    ptc.RE_MODIFIER  = r'''(\s?|^)
755
 
                           (?P<modifier>
756
 
                            (previous|prev|last|next|eod|eo|(end\sof)|(in\sa)))''' % ptc.re_values
757
 
    ptc.RE_MODIFIER2 = r'''(\s?|^)
758
 
                           (?P<modifier>
759
 
                            (from|before|after|ago|prior))
760
 
                           (\s?|$|[^0-9a-zA-Z])''' % ptc.re_values
761
 
    ptc.RE_TIMEHMS   = r'''(\s?|^)
762
 
                           (?P<hours>\d\d?)
763
 
                           (?P<tsep>%(timeseperator)s|)
764
 
                           (?P<minutes>\d\d)
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|)
768
 
                            (?P<minutes>(\d\d?))
769
 
                            (?:(?P=tsep)
770
 
                               (?P<seconds>\d\d?
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
 
444
 
 
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
772
446
 
773
447
    if 'meridian' in ptc.re_values:
774
448
        ptc.RE_TIMEHMS2 += r'\s?(?P<meridian>(%(meridian)s))' % ptc.re_values
775
449
 
776
 
    dateSeps = ''.join(ptc.dateSep) + '.'
777
 
 
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)
786
 
                        ''' % ptc.re_values
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+'
791
455
 
792
 
    # Regex for date/time ranges
793
 
    ptc.RE_RTIMEHMS  = r'''(\s?|^)
794
 
                           (\d\d?)%(timeseperator)s
795
 
                           (\d\d)
796
 
                           (%(timeseperator)s(\d\d))?
797
 
                           (\s?|$)''' % ptc.re_values
798
 
    ptc.RE_RTIMEHMS2 = r'''(\s?|^)
799
 
                           (\d\d?)
800
 
                           (%(timeseperator)s(\d\d?))?
801
 
                           (%(timeseperator)s(\d\d?))?''' % ptc.re_values
 
456
      # Regex for date/time ranges
 
457
 
 
458
    ptc.RE_RTIMEHMS  = r'(\d\d?)%(timeseperator)s(\d\d)(%(timeseperator)s(\d\d))?' % ptc.re_values
 
459
 
 
460
    ptc.RE_RTIMEHMS2 = r'(\d\d?)(%(timeseperator)s(\d\d?))?(%(timeseperator)s(\d\d?))?' % ptc.re_values
802
461
 
803
462
    if 'meridian' in ptc.re_values:
804
463
        ptc.RE_RTIMEHMS2 += r'\s?(%(meridian)s)' % ptc.re_values
805
464
 
806
 
    ptc.RE_RDATE  = r'(\d+([%s]\d+)+)' % dateSeps
807
 
    ptc.RE_RDATE3 = r'''((((%(months)s))\s?
808
 
                         ((\d\d?)
809
 
                          (\s?|%(daysuffix)s|$)+)?
810
 
                         (,\s?\d\d\d\d)?))''' % ptc.re_values
811
 
 
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
815
 
 
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
819
 
 
820
 
    # "march 1rd -13th"
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
823
 
 
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
827
 
 
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
831
 
 
832
 
    # "4-5pm "
833
 
    ptc.TIMERNG3 = r'\d\d?\s?%(rangeseperator)s\s?' + ptc.RE_RTIMEHMS2
834
 
    ptc.TIMERNG3 = ptc.TIMERNG3 % ptc.re_values
835
 
 
836
 
    # "4:30-5pm "
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 "
839
473
 
840
474
 
841
475
def _initConstants(ptc):
843
477
    Create localized versions of the units, week and month names
844
478
    """
845
479
      # build weekday offsets - yes, it assumes the Weekday and shortWeekday
846
 
      # lists are in the same order and Mon..Sun (Python style)
 
480
      # lists are in the same order and Sun..Sat
847
481
    ptc.WeekdayOffsets = {}
848
482
 
849
483
    o = 0
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 = {}
 
495
    ptc.DaysInMonth  = {}
861
496
 
862
497
    o = 1
863
498
    for key in ptc.Months:
864
499
        ptc.MonthOffsets[key] = o
 
500
        ptc.DaysInMonth[key]  = ptc.DaysInMonthList[o - 1]
865
501
        o += 1
866
502
    o = 1
867
503
    for key in ptc.shortMonths:
868
504
        ptc.MonthOffsets[key] = o
 
505
        ptc.DaysInMonth[key]  = ptc.DaysInMonthList[o - 1]
869
506
        o += 1
870
507
 
871
 
    # ptc.DaySuffixes = ptc.re_consts['daysuffix'].split('|')
872
 
 
873
508
 
874
509
class Constants:
875
510
    """
876
511
    Default set of constants for parsedatetime.
877
512
 
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.
882
 
 
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.
885
 
 
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}.
 
515
 
 
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.
888
519
    """
889
 
    def __init__(self, localeID=None, usePyICU=True, fallbackLocales=['en_US']):
890
 
        self.localeID        = localeID
891
 
        self.fallbackLocales = fallbackLocales
892
 
 
893
 
        if 'en_US' not in self.fallbackLocales:
894
 
            self.fallbackLocales.append('en_US')
 
520
    def __init__(self, localeID=None, usePyICU=True):
 
521
        if localeID is None:
 
522
            self.localeID = 'en_US'
 
523
        else:
 
524
            self.localeID = localeID
895
525
 
896
526
          # define non-locale specific constants
897
527
 
898
528
        self.locale   = None
899
529
        self.usePyICU = usePyICU
900
530
 
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 ]
909
 
 
910
531
        self.Second =   1
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
917
538
 
918
 
        self.rangeSep = u'-'
919
 
 
920
 
        self._DaysInMonthList = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
921
 
 
922
 
        self.BirthdayEpoch = 50
923
 
 
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
927
 
        # -1, 0, +1
928
 
        #
929
 
        # Current day marked as ***
930
 
        #
931
 
        #          Sun Mon Tue Wed Thu Fri Sat
932
 
        # week -1
933
 
        # current         -1,0     ***
934
 
        # week +1          +1
935
 
        #
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
938
 
        # -1, 0, +1
939
 
        #
940
 
        #          Sun Mon Tue Wed Thu Fri Sat
941
 
        # week -1           -1
942
 
        # current      *** 0,+1
943
 
        # week +1
944
 
 
945
 
        self.DOWParseStyle = 1
946
 
 
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.
951
 
        #
952
 
        # Current day marked as ***
953
 
        #
954
 
        # DOWParseStyle = 0
955
 
        #          Sun Mon Tue Wed Thu Fri Sat
956
 
        # week -1
957
 
        # current                      T,F
958
 
        # week +1
959
 
        #
960
 
        # DOWParseStyle = -1
961
 
        #          Sun Mon Tue Wed Thu Fri Sat
962
 
        # week -1                       F
963
 
        # current                       T
964
 
        # week +1
965
 
        #
966
 
        # DOWParseStyle = +1
967
 
        #
968
 
        #          Sun Mon Tue Wed Thu Fri Sat
969
 
        # week -1
970
 
        # current                       T
971
 
        # week +1                       F
972
 
 
973
 
        self.CurrentDOWParseStyle = False
974
 
 
975
 
        # initalize attributes to empty values to ensure
976
 
        # they are defined
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
983
 
        self.dateSep        = None
984
 
        self.timeSep        = None
985
 
        self.am             = None
986
 
        self.pm             = None
987
 
        self.meridian       = None
988
 
        self.usesMeridian   = None
989
 
        self.uses24         = None
990
 
        self.dp_order       = None
991
 
 
992
 
        self.RE_DATE4     = r''
993
 
        self.RE_DATE3     = r''
994
 
        self.RE_MONTH     = r''
995
 
        self.RE_WEEKDAY   = r''
996
 
        self.RE_SPECIAL   = r''
997
 
        self.RE_UNITS     = r''
998
 
        self.RE_QUNITS    = r''
999
 
        self.RE_MODIFIER  = r''
1000
 
        self.RE_MODIFIER2 = r''
1001
 
        self.RE_TIMEHMS   = r''
1002
 
        self.RE_TIMEHMS2  = r''
1003
 
        self.RE_DATE      = r''
1004
 
        self.RE_DATE2     = r''
1005
 
        self.RE_DAY       = r''
1006
 
        self.RE_DAY2      = r''
1007
 
        self.RE_TIME      = r''
1008
 
        self.RE_REMAINING = r''
1009
 
        self.RE_RTIMEHMS  = r''
1010
 
        self.RE_RTIMEHMS2 = r''
1011
 
        self.RE_RDATE     = r''
1012
 
        self.RE_RDATE3    = r''
1013
 
        self.DATERNG1     = r''
1014
 
        self.DATERNG2     = r''
1015
 
        self.DATERNG3     = r''
1016
 
        self.TIMERNG1     = r''
1017
 
        self.TIMERNG2     = r''
1018
 
        self.TIMERNG3     = r''
1019
 
        self.TIMERNG4     = r''
 
539
        self.DaysInMonthList = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
1020
540
 
1021
541
        _initLocale(self)
1022
542
        _initConstants(self)
1023
543
        _initSymbols(self)
1024
544
        _initPatterns(self)
1025
545
 
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,
1055
 
                          }
1056
 
        self.cre_keys = self.cre_source.keys()
1057
 
 
1058
 
 
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)
1063
 
            return value
1064
 
        else:
1065
 
            raise AttributeError, name
1066
 
 
1067
 
    def daysInMonth(self, month, year):
1068
 
        """
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
1071
 
        """
1072
 
        result = None
1073
 
 
1074
 
        if month > 0 and month <= 12:
1075
 
            result = self._DaysInMonthList[month - 1]
1076
 
 
1077
 
            if month == 2:
1078
 
                if year in self._leapYears:
1079
 
                    result += 1
1080
 
                else:
1081
 
                    if calendar.isleap(year):
1082
 
                        self._leapYears.append(year)
1083
 
                        result += 1
1084
 
 
1085
 
        return result
1086
546
 
1087
547
    def buildSources(self, sourceTime=None):
1088
548
        """
1103
563
                     'hr': hr, 'mn':  mn,  'sec': sec, }
1104
564
 
1105
565
        for item in self.re_sources:
1106
 
            values = {}
1107
 
            source = self.re_sources[item]
 
566
            values = self.re_sources[item]
1108
567
 
1109
568
            for key in defaults.keys():
1110
 
                if key in source:
1111
 
                    values[key] = source[key]
1112
 
                else:
 
569
                if not key in values:
1113
570
                    values[key] = defaults[key]
1114
571
 
1115
572
            sources[item] = ( values['yr'], values['mth'], values['dy'],
1117
574
 
1118
575
        return sources
1119
576
 
 
577
        
 
 
b'\\ No newline at end of file'