Interface ( DateTime : DateTimeDelta : RelativeDateTime : Constants : Functions ) : Arithmetic : Submodules ( ISO : ARPA : Feasts : Parser : NIST ) : Examples : C API : Structure : Support : Download : Copyright & License : History : Home | Version 2.0.3 |
These types were created to provide a consistent way of transferring date and time data between Python and databases. Apart from handling date before the Unix epoch (1.1.1970) they also correctly work with dates beyond the Unix time limit (currently with Unix time values being encoded using 32bit integers, the limit is reached in 2038) and thus is Year 2000 and Year 2038 safe.
The primary absolute date/time type DateTime uses the following internal format:
The Epoch used by the module is January 1st of the year 1 at midnight (0:00:00.00) in the Gregorian calendar. This date corresponds to absolute day 1 and absolute time 0. Dates before the Epoch are handled by extrapolating the calendars using negative years as basis (the year 1 BCE corresponds to the year 0, 2 BCE is represented as year -1 and so on).
For the purpose of storing absolute time differences, the package provides a second type called DateTimeDelta. The internal representation for this type is seconds and stored in a signed C double.
To handle relative time deltas a third object type is available: RelativeDateTime. This object is currently implemented in Python and may be used to store relative time deltas (see below for an exact description). It's main purpose is providing an intuitive way to calculate e.g. the "first of next month".
Designing the types wasn't as easy as expected, since many criteria had to be taken into account. Here are some of them and their implementation:
Time zones are among the most difficult to handle issues when it comes to implementing and using types for date and time. We chose to move the time zone handling functionality out of the C implementation and into Python. This means that the types know nothing about the time zones of the values they store and calculations are done using the raw data.
If you need to store and use these informations in calculations, you can "subclass" the types to implement your ideas rather than having to stick to what the C implementation defines. The included ODMG submodule is an example of how this can be done.
Leap seconds are not supported either. You can implement classes respecting these by "subclassing" DateTime and DateTimeDelta and then overriding the calculation methods with methods that work on Unix ticks values (provided the underlying C lib knows about leap seconds -- most don't and the POSIX standard even invorces not to use leap seconds).
The module supports two calendars, the Gregorian (default and needed for most conversions) and the Julian, which is handy for dates prior to the year 1582 when the calendar was revised by Pope Gregory XIII.
Construction of Julian dates can be done using either the
JulianDateTime()
constructor or indirect through the
.Julian()
method of DateTime instances. To check which
calendar a DateTime instance uses, query the calendar
instance attribute.
Note that Julian dates output the Julian date through the instances date attributes and broken down values. Not all conversions are available on instances using the Julian calendar. Even though in the Julian calendar days start at noon (12:00:00.0), mxDateTime will use the Gregorian convention of using the date for the period from 00:00:00.0 to 23:59:59.99 of that day. (This may change in future versions, though.)
Both calendars use mathematical models as basis -- they do not account
for the many inaccuracies that occurred during their usage history. For
this reason, the .absdate
values should be interpreted with
care, esp. for dates using the Julian calendar. As a result of the
mathematical models, the Epochs in the calendars differ by a few days.
This was needed in order to synchronize the calendars in the switching
year 1582 (I'm still not 100% sure whether this is correct or not:
JulianDate(1,1,1) lies two days before Date(1,1,1)).
For the purpose of converting the stored values to Unix ticks (number of seconds since the Unix epoch; the C lib also uses this representation) we assume that the values are given in local time. This assumption had to be made because the C lib provides no standard way to convert a broken down date/time value in any other way into a ticks value.
Conversions to COM dates and tuples are done without any assumption on the time zone. The raw values are used.
Conversion from other formats to DateTime instances is always done by first calculating the corresponding absolute time and date values (which are also used as basis for calculations).
The internal representation of date/times behaves much like floats do
in Python, i.e. rounding errors can occur when doing calculations.
There is a special compare function included (cmp()
) in the
package that allows you to compare two date/time values using a given
accuracy, e.g. cmp(date1,date2,0.5)
will allow 12:00:00.5
and 12:00:01.0 to compare equal.
Special care has been taken to prevent these rounding errors from occurring for COM dates. If you create a DateTime instance using a COM date, then the value returned by the .COMDate() method is guaranteed to be exactly the same as the one used for creation. The same is true for creation using absolute time and absolute date and broken down values.
One other thing to keep in mind when working with DateTime and DateTimeDelta instances is that they are immutable (like tuples). Once an instance is created you can not change its value. Instead, you will have to create a new instance with modified values. The advantage of having immutable objects is that they can be used as dictionary keys.
UTC (Universal Time Code) and GMT (Greenich Mean Time) are two names for more or less the same thing: they both refer to the international universal time which is used throughout the world to coordinate events in time regardeless of time zone, day light savings time or other local time alterations. See the Calendar FAQ for more infos.
The mx.DateTime package uses these two names interchangeably. Sometimes API only refer to one name for simplicity. The name preference (GMT or UTC) is often chosen according to common usage.
DateTime and DateTimeDelta instances can be compared and hashed, making them compatible to the dictionary implementation Python uses (they can be used as keys). The copy protocol, simple arithmetic and pickleing are also supported (ee below for details).
DateTime and DateTimeDelta instances know how to output themselves as
ISO8601-strings. The format is very simple: YYYY-MM-DD HH:MM:SS.ss for
DateTime instances and [-][DD:]HH:MM:SS.ss for DateTimeDelta instances
(the DD-part (days) is only given if the absolute delta value is greater
than 24 hours). Customized conversion to strings can be done using the
strftime
-methods or the included submodules.
String parsing is supported through the strptime()
constructor which implements a very strict parsing scheme and the
included submodules (e.g. ISO and ARPA), which allow a little more freedom.
Comparing the types to time-module based routines is not really possible, since the used strategies differ. You can compare them to tuple-based date/time classes though: DateTime[Delta] are much faster on creation, use less storage and are faster to convert to the supported other formats than any equivalent tuple-based implementation written in Python.
Creation of time-module values using time.mktime() is much slower than doing the same thing with DateTime(). The same holds for the reverse conversion (using time.localtime()).
The storage size of ticks (floats, which the time module uses) is about 1/3 of the size a DateTime instance uses. This is mainly due to the fact that DateTime instances cache the broken down values for fast access.
To summarize: DateTime[Delta] are faster, but also use more memory than traditional time-module based techniques.
Here is a small list of links I used as starting points to find some of the date/time related information included in this package:
The package provides three data structures for working with date and time values. These are:
Several constructors are available in the module DateTime. All of these return DateTime instances using the Gregorian calendar except for JulienDateTime() which returns instances using the Julian calendar.
DateTime(year,month=1,day=1,hour=0,minute=0,second=0.0)
Assumes that the date is given in the Gregorian calendar (which it the one used in many countries today).
The entry for day
can be negative to indicate days
counted in reverse order, that is the last day becomes -1, the day
before that -2, and so on, e.g. DateTime(1997,12,-2)
gives the 30.12.1997 (this is useful especially for months).
Note that although the above makes it look like this function can handle keywords, it currently cannot.
GregorianDateTime(year,month=1,day=1,hour=0,minute=0,second=0.0)
JulianDateTime(year,month=1,day=1,
hour=0,minute=0,second=0.0)
The instance will use the Julian calendar for all date related methods and attributes.
Same comments as for DateTime().
JulianDate(year,month=1,day=1)
Timestamp(year,month,day,hour=0,minute=0,second=0.0)
Date(year,month,day)
GregorianDate(year,month,day)
mktime(tuple)
Note that the tuple elements dow
,doy
and dst
are not used in any way.
You should only use this contructor for porting applications from time module based functions to DateTime.
DateTimeFromAbsDateTime(absdate,abstime)
This interface can be used by classes written in Python which implement other calendars than the Gregorian, for example.
localtime(ticks)
The instance will hold the associated local time.
now()
gmt()
utc()
gmtime(ticks=time.time())
The instance will hold the associated UTC time. If ticks is not
given, the current time is used. gmticks()
is the
inverse of this function.
utctime(ticks=time.time())
gmtime()
.today(hour=0,minute=0,second=0.0)
DateTimeFromAbsDays(days)
DateTimeFromCOMDate(comdate)
This is used in the COM mechanism I'm told and repesents the date/time difference between 30.12.1899 and the represented date/time, with time being encoded as fraction of a whole day, thus 0.5 corresponds to 12:00:00.00.
Special care is taken that the resulting instance's method
COMDate()
returns exactly the same value as the one
used for constructing it -- even though the internal representation
is more accurate.
strptime(string,format_string[,default])
If default
is given (must be a DateTime instance),
it's entries are used as default values. Otherwise, 0001-01-01
00:00:00.00 is used. An Error
is raised if the
underlying C parsing function strptime()
fails.
Portability note: default
does not work on Solaris.
You will have to reassemble the correct DateTime instance yourself
(knowing which parts the strptime()
function parsed)
if you intend to use default values. Solaris sets the defaults to
1900-01-01 00:00:00.00 and then overwrites them with the parsed
values.
Note: Since this C API is relatively new, you may not have
access to this constructor on your platform. For further
information on the format, please refer to the Unix manpage (it is
very similar to that of strftime()
which is documented
in the Python library reference for the time module).
DateTimeFromMJD(mjd)
Since MJD values are given in UTC, the instance will represent UTC. See the Calendar FAQ for details.
Note: Usage of MJD notation is discouraged by the International Astronomical Union (IAU). Use JDN instead.
DateTimeFromTJD(tjd,tjd_myriad=current_myriad)
tjd_myriad will default to the tjd_myriad current at package import time, if not given. It refers to the truncated part of the TDJ number. The current myriad (245) started on 1995-10-10 00:00:00.00 UTC and will last until 2023-02-24 23:59:59.99 UTC.
Since TJD values are always given in UTC, the instance will represent UTC.
Please note that usage of TJD is depreciated because of the information loss involved with truncating data: use MJD or JDN instead.
DateTimeFromJDN(jdn)
Since JDN values are given in UTC, the instance will represent UTC. See the Calendar FAQ for details.
DateTimeFrom(*args,**kws)
This constructor can parse strings, handle numeric arguments and
knows about the keywords
year,month,day,hour,minute,second
.
It uses type inference to find out how to interpret the arguments and makes use of the Parser module.
TimestampFrom(*args,**kws)
DateFromTicks(ticks)
TimestampFromTicks(ticks)
A DateTime instance has the following methods. Note that the calendar setting of the instance effects all methods relying on date values.
tuple()
DST is set assuming local time. It can also be -1, meaning that the information is not available.
absvalues()
(absdate,
abstime)
.ticks(offset=0.0,dst=-1)
The conversion routine assumes that the stored date/time value is given in local time.
The given value for DST is used by the conversion (0 = DST off, 1 = DST on, -1 = unkown) and offset is subtracted from the resulting value.
The method raises a RangeError
exception if the
objects value does not fit into the system's ticks range.
Note: On some platforms the C lib's mktime() function
that this method uses does not allow setting DST to an arbitrary
value. The module checks for this and raises a
SystemError
in case setting DST to 0 or 1 does not
result in valid results.
gmticks(offset=0.0)
The conversion routine assumes that the stored date/time value is given in UTC time. offset is subtracted from the resulting value.
The method raises an RangeError
exception if the
objects value does not fit into the system's ticks range.
gmtoffset()
The UTC offset is defined as: local time - UTC time, e.g. it is negative in the US and positive in eastern Europe and Asia.
gmtime()
localtime()
COMDate()
strftime(format_string="%c")
This is the same function as the one in the time module. For further information please refer to the manpage or the Python reference manual.
Note: strftime() and strptime() try to be the inverse of each other. The output from strftime() given to strptime() together with the format string passed to strftime() will in most cases give you a DateTime instance referring to the same date and time.
Time zone information is not available. Use the instance
variable tz
instead.
Format(format_string="%c")
Gregorian()
Julian()
To make life easier, the instances also provide a more direct interface to their stored values (these are all read-only). Note that the calendar setting of the instance effects all attributes referring to date values.
hour, minute,
second
Note that in a future release, leap seconds may also be considered and thus second has a range of 0-60.
year, month, day
date, time
time
dst
The value is calculated assuming that the stored value is local time.
tz
day_of_week
day_of_year
days_in_month
iso_week
Note: isoday 1 is Monday !
is_leapyear
yearoffset
absdays
The value is calculated using a 86400.0 seconds/day basis and does not account for leap seconds. This value is handy if you need the date/time value stored in one number. By using a Python float, which is mapped to a C double internally, the accuracy should give a fairly large range of valid dates.
absdate
abstime
mjd
It is assumed for the calculation that the stored value is given in UTC. Fractions indicate parts of the full day, e.g. 0.5 referrs to noon on the 17 November 1858.
See the Calendar FAQ or Systems of Time for details.
Note: Usage of MJD notation is discouraged by the International Astronomical Union (IAU). Use JDN instead.
tjd
TJDs are calculated using 00:00 UTC on 1 January 4713 BC as
epoch, counting the number of days as for the Julian Day Numbers
and then omitting the myriad part (div 10000) from it. As a result
the TJD will always have at most 4 digits. The divisor is available
through the tjd_myriad
attribute.
It is assumed for the calculation that the stored value is given in UTC. Fractions indicate parts of the full day.
Some people claim that this term is also known under the name Star Date. Remember ? ... "Captain's Log, Star Date 8143.65". I wonder which myriad these dates refer to.
tjd_myriad
jdn
It is assumed for the calculation that the stored value is given in UTC. Fractions indicate parts of the full day, e.g. JDN 2451170.17393 referrs to Tue, 22 Dec 1998 16:10:27 UTC.
See the Calendar FAQ for details.
calendar
Julian
or Gregorian
.Several constructors are available:
DateTimeDelta(days[,hours=0.0,minutes=0.0,seconds=0.0])
The internal value is calculated using the formula
days*86400.0 + hours*3600.0 + minutes*60.0 + seconds
.
Keep this in mind when passing negative values to the
constructor.
TimeDelta(hour=0.0,minute=0.0,second=0.0)
The internal value is calculated using the formula hours *
3600 + minutes * 60 + seconds
. Keep this in mind when
passing negative values to the constructor.
The constructor allows usage of keywords, e.g. Time(seconds=1.5) works.
Time(hour,minute=0.0,second=0.0)
DateTimeDeltaFromSeconds(seconds)
DateTimeDeltaFromDays(days)
The internal value is calculated using a 86400.0 seconds/day basis.
DateTimeDeltaFrom(*args,**kws)
This constructor can parser strings, handle numeric arguments
and knows about the keywords
year,month,day,hour,minute,second
.
It uses type inference to find out how to interpret the arguments and makes use of the Parser module.
TimeDeltaFrom(*args,**kws)
The interface is the same as for DateTimeDeltaFrom() with the exception that numeric arguments are interpreted without day part as for the TimeDelta() constructor.
TimeFrom(*args,**kws)
TimeFromTicks(ticks)
A DateTimeDelta instance has the following methods:
absvalues()
(absdays, absseconds)
tuple.
The absseconds
part is normalized in such way that
it is always smaller than 86400.0. Both values are signed.
tuple()
The values are the same those returned by the attributes of the same name.
strftime(format_string)
This is the same function as the one in the time module. For further information please refer to the manpage or the Python reference manual.
Since some descriptors don't make any sense for date/time deltas
these return undefined values. Only the fields hour, minute,
seconds and day are set according to the objects value (the
descriptors %d %H %M %S %I %p %X
work as
expected).
Negative values show up positive -- you'll have to provide your
own way of showing the sign (the seconds
instance
variable is signed).
To make life easier, the instances also provide a more direct interface to their stored values (these are all read-only):
day, hour, minute,
second
days, hours, minutes,
seconds
TimeDelta(12,00,00).days == 0.5
.These constructors are avaiable:
RelativeDateTime(years=0,months=0,days=0,
year=0,month=0,day=0, hours=0,minutes=0,seconds=0,
hour=None,minute=None,second=None,
weekday=None,weeks=0)
The constructor handles keywords, so you'll only have to give those parameters which should be changed when you add the relative to an absolute DateTime instance.
Do not pass arguments directly, always use the keyword notation !
Absolute values passed to the constructor will override delta
values of the same type. Note that weeks
is added to
days
so that the instances days values will be
days + 7*weeks
.
weekday must be a 2-tuple if given: (day_of_week, nth). The value is applied after all other calculations have been done resulting in moving the date to the nth weekday in the month that the date points to. Negative values for nth result in the ordering of the month's weekdays to be reversed, e.g. (Monday,-1) will move to the last Monday in that month. Setting nth to 0 results in the date's week to be used as reference, e.g (Tuesday,0) will move to Tuesday that week (which could lie in a different month). weekday is considered an absolute value, so multiplication or negation will not touch it.
RelativeDate(years=0,months=0,days=0,
year=0,month=0,day=0, weeks=0)
RelativeDateTimeFrom(*args,**kws)
This constructor can parse strings, handle numeric arguments and
knows about the same keywords as the
RelativeDateTime()
constructor.
It uses type inference to find out how to interpret the arguments and makes use of the Parser module.
RelativeDateFrom(*args,**kws)
RelativeDateTime()
.
Note that in future versions this constructor may explicitly ignore the time parts.
RelativeTimeFrom(*args,**kws)
RelativeDateTime()
.
Note that in future versions this constructor may explicitly ignore the date parts.
RelativeDateTimeDiff(date1,date2)
date2 + RelativeDateDiff(date1,date2) == date1
for all dates date1 and date2.
Note that due to the algorithm used by this function, not the whole range of DateTime instances is supported; there could also be a loss of precision
This constructor is still experimental. It is not fully debugged yet.
RelativeDateDiff(date1,date2)
RelativeDateTimeDiff()
.Age(date1,date2)
RelativeDateTimeDiff()
.RelativeDateTime objects store the given settings (plural nouns meaning deltas, singular nouns absolute values) and apply them when used in calculations. Delta values will have the effect of changing the corresponding attribute of the involved absolute DateTime object accordingly, while absolute values overwrite the DateTime objects attribute value with a new one. The effective value of the object is thus determined at calculation time and depends on the context it is used in.
Adding and subtracting RelativeDateTime instances is supported with the following rules: deltas will be added together and right side absolute values override left side ones.
Multiplying RelativeDateTime instances with numbers will yield instances with scaled deltas (absolute values are not effected).
Adding RelativeDateTime instances to and subtracting
RelativeDateTime instances from DateTime instances will return DateTime
instances with the appropriate calculations applied, e.g. to get a
DateTime instance for the first of next month, you'd call now() +
RelativeDateTime(months=+1, day=01)
.
Note that dates like Date(1999,1,30) +
RelativeDateTime(months=+1)
are not supported. The package
currently interprets these constructions as Date(1999,2,1) +
30
, thus giving the 1999-03-02 which may not be what you'd
expect.
When providing both delta and absolute values for an entity the absolute value is set first and then the delta applied to the outcome.
In tests, RelativeDateTime instances are false in case they do not define any date or time alterations and true otherwise.
A few examples will probably make the intended usage clearer:
>>> from mx.DateTime import * >>> print now() 1998-08-11 16:46:02.20 # add one month >>> print now() + RelativeDateTime(months=+1) 1998-09-11 16:46:24.59 # add ten months >>> print now() + RelativeDateTime(months=+10) 1999-06-11 16:47:03.07 # ten days from now >>> print now() + RelativeDateTime(days=+10) 1998-08-21 16:47:10.58 # first of next month >>> print now() + RelativeDateTime(months=+1,day=1) 1998-09-01 16:47:25.15 # first of this month, same time >>> print now() + RelativeDateTime(day=1) 1998-08-01 16:47:35.48 # first of this month at midnight >>> print now() + RelativeDateTime(day=1,hour=0,minute=0,second=0) 1998-08-01 00:00:00.00 # next year, first of previous month, same time >>> print now() + RelativeDateTime(years=+1,months=-1,day=1) 1999-07-01 16:48:31.87 # Last Sunday in October 1998 >>> print Date(1998) + RelativeDateTime(weekday=(Sunday,-1),month=10) 1998-10-25 00:00:00.00 # The result in ARPA notation: >>> print ARPA.str(Date(1998) + RelativeDateTime(weekday=(Sunday,-1),month=10)) Sun, 25 Oct 1998 00:00:00 +0200 # Generic way of specifying "next tuesday": >>> NextTuesday = RelativeDateTime(days=+6,weekday=(Tuesday,0))
RelativeDateTime instances currently don't have any instance methods.
The following attributes are exposed, but should not be written to directly (the objects are currently implemented in Python, but that could change in future releases).
year, month, day, hour, minute,
second, weekday
years, months, days, hours, minutes,
seconds
The given values are only defined in case they were set at instance creation time.
The package defines these constants:
oneWeek, oneDay, oneHour, oneMinute,
oneSecond
Error, RangeError
DateTimeType,
DateTimeDeltaType
Epoch
mxDateTimeAPI
MaxDateTime, MinDateTime,
MaxDateTimeDelta, MinDateTimeDelta
Monday, Tuesday, Wednesday, Thursday,
Friday, Saturday, Sunday
Weekday
January, February, March, April, May,
June, July, August, September, October, November,
December
Month
Gregorian, Julian
calendar
attribute of
DateTime objects. Currently these are the strings 'Gregorian' and
'Julian', but this mught change in future versions: always use these
objects for checking the calendar type.POSIX
If the system's time package uses POSIX time_t values (without counting leap seconds), it is set to 1. In case the system's ticks values include leap seconds and thus correctly represent the term "seconds since the epoch", the constant is set to 0.
The package defines these additional functions:
cmp(obj1,obj2,accuracy=0.0)
If accuracy is given, then equality will result in case the absolute difference between the two values is less than or equal to accuracy.
gmticks(datetime)
DEPRECIATED: Use the .gmticks() method instead.
utcticks(datetime)
gmticks()
.
DEPRECIATED: Use the .gmticks() method instead.
tz_offset(datetime)
DEPRECIATED: Use the .gmtoffset() method instead.
gm2local(datetime)
utc2local(datetime)
gm2local()
.local2gm(datetime)
local2utc(datetime)
local2gm()
.If you find any bugs, please report them to me so that I can fix them for the next release.
The three objects DateTime, DateTimeDelta and RelativeDateTime can be used to do simple date/time arithmetic. Addition and subtraction are supported and result in the expected results. In addition to handling arithmetic using only the two types, mixed arithmetic with numbers is also understood to a certain extent:
Argument 1 | Argument 2 | Result |
DateTime object v | DateTime object w |
|
DateTime object v | A number w |
|
DateTime object v | DateTimeDelta object w |
|
DateTime object v | RelativeDateTime object w |
|
RelativeDateTime object v | A number w |
|
DateTimeDelta object v | DateTime object w |
No operations defined. |
DateTimeDelta object v | A number w |
|
DateTimeDelta object v | DateTimeDelta object w |
|
Notes:
Operation and argument order are important because of the different ways arguments are coerced. Use parenthesis to make your intent clear or you will get unwanted results.
Due to a flaw in the C interface for coercion in the interpreter, it
is not possible to do proper handling of mixed type arithmetic for types
which don't coerce to a common type (without creating temporary objets
all the time). The module uses a workaround, but unfortunately the order
of the operands is lost along the way. Under normal circumstances you
won't notice this defect, but be warned since e.g. oneDay - 1 == 1
- oneDay
, yet oneDay - oneSecond != oneSecond -
oneDay
.
Comparing RelativeDateTime instances does not work.
Adding/Subtracting DateTime instances causes the result to inherit the calendar of the left operand.
The package provides additional features in form of the following submodules. All submodules are imported on request only.
The ISO submodule is intended to provide interfacing functions to ISO 8601 date and time representations (the ISO document is also available as PDF file). The most common format is:
YYYY-MM-DD HH:MM:SS[+-HH:MM]
Note: timezone information (+-HH:MM) is only
interpreted by the ParseDateTimeUTC()
constructor. All
others ignore the given offset and store the time value as-is.
You can access the functions and symbols defined in the submodule
through DateTime.ISO
-- it is imported on demand.
The module defines these constructors and functions:
WeekTime(year,isoweek=1,isoday=1,hour=0,minute=0,second=0.0)
iso_week
provides an inverse to this function.Week(year,isoweek,isoday=1)
WeekTime()
.DateTime(), Time(),
TimeDelta()
ParseDateTime(isostring)
A time part is optional and must be delimited from the date by a space or 'T'. Year must be given, month and day default to 1. For the time part, hour and minute must be given, while second defaults to 0.
Time zone information is parsed, but not evaluated.
ParseDateTimeGMT(isostring)
Note: UTC is practically the same as GMT, the old time standard.
ParseDateTimeUTC(isostring)
Note: UTC is practically the same as GMT, the old time standard.
ParseDate(isostring)
ParseWeek(isostring)
ParseWeekTime(isostring)
ParseTime(isostring)
ParseTimeDelta(isostring)
ParseAny(isostring)
str(datetime)
strGMT(datetime)
strUTC(datetime)
The parsing routines strip surrounding whitespace from the strings,
but are strict in what they want to see. Additional characters are not
allowed and will cause a ValueError
to be raised.
Timezone information may be included, but will not be interpreted unless explicitly stated.
The parsing routines also understand the ISO 8601 date/time formats without seperating dashes and colons, e.g. '19980102T142020', and mixtures of both notations.
DateTime and DateTimeDelta instances use a slightly enhanced ISO format for string represenation:
DateTime instances are converted to 'YYYY-MM-DD
HH:MM:SS.ss'
where the last ss indicate hundredths of a second
(ISO doesn't define how to display these).
DateTimeDelta instances use '[-][DD:]HH:MM:SS.ss'
as
format, where DD: is only shown for deltas spanning more than one day
(24 hours). The ss part has the same meaning as for DateTime instances:
hundredths of a second. A minus is shown for negative deltas. ISO does
not define relative time deltas, but the time representation is allowed
to be 'HH:MM:SS'.
The ARPA submodule is intended to provide interfacing functions to ARPA date representations. These are used throughout the Internet for passing around mails, postings, etc. The format is very simple:
[Day, ]DD Mon YYYY HH:MM[:SS] ZONE
where ZONE can be one of these: MDT, O, EDT, X, Y, CDT, UT, AST, GMT, PST, Z, V, CST, ADT, I, W, T, U, R, S, P, Q, N, EST, L, M, MST, K, H, E, F, G, D, PDT, B, C, UTC, A (the single letter ones being military time zones). Use of explicit time zone names other than UTC and GMT is depreciated, though. The better alternative is providing the offset from UTC being in effect at the given local time: +-HHMM (this is the offset you have to subtract from the given time in order to get UTC).
You can access the functions and symbols defined in the submodule
through DateTime.ARPA
-- it is imported on demand.
The module defines these constructors and functions:
ParseDate(arpastring)
ParseDateTime(arpastring)
ParseDateTimeGMT(arpastring)
ParseDateTimeUTC(arpastring)
str(datetime,tz=DateTime.tz_offset(datetime))
strGMT(datetime)
Note: Most Internet software expects to find 'GMT' and not 'UTC'.
strUTC(datetime)
The parsing routines strip surrounding whitespace from the strings. Additional characters are allowed (because some mail apps add extra information to the date header).
The Feasts submodule is intended to provide easy-to-use constructors for common moveable christian feasts that can be deduced from the date of Easter Sunday. The algorithm used to calculate Easter Sunday is based on the one presented in the Calendar FAQ by Claus Tondering, which in return is based on the algorithm of Oudin (1940) as quoted in "Explanatory Supplement to the Astronomical Almanac", P. Kenneth Seidelmann, editor.
The module defines these constructors and functions:
EasterSunday(year),
Ostersonntag(year), DimanchePaques(year)
The other feasts are deduced from this date and all use the same interface. The module defines these sets of constructors the return the corresponding DateTime instance for midnight of the implied day:
CarnivalMonday(year),
Rosenmontag(year)
MardiGras(year)
AshWednesday(year),
Aschermittwoch(year), MercrediCendres(year)
PalmSunday(year), Palmsonntag(year),
DimancheRameaux(year)
EasterFriday(year), GoodFriday(year),
Karfreitag(year), VendrediSaint(year)
EasterMonday(year), Ostermontag(year),
LundiPaques(year)
Ascension(year),
Himmelfahrt(year)
Pentecost(year), WhitSunday(year),
Pfingstsonntag(year), DimanchePentecote(year)
WhitMonday(year), Pfingstmontag(year),
LundiPentecote(year)
TrinitySunday(year)
CorpusChristi(year),
Fronleichnam(year), FeteDieu(year)
For further reading, have a look at the Ecclesiastical Calendar.
The Parser submodule provides constructors for DateTime[Delta] values taking a string as input. The module knows about quite a few different date and time formats and will try very hard to come up with a reasonable output given a valid input.
Date/time parsing is a very diffcult field of endeavour and that's why the exact definition of what the module can parse and what not is defined by implementation rather than a rigorous set of formats.
Note: The module still has experimental status. It is constantly being improved. This can also mean that some formats might be dropped again in favour of more general parsing regexps.
Things the module will recognize are the outputs of ISO, ARPA and the .strftime() method. Currently only English, German, French, Spanish and Portuguese month and day names are supported.
The module defines these constructors and functions:
DateTimeFromString(text)
Inserts default values for missing parts. Default is today for the date part and 0:00:00 for the time part.
DateFromString(text)
Inserts default values for missing parts. Default is today for the date parts.
DateTimeDeltaFromString(text)
TimeFromString(text)
DateTimeDeltaFromString()
.TimeDeltaFromString(text)
DateTimeDeltaFromString()
.RelativeDateTimeFromString(text)
Defaults to wildcards (None or 0) for parts or values which are not included in the textual representation or cannot be parsed.
The format used in text must adhere to the following ISO-style syntax:
[YYYY-MM-DD] [HH:MM[:SS]]
with the usual meanings.
Values which should not be altered may be replaced with '*', '%', '?' or any combination of letters, e.g. 'YYYY'. Relative settings must be enclosed in parenthesis if given and should include a sign, e.g. '(+0001)' for the year part. All other settings are interpreted as absolute values.
Date and time parts are both optional as a whole. Seconds in the time part are optional too. Everything else (including the hyphens and colons) is mandatory.
RelativeDateFromString(text)
RelativeDateTimeFromString(text)
except that
only the date part of text
is taken into account.RelativeTimeFromString(text)
RelativeDateTimeFromString(text)
except that
only the time part of text
is taken into account.The parsing routines ignore surrounding whitespace. Additional characters and symbols are ignored.
The NIST submodule is useful when you are connected to the Internet and want access to the accurate world standard time, the NIST atomic clocks.
The module accesses a special service provided by NIST and other partner organizations, which allows anyone with Internet access to query the current UTC time. Of the three provided protocols, daytime, time and ntp, I chose the daytime protocol because of its simplicity and robustness.
Since access through the Internet can be slow, the module also provides a way to calibrate itself and then use the computer's clock without the need to go accross the Internet for every call to the current time constructors. The defaults are set in such a way that calibration occurrs without further interaction on part of the programmer. See the code for details.
The module defines these constructors and functions:
utctime(nist_lookup=0)
Works must like the standard DateTime.now(), but tries to use the NIST time servers as time reference -- not only the computer's builtin clock.
Note that the contructor may take several seconds to return in
case no calibration was performed (see calibrate()
).
With calibration information, the computer's clock is used as
reference and the offset to NIST time is compensated by the
contructor.
In case the NIST service is not reachable, the contructor falls back to using either the calibrated (preferred) or uncalibrated computer's clock.
Setting nist_lookup
to false (default) will cause
the contructor to prefer the calibrated CPU time over the expensive
Internet queries. If it is true, then Internet lookups are always
tried first before using the local clock. A value of 2 will cause
an Error
(see below) to be raised in case the NIST
servers are not reachable.
The constructor will use the received NIST information for auto calibration.
gmtime()
localtime(nist_lookup=0)
Same notes as for utctime().
now()
time_offset(iterations=10)
If you add the return value to the return value of
time.time()
, you will have a pretty accurate time base
to use in your applications.
Note that due to network latencies and the socket overhead, the calculated offset will include a small hopefully constant error.
iterations sets the number of queries done to the NIST time base. The average is taken over all queries.
calibrate(iterations=20)
Uses the NIST time service as time base. The computer must have an active internet connection to be able to do calibration using the NIST servers.
iterations sets the number of round to be done.
Note: This function takes a few seconds to complete. For long running processes you should recalibrate every now and then because the system clock tends to drift (usually more than the hardware clock in the computer).
set_calibration(calibration_offset)
This also sets the global calibrated
to 1 and
disables auto calibration.
reset_auto_calibration()
This does not clear possibly available calibration information, so the two time APIs will continue to revert to the calibrated clock in case no connection to the NIST servers is possible.
Auto calibration is on per default when the module is imported.
enable_auto_calibration()
reset_auto_calibration()
.disable_auto_calibration()
The package defines these constants:
Error
calibration
calibrated
calibration
contains valid
information.calibrating
There's an example called AtomicClock.py in the Examples/ subdir which demonstrates how easy it is to turn your PC into a fairly accurate time piece.
For even better time accuracy, one would have to use NTP...
For an example of how to use the two types to develop other date/time classes (e.g. ones that support time zones or other calendars), see the included ODMG module. It defines types similar to those of the ODMG standard.
Here is a little countdown script:
#!/usr/local/bin/python -u """ Y2000.py - The year 2000 countdown. """ from mx.DateTime import * from time import sleep while 1: d = Date(2000,1,1) - now() print 'Y2000... time left: %2i days %2i hours ' '%2i minutes %2i seconds\r' % \ (d.day,d.hour,d.minute,d.second), sleep(1)
This snippet demonstrates some of the possible string representations for DateTime instances:
>>> from mx.DateTime import * >>> ISO.str(now()) '1998-06-14 11:08:27+0200' >>> ARPA.str(now()) 'Sun, 14 Jun 1998 11:08:33 +0200' >>> now().strftime() 'Sun Jun 14 11:08:51 1998' >>> str(now()) '1998-06-14 11:09:17.82'
More examples are available in the Examples subdirectory of the package.
#include "mxDateTime.h" ... PyObject *v; /* Import the mxDateTime module */ if (mxDateTime_ImportModuleAndAPI()) goto onError; /* Access functions from the exported C API through mxDateTime */ v = mxDateTime.DateTime_FromAbsDateAndTime(729376, 49272.0); if (!v) goto onError; /* Type checking */ if (mxDateTime_Check(v)) printf("Works.\n"); Py_DECREF(v); ...
[DateTime] Doc/ [Examples] AtomicClock.py CommandLine.py Y2000.py alarm.py lifespan.py [mxDateTime] test.py ARPA.py DateTime.py Feasts.py ISO.py LazyModule.py Locale.py NIST.py ODMG.py Parser.py Timezone.py timegm.py
Names with trailing / are plain directories, ones with []-brackets are Python packages, ones with ".py" extension are Python submodules.
The package imports all symbols from the extension module and also registers the types so that they become compatible to the pickle and copy mechanisms in Python.
eGenix.com is providing commercial support for this package. If you are interested in receiving information about this service please see the eGenix.com Support Conditions.
© 1997-2000, Copyright by Marc-André Lemburg; All Rights Reserved. mailto: mal@lemburg.com
© 2000-2001, Copyright by eGenix.com Software GmbH, Langenfeld, Germany; All Rights Reserved. mailto: info@egenix.com
This software is covered by the eGenix.com Public License Agreement. The text of the license is also included as file "LICENSE" in the package's main directory.
By downloading, copying, installing or otherwise using the software, you agree to be bound by the terms and conditions of the eGenix.com Public License Agreement.
Things that still need to be done:
Things that changed from 2.0.2 to 2.0.3:
Things that changed from 2.0.0 to 2.0.2:
Things that changed from 1.3.0 to 2.0.0:
Things that changed from 1.2.0 to 1.3.0:
The exported C API DateTime_AsTmStruct() will also reflect this change, since it uses the same conversion routines.
Things that changed from 1.1.0 to 1.2.0:
XXX Note that the support is still experimental and still contains some bugs that need fixing... e.g. DateTimeFromJDN(0).jdn == 1.
Note that the function no longer does rounding of the seconds part: you get the full precision returned by the time.time() function (which is system dependent).
If you have the timegm() API, enable it in Setup -- it's more accurate and probably faster too.
Things that changed from 1.0.1 to 1.1.0:
Things that changed from 1.0.0 to 1.0.1:
Things that changed from 0.9.2 to 1.0.0:
This change was needed since there is no way in Python to make sure that C extensions are really only imported once: importing mxDateTime directly and indirectly through the DateTime package lead to two versions of the extensions being loaded. While this is not too serious at first sight (it may even be useful in some cases) it turns out to be a significant problem because the objects declared by the two versions are seen as being of different type (type checks in Python are done via comparing the address of type objects).
As a result, you no longer have to run 'make install' to install the C extension.
Things that changed from 0.9.1 to 0.9.2:
Things that changed from 0.9.0 to 0.9.1:
Older history entries can be found in a seperate list.