Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Mail Systems
Eclipse Documentation

How To Guides
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Problem Solutions




Chapter 32. Dates and Times: the time and datetime Modules

When processing dates and times, we have a number of problems. Most of these problems stem from the irregularities and special cases in the units we use to measure time. We generally measure time in a number of compatible as well as incompatible units. For example, weeks, days, hours, minutes and seconds are generally compatible, with the exception of leap-second handling. Months, and years, however are incompatible with days and require sophisticated conversion.

Problems which mix month-oriented dates and numbers of days are particularly difficult. The number of days between two dates, or a date which is 90 days in the future are notoriously difficult to compute correctly.

We need to represent a point in time, a date, a time of day or a date-time stamp. We need to be able to do arithmetic on this point in time. And, we need to represent this point in time as a properly-punctuated string.

The time module contains a number of portable functions needed to format times and dates. The datetime module builds on this to provide a representation that is slightly more convenient for some things. We'll look at the definition of a moment in time in the section called “Semantics: What is Time?”.

Semantics: What is Time?

The Gregorian calendar is extremely complex. Most of that complexity stems from trying to impose a fixed "year" on the wobbly, irregular orbit of our planet. There are several concesssions required to impose a calendar year with integer numbers of days that will match the astronomial year of approximately 365.2425 days. The Gregorian calendar's concession is the periodic addition of a leap day to approximate this fractional day. The error is just under .25, so one leap day each four years gets close to the actual duration of the year.

Clearly, we have several systems of units available to us for representing a point in time.

  • Seconds are the least common denominator. We can easily derive hours and minutes from seconds. There are 24×60×60 = 86,400 seconds in a day. Astronomers will periodically add a leap second, so this is not absolutely true. We can use seconds as a simple representation for a point in time. We can pick some epoch and represent any other point in time as the number of seconds after the epoch. This makes arithmetic very simple. However, it's hard to read; what month contains second number 1,190,805,137?

  • Days are another common denominator in the calendar. There are seven days in a week, and (usually) 86,400 seconds in day, so those conversions are simple. We can pick some epoch and represent any other point in time as the number of days after the epoch. This also makes arithmetic very simple. However, it's hard to read; what month contains day number 732,945?

  • Months are the real root cause of our problems. If we work with the conventional date triple of year, month, and day, we can't compute intervals between dates very well at all. We can't locate a date 90 days in the future without a rather complex algorithm.

We also to have acknowledge the subtlety of local time and the potential differences between local standard time and local daylight time (or summer time). Since the clock shifts, some time numbers (1:30 AM, for example) will appear to repeat, this can require the timezone hint to decode the time number.

The more general solution is to do all work in UTC. Input is accepted and displayed in local time for the convenience of users. This has the advantage of being timezone neutral, and it makes time values monotonically increasing with no confusing repeats of a given time of day during the hour in which the clock is shifted.

The time Solution. The time module uses two different representations for a point in time, and provides numerous functions to help us convert back and forth between the two representations.

  • A float seconds number. This is the UNIX internal representation for time. (The number is seconds past an epoch; the epoch happens to January 1st, 1970.) In this representation, a duration between points in time is also a float number.

  • A struct_time object. This object has nine attributes for representing a point in time as a Gregorian calendar date and time. We'll look at this structure in detail below. In this representation, there is no representation for the duration between points in time. You need to convert back and forth between struct_time and seconds representations.

The datetime Solution. The datetime module contain all of the objects and methods required to correctly handle the sometimes obscure rules for the Gregorian calendar. Additionally, it is possible to use date information in the datetime to usefully conver among the world's calendars. For details on conversions between calendar systems, see Calendrical Calculations [Deshowitz97].

The datetime module has just one representation for a point in time. It assigns an ordinal number to each day. The numbers are based on an epochal date, and algorithms to derive the year, month and day information for that ordinal day number. Similarly, this class provides algorithms to convert a calendar date to an ordinal day number. (Note: the Gregorian calendar was not defined until 1582, all dates before the official adoption are termed proleptic. Further, the calendar was adopted at different times in different countries.)

There are four classes in this module that help us handle dates and times in a uniform and correct manner. We'll skip the more advanced topic of the datetime.tzinfo class.

  • datetime.timeAn instance of datetime.time has four attributes: hour, minute, second and microsecond. Additionally, it can also carry an instance of tzinfo which describes the time zone for this time.

  • datetime.dateAn instance of has three attributes: year, month and day. There are a number of methods for creating datetime.dates, and converting datetime.dates to various other forms, like floating-point timestamps, 9-tuples for use with the time module, and ordinal day numbers.

  • datetime.datetimeAn instance of datetime.datetime combines and datetime.time. There are a number of methods for creating datetime.datetimes, and converting datetime.datetimes to various other forms, like floating-point timestamps, 9-tuples for use with the time module, and ordinal day numbers.

  • datetime.timedeltaA datetime.timedelta is the duration between two dates, times or datetimes. It has a value in days, seconds and microseconds. These can be added to or subtracted from dates, times or datetimes to compute new dates, times or datetimes.

  Published under the terms of the Open Publication License Design by Interspire