[Top][All Lists]
[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [gnue] r9352 - trunk/gnue-forms/src/input/displayHandlers,
johannes <=