def evalRanges(self, datetimeString, sourceTime=None):
        """
        Evaluate the C{datetimeString} text and determine if
        it represents a date or time range.

        @type  datetimeString: string
        @param datetimeString: datetime text to evaluate
        @type  sourceTime:     struct_time
        @param sourceTime:     C{struct_time} value to use as the base

        @rtype:  tuple
        @return: tuple of: start datetime, end datetime and the invalid flag
        """
        startTime = ''
        endTime   = ''
        startDate = ''
        endDate   = ''
        rangeFlag = 0

        s = datetimeString.strip().lower()

        if self.ptc.rangeSep in s:
            s = s.replace(self.ptc.rangeSep, ' %s ' % self.ptc.rangeSep)
            s = s.replace('  ', ' ')

        m = self.ptc.CRE_TIMERNG1.search(s)
        if m is not None:
            rangeFlag = 1
        else:
            m = self.ptc.CRE_TIMERNG2.search(s)
            if m is not None:
                rangeFlag = 2
            else:
                m = self.ptc.CRE_TIMERNG4.search(s)
                if m is not None:
                    rangeFlag = 7
                else:
                    m = self.ptc.CRE_TIMERNG3.search(s)
                    if m is not None:
                        rangeFlag = 3
                    else:
                        m = self.ptc.CRE_DATERNG1.search(s)
                        if m is not None:
                            rangeFlag = 4
                        else:
                            m = self.ptc.CRE_DATERNG2.search(s)
                            if m is not None:
                                rangeFlag = 5
                            else:
                                m = self.ptc.CRE_DATERNG3.search(s)
                                if m is not None:
                                    rangeFlag = 6

        if _debug:
            print 'evalRanges: rangeFlag =', rangeFlag, '[%s]' % s

        if m is not None:
            if (m.group() != s):
                # capture remaining string
                parseStr = m.group()
                chunk1   = s[:m.start()]
                chunk2   = s[m.end():]
                s        = '%s %s' % (chunk1, chunk2)
                flag     = 1

                sourceTime, flag = self.parse(s, sourceTime)

                if flag == 0:
                    sourceTime = None
            else:
                parseStr = s

        if rangeFlag == 1:
            m                = re.search(self.ptc.rangeSep, parseStr)
            startTime, sflag = self.parse((parseStr[:m.start()]),       sourceTime)
            endTime, eflag   = self.parse((parseStr[(m.start() + 1):]), sourceTime)

            if (eflag != 0)  and (sflag != 0):
                return (startTime, endTime, 2)

        elif rangeFlag == 2:
            m                = re.search(self.ptc.rangeSep, parseStr)
            startTime, sflag = self.parse((parseStr[:m.start()]),       sourceTime)
            endTime, eflag   = self.parse((parseStr[(m.start() + 1):]), sourceTime)

            if (eflag != 0)  and (sflag != 0):
                return (startTime, endTime, 2)

        elif rangeFlag == 3 or rangeFlag == 7:
            m = re.search(self.ptc.rangeSep, parseStr)
            # capturing the meridian from the end time
            if self.ptc.usesMeridian:
                ampm = re.search(self.ptc.am[0], parseStr)

                # appending the meridian to the start time
                if ampm is not None:
                    startTime, sflag = self.parse((parseStr[:m.start()] + self.ptc.meridian[0]), sourceTime)
                else:
                    startTime, sflag = self.parse((parseStr[:m.start()] + self.ptc.meridian[1]), sourceTime)
            else:
                startTime, sflag = self.parse((parseStr[:m.start()]), sourceTime)

            endTime, eflag = self.parse(parseStr[(m.start() + 1):], sourceTime)

            if (eflag != 0)  and (sflag != 0):
                return (startTime, endTime, 2)

        elif rangeFlag == 4:
            m                = re.search(self.ptc.rangeSep, parseStr)
            startDate, sflag = self.parse((parseStr[:m.start()]),       sourceTime)
            endDate, eflag   = self.parse((parseStr[(m.start() + 1):]), sourceTime)

            if (eflag != 0)  and (sflag != 0):
                return (startDate, endDate, 1)

        elif rangeFlag == 5:
            m       = re.search(self.ptc.rangeSep, parseStr)
            endDate = parseStr[(m.start() + 1):]

            # capturing the year from the end date
            date    = self.ptc.CRE_DATE3.search(endDate)
            endYear = date.group('year')

            # appending the year to the start date if the start date
            # does not have year information and the end date does.
            # eg : "Aug 21 - Sep 4, 2007"
            if endYear is not None:
                startDate = (parseStr[:m.start()]).strip()
                date      = self.ptc.CRE_DATE3.search(startDate)
                startYear = date.group('year')

                if startYear is None:
                    startDate = startDate + ', ' + endYear
            else:
                startDate = parseStr[:m.start()]

            startDate, sflag = self.parse(startDate, sourceTime)
            endDate, eflag   = self.parse(endDate, sourceTime)

            if (eflag != 0)  and (sflag != 0):
                return (startDate, endDate, 1)

        elif rangeFlag == 6:
            m = re.search(self.ptc.rangeSep, parseStr)

            startDate = parseStr[:m.start()]

            # capturing the month from the start date
            mth = self.ptc.CRE_DATE3.search(startDate)
            mth = mth.group('mthname')

            # appending the month name to the end date
            endDate = mth + parseStr[(m.start() + 1):]

            startDate, sflag = self.parse(startDate, sourceTime)
            endDate, eflag   = self.parse(endDate, sourceTime)

            if (eflag != 0)  and (sflag != 0):
                return (startDate, endDate, 1)
        else:
            # if range is not found
            sourceTime = time.localtime()

            return (sourceTime, sourceTime, 0)
Evaluate the C{datetimeString} text and determine if
        it represents a date or time range.

        @type  datetimeString: string
        @param datetimeString: datetime text to evaluate
        @type  sourceTime:     struct_time
        @param sourceTime:     C{struct_time} value to use as the base

        @rtype:  tuple
        @return: tuple of: start datetime, end datetime and the invalid flag