How do libraries in different programming languages handle Date & Time, Timestamps & Durations, Leapseconds & -years, DSTs & Timezones, ...?
Is there a standard body or a specific normative way how time-related things should be implemented in practice (like ICU for Unicode-related tasks) or is this currently a "best-effort", depending on how much effort, time and money language and library implementers want to spend?
Is there a specific and complete implementation which could serve as a example for how time-related things should be handled?
Which existing library would you consider as a bad, a decent开发者_StackOverflow社区 or a good example?
I'll try to give an answer to the second and third question using the Java library which might become part of Java 7.
javax.time.* (JSR 310)
These classes are a complete rewrite of JodaTime trying to fix the design flaws of util.Date
/util.Time
as well as JodaTime.
JSR 310 tries to provide a comprehensive model for date and time, which is type-safe and self-documenting. It is interoperable with existing classes, but also considers XML- and DBMS-based use-cases. The classes are final, immutable, thread-safe and cannot be modified after construction. Instances are created via a rich set of Factory methods which can cache things in the background.
LocalDate dateToday = LocalDate.of(2010, 9, 14);
LocalDate oneMonthLater = dateToday.with(OCTOBER);
LocalDate oneYearLater = dateToday.withYear(2011);
The API has some "machine-oriented" classes and some "human-oriented" classes:
Machine-oriented
Instant
For a point of time comparable to an Unix or Java timestamp. Actually there are Instant
, TAIInstant
and UTCInstant
which enable people to exactly choose which definition of time they need i. e. "day-based", "linear, without leap seconds" etc.
Duration
A time range not necessarily associated with a specific Date or Calendar.
Human-oriented
There is a rich collection of classes handling different use-cases like Date-only, Time-only, Time and Date, with and without Timezones, with and without DST.
DateProvider
OffsetDate
, LocalDate
(, java.sql.Date
compatibility)
TimeProvider
OffsetTime
, LocalTime
(, java.sql.Time
compatibility)
DateTimeProvider
ZonedDateTime
, OffsetDateTime
, LocalDateTime
(, java.util.GregorianCalendar
compatibility)
InstantProvider
Instant
, ZonedDateTime
, OffsetDateTime
(, java.util.Date
compatibility)
Period
Periods represent a time span like "5 days" that can be added and subtracted from a date/time.
Matcher
Matchers enable queries like "is this date in the year 2006?" or "is this day the last day of this year".
Adjuster
Adjusters come to the rescue if you have want to make more complex changes, like "Give me the last day of the month!" or "The second Tuesday after Christmas, please!".
Resolver
Resolvers allow users to define what should happen if a certain date is not valid, like February 31st 2010:
DateResolver previous = DateResolvers.previousValid();
LocalDate date = date(2010, 2, 30, previous);
// date = 2010-02-28
Working with Timezone and DST data
It is possible to serialize these classes and deserialize them using either the current timezone data or the timezone data when they were serialized. Additionally, rules from different timezones can be compared: It is possible to find out if DST rules have changed, e. g. between version 2010e and 2010f for Dates in London or Moscow and decide what should be done if a Time is in a gap or overlap.
Calendar systems
Although everything is based on ISO-8601, simple calendars for Hebrew, Hijrah, Japanese, ThaiBuddist, etc. time systems are provided.
Formatting and Parsing
toString()
returns ISO8601 and patterns like those in SimpleDateFormat
and more advanced are supported.
Integration
- Databases
- JodaTime
- Legacy JDK classes (
java.util.*
) - XML
References:
- https://jsr-310.dev.java.net/nonav/doc-2010-06-22/index.html
- JavaZone 2010 - Stephen Colebourne: Time to fix it! - JSR-310 Date and Time API
I don't think there's a single standard to such things at the moment, however there are multiple standards which such things may conform to: ISO 8601 for example.
ICU's own date/time handling is a cross-language (C/C++ and Java) and multi-platform library.
It handles dates and times internally, typically, using for a single time a UDate (C/C++) or a java.util.Date/long (Java), as number of milliseconds since 1-1-1970, or a Calendar object which is specific to the type of calendar (Gregorian vs Hijri, etc). Durations are available for formatting. Leap years are calculated as part of calendar systems, and leap seconds are assumed to be handled by the underlying operating system. DST/Timezone data is kept up to date with 'the tz database' sometimes referred to by its author's surname, Olson.
Hope this has answered your question some as regards ICU.
There are time(s) and there are dates (calendars)
The first problem is that dates are not linked to time but to astronomical position of Earh, Moon, etc. + regularity/periodicity of human activity. The time is also subjective and relative or even relativistic and measured either astronomically or or atomically.
The time bodies and the date/calendar bodies
The International Standartization Organization (ISO) [4] has issued
- "ISO 8601 Data elements and interchange formats — Information interchange — Representation of dates and times" [4a]
which, like other international standards, is recommendation and is based on already established practices.
It is (subjectively) based only on Gregorian Calendar [5] and on proleptic one (projected backwards to well before it was actually invented so is of limited use in dealing with historic dates) [5a].
The World Calendar Association [1d] initiated the introduction of new World Calendar since 2012 [1b-1d] which would make useless already existing date libraries. Again, the same main problem, see on it further on.
The most covering, I ever saw, date-time-related comparison in IT systems is [2] between BIG8 DBMS (IBM DB2, Informix, Ingres, InterBase, Microsoft SQL Server, MySQL, Oracle, and Sybase).
This and all other surveys show that the processing of the same, for ex., Gregorian calendar time/dates are different between all systems as well as inside the same platforms (between different products and versions of the same product), see for ex., [3].
THE MAIN PROBLEM with all date/time libraries in all-all systems, frameworks is that their date/time datatypes do not permit to include geographical and calendar information in date/time datatypes.
Without which they are mainly half- useless - what is the sense of milliseconds in SQL Server datetime2 values in 7th century? At that time there was even no clocks measuring time with accuracy of minutes (Galileo Galilei used, for ex., his heart beats to measure intervals of time in his experiments) as well as Gregorian Calendar was not even invented.
So, plenty of datetime type space is misused failing to give the most important flexibility of working with dates by linking and including with them to geography and/or calendar info.
Just fast illustrations:
- Modern Russia uses Gregorian calendar and the Russian Orthodox Church uses Julian calendar by which many state holidays in Russia are determined (for example, Christmas in Russia is on 7th of January and Old New Year is on 14th of January by Gregorian Calendar while the dates of other religious holidays are floating relatively to Gregorian Calendar).
- In pre-1917 Russia, Poland as its part, used Gregorian Calendar while all the rest Russia used Julian Calendar (with floating difference of 13-18 days at the "same" time zone) [5b];
- Double-click on clock in MS Windows (or open Control Panel --> Date and Time) --> Time Zone tab --> view time zones in combobox. You will see that there are 25 hours from GMT-12:00 to GMT+13:00 over a hundred of time zones with fractions of hour like GMT+5:00, GMT+5:30, GMT+5:45, etc.
==== Cited:
[1] New World Calendar
[1a]Update: Sorry, do not read [1a], author confused calendars and wrote wrong info in this news brief
World Calendar 2012: 35 days in a month
http://www.panorama.am/en/society/2010/01/29/newcalendar
[1b] http://en.wikipedia.org/wiki/World_Calendar
[1c] http://www.theworldcalendarin2012.org/Index2.htm
[1d] http://www.theworldcalendar.org/TWCA.htm
[2] Peter Gulutzan,Trudy Pelzer. SQL Performance Tuning: Dates in SQL
http://www.informit.com/articles/printerfriendly.aspx?p=30939
[3] SqlDateTime.MinValue != C# DateTime.MinValue, why?
SqlDateTime.MinValue != DateTime.MinValue, why?
[4]
International Organization for Standardization
http://en.wikipedia.org/wiki/International_Organization_for_Standardization
[4a] ISO 8601 Data elements and interchange formats — Information interchange — Representation of dates and times
http://en.wikipedia.org/wiki/ISO_8601
[5]
Gregorian Calendar
http://en.wikipedia.org/wiki/Gregorian_calendar
[5a] Proleptic Gregorian calendar
http://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar
[5b] Gregorian Calendar Adoption
http://en.wikipedia.org/wiki/Gregorian_calendar#Adoption
[6]
http://en.wikipedia.org/wiki/Galileo_Galilei
I haven't used it in a while, but from past experience I'd say that Boost.Date_Time is a pretty good example.
While probably not the first choice for many fast paced projects today, the expressive power of C++ still seems to be a very good match for a complex problem domain like date/time, so combined with the high quality peer review process to pass for becoming an official Boost C++ library I'd hope that the library at hand could serve as a example for how time-related things should be handled, albeit not as a complete implementation, see below.
Boost Date Time
The library is documented very well, so I could probably assemble the entire answer from quotes, but I'll try to extract some fragments according to the template suggested by soc's answer instead - nonetheless I'm going to start with an entire quote:
Motivation
The motivation for this library comes from working with and helping build several date-time libraries on several projects. [...]
Programming with dates and times should be almost as simple and natural as programming with strings and integers. Applications with lots of temporal logic can be radically simplified by having a robust set of operators and calculation capabilities. Classes should provide the ability to compare dates and times, add lengths or time durations, retrieve dates and times from clocks, and work naturally with date and time intervals.
Domain Concepts
The library supports 3 basic temporal types:
- Time Point - Specifier for a location in the time continuum.
- Time Duration - A length of time unattached to any point on the time continuum.
- Time Interval - A duration of time attached to a specific point in the time continuum. Also known as a time period.
Calculations
You can get a pretty intuitive overview on how the domain concepts relate to each other in section Details - Calculations.
Constraints
An important part of my original decision to evaluate the library has been the available documentation of design goals and necessary tradeoffs in light of the complex problem domain, which seems to outline the real world expertise that has been put into the library - you can read more about it in the following two sections:
- Design Goals
- Tradeoffs: Stability, Predictability, and Approximations
Working with Timezone and DST data
There is full support for all kind of calculations and conversions one could think of, as far as I'm concerned - see the headings in section Examples for an initial impression.
Calendar/Time systems
This is definitely the weak spot concerning your specification, despite the library being specifically designed with extensibility in mind:
A large part of the genesis of this library has been the observation that few date-time libraries are built in a fashion that allows customization and extension. A typical example, the calendar logic is built directly into the date class. Or the clock retrieval functions are built directly into the time class. These design decisions usually make it impossible to extend or change the library behavior. At a more fundamental level, there are usually assumptions about the resolution of time representation or the gregorian calendar.
However, I'm not aware of any implementations of other calendar/time systems than the ones included, see Library Reference for the current implementations of:
- Date Time
- Gregorian
- Posix Time
- Local Time
Formatting and Parsing
This is fully supported and one of the strong points of the library due to the respective power of the underlying C++ I/O system, see Date Time Input/Output - the stream oriented C++ I/O has both merit and issues depending on your needs and expectations, but this topic is discussed elsewhere on this site.
Integration
This is provided as well via compatibility with Boost Serialization, which is archive oriented though, usually meaning a file of binary data, text data, XML or so; i.e. databases are not explicitly supported as in your JSR 310 example.
You mention Python in an earlier comment.
Python's builtin datetime
support (docs) is pretty practical, but you have to use a third-party timezone database such as pytz
(docs) to make it close to complete. And, as the pytz docs mention, you may still have problems with adding deltas to times right around DST transitions if you aren't careful.
It was once the case that eGenix's mx.DateTime was the way to go if datetime didn't do it for your application, particularly for string to timestamp conversions, but dateutil seems to be popular these days (I haven't used it though).
To answer your "Good Example" question, take a look at Noda Time - Jon Skeet's port of the Joda-Time libraries for Java to .Net
精彩评论