Representing local timestamps in Ruby based REST API - ruby

Perhaps this question should be broken up into two posts, but I currently have an API for a few business customers. I am currently using ISO 8601 timestamps with a UTC time zone to represent times. However, I don't like the idea of these timestamps being attached to any timezone because the times should be the same no matter what timezone you are in. 5PM UTC should be 5PM CST, etc...
I know that you can leave the Z off of an ISO timestamp, and it will be interpreted as whatever local time you are in. Is this ok practice? And if so, how do I do this in Ruby? I read the doc for the Time class and didn't see anything about this.
EDIT: Let me re-word this just a little bit, or atleast clarify something. The reason why I'm seeking timestamps that aren't attached to a timezone is exactly because I know that my client servers and API server will hardly ever match up. If a client is submitting an event with a time, that time needs to be ambiguously equal to the ambiguous locale specific to the event that the user is working on.
That's a mouthful...assume that I'm working on an event scheduler. Each event belongs to a storefront or location of a company. When times are being shown for a location, it is assumed that the times shown are in the timezone of the location, and for clarity's sake should never be shown at a time formatted to a user's local timezone. If I'm looking at the scheduler on the East Coast, but looking at events for locations on the West Coast, the times I should see should be local to the locations on the West Coast, not adjusted for my timezone.
I know a solution could be to simply store times with timezone information for the location its associated to. But the use case that a user would want to convert a time to their timezone is VERY rare, and I'd rather make implementing my API easier...this was actually my original implementation but implementing the API in many different environments and across multiple programming languages, it became clear that it is a hurdle to show times local to that timestamp's timezone for a lot of languages. If a user wanted to convert times to their local timezone I could easily store global timezone information for the location object itself.

I don't know what you mean by "the times should be the same no matter what timezone you are in. 5PM UTC should be 5PM CST, etc..". 5PM UTC clearly isn't 5PM CST!
Anyway, I don't think that what you are proposing is an ok practice. Suppose you leave off the Z and have a timestamp be interpreted as whatever local time you are in. Since this is a network API, the client and server might not be in the same timezone. When the client submits a "local" time, what does it mean? The local time on the client (if so, how does the server know what that is?)? The local time on the server? It's ambiguous. This is the crux of the reason why just about the only reasonable thing to do is to use UTC throughout.
What you can do is attach a timezone to a timestamp if it might be relevant. For example, "you should observe one minute of silence at 2012-11-10T22:00:00Z in honour of the soldiers who died in WW1" sounds weird because Rememberance Day isn't on November 10! "you should observe one minute of silence at 2012-11-11T11:00:00+13:00" sounds a lot better once you put that New Zealand time zone in there... In this case you can keep and timestamp (in either local or UTC) together with the timezone offset (e.g. store both of them together in your database).
It does, however, depend on what your times represent. For example, in "at equinoxes, sunset happens at 18:00" it makes sense to use an abstract time that isn't qualified with a timezone (it's true in every timezone, and/or you're talking about solar time). But attaching a date to this abstract time makes little sense, so I don't think you would be talking about ISO8601 in this case.

Related

How to get current IANA Timezone Database version in Golang?

I need to store datetime records with IANA database current version used (2022g for example). How could I get it with Go?
I tried to search this on standard "time" package, but it seems that there isn't any functionality for this. I am expecting that there is some function that can return IANA tzdb version as a string.
UPDATE 1 according to comments below I need to clarify the problem:
The main problem is I want to store some FUTURE events. The event object has several fields:
Local dateTime
Timezone
UTC datetime
To keep my data up to date with IANA database (timezone, daylight saving time may change) I need to store current version of tzdb version. That will help me to write correct data migration of my events when new version of tzdb was released. So I need to add one more field with version of current tzdb that had been used to populate the time.
And I am trying to figure out how can I get the current version of my tzdb that Go application is using right now to store that version.
Also I am opened to alternative solutions of storing time records with extra accuracy of long-lived future events.
Update 2: This events are bounded to exact location.
The discussion thread in the comment is pretty long, but I'll attempt to answer and address some of the concerns. (I won't address the question in the title, as I believe that is not straightforward in Go.)
Indeed, future scheduling of events should be in terms of the time zone where the event takes place - which is usually not UTC.
Time zone identifiers will never be removed or renamed (with rare exception anyway). Once introduced, the identifier will either maintained as a Zone or as a Link in the TZDB indefinitely. Thus, you don't need to check that the time zone still exists. (Windows time zone IDs are also like this.)
DST is only one aspect of picking the correct offset. The standard time may have changed as well. However, all of that is encapsulated in the tzdb itself. You shouldn't need to concern yourself about which version of the tzdb was in effect when you created the event.
The general approach to this issue in most cases is:
Store the scheduled local date, time, and time zone ID of the event (local with regard to the time zone of the event).
Example: 2030-12-31T00:00:00[America/New_York]
At the time you create the event, also calculate a UTC value (or equivalent DateTimeOffset value) and store that in a separate field - so you know exactly when to fire the event:
Example: 2030-12-31T05:00:00Z (or 2030-12-31T00:00:00-05:00)
Periodically check that your UTC equivalent is correct. This can be in a daily maintenance task, or on application startup, or just before the event (perhaps also an hour before the event), or all of these.
The offset will only be different than projected if the time zone data changed on the device to give it a new offset. For example, let's hypothetically say the lawmakers in the USA succeed at making DST permanent sometime before this event takes place. Then the equivalent UTC time for the same event would now be 2030-12-31T04:00:00Z (or 2030-12-31T00:00:00-04:00).
In such cases, update the UTC time of the event if it has changed, but the original local time of the event usually should not be modified. Human beings tend to schedule things in terms of local time, not in terms of their UTC equivalents.
The only advantage knowing the TZDB version would give you, is you could do that last step less often - only when knowing the data has changed. I see that as an optimization though - it's not usually required.
Without such legal changes to time zone definitions, the mere start/stop of DST as scheduled is not a reason to worry about this. That is already accounted for by using the TZDB in the first place.
If the event is recurring (say a 10:00 AM daily meeting), each occurrence might have a different offset, but the local time will be consistent and the TZDB doesn't need to be updated to calculate it.

How to set correct timezone for Google Classroom coursework

When creating a new Coursework via the Classroom API, a "due" date and time can be added (
Classroom API TimeOfDay reference ) and the instructions say that "The date and time zone are either not significant or are specified elsewhere.".
In the context of a class, my expectation was that the number sent would be the number displayed (the teacher generally knows what "11AM" will mean to the class).
However, what actually happens is that the time zone that the server communicating with the API is located in is used to interpret the time. I.e. if the teacher is two time zones away from the backend server, the time will be two hours out.
Is the documentation just wrong? Or is there some way to "specify elsewhere" which I can't find?
This question is a little old, but I just went through some of the same issues, so responding here in case anyone else needs help...
It's not entirely clear how you formatted your create request based on the original question. The TimeOfDay object is used to set dueTime, and as stated in the docs, all dates and times for CourseWork create requests should be converted into UTC: https://developers.google.com/classroom/reference/rest/v1/courses.courseWork
I.e. you need to do any conversions into UTC based on your application/user needs, and the Google Classroom UI automatically converts this date/time into the user's local/date time. Currently there is no other way to do this with this API
Implementing this properly can get tricky depending on how your app/UI is set up, and is further complicated by variations like Daylight Savings Time. For example, if you are using JavaScript, JS dates use UTC internally, the user's browser tracks the current time for that user, and there is currently no other built in functionality for any other timezones. See some of the really excellent explanations about this (and various workarounds) below:
Calculate the UTC offset given a TimeZone string in JavaScript
get timezone offset of another timezone in javascript without using Strings
How to initialize a JavaScript Date to a particular time zone
I hope that's at least a little helpful. It's hard to specifically answer your question about 'what's happening' without more information :)

When the user's timezone is known, can the bot framework handle yesterday/tomorrow correctly?

In some cases, the bot may have knowledge of the user's timezone. Is there a way to pass this knowledge to the bot framework so that it can handle certain date forms correctly - e.g. "tomorrow" & "yesterday"? Even things like "next friday" are sometimes sensitive to the timezone.
Currently, it appears that these are handled assuming the user's timezone offset is zero.
It seems that the chronic parser is unreachable so you can't really change anything to that. I see 3 solutions.
Solution 1: Create your own RecognizeDateTime class to work with utc time or however you want.
Solutions 2: When you get the date (in the validation method for example) add the utc offset to the time. This will preserve the right date, for utc times and local times.
dateTime += TimeZone.CurrentTimeZone.GetUtcOffset(dateTime);
solution 3: When the datetime is created by using a string like "yesterday", the day is correct but the time defaults to 00:00 or 12AM. To make this less sensitive you can just add 12 hours to the UTC time. This will preserve the day in almost all timezones. (All timezones above 12+ will have a problem. Luckily there aren't many people there.) (This is the solution I'm currently using for one of my solutions)

Linux- Windows Timezone Mapping?

All the Timezone in Windows are displayed in such a way like
(GMT+10:00) Canberra, Melbourne, Sydney,
GMT and Offset and the place. In turn , the Linux is having every timezone as directory mapping in /usr/share/zoneinfo/[Continent]/[Place].
I am in need of mapping every Windows timezone to the Linux timezone for my application.
like
(GMT+05:30) Chennai, Kolkata, Mumbai, New Delhi => Asia/Calcutta
Now the problem surface for the International Date Line West which lies between Russia and America. In Windows, its marked by (GMT-12:00) International Date Line West and from various sources I found that in Linux its Etc/GMT+12.
(GMT-12:00) International Date Line West => Etc/GMT+12
also
(GMT+12:00) Coordinated Universal Time+12 => Etc/GMT-12
(GMT-02:00) Coordinated Universal Time-02 => Etc/GMT+2
(GMT-11:00) Coordinated Universal Time-11 => Etc/GMT+11
This keeps me puzzled and my app works closely with the Timestamp w.r.t UTC and the UTC offset. So this mapping is confusing me and the app.
Can anyone explain why there is a vice versa of -12 and +12 Offset in both for a same place?
Thanks in Advance :)
Unicode.org hosts a mapping as part of the CLDR. You can get to the latest version here. There are also XML versions of the data linked from that page.
You can find example code (in Python) of how to generate a mapping from the XML data here.
Obligatory Time Zone Rant:
Note that whoever implemented the timezone support in Windows was on drugs. I'm not kidding you. Look at the timezone names. Why is Central European time known as "Romance standard Time". Romance? What, because it includes Paris, or? Roman Standard Time could have made sense a it also includes Rome, but Romance!?
Also, in the registry the timezones are not organized under their id. No, they are, insanely, organized under their display name! Since that is localized, it means every timezone will be located under a different key in different translations of Windows!!! So to find the right timezone, you have to look through all the timezone to see which has the correct id.
I have example code of that too here. See the get_win_timezone() function.
I wonder if it is the same guy who designed this that decided that POSIX should reverse the sign on timezones, so that -8 hours mean plus 8 hours. In any case, I'm sure they were smoking something illegal together.
If all the files have the signs reversed, then the files you are looking at are forward mapping offsets, while what you are probably more familiar with is reverse mapping offsets.
Windows typically uses the local timezone for the machine's internal time, so it needs timezone files which can translate back to UTC. Linux typically uses UTC as the machine's internal time, so it needs timezone files which can translate to local time.
Since the offsets for the two machines describe complimentary but opposite directions of time, it stands to reason that the time zone files are inversely related to each other. In other words, if you pick up a set of zone files from one, the other set will be negative.
The definitions in the Etc directory are meant to be POSIX style, thus they have their sign reversed from what you would expect. I'm not an expert for POSIX, but as far as I get it, the basic idea was to express timzones by the combination of their local name and the offset to GMT. An example for middle europe (Central European Time / CET):
Europe/Berlin (w/o daylight savings) equals GMT+01:00 equals CET-1
GMT-1 in the Etc directory in fact describes a (fictous) timezone called "GMT" which is one hour ahead of (the real) GMT.
As far as I know, these files are only there to allow you to create (symbolic) links against them, so if you were situated somwhere in middle europe, you would create a link to GMT-1 and call it CET-1.
The best recommendation I can give you is to entirely ignore the Etc directory and use some mapping table from windows timezone names to unix timezone folders/files. Windows timezone info does not only give the offset to GMT, but also knows about Daylight Savings (and when in begins or ends). The same is true for the folders/files in the timezone database, but not for the files in the Etc directory - they give a simple static offset to GMT.
A list of time zones in the tz database can be found in the wikipedia.

relativity of the timestamp to the time zone

I wonder if, when you call something like that
time();
it returns the timestamp relatively to your time zone setting or to UTC ?
For example, when syncing two agents, that must be important to take care of it, doesn't it ?
You are absolutely right that the time needs to be adjusted for users at different locations.
First, you need to be able to know
what timezone each agent is in, which you cannot really guess, but ask the client to include the info in the request.
Then, depending on the language you
are using, you can either call some
function with the timezone offset as
the parameter to get the adjusted time, or calculate the
time yourself by adding
60*60*1000*offset milliseconds to the
UTC time.
In python e.g. time.time
[r]eturns the time as a floating point number expressed in seconds since the epoch, in UTC.

Resources