Quite some time ago I used to work on the specific project using Spring on the backend. The system supposed to work across multiple timezones. Therefore it was decided to use integer values (Long) to store and transfer dates between backend and the web app. As I remember the main reason was to simplify and minimize work with timezones since the timestamp will always represent exact time and we always able to retrieve Date from it without worrying of incorrect timezone (the user's browser will apply proper timezone).
At that time I was little occupied with architecture, as I was only a junior. But since then I have not seen any application of this practice, and I can not find anything on the Internet.
I know there are some cases when we do not need to rely on time zones, for example when I travel to different country I don't want my alarm clock to be changed according to the new timezone. But I still want my reminder to notify me when I need to make an important call at the right time.
I believe the second case is much more common in the software.
Therefore I wanted to know is there any real benefit of using numeric timestamps?
I see at least two potential benefits:
Less hassle with the timezones (especially for the less experienced devs who can be confused at times working with dates)
Less data is transferred through the REST (?)
Downsides:
We have to extract Date value every time to process or display it (this can be automated using most of the frontend frameworks)
Database values and server debugging is not that self-evident
Underneath the scenes of DATE types in databases and higher-level languages, there is always some version of a relative date offset and resolution. In example:
DOS used 1 January 1980 with 10ms,
COBOL assumed 1 January 1601 with 1s resolution
UNIX and its ilk just happened to chose 1 Jan 1970 Midnight GMT.
Benefits of using a numeric and not interpreted numeric in your data storage is arguably (but subjective) easier date arithmetic. For TZ-heavy stuff like airline scheduling/logistics relying on the numeric (vs date type) as the numeric native allows one to keep consistency without date type function conversions despite TZs as well as politically-arbitrary DST adjustments. Because, the Uniform Time Act is the furthest thing from being uniform.
I would say that this really depends on the designated use of that value. It would probably make more sense to expose the timestamp value if you expect a technical usage, and ISO 8601 if you expect any other usage. For majority of usages they would probably be synonymous (watch out for leap seconds). They both refer to a fixed point in time.
Exposing the dates as ISO 8601 strings is definitely easier for debugging and for human eyes. You know straight away, which point in time it is.
UNIX timestamps historically also had a flaw of being restricted to the size of integer values. In 64 bit architecture this is usually no longer an issue, but for backwards compatibility strings would be a better option.
I would definitely not recommend to expose the dates through an API in the local time zones. Such values are usually ambiguous and unreliable. They are good for humans, but not good for anything else. Consider daylight saving time for example. Some periods in time exist twice, and some hours do not exist at all.
Related
In many languages, a signed value is used to represent time instead of an unsigned one. What is the rationale behind this? I'm interested in this in a general way, not just a specific language.
Time extends indefinitely in both directions. (At least for practical purposes, the Big Bang notwithstanding.) You may only wish to measure times after the start of some process, but some software works with times in the past, such as historical records, physics calculations, archeological studies, records of birth dates of patients, and so on.
Given any two or more timezones, I would like to convert the local time in any timezone to any other such that the time representation accurately represents any local alterations (DST, etc) that each timezone has in effect.
Specifically, if some of the timezones I provide happen to deal with DST considerations, I need to detect and catch this such that the appropriate recalculations will automatically be made - for example, that the output for those timezones is automatically adjusted forward or backward by one hour.
I want to do all of this from the shell, if possible, preferably using portable techniques; I was considering handing off the heavy lifting to date, but I'm not sure how to have it perform relative timezone-accurate calculation, especially in a way that's crossplatform to at least Linux and BSD.
Convert to UTC first and then convert to the target time zone (using CET as an example)
TZ=CET date --date=#$(TZ=UTC date +%s)
DST will be taken automatically.
This is not a post about technology per se, rather a post about the appropriate algorithm. I want my users to be able to schedule an event on my application to occur at a specific time (which they will see displayed in their time zone on my site) every week.
Say a user in New York schedules the event to occur at 8pm EST. I would like the event to occur for this user at 8pm EST every week for the entire year, regardless of daylight savings time.
Currently I'm storing the time value in UTC in my database, but UTC does not change based on the time of year. It seems that some timezones do have a concept of daylight savings and some dont, which means that if I were to do any timezone translation processing on the fly (either before any queries that lookup the date in order to schedule the event, or to display the scheduled time on the site) I would have to see if the user's timezone supports daylight savings and if the target timestamp falls within a daylight savings period.
How do people typically solve this type of problem? In other words, how should I store a logical time in my database, display it properly, use it for scheduling a task properly regardless of daylight savings time, for all user timezones, in the simplest way possible?
I will make one assumption, you meant "...in Eastern Time every week for the entire year". When you say EST, you are specifically referring to Eastern Standard Time. When DST is applicable, it is known as Eastern Daylight Time (EDT).
Also, abbreviations are not a good way to identify time zones. How I would I know you meant EST in the United States (UTC-5) and not EST in Australia (UTC+10)? Abbreviations are ambiguous. You can see a fairly comprehensive list here.
The first thing to do is to decide how you want to identify the user's time zone. There are two databases in common use:
The Microsoft Time Zone Database
PROs
Built in to Windows operating system.
Updates deployed automatically through Windows Update.
Easy to consume from Win32 or .Net Framework.
CONs
Maintained by Microsoft instead of a standards body or community.
Zones tend to be very broad instead of refined.
Not good with historical time zone changes.
Interoperability with non-Microsoft servers can be painful.
Updated less frequently.
The IANA/Olson Time Zone Database
PROs
Widely implemented on Linux, Mac, Java, PHP, and many other platforms.
Libraries are available for JavaScript and for Windows/.Net.
Refined, distinct time zones named from an exemplar city.
Contains historical data for time zone changes.
Referenced in many RFCs and other standards.
Community maintained, recently backed by IANA.
Frequent updates, several times a year.
CONs
Not usually maintained automatically, although some implementations may do so.
There are so many zones, it can be difficult to present a simple drop-down list to your users. Map-based timezone pickers, such as this one, are needed for a good user experience.
Now that you have identified which time zone your user is in - let's get to the heart of your original question. How should you deal with a recurring event that is at the same local time without regard to DST changes?
You actually have two different concerns, persistence and execution.
For persistence (and transport, display, etc.) you need to store a combined local time and time zone. For example, 8:00 PM in the America/New_York IANA zone. If possible in your framework, store this time without a date component. Don't convert it to UTC or try to adjust it for DST. You are simply capturing the users intent in the way they have expressed it to you.
For execution, you need to fire your recurring job at a specific scheduled time. The server your job is running on might be in a different time zone entirely. What you need is a series of UTC DateTime values, so you can set a task scheduler to fire at specific moments in instantaneous time. You might also use a local-time-plus-utc-offset for this, such as a DateTimeOffset in .Net. That would have the advantage of seeing 8:00PM on every value, even if the offset was switching between -4 and -5. See DateTime vs DateTimeOffset.
To align these two concepts, you need some code that will evaluate the local time and compute the execution timestamp. You could just set up the next scheduled job as each job runs, or you could do this periodically and project event times for some future X number of events. That's up to you. If you need to put future event dates on a calendar - then you certainly need the latter approach.
Perhaps you can use any of the publicly available time zone APIs. Eg. https://developers.google.com/maps/documentation/timezone/ .
I would convert into UTC as soon as possible and out of UTC as late as possible, because when countries switch out of DST at the end of the summer they put the clocks back, and there are two hours in the day with the same time - so DST times cannot uniquely describe all times.
I'm working on an application that uses a lot of dates, but that doesn't rely on times at all. I'd like to store them internally as NSDates so that I can use NSDatePicker controls, built-in date functions, etc.
However, I keep tripping over the fact that NSDates insist on storing a time as well as a date. Many of the date initialization functions append either the current time or an arbitrary time. I've written my code to wipe out the times on all dates by setting the time components to 0 - but even so, time zone issues screw up some of the comparisons (e.g., comparing the current date to a specific date produces the wrong answer if the current date in the local time zone is different than the date in GMT).
Surely there's a better way to tackle this problem...?
The answer, as Thilo mentioned, was to set a fixed time zone.
Note that that wasn't quite enough. Initially, I chose GMT, and just fixed the time at 00:00:00. As it happens, that's kind of a stupid move, because any actual adjustment of the time can cause problems. Like, say... loading that value into a DatePicker control, and then using the application around 1am in a time zone west of GMT. Whoops.
To work around most of those problems, I instead chose GMT and set the time at a fixed 12:00:00. That should keep dates concurrent for eleven time zones east or west of GMT.
Is there a way to estimate the offset from GMT (or time zone) from a latitude/longitude? I've seen geonames, but this would need to work long term and we don't really want to rely on a web service. It'd just be used for determining whether to display "today" or "tonight" when giving information to various users so it wouldn't need to be too accurate (an hour or two off wouldn't be bad).
offset = direction * longitude * 24 / 360
where direction is 1 for east, -1 for west, and longitude is in (-180,180)
Basing the time zone on the longitude alone is wildly inaccurate outside of international waters. See the map on this page:
http://askgeo.com/database/TimeZone
The vertical colored stripes in the deep ocean are the so-called natural time zones derived from longitude alone, and the colors of the land are the actual time zones per the governing laws. You can see that they don't line up very well at all.
I actually ran into this problem while working on a different project and did substantial research and development on it. First my research:
First, time zones are not typically encoded by just an offset from GMT (aka UTC). That fails to take into account Daylight Savings Time, and changes in the time zones over the years. Instead, time zone IDs are used to designate a geographic area in which the official clock time has been the same throughout the area for a given period of time (e.g., since 1970). The most important system of such IDs is the "Olson time zone ID" (together these IDs and their offset rules are known as the "tz database"), which is used by Linux and other Unix operating systems. Most programming languages and operating systems have native or third party support for Olson time zone IDs.
In terms of existing solutions to convert latitude and longitude to time zone:
GeoNames.org has a vast database of point locations (centers of cities, airports, public buildings, etc.), each of which is annotated with a bunch of useful metadata, including the Olson time zone ID. And they have a nice API to let you access these via the web. The trouble is that if unless the point you are querying is right on top of a record in their database, you might get a result that is on the other side of a time zone border, or you might get no response at all if your query is far from their nearest point. The web service is also painfully slow, and they limit the number of queries you can make in a day to a relatively small number.
Earth Tools (http://www.earthtools.org/webservices.htm) also has a service for this, and it is much faster than GeoNames, but it returns just an offset from GMT, not a time zone ID, and it doesn't handle Daylight Savings Time correctly for most of the world. Also, it seems to not be maintained, so I'm not sure if the data is accurate anymore (time zones change over time).
After reviewing those options and searching for other possibilities without success, I decided to build my own solution, and have released it at:
http://askgeo.com
AskGeo is based on a time zone map of the world, so it returns a valid time zone for every valid latitude and longitude. It returns the standard Olson time zone ID (e.g., "America/Los_Angeles") used on Linux and most other operating systems and programming frameworks. It also returns the current offset, taking full account of daylight savings time.
It is extremely easy to use and usage is documented on the main page of the site. The API supports batch queries, so if you need to do a lot of look-ups, please use the batch interface rather than bog down our servers with serial requests. The bulk queries are also much faster, so everybody wins.
When we first launched this, we built it on Google App Engine (GAE) and made it free to all users. This was possible because GAE's prices were so low at that time. Since then, our server load has increased substantially and GAE's prices went way up. Both factors combined led us to switch to Amazon Web Services for hosting and to start charging for commercial use, while keeping the service free for non-profit, non-commercial open source projects, and researchers. For commercial users, we provide 1000 free queries to let potential customers evaluate the API to make sure it meets their needs. See the web site for pricing and terms.
The underlying library was written in Java and due to popular demand, we also released the library under a commercial license. Full documentation of the library and pricing details are on the web site.
I hope this is useful. It certainly was useful for the project I was working on.
If you know the users longitude, you completely know every aspect of time for them (neglecting some small errors like special relativity etc). The mean solar time is simply the difference of GMT and longitude (convert degrees part to minutes, 1 degree = 60 minutes). You add or subtract based on East or West. Mean solar time is basically more accurate time then time zones. Day time and night time times are variable and depend on latitude, so you use some approximations of sunrise and sunset times taking in latitude and the date and year. This alone would provide fairly accurate notion of daytime and night.