The whole concept of Dates and Times is incredibly flaky and constantly being updated so from the beginning it's an incredibly difficult task. From leap years to leap seconds there are so many variables to take into account.
John Skeet's library looks good but has taken him 3 years to get it this far and it's still far from perfect.
Could someone give me an indication on how the Go programming language handled DateTime's differently or similarly compared to other languages/libraries? This is purely for curiosity's sake.
This question is more about the similarities and differences between current available libraries - preferably in english, not pages and pages of documentation.
See the Go time package documentation and source code. A Time represents an instant in time with nanosecond precision without leap seconds. The IANA Time Zone Database is used for time zone and daylight savings time. The time zone database contains code and data that represent the history of local time for many representative locations around the globe. It is updated periodically to reflect changes made by political bodies to time zone boundaries, UTC offsets, and daylight-saving rules.
type Time struct {
// sec gives the number of seconds elapsed since
// January 1, year 1 00:00:00 UTC.
sec int64
// nsec specifies a non-negative nanosecond
// offset within the second named by Seconds.
// It must be in the range [0, 999999999].
nsec int32
// loc specifies the Location that should be used to
// determine the minute, hour, month, day, and year
// that correspond to this Time.
// Only the zero Time has a nil Location.
// In that case it is interpreted to mean UTC.
loc *Location
}
Related
At 6:00am Sydney time, Rory Allan clicks the foofoo button in their browser.
This inserts into the foofoo table with an 8:00pm UTC timestamp in the database of my server.
A lot of people are excited about this foofoo button, and they wanted to see what time of the day Sydney time Rory clicked it.
As I stare at my screen in California and view the status of the click, I want to see that he clicked it at 6:00am, not 1:00pm, which is what I will see if I pull the UTC time from the server and let my browser convert it.
You see, a lot of different people click foofoo, such as Phillip Herman in Germany, or Ivan Efimiov in Russia. And all we care about is the relative time of the day they clicked it, in the location they clicked it, regardless of the viewing location.
I don't know the best way to do this. Do I take the local timestamp and convert it to a string, storing it in addition to the real UTC timestamp? Or is this a common problem with a common resolution that I haven't found? I'm guessing / hoping the latter.
This isn't Language specific. These dates have a long journey:
Unix timestamp > Python date > JSON > Node > Mongo > Node > Browser
Ok, clearly 8:00pm UTC is not enough information. But what do you really want to know?
Is 06:00 enough information?
Look for time-only data types, preferably those that reflect time-of-day, rather than elapsed-time. These are often called LocalTime, TimeOfDay, etc.
Or, use strings in HH:MM format (on a 24-hour clock)
Or record the total number of minutes as an integer (60 * HH) + MM.
Or if you need a higher precision, then use seconds, or milliseconds, or microseconds, etc...
Is 06:00 Australia/Sydney enough information?
Store the time as mentioned earlier and store the time zone name in a separate string.
But be careful, because without a date you don't know if UTC+10 or UTC+11 was in effect.
Is 06:00+10:00 enough information?
You could look for a time with time zone data type, such as the one that exists in PostgreSQL, though even the PostgreSQL docs strongly discourage using this type.
Instead, store the time and offset as separate components.
Be careful, because you'd not necessarily know if this data was from Sydney. There are other time zones with UTC+10 at parts of the year too.
Assuming you have the date, such as today, then:
Is 2017-05-31T06:00 enough information?
Store the date and time together in a component that is sometimes called DateTime or LocalDateTime in various languages - but be careful that it is not bound to any specific time zone. Use DateTimeKind.Unspecified in .NET, or "naive" DateTime's in Python, etc.
For MongoDB and others that don't have such a type, use a string in ISO8601 format.
Be careful, because this time could come from anywhere in the world. Nothing here relates it to a specific point in time.
Is 2017-05-31T06:00+10:00 enough information?
Some languages and databases have a DateTimeOffset or OffsetDateTime type for this purpose.
If not, you can store a "Unix Timestamp" and also store the offset from UTC separately.
Or you can just store a string in ISO8601 format with the offset included - just be very careful with regard to comparisons / sorting.
Is 2017-05-31T06:00 Australia/Sydney enough information?
Store separately the date+time component from the time zone.
Consider that a time may be ambiguous during a DST fall-back transition.
Is 2017-05-31T06:00+10:00 Australia/Sydney enough information?
Here we have everything we might possibly need. Use a ZonedDateTime in Java/Joda-Time/Noda-Time, or an "aware" DateTime in Python (pytz, dateutils, etc.), or similar types when they exist in your platform.
Watch out for timestamp with time zone, as you might expect it to store the time zone and it typically does not (despite the name).
If not available, then consider storing a Unix timestamp and separate the time zone name as a string.
As you can tell - there are a LOT of options, and it really depends on exact use case and features available in each language/platform. You'll find more details if you search/ask for each one separately.
tl;dr
Exchange date-time values in UTC as strings in standard ISO 8601 format.
Work in UTC
General rule in date-time handling is to think in UTC, work in UTC, log in UTC, share in UTC, and store in UTC. But present in zoned time for the user.
By think in UTC, I mean every programmer needs to learn to stop their parochial thinking about their own particular home time zone. Translating back-and-forth to your own zone to UTC to other zones will drive a person nuts. Think of UTC as The One True Time®. All other zones and offsets are mere variations.
This strategy is much like internationalization. The programmer uses key strings in her own human language to look up string values from the localization tool to present a value (piece of text) in the human language preferred by her user. In date-time handling, the programmer works in UTC but applies a zone preferred by her user for presenting text in the user-interface.
Moment in UTC
The basic Java class for this Instant. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
So when Rory in Sydney clicks his button, we record an Instant object.
Instant instant = Instant.now() ;
instant.toString(): 2017-06-01T09:24:54.435Z
Zoned
To present that moment to Rory in his own time zone, we apply a ZoneId to get a ZonedDateTime object.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "Australia/Sydney" ) ;
ZonedDateTime zdt = instant.atZone( z );
zdt.toString(): 2017-06-01T19:24:54.435+10:00[Australia/Sydney]
Now we have two objects, instant & zdt, that both refer to the same simultaneous moment on the timeline. The only difference is wall-clock time.
If the user in California wants to see the moment of Rory's button click according to Sydney time, then we already have that solution seen above. If not, if the California user wants to see the moment of Rory's button click in her own California clock, then read on.
We can adjust into yet another region’s wall-clock time by applying another time zone.
ZoneId zAmericaLosAngeles = ZoneId.of( "America/Los_Angeles" );
ZonedDateTime zdtAmericaLosAngeles = instant.atZone( zAmericaLosAngeles );
zdtAmericaLosAngeles.toString(): 2017-06-01T02:24:54.435-07:00[America/Los_Angeles]
Now we have three objects that all represent the same simultaneous moment: instant, zdt, and zdtAmericaLosAngeles. One moment, three wall-clock times.
See this above code run live at IdeOne.com.
Time-of-day
If you literally meant you want the time-of-day only, without the date, you can extract a LocalTime object from those objects above.
But think twice about doing this, as presenting a time-only without date and zone can lead to ambiguity and misunderstanding.
LocalTime lt = zdt.toLocalTime();
all we care about is the relative time of the day they clicked it, in the location they clicked it, regardless of the viewing location
If you are really really really sure that is what you want, then combine my advice above. (But I doubt this is a wise way to go.)
LocalTime lt = LocalTime.now( ZoneId.of( "Australia/Sydney" ) ) ; // Current time-of-day in Sydney.
Library for date-time
We have been using the modern java.time classes in examples above. They are exceptional – I mean than literally. They are virtually unique. Virtually all other platforms have terrible support for date-time work. The predecessor to java.time was the Joda-Time project which was ported to .Net platform as Noda Time. Other than java.time & Noda Time, I know of no other decent library on other platforms.
ISO 8601
The ISO 8601 standard defines many sensible practical formats for textual representation of date-time values.
The java.time classes use the standard formats by default when generating & parsing strings. You have been viewing those ISO 8601 formats in examples above. Except for ZonedDateTime which wisely extends the standard by appending the name of the time zone in square brackets.
The T in the middle separates the date portion from the time-of-day portion.
For UTC, the Z on the end is short for Zulu and means UTC.
For offset-from-UTC, you see a plus/minus number of hours and minutes ahead of or behind UTC. A time zone is history of past, present, and future offsets in use by a particular region.
Database
How databases handle date-times varies widely, though poor support is most common. A database driver, such as JDBC drivers, add another layer of behavior. So no way to succinctly address that here. And this topic is already asked and answered in many other pages in Stack Overflow.
If your database lacks serious date-time support, you may be better off storing the ISO 8601 strings with the Z on the end. These values when sorted alphabetical are also in chronological order.
The typical Date data type, in most programming languages, is a Unix timestamp that represents an "exact moment in time".
But I want to know if there's a more "ambiguous" Date structure, that more closely represents human perception of dates.
For example, say I want to represent a specific year (2000), or a specific month (January 2000), or a specific day (January 1, 2000)?
I could store it as a Unix timestamp, which would be 1/1/2000 12:00 AM GMT.
But computers interpret timestamps according to its local timezone, so my computer would show 12/31/1999 5:00 PM PDT, and each computer would interpret it differently.
Since Unix timestamps seems to be the standard for exact moments in time, I'm just wondering if there's any sort of standard for ambiguous moments in time.
If there's not a standard, I'd be happy to read about any specific implementations (in any language) that handle these scenarios.
Yes, there are many places you'll encounter this:
In the ISO-8601 standard, as a string in YYYY-MM-DD format. For example "2014-10-08" is the 8th day of October, 2014.
In .NET languages, such as C#, the DateTime type is a date and time, but it is not necessarily bound to a specific moment in time. That depends on an internal property called Kind, which can be either Utc, Local, or Unspecified. When it's unspecified, then it is just a date and time without reference to any time zone. It still has a time component though.
In the .NET library Noda Time, the LocalDate type is a pure date without time or time zone. Similarly, LocalDateTime is a date and time type without a time zone.
In the Java library Joda Time, the LocalDate type is a pure date without time or time zone. Similarly, LocalDateTime is a date and time type without a time zone. You'll also find these types in the new java.time API in Java 8.
In C or C++, the tm structure represents a calendar date and time, without regard to time zone. It's in the standard library, along with the t_time structure that has the behavior you described in your question.
In Python, the date object represents a date without a time or timezone. The datetime object represents a date and time, with an optional time zone. Python calls them naive when there is no time zone information present, and aware when a time zone is provided.
In many databases, there are data types for date and time, or for date-only, without regard to time zone. I won't list all databases, but consider Microsoft SQL Server which has separate datetime and date types.
I'm sure there are many others, however they don't necessarily exist for all languages. For example, PHP has a DateTime class, but it's time zone aware, and I don't believe a class exists that isn't (or I couldn't find it anyway). JavaScript is another example, as its Date object is really a date and time object that's bound to a UTC-based timestamp.
By the way, these types (and much more) are covered in the Pluralsight course, Date and Time Fundamentals, of which I am the author. You may wish to check it out.
I am pulling a date from a server in ISO 8601 format. The date represents the time a specific episode of a specific show airs. Here is an example date:
"2013-07-30T21:00:00-05:00"
That is July 30th, 2013 at 9:00PM EST. EST being -05:00. The problem comes in when I try and display the date back to the user(myself in this case). I am currently in central time but daylight savings time is active. Which means iOS says that I am currently in Central Daylight Time which is also -05:00(normal CST is -06:00).
This show airs in my CST time zone at 8:00PM. It doesn't matter if daylight savings time is on or off, the show always airs whenever the clock hits 8:00PM. Normally if I wasn't in daylight savings time iOS would be able to do the proper conversions as it would be moving from -05:00 to -06:00. SInce I am currently in daylight savings time though it sees -05:00 as the original offset and -05:00 as my current offset so it does no conversion and displays the show starting at 9:00PM. Any idea how to deal with this?
Unfortunately there is no way to map just a time zone offset like -05:00 back to an actual time zone like Central Time or Eastern Time. As you pointed out, it could be Central Daylight Time, or Eastern Standard Time. However, it could be any number of other time zones that happen to use a -05:00 offset at one point or another. See this list of time zones and sort by one of the offset columns so you can get an idea of how many their are. You can also look here.
Now fortunately, you have another piece of information - the date/time. So you can use this to partially distinguish between some of these zones. You also may be able to further limit the ambiguities if you know for certain that your data is the USA.
There is still one problem though. A time like 2013-11-03T01:00:00-05:00 is actually in both CDT and EST simultaneously! How can that be? Well, in the USA we do not all change our clocks at the same moment. Each time zone changes it at 2AM in their own local time. So there is one hour every year that Eastern time has already encountered their fall-back transition, but Central time hasn't yet.
The only real way to deal with all of this is to store some other bit of context information, such as the full IANA time zone (America/New_York for Eastern or America/Chicago for Central, etc.) - or if it's just for display then you can store a string with the time zone abbreviation of your choosing (EST, CDT, etc.).
See also: "Time Zone != Offset" in the timezone tag wiki.
I need to do some date + time stuff that is not covered well by NSDate on the iPhone. I wonder if there is a library that has more sophisticated functionality regarding dates and time on a international level.
What I want to do is advanced date + time mathemathics. I need to:
convert between different calendar types (Gregorian <> Jewish <> Muslimish <> others)
convert times between different time zones (i.e. I have a swedish time and want to know what time is it in chicago)
add microseconds, seconds, minutes, hours, days, weeks, months, years to a date and find out what exact date+time it is then
find out how many microseconds, seconds, minutes, hours, days, weeks, months and years are between two given dates
draw calendars, so I need data about how many days a specific month has in a specific year
use case, for example: I fly from paris to chicago, and at 10:00 'clock in paris I only know the flight will take 10 hours. So I need to convert time zones and all this stuff to calculate what time I'll arrive in chicago. And then all this ugly summer and winter time stuff where they add or reduce one hour at some point in the year, and I think every country does that to their own liking, some may even fake the time way more than that adding a whole day to a year just to have more time. Don't know. Maybe there's a lib that protects me from all this complexity.
Basically what I want to do is a kind of world calendar but with some special features.
It's in the Date and time programming guide.
Convert from one calender to another
Convert between time zones
Calendrical calculations
etc...
NSCalendar + NSDateComponents?
However, like Peter Hosey said, it's hard to know without knowing what it is you want to do.
For people coming here looking for a lib, try Erica Saduns NSDate-Extensions. It doesn't cover everything you might want, but at least you won't have to do the basic stuff yourself.
I'm developing an international software that act as a simple project management software and I'm facing a problem. This problem is about date/hour and time zone.
When a message is sent from one time zone to another time zone I can store the UTC (GMT) time in my database and then have it displayed differently according to the user's time zone. But this can't be done when I only work with date.
If I say a task is due to the 21st of March. Should I consider that this date can be 20 or 22 in some other countries ? What are your advices on this problem ?
Let's say a user in New York sets a due date for a project as "anytime on Monday 26 January". That means "anytime from 0600 Monday 26 January to 0600 Tuesday 27 January" in Brussels and "anytime from 2000 Sunday 25 January to 2000 Monday 26 January" in L.A.
So completing the task at 2100 on Monday 26 is fine in Brussels and N.Y., but too late in L.A.
One possible work around is never just work with the date. If the time is not specified, either set it for 0000 hrs or 2400 hrs on the date specified in the timezone of the user.
The users may have to deal with strange due dates/times, but speaking as someone who used to work internationally, it kinda goes with the territory.
You won't be able to achieve what you are trying to do without storing the exact time. You simply don't have enough information.
When you don't have a time, assume that the time is the end of business in the main locale for the application, then translate that time as you would any other time. An alternative would be assuming end of the business day in local time and adjust that to UTC. Everyone using the application would need to understand whatever default time assumption you make when the time is not specified. Coordinating to the main office may be best in a large enterprise whereas coordinating to local time may be best in highly decentralized environments where the local context is equally important.
If you aren't storing the minutes and seconds you have to assume that the date being entered is the desired date and not to any adjustments for GMT. Just put it in the database as is. The people on the west coast will have to assume that the due date is the same regardless of where you are in the world. If you want to adjust for time zones, you'll have to collect more information, like hour, minutes, and seconds.
The easiest solution would be just to display as the same date for everyone. The deadline would then effectively be midnight in the latest timezone.
Otherwise, decide what the default time of the deadline should be in the timezone the task was created in, e.g. 21st March 17:00 EST or 22nd March 00:00 EST and display that in the local timezone. The timezone difference will then push it into the previous day or next day accordingly for the viewer.
SQL 2008 allows for a Date datatype that does not have any time value associated with it. That allows someone to say I need this done by this Date, but I don't care if it is +/- several hours. If the date selected is 1/1/2009 but it happens on 1/2/2009 at 2AM their time, they probably don't care.
When the user needs something done by a specific date and time, like close of business on 1/1/2009 then you need to store it in a DateTime as UTC and convert it to local time client-side.
This will take much of the complexity out of indicating when something is completed, it'll either be completed near a specific day or by a specific time.
If you have a single instance of a DB, I would store all dates in the datetime timestamp of your DB server. If you are timestamping rows, consider GetDate() in T-SQL or as default value of the timestamped date column. Then you have your single reference point for all times. Consider UTC format there.
Then, all clients accessing the date do their own conversion into "local time" , which can be interpreted by things like : user preferences, date time stamp on client computer, etc.
Without knowing more, it hard to say exactly what the resolution is.
Your solution depends on your application and requirements.
I'd first store UTC + offset in your data structures, so it's easy to display for any timezone.
Most likely if a task or meeting is due at 12pm on 21/March in London then it will occur at 2130 on 21/March in Adelaide (+0930), but that is an application requirement not any sinister timezone related standard.
If you want the ultimate in flexibility, add a flag that can make the even due simultaneously in every timezone or at the same time no matter where you are (staggered) and show the event accordingly.
You might want to store the date in a from that is timezone aware. This will help you in your calculations. SQL Server 2008 for instance supports a datetimeoffset that does precisely this. Alternatively if you're using SQL 2005 with a bit of effort you can write your own SQL CLR data type to support this.