"""Canonical ISO date format YYYY-MM-DDTHH:mm:SS+HH:mm
This parser is _extremely_ strict, and the dates that match it,
though really easy to work with for the computer, are not particularly
readable. See the iso_date_loose module for a slightly relaxed
definition which allows the "T" character to be replaced by a
" " character, and allows a space before the timezone offset, as well
as allowing the integer values to use non-0-padded integers.
ISO_date -- YYYY-MM-DD format, with a month and date optional
ISO_time -- HH:mm:SS format, with minutes and seconds optional
ISO_date_time -- YYYY-MM-DD HH:mm:SS+HH:mm format,
with time optional and TimeZone offset optional
Interpreter:
MxInterpreter
Interprets the parse tree as mx.DateTime values
ISO_date and ISO_time
returns DateTime objects
Time only
returns RelativeDateTime object which, when
added to a DateTime gives you the given time
within that day
"""
try:
from mx import DateTime
haveMX = 1
except ImportError:
haveMX = 0
from simpleparse.parser import Parser
from simpleparse import common, objectgenerator
from simpleparse.common import chartypes, numbers
from simpleparse.dispatchprocessor import *
c = {}
declaration ="""
year := digit,digit,digit,digit
month := digit,digit
day := digit,digit
hour := digit,digit
minute := digit,digit
second := digit,digit
offset_sign := [-+]
offset := offset_sign, hour, time_separator?, minute
<date_separator> := '-'
<time_separator> := ':'
ISO_date := year, (date_separator, month, (date_separator, day)?)?
ISO_time := hour, (time_separator, minute, (time_separator, second)?)?
ISO_date_time := ISO_date, ([T], ISO_time)?, offset?
"""
_p = Parser( declaration )
for name in ["ISO_time","ISO_date", "ISO_date_time"]:
c[ name ] = objectgenerator.LibraryElement(
generator = _p._generator,
production = name,
)
common.share( c )
if haveMX:
class MxInterpreter(DispatchProcessor):
"""Interpret a parsed ISO_date_time_loose in GMT/UTC time or localtime
"""
def __init__(
self,
inputLocal = 1,
returnLocal = 1,
):
self.inputLocal = inputLocal
self.returnLocal = returnLocal
dateName = 'ISO_date'
timeName = 'ISO_time'
def ISO_date_time( self, (tag, left, right, sublist), buffer):
"""Interpret the loose ISO date + time format"""
set = singleMap( sublist, self, buffer )
base, time, offset = (
set.get(self.dateName),
set.get(self.timeName) or DateTime.RelativeDateTime(hour=0,minute=0,second=0),
set.get( "offset" ),
)
base = base + time
offset = set.get( "offset" )
if offset is not None:
# an explicit timezone was entered, convert to gmt and return as appropriate...
gmt = base - offset
if self.returnLocal:
return gmt.localtime()
else:
return gmt
# was in the default input locale (either gmt or local)
if self.inputLocal and self.returnLocal:
return base
elif not self.inputLocal and not self.returnLocal:
return base
elif self.inputLocal and not self.returnLocal:
# return gmt from local...
return base.gmtime()
else:
return base.localtime()
def ISO_date( self, (tag, left, right, sublist), buffer):
"""Interpret the ISO date format"""
set = {}
for item in sublist:
set[ item[0] ] = dispatch( self, item, buffer)
return DateTime.DateTime(
set.get("year") or now().year,
set.get("month") or 1,
set.get("day") or 1,
)
def ISO_time( self, (tag, left, right, sublist), buffer):
"""Interpret the ISO time format"""
set = {}
for item in sublist:
set[ item[0] ] = dispatch( self, item, buffer)
return DateTime.RelativeDateTime(
hour = set.get("hour") or 0,
minute = set.get("minute") or 0,
second = set.get("second") or 0,
)
integer = numbers.IntInterpreter()
second = offset_minute = offset_hour = year = month = day = hour =minute =integer
def offset( self, (tag, left, right, sublist), buffer):
"""Calculate the time zone offset as a date-time delta"""
set = singleMap( sublist, self, buffer )
direction = set.get('offset_sign',1)
hour = set.get( "hour", 0)
minute = set.get( "minute", 0)
delta = DateTime.DateTimeDelta( 0, hour*direction, minute*direction)
return delta
def offset_sign( self , (tag, left, right, sublist), buffer):
"""Interpret the offset sign as a multiplier"""
v = buffer [left: right]
if v in ' +':
return 1
else:
return -1
syntax highlighted by Code2HTML, v. 0.9.1