def __init__(self, localeID=None, usePyICU=True, fallbackLocales=['en_US']):
        self.localeID        = localeID
        self.fallbackLocales = fallbackLocales

        if 'en_US' not in self.fallbackLocales:
            self.fallbackLocales.append('en_US')

          # define non-locale specific constants

        self.locale   = None
        self.usePyICU = usePyICU

        # starting cache of leap years
        # daysInMonth will add to this if during
        # runtime it gets a request for a year not found
        self._leapYears = [ 1904, 1908, 1912, 1916, 1920, 1924, 1928, 1932, 1936, 1940, 1944,
                            1948, 1952, 1956, 1960, 1964, 1968, 1972, 1976, 1980, 1984, 1988,
                            1992, 1996, 2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028, 2032,
                            2036, 2040, 2044, 2048, 2052, 2056, 2060, 2064, 2068, 2072, 2076,
                            2080, 2084, 2088, 2092, 2096 ]

        self.Second =   1
        self.Minute =  60 * self.Second
        self.Hour   =  60 * self.Minute
        self.Day    =  24 * self.Hour
        self.Week   =   7 * self.Day
        self.Month  =  30 * self.Day
        self.Year   = 365 * self.Day

        self._DaysInMonthList = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
        self.rangeSep         = '-'
        self.BirthdayEpoch    = 50

        # YearParseStyle controls how we parse "Jun 12", i.e. dates that do
        # not have a year present.  The default is to compare the date given
        # to the current date, and if prior, then assume the next year.
        # Setting this to 0 will prevent that.

        self.YearParseStyle = 1

        # DOWParseStyle controls how we parse "Tuesday"
        # If the current day was Thursday and the text to parse is "Tuesday"
        # then the following table shows how each style would be returned
        # -1, 0, +1
        #
        # Current day marked as ***
        #
        #          Sun Mon Tue Wed Thu Fri Sat
        # week -1
        # current         -1,0     ***
        # week +1          +1
        #
        # If the current day was Monday and the text to parse is "Tuesday"
        # then the following table shows how each style would be returned
        # -1, 0, +1
        #
        #          Sun Mon Tue Wed Thu Fri Sat
        # week -1           -1
        # current      *** 0,+1
        # week +1

        self.DOWParseStyle = 1

        # CurrentDOWParseStyle controls how we parse "Friday"
        # If the current day was Friday and the text to parse is "Friday"
        # then the following table shows how each style would be returned
        # True/False. This also depends on DOWParseStyle.
        #
        # Current day marked as ***
        #
        # DOWParseStyle = 0
        #          Sun Mon Tue Wed Thu Fri Sat
        # week -1
        # current                      T,F
        # week +1
        #
        # DOWParseStyle = -1
        #          Sun Mon Tue Wed Thu Fri Sat
        # week -1                       F
        # current                       T
        # week +1
        #
        # DOWParseStyle = +1
        #
        #          Sun Mon Tue Wed Thu Fri Sat
        # week -1
        # current                       T
        # week +1                       F

        self.CurrentDOWParseStyle = False

        if self.usePyICU:
            self.locale = pdtLocales['icu'](self.localeID)

            if self.locale.icu is None:
                self.usePyICU = False
                self.locale   = None

        if self.locale is None:
            if not self.localeID in pdtLocales:
                for id in range(0, len(self.fallbackLocales)):
                    self.localeID = self.fallbackLocales[id]
                    if self.localeID in pdtLocales:
                        break

            self.locale = pdtLocales[self.localeID]()

        if self.locale is not None:
              # escape any regex special characters that may be found
            wd   = tuple(map(re.escape, self.locale.Weekdays))
            swd  = tuple(map(re.escape, self.locale.shortWeekdays))
            mth  = tuple(map(re.escape, self.locale.Months))
            smth = tuple(map(re.escape, self.locale.shortMonths))

            self.locale.re_values['months']      = '%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s' % mth
            self.locale.re_values['shortmonths'] = '%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s' % smth
            self.locale.re_values['days']        = '%s|%s|%s|%s|%s|%s|%s' % wd
            self.locale.re_values['shortdays']   = '%s|%s|%s|%s|%s|%s|%s' % swd

            l = []
            for s in self.locale.units:
                l = l + self.locale.units[s]
            self.locale.re_values['units'] = '|'.join(tuple(map(re.escape, l)))

            l = []
            lbefore = []
            lafter  = []
            for s in self.locale.Modifiers:
                l.append(s)
                if self.locale.Modifiers[s] < 0:
                    lbefore.append(s)
                elif self.locale.Modifiers[s] > 0:
                    lafter.append(s)
            self.locale.re_values['modifiers']        = '|'.join(tuple(map(re.escape, l)))
            self.locale.re_values['modifiers-before'] = '|'.join(tuple(map(re.escape, lbefore)))
            self.locale.re_values['modifiers-after']  = '|'.join(tuple(map(re.escape, lafter)))

            l = []
            for s in self.locale.re_sources:
                l.append(s)
            self.locale.re_values['sources'] = '|'.join(tuple(map(re.escape, l)))

              # build weekday offsets - yes, it assumes the Weekday and shortWeekday
              # lists are in the same order and Mon..Sun (Python style)
            o = 0
            for key in self.locale.Weekdays:
                self.locale.WeekdayOffsets[key] = o
                o += 1
            o = 0
            for key in self.locale.shortWeekdays:
                self.locale.WeekdayOffsets[key] = o
                o += 1

              # build month offsets - yes, it assumes the Months and shortMonths
              # lists are in the same order and Jan..Dec
            o = 1
            for key in self.locale.Months:
                self.locale.MonthOffsets[key] = o
                o += 1
            o = 1
            for key in self.locale.shortMonths:
                self.locale.MonthOffsets[key] = o
                o += 1

            # self.locale.DaySuffixes = self.locale.re_values['daysuffix'].split('|')

        _initSymbols(self)

        # TODO add code to parse the date formats and build the regexes up from sub-parts
        # TODO find all hard-coded uses of date/time seperators

        self.RE_DATE4     = r'''(?P<date>(((?P<day>\d\d?)(?P<suffix>%(daysuffix)s)?(,)?(\s)?)
                                           (?P<mthname>(%(months)s|%(shortmonths)s))\s?
                                           (?P<year>\d\d(\d\d)?)?
                                         )
                                )''' % self.locale.re_values

        # I refactored DATE3 to fix Issue 16 http://code.google.com/p/parsedatetime/issues/detail?id=16
        # I suspect the final line was for a trailing time - but testing shows it's not needed
        # ptc.RE_DATE3     = r'''(?P<date>((?P<mthname>(%(months)s|%(shortmonths)s))\s?
        #                                  ((?P<day>\d\d?)(\s?|%(daysuffix)s|$)+)?
        #                                  (,\s?(?P<year>\d\d(\d\d)?))?))
        #                        (\s?|$|[^0-9a-zA-Z])''' % ptc.locale.re_values
        self.RE_DATE3     = r'''(?P<date>(
                                          (((?P<mthname>(%(months)s|%(shortmonths)s))|
                                          ((?P<day>\d\d?)(?P<suffix>%(daysuffix)s)?))(\s)?){1,2}
                                          ((,)?(\s)?(?P<year>\d\d(\d\d)?))?
                                         )
                                )''' % self.locale.re_values
        self.RE_MONTH     = r'''(\s?|^)
                                (?P<month>(
                                           (?P<mthname>(%(months)s|%(shortmonths)s))
                                           (\s?(?P<year>(\d\d\d\d)))?
                                          ))
                                (\s?|$|[^0-9a-zA-Z])''' % self.locale.re_values
        self.RE_WEEKDAY   = r'''(\s?|^)
                                (?P<weekday>(%(days)s|%(shortdays)s))
                                (\s?|$|[^0-9a-zA-Z])''' % self.locale.re_values

        self.RE_SPECIAL   = r'(?P<special>^[%(specials)s]+)\s+' % self.locale.re_values
        self.RE_UNITS     = r'''(?P<qty>(-?\d+\s*
                                         (?P<units>((%(units)s)s?))
                                        ))''' % self.locale.re_values
        self.RE_QUNITS    = r'''(?P<qty>(-?\d+\s?
                                         (?P<qunits>%(qunits)s)
                                         (\s?|,|$)
                                        ))''' % self.locale.re_values
        # self.RE_MODIFIER  = r'''(\s?|^)
        #                         (?P<modifier>
        #                          (previous|prev|last|next|eod|eo|(end\sof)|(in\sa)))''' % self.locale.re_values
        # self.RE_MODIFIER2 = r'''(\s?|^)
        #                         (?P<modifier>
        #                          (from|before|after|ago|prior))
        #                         (\s?|$|[^0-9a-zA-Z])''' % self.locale.re_values
        self.RE_MODIFIER  = r'''(\s?|^)
                                (?P<modifier>
                                 (%(modifiers-after)s))''' % self.locale.re_values
        self.RE_MODIFIER2 = r'''(\s?|^)
                                (?P<modifier>
                                 (%(modifiers-before)s))
                                (\s?|$|[^0-9a-zA-Z])''' % self.locale.re_values
        self.RE_TIMEHMS   = r'''(\s?|^)
                                (?P<hours>\d\d?)
                                (?P<tsep>%(timeseperator)s|)
                                (?P<minutes>\d\d)
                                (?:(?P=tsep)(?P<seconds>\d\d(?:[.,]\d+)?))?''' % self.locale.re_values
        self.RE_TIMEHMS2  = r'''(?P<hours>(\d\d?))
                                ((?P<tsep>%(timeseperator)s|)
                                 (?P<minutes>(\d\d?))
                                 (?:(?P=tsep)
                                    (?P<seconds>\d\d?
                                     (?:[.,]\d+)?))?)?''' % self.locale.re_values

        if 'meridian' in self.locale.re_values:
            self.RE_TIMEHMS2 += r'\s?(?P<meridian>(%(meridian)s))' % self.locale.re_values

        dateSeps = ''.join(self.locale.dateSep) + '.'

        self.RE_DATE      = r'''(\s?|^)
                                (?P<date>(\d\d?[%s]\d\d?([%s]\d\d(\d\d)?)?))
                                (\s?|$|[^0-9a-zA-Z])''' % (dateSeps, dateSeps)
        self.RE_DATE2     = r'[%s]' % dateSeps
        self.RE_DAY       = r'''(\s?|^)
                                (?P<day>(today|tomorrow|yesterday))
                                (\s?|$|[^0-9a-zA-Z])''' % self.locale.re_values
        self.RE_DAY2      = r'''(?P<day>\d\d?)|(?P<suffix>%(daysuffix)s)
                             ''' % self.locale.re_values
        # self.RE_TIME      = r'''(\s?|^)
        #                         (?P<time>(morning|breakfast|noon|lunch|evening|midnight|tonight|dinner|night|now))
        #                         (\s?|$|[^0-9a-zA-Z])''' % self.locale.re_values
        self.RE_TIME      = r'''(\s?|^)
                                (?P<time>(%(sources)s))
                                (\s?|$|[^0-9a-zA-Z])''' % self.locale.re_values
        self.RE_REMAINING = r'\s+'

        # Regex for date/time ranges
        self.RE_RTIMEHMS  = r'''(\s?|^)
                                (\d\d?)%(timeseperator)s
                                (\d\d)
                                (%(timeseperator)s(\d\d))?
                                (\s?|$)''' % self.locale.re_values
        self.RE_RTIMEHMS2 = r'''(\s?|^)
                                (\d\d?)
                                (%(timeseperator)s(\d\d?))?
                                (%(timeseperator)s(\d\d?))?''' % self.locale.re_values

        if 'meridian' in self.locale.re_values:
            self.RE_RTIMEHMS2 += r'\s?(%(meridian)s)' % self.locale.re_values

        self.RE_RDATE  = r'(\d+([%s]\d+)+)' % dateSeps
        self.RE_RDATE3 = r'''((((%(months)s))\s?
                              ((\d\d?)
                               (\s?|%(daysuffix)s|$)+)?
                              (,\s?\d\d\d\d)?))''' % self.locale.re_values

        # "06/07/06 - 08/09/06"
        self.DATERNG1 = self.RE_RDATE + r'\s?%(rangeseperator)s\s?' + self.RE_RDATE
        self.DATERNG1 = self.DATERNG1 % self.locale.re_values

        # "march 31 - june 1st, 2006"
        self.DATERNG2 = self.RE_RDATE3 + r'\s?%(rangeseperator)s\s?' + self.RE_RDATE3
        self.DATERNG2 = self.DATERNG2 % self.locale.re_values

        # "march 1rd -13th"
        self.DATERNG3 = self.RE_RDATE3 + r'\s?%(rangeseperator)s\s?(\d\d?)\s?(rd|st|nd|th)?'
        self.DATERNG3 = self.DATERNG3 % self.locale.re_values

        # "4:00:55 pm - 5:90:44 am", '4p-5p'
        self.TIMERNG1 = self.RE_RTIMEHMS2 + r'\s?%(rangeseperator)s\s?' + self.RE_RTIMEHMS2
        self.TIMERNG1 = self.TIMERNG1 % self.locale.re_values

        # "4:00 - 5:90 ", "4:55:55-3:44:55"
        self.TIMERNG2 = self.RE_RTIMEHMS + r'\s?%(rangeseperator)s\s?' + self.RE_RTIMEHMS
        self.TIMERNG2 = self.TIMERNG2 % self.locale.re_values

        # "4-5pm "
        self.TIMERNG3 = r'\d\d?\s?%(rangeseperator)s\s?' + self.RE_RTIMEHMS2
        self.TIMERNG3 = self.TIMERNG3 % self.locale.re_values

        # "4:30-5pm "
        self.TIMERNG4 = self.RE_RTIMEHMS + r'\s?%(rangeseperator)s\s?' + self.RE_RTIMEHMS2
        self.TIMERNG4 = self.TIMERNG4 % self.locale.re_values

        self.re_option = re.IGNORECASE + re.VERBOSE
        self.cre_source = { 'CRE_SPECIAL':   self.RE_SPECIAL,
                            'CRE_UNITS':     self.RE_UNITS,
                            'CRE_QUNITS':    self.RE_QUNITS,
                            'CRE_MODIFIER':  self.RE_MODIFIER,
                            'CRE_MODIFIER2': self.RE_MODIFIER2,
                            'CRE_TIMEHMS':   self.RE_TIMEHMS,
                            'CRE_TIMEHMS2':  self.RE_TIMEHMS2,
                            'CRE_DATE':      self.RE_DATE,
                            'CRE_DATE2':     self.RE_DATE2,
                            'CRE_DATE3':     self.RE_DATE3,
                            'CRE_DATE4':     self.RE_DATE4,
                            'CRE_MONTH':     self.RE_MONTH,
                            'CRE_WEEKDAY':   self.RE_WEEKDAY,
                            'CRE_DAY':       self.RE_DAY,
                            'CRE_DAY2':      self.RE_DAY2,
                            'CRE_TIME':      self.RE_TIME,
                            'CRE_REMAINING': self.RE_REMAINING,
                            'CRE_RTIMEHMS':  self.RE_RTIMEHMS,
                            'CRE_RTIMEHMS2': self.RE_RTIMEHMS2,
                            'CRE_RDATE':     self.RE_RDATE,
                            'CRE_RDATE3':    self.RE_RDATE3,
                            'CRE_TIMERNG1':  self.TIMERNG1,
                            'CRE_TIMERNG2':  self.TIMERNG2,
                            'CRE_TIMERNG3':  self.TIMERNG3,
                            'CRE_TIMERNG4':  self.TIMERNG4,
                            'CRE_DATERNG1':  self.DATERNG1,
                            'CRE_DATERNG2':  self.DATERNG2,
                            'CRE_DATERNG3':  self.DATERNG3,
                          }
        self.cre_keys = list(self.cre_source.keys())