commit-gnue
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnue] r9352 - trunk/gnue-forms/src/input/displayHandlers


From: johannes
Subject: [gnue] r9352 - trunk/gnue-forms/src/input/displayHandlers
Date: Tue, 6 Feb 2007 04:51:55 -0600 (CST)

Author: johannes
Date: 2007-02-06 04:51:54 -0600 (Tue, 06 Feb 2007)
New Revision: 9352

Modified:
   trunk/gnue-forms/src/input/displayHandlers/datehandler.py
Log:
Improved the display handler for datetime values


Modified: trunk/gnue-forms/src/input/displayHandlers/datehandler.py
===================================================================
--- trunk/gnue-forms/src/input/displayHandlers/datehandler.py   2007-02-06 
10:10:26 UTC (rev 9351)
+++ trunk/gnue-forms/src/input/displayHandlers/datehandler.py   2007-02-06 
10:51:54 UTC (rev 9352)
@@ -487,73 +487,270 @@
 
 
 
-class DateTime(BaseCursor):
+# =============================================================================
+# Displayhandler for date- and time-values
+# =============================================================================
+
+class DateTime(DateRelated):
     """
     Class to handle the display and entry of date based fields.
     """
-    def __init__(self, entry, eventHandler, subEventHandler, displayMask,
-                 inputMask):
-        BaseCursor.__init__(self, entry, eventHandler, subEventHandler,
-                displayMask, inputMask)
-        self._displayMask = displayMask
-        self._inputMask = inputMask
 
+    # -------------------------------------------------------------------------
+    # Constructor
+    # -------------------------------------------------------------------------
 
-    def build_display(self, value, editing):
-        if editing:
-            if self._inputMask:
-                format = self._inputMask
+    def __init__(self, entry, eventHandler, subEventHandler, display_mask,
+                 input_mask):
+
+        DateRelated.__init__(self, entry, eventHandler, subEventHandler,
+                display_mask, input_mask)
+
+        self._input_mask = input_mask or gConfigForms('DateEditMask_Timestamp')
+        self._display_mask = display_mask or gConfigForms('DateMask_Timestamp')
+
+        self.__get_ordering()
+
+
+    # -------------------------------------------------------------------------
+    # Get the ordering for the components
+    # -------------------------------------------------------------------------
+
+    def __get_ordering(self):
+
+        sample = datetime.datetime(1978, 3, 21, 13, 24, 56)
+        text = sample.strftime(str(self._input_mask))
+
+        self.__order = []
+        self.__inter = []
+        pat = re.compile('^(\d+)(\D*)')
+
+        match = pat.match(text)
+        while match:
+            part, rest = match.groups()
+            if part in ['1978', '78']:
+                self.__order.append('year')
+            elif part in ['03', '3']:
+                self.__order.append('month')
+            elif part == '21':
+                self.__order.append('day')
+            elif part in ['13', '01']:
+                self.__order.append('hour')
+            elif part == '24':
+                self.__order.append('minute')
+            elif part == '56':
+                self.__order.append('second')
             else:
-                format = "%m/%d/%Y"
-        else:
-            if self._displayMask:
-                format = self._displayMask
-            else:
-                format = "%m/%d/%y"
+                self.__order.append('?')
 
-        if value in (None, ""):
-            return ""
-        try:
-            return value.strftime (str (format))
-        except AttributeError:
-            return str(value)
+            if rest:
+                self.__inter.append(rest)
 
+            text = text[len(part + rest):]
+            if not text:
+                break
 
+            match = pat.match(text)
+
+
+    # -------------------------------------------------------------------------
+    # Try to get an apropriate datetime value from a string
+    # -------------------------------------------------------------------------
+
     def parse_display(self, display):
+
         if not len(display):
             return None
 
-        # TODO: Replace with format mask
-        if self._inputMask:
+        try:
+            # First have a look wether the input follows the requested format 
+            temp = time.strptime(display, self._input_mask)
+            return datetime.datetime(*temp[0:6])
+
+        except ValueError:
+            pass
+
+
+        today = datetime.datetime.today().replace(hour=0, minute=0, second=0,
+                microsecond=0)
+
+        # If the input is a number of length 2 we treat it as day
+        if display.isdigit() and len(display) <= 2:
             try:
-                tempVal = time.strptime (display, self._inputMask)
-                return datetime.datetime(*tempVal[0:6])
+                return today.replace(day=int(display))
+
             except ValueError:
                 raise InvalidDateLiteral, display
 
-        # TODO: Candidate for maketrans?
-        # TODO: This logic does not work for timestamps
-        #       as it skips the hour,minute, second
-        value = display.replace('.','/').replace('-','/')
+        # If the input is a 4-digit number or a string with two numbers
+        # separated by a non-digit string we treat it as "day and month"
+        # according to the order of the original input mask
+        match = re.match('^(\d+)\D+(\d+)\s*$', display)
+        if (display.isdigit() and len(display) == 4) or match is not None:
+            if match:
+                (val1, val2) = match.groups()
+            else:
+                val1, val2 = display[:2], display[2:]
 
-        # Support for quick entry like '123102' for '12/31/02'
-        if len(value) in (6, 8) and value.find('/') == -1:
-            month = value[:2]
-            day = value[2:4]
-            year = value[4:]
+            if self.__order.index('day') < self.__order.index('month'):
+                day = int(val1)
+                month = int(val2)
+            else:
+                day = int(val2)
+                month = int(val1)
 
-        elif value.find ('/') == -1:
-            raise InvalidDateLiteral, value
+            try:
+                return today.replace(day=day, month=month)
 
-        else:
-            month, day, year = value.split('/')
+            except ValueError:
+                raise InvalidDateLiteral, display
 
-        # TODO: Shouldn't the 50 be a config option
-        year = int(year)
-        if year < 100:
-            if year > 50:
-                year = year + 1900
+        # If the input is a 6-digit number or a triple of numeric values
+        # separated by non-digit characters it is likely a complete date
+        match = re.match('^(\d+)\D+(\d+)\D+(\d+)$', display)
+        if (display.isdigit() and len(display) == 6) or match is not None:
+            if match:
+                values = match.groups()
             else:
-                year = year + 2000
+                values = display[:2], display[2:4], display[4:]
 
-        return datetime.datetime(year, int(month), int(day))
+            kw = {}
+            for index, item in enumerate(values):
+                value = int(item)
+                part = self.__order[index].lower()
+
+                # If the year is given without a century we will figure out
+                # which one to use.
+                if part == 'year' and value < 100:
+                    if value % 100 >= 50:
+                        value += 1900
+                    else:
+                        value += 2000
+
+                kw[part] = value
+
+            try:
+                return datetime.datetime(**kw)
+
+            except ValueError:
+                raise InvalidDateLiteral, display
+
+        # If the input is a 8-digit number it should be a complete date.  We
+        # derive the order of the elements from the order as given in the input
+        # mask.
+        if display.isdigit() and len(display) == 8:
+            for item in self.__order:
+                if item.lower() == 'year':
+                    year = int(display[:4])
+                    display = display[4:]
+                elif item == 'month':
+                    month = int(display[:2])
+                    display = display[2:]
+                elif item == 'day':
+                    day = int(display[:2])
+                    display = display[2:]
+
+            try:
+                return datetime.datetime(day=day, month=month, year=year)
+
+            except ValueError:
+                raise InvalidDateLiteral, display
+
+                
+        # If the input is a triple of numeric values separated by non-digit
+        # characters followed by non-digit characters and something else it is
+        # likely a complete date with a time-part
+        match = re.match('^(\d+)\D+(\d+)\D+(\d+)\D+(.*)$', display)
+        if match is not None:
+            values = list(match.groups())
+            timepart = values.pop()
+
+            kw = {}
+            for index, item in enumerate(values):
+                value = int(item)
+                part = self.__order[index].lower()
+
+                # If the year is given without a century we will figure out
+                # which one to use.
+                if part == 'year' and value < 100:
+                    if value % 100 >= 50:
+                        value += 1900
+                    else:
+                        value += 2000
+
+                kw[part] = value
+
+            # now try to guess what the timepart means
+            timeres = self.__parse_time(timepart)
+
+            try:
+                return datetime.datetime.combine(datetime.date(**kw), timeres)
+
+            except ValueError:
+                raise InvalidDateLiteral, display
+        raise InvalidDateLiteral, display
+
+
+    # -------------------------------------------------------------------------
+    # Try to figure out which time is meant by a given string
+    # -------------------------------------------------------------------------
+
+    def __parse_time(self, display):
+
+        # Catch the ordering of the time components
+        order = [i for i in self.__order if i in ['hour', 'minute', 'second']]
+
+        kw = {'hour': 0, 'minute': 0, 'second': 0}
+
+        # If the input is a number of length 2 we treat it as the first
+        # component
+        if display.isdigit() and len(display) <= 2:
+            try:
+                kw[order[0]] = int(display)
+                return datetime.time(**kw)
+
+            except ValueError:
+                raise InvalidTimeLiteral, display
+
+
+        # If the input is a 4-digit number or a string with two numbers
+        # separated by a non-digit string we treat it as the first two
+        # components according to the order of the original input mask
+        match = re.match('^(\d+)\D+(\d+)\s*$', display)
+        if (display.isdigit() and len(display) == 4) or match is not None:
+            if match:
+                (val1, val2) = match.groups()
+            else:
+                val1, val2 = display[:2], display[2:]
+
+            kw[order[0]] = int(val1)
+            kw[order[1]] = int(val2)
+
+            try:
+                return datetime.time(**kw)
+
+            except ValueError:
+                raise InvalidTimeLiteral, display
+
+        # If the input is a 6-digit number or a string with three numbers
+        # separated by a non-digit string we treat it as complete time part
+        # according to the order of the original input mask
+        match = re.match('^(\d+)\D+(\d+)\D+(\d+)\s*$', display)
+        if (display.isdigit() and len(display) == 6) or match is not None:
+            if match:
+                (val1, val2, val3) = match.groups()
+            else:
+                val1, val2, val3 = display[:2], display[2:4], display[4:]
+
+            kw[order[0]] = int(val1)
+            kw[order[1]] = int(val2)
+            kw[order[2]] = int(val3)
+
+            try:
+                return datetime.time(**kw)
+
+            except ValueError:
+                raise InvalidTimeLiteral, display
+
+        # Does not seem to fit any pattern
+        raise InvalidTimeLiteral, display





reply via email to

[Prev in Thread] Current Thread [Next in Thread]