Difference between timezones America/Los_Angeles and US/Pacific and PST8PDT? - mysql

I need to convert a bunch of dates in a MySQL database from Pacific time (America/Los_Angeles) to UTC. I found a great SO answer on how to do this.
During my tests and preparation, I'm finding that I'm getting the same time conversions when using any of the following time zone names:
America/Los_Angeles
US/Pacific
PST8PDT
So my questions are the following:
Are these all just aliases to the same thing? Or are there actual differences between them at some point in time?
If I want to provide a list of timezones to users on a website, would it be better to give them selections from the America group of names, or the US group of names?

US/Pacific and PST8PDT both belong to the "other" timezones, which come with this warning:
Please do not use any of the timezones listed here (besides UTC), they only exist for backward compatible reasons.
They should all refer to the same timezone, compare:
http://www.travelmath.com/time-zone/PST8PDT
http://www.travelmath.com/time-zone/US/Pacific
http://www.travelmath.com/time-zone/America/Los_Angeles
As such, you should use America/Los_Angeles, which incidentally should also be a pretty "natural" and easy thing to select for users.

I ran into an issue with the parallel US/Eastern, Americas/New_York, and EST5EDT. Here is what I discovered.
For dates after the Uniform Time Act of 1966 went into effect in 1967, these timezones are all identical. Also the US enforced standard DST rules during the World Wars, so they are all identical 1918-1919 and 1942-1945.
For any date before 1918, between 1920 and 1941 inclusive, and between 1946 and 1966 inclusive, EST5EDT will always be identical to EST. PST8PDT will always be identical to PST.
Prior to 1967, Americas/New_York will provide the time as observed in New York City. So Daylight Savings Time will follow the rules in place by the NYC municipal or NY state government. Any date before 1883 Nov 18 12:03:58 will be in local mean time with an offset of -4:56:02 from UTC. For Americas/Los_Angeles any time before 1883 Nov 18 12:07:02 will be local mean time with an offset of -7:52:58 from UTC. Between 1883 and 1967, Los Angeles follows the LA and California Daylight Savings rules.
Here is a fragment of Ruby showing the difference:
# In PST8PDT 1966 has no DST, but 1967 does.
ENV['TZ']='PST8PDT'
[Time.mktime(1966,6,2),Time.mktime(1967, 6, 2)]
=> [1966-06-02 00:00:00 -0800, 1967-06-02 00:00:00 -0700]
# In America/Los_Angeles both dates are in DST.
ENV['TZ']='America/Los_Angeles'
[Time.mktime(1966,6,2),Time.mktime(1967, 6, 2)]
=> [1966-06-02 00:00:00 -0700, 1967-06-02 00:00:00 -0700]
If you install the tzinfo gem for ruby you can see the difference between PST8PDT and Americas/Los_Angeles for historic dates:
require 'tzinfo'
# Here an old date will use modern timezone rules.
Time.new(1867, 6, 2, 0, 0, 0, TZInfo::Timezone.get("PST8PDT"))
=> 1867-06-02 00:00:00 -0800
# Here an old date predates timezones, so local time is used.
Time.new(1867, 6, 2, 0, 0, 0, TZInfo::Timezone.get("America/Los_Angeles"))
=> 1867-06-02 00:00:00 -0752
Odd things can happen if you have multiple systems where one assumes PST8PDT and the other assumes Americas/Los_Angeles, especially when a system is storing DATE fields as DATETIME fields with the hours/minutes/seconds set to midnight. Data might look fine for anything recent. But a birthdate for example, from the summer of 1966 might get moved an hour, then truncated so it appears to be on the prior day.
And just for extra fun if you are dealing with old dates in Alaska, you need to remember that Alaska was Purchased from Russia. Dates before 1867 Oct 18 are on the other side of the international date line and use the Julian, not Gregorian Calendar. So Juneau, for example, went from 6 Oct 1867 (Julian) +15:02:19 to 18-Oct-1867 (Gregorian) -8:57:41. (The TZInfo library doesn't handle the Gregorian to Julian change.)
Time.new(1867, 10, 18, 0, 0, 0, TZInfo::Timezone.get("America/Juneau"))
=> 1867-10-18 00:00:00 +1502
Time.new(1867, 10, 19, 0, 0, 0, TZInfo::Timezone.get("America/Juneau"))
#error message
TZInfo::AmbiguousTime (1867-10-19 00:00:00 is an ambiguous local time.)
Time.new(1867, 10, 20, 0, 0, 0, TZInfo::Timezone.get("America/Juneau"))
=> 1867-10-20 00:00:00 -0857
Time.new(1867, 10, 18, 0, 0, 0, TZInfo::Timezone.get("America/Juneau")).to_datetime.julian
=> 1867-10-06 00:00:00 +1502

US/Pacific is a "link" to America/Los_Angeles in the IANA database (see wikipedia). On Linux systems I've seen, the former is a hard linked file to the latter; on OS X it might be a copy. If you run a checksum (e.g. md5 or sha1) on the entries in /usr/share/zoneinfo/ the 2 should match.
However, PST8PDT may be different - I haven't figured out exactly how. This bug report indicates that it doesn't track the history of daylight-saving changes, i.e. that it just retroactively applies the current DST rules to the past; but that doesn't seem to be the case in this ruby example. If it were retroactively applying the current rules, both would be -0700:
> ENV['TZ']='PST8PDT'
> [Time.mktime(2006, 4, 2, 1, 59, 59), Time.mktime(2006, 4, 2, 2)]
=> [2006-04-02 01:59:59 -0800, 2006-04-02 03:00:00 -0700]
On this message there's a quote from the original database maintainer. The message author explains that the legacy zones including PST8PDT used to have obsolete info, but now are "less incorrect" whatever that means.
To sum up, don't use PST8PDT, but it should be safe to use either US/Pacific or America/Los_Angeles.

Related

chrome 67 date vs Chrome 66 date

The code is:
var rightNow = new Date();
console.log(rightNow);
In Chrome 66 it returns:
Tue Jun 12 2018 15:36:19 GMT+0530 (IST)
In Chrome 67 it returns:
Tue Jun 12 2018 15:36:43 GMT+0530 (India Standard Time)
Why the difference?
A lot of my code works with the behaviour in chrome 66. Do I need to change all the code?
In general, you should not code for a specific browser, but to the standards. In this case, the standard is ECMAScript (ECMA-262). Section 20.3.4.41 covers Date.prototype.toString(), which refers to the following section describing the internal ToDateString(tv) function, which explains:
Return an implementation-dependent String value that represents tv as a date and time in the current time zone using a convenient, human-readable form.
By "implementation-dependent", it means that the actual string value is not defined by the specification, and can vary from one implementation to another. You are not guaranteed the same result from one browser to the next, or from one version of a browser to the next, or even from one operating system to the next from the same version of the same browser.
By "human-readable form", it means that the value produced is suitable for display to a human being. It makes no guarantees about that value being represented in a manner that can be parsed consistently by computer code.
Thus, if you intend for the string value to be sent to other code, you should not use .toString(). In general, you should prefer an ISO 8601 formatted string for this purpose. Use .toISOString() if you want the result in terms of UTC. Refer to this answer (or use a library) if you want the result in terms of local time including a time zone offset.
As to why things changed between Chrome 66 and Chrome 67 - I don't have the exact details, but I assume Chrome switched from using IANA TZDB abbreviations to using CLDR time zone names, probably through its use of ICU. This is reasonable, and is what many other implementations are doing. There's no requirement it use one set of data or the other though, so don't rely on such things.

Does the Google Directions API use UTC or Local Time?

I am developing a transit navigation app using the Google Directions API.
The API requires me to submit a departure time (departure_time) for transit queries.
Is it necessary to convert the local time to UTC time for this parameter?
I could not validate it through the API's response, as there is no accurate time returned in it.
That Doc Was In Error
Apparently the Google team writing that doc page made an error and later fixed it.
The number you report 1343605500 is no longer found on that page. Today the number on that page is 1343641500. I suspect you did indeed see that number on that page previously. Googling (ironically enough) for site:https://developers.google.com 1343605500 does list that page as a hit. Apparently the hit is based on a cached copy of the old erroneous page. Even Google cannot escape the reach of Google.
Work in UTC/GMT
Is it necessary to convert the local time to UTC time for this parameter?
Yes.
The API works with GMT/UTC (no time zone offset), which only makes sense when you think about it. Almost always, the best practice for handling date-time is to perform your business logic, serialization, database records, and so on in UTC, then convert to local time only for presentation to the user.
Just looking at the example URL itself suggests it is in UTC. The only possible reference to a local time zone would be the word "Brooklyn" which is certainly not a clear unique identifier for a time zone.
http://maps.googleapis.com/maps/api/directions/json?origin=Brooklyn&destination=Queens&sensor=false&departure_time=1343641500&mode=transit
And of course the doc says the API uses UTC/GMT:
the desired time of departure as seconds since midnight, January 1, 1970 UTC
Poor Writing
The confusion stems from the poor writing in that documentation page. They need to append a crucial "UTC" or "GMT" to that "9:45 am". Mentioning New York and 9:45 in the same breath implies local time, whereas that example is truly 5:45 in the morning local time in Brooklyn.
The below request searches for Transit Directions from Brooklyn, New York to Queens, New York. When requesting transit directions, be sure to specify either a departure_time or arrival_time.
Note that in this example the departure time is specified as July 30, 2012 at 09:45 am. Update the parameter to a point in the future before submitting the request.
Old Versus New Numbers
Old number: 1343605500 (reported in the answer by davidg, and by googling)
New number: 1343641500 (found 2013-12)
Number if they had actually meant 9:45 in New York: 1343655900.
Example Code
I don't do JavaScript. So instead, I present some Java code using the sophisticated Joda-Time 2.3 date-time handling library running in Java 7. I use both the old (erroneous) and new (correct) numbers to show the date-time in both UTC and New York time zones. Furthermore, I calculate the number of seconds since epoch would have been used to get to 9:45 am July 30 2012 in New York, to produce a third number of seconds.
The Google API uses seconds, while Joda-Time uses milliseconds, so I multiply or divide by a thousand.
// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// import org.joda.time.*;
DateTimeZone timeZone_NewYork = DateTimeZone.forID( "America/New_York" );
// On this page:
// https://developers.google.com/maps/documentation/directions/#ExampleRequests
// …look for the following two paragraphs…
// --
// The below request searches for Transit Directions from Brooklyn, New York to Queens, New York. When requesting transit directions, be sure to specify either a departure_time or arrival_time.
// Note that in this example the departure time is specified as July 30, 2012 at 09:45 am. Update the parameter to a point in the future before submitting the request.
// --
// Below that text, find this URL:
// http://maps.googleapis.com/maps/api/directions/json?origin=Brooklyn&destination=Queens&sensor=false&departure_time=1343641500&mode=transit
// Extract that departure time of 1,343,641,500 seconds since the Unix Epoch of beginning of 1970 UTC.
// Apparently in the past that page erroneously used the number 1343605500 where today it uses 1343641500.
// Use the correct number found on that page today, 2013-12-25: 1343641500.
DateTime dateTimeInUtcWithNewNumber = new DateTime ( ( 1343641500L * 1000L ), DateTimeZone.UTC );
DateTime dateTimeInNewYorkWithNewNumber = dateTimeInUtcWithNewNumber.toDateTime( timeZone_NewYork );
System.out.println( "dateTimeInUtcWithNewNumber: " + dateTimeInUtcWithNewNumber );
System.out.println( "dateTimeInNewYorkWithNewNumber: " + dateTimeInNewYorkWithNewNumber );
// Use the old erroneous number previously found on that page: 1343605500.
DateTime dateTimeInUtcWithOldNumber = new DateTime ( ( 1343605500L * 1000L ), DateTimeZone.UTC );
DateTime dateTimeInNewYorkWithOldNumber = dateTimeInUtcWithOldNumber.toDateTime( timeZone_NewYork );
System.out.println( "dateTimeInUtcWithOldNumber: " + dateTimeInUtcWithOldNumber );
System.out.println( "dateTimeInNewYorkWithOldNumber: " + dateTimeInNewYorkWithOldNumber );
// Calculating the number that should have been used if the Google team had actually meant 9:45 AM local time in New York: 1343655900.
DateTime dateTimeInNewYork_2012_07_30_09_45 = new DateTime ( 2012, 7, 30, 9, 45, 0, timeZone_NewYork );
System.out.println( "dateTimeInNewYork_2012_07_30_09_45: " + dateTimeInNewYork_2012_07_30_09_45 );
System.out.println( "dateTimeInNewYork_2012_07_30_09_45 in seconds since Unix epoch: " + ( dateTimeInNewYork_2012_07_30_09_45.getMillis() / 1000L ) );
When run…
dateTimeInUtcWithNewNumber: 2012-07-30T09:45:00.000Z
dateTimeInNewYorkWithNewNumber: 2012-07-30T05:45:00.000-04:00
dateTimeInUtcWithOldNumber: 2012-07-29T23:45:00.000Z
dateTimeInNewYorkWithOldNumber: 2012-07-29T19:45:00.000-04:00
dateTimeInNewYork_2012_07_30_09_45: 2012-07-30T09:45:00.000-04:00
dateTimeInNewYork_2012_07_30_09_45 in seconds since Unix epoch: 1343655900

Real world examples of a kind of "sorted" data

Consider a sorted list of numbers which is "cut," so that it is increasing except for one jump. For instance the order might be,
11, 12, 13, 14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
What kinds of data naturally have this representation, with one or possibly many "cuts" obscuring the default ordering? The only one I can think of is a deck of cards, but I was asked to produce examples of data that might look like this in an interview. Weeks later, and I still can't think of any, but my curiosity prevails.
Is there a special name for this kind of data? I tried googling "cut data" but that obviously didn't work.
All insight is appreciated.
[Edit] From the discussions below this appears to have some interesting relationships with symmetry groups, and what sorts of rearrangements are possible with just the cut operation. I may have to ask my local mathematicians what I can do with this.
I can think of a few off the top of my head.
The first is the hour of the day as it rolls into a new day: ... 22 23 0 1 2 ....
The second is the alpha ordering on file names: pax1 pax10 pax11 ... pax19 pax2 pax20 ....
Yet another is the months of the financial year (in Australia, most companies close off their financial year at the end of June): 7 8 9 10 11 12 1 2 3 4 5 6.
After a quick analysis, it's obvious to see that any sequence of "cuts" results in a single cut with respect to a different index. In fact, it is only the most recent cut point that matters, as that value will end up at the front of the list, and it will be equivalent to a cut of this data from the original index of that element.
So not so interesting.

Timezones in MySQL

I'm playing with timezones in MySQL.
I need to assign people to timezones, and so I looked in mysql.time_zone_data.
Australia seems to have 5 independent timezones [1], so why does mysql.time_zone_data have 23 options?
Australia/ACT
Australia/Adelaide
Australia/Brisbane
Australia/Broken_Hill
Australia/Canberra
Australia/Currie
Australia/Darwin
Australia/Eucla
Australia/Hobart
Australia/LHI
Australia/Lindeman
Australia/Lord_Howe
Australia/Melbourne
Australia/NSW
Australia/North
Australia/Perth
Australia/Queensland
Australia/South
Australia/Sydney
Australia/Tasmania
Australia/Victoria
Australia/West
Australia/Yancowinna
[1] http://www.timetemperature.com/australia/australia_time_zones.shtml
The same reason, why there are several options in your OS, ...
Not everyone knows in which timezone his town is. So there are some huge cities (which are in the same zone) for selection. So you can look for a city near your location and automatically select the correct timezone.
For example: Berlin and Munich are in the same zone as well as Canberra and Sydney
why does mysql.time_zone_data have 23 options?
Usually because each of those mini-regions has historically had different time rules. They may be using the same timezones now, but if you want to reliably convert a time that might be in the past, you'll need to know which exact set of rules the locale has not just now, but for as far back in history as timezones have been stably legislated.
This is what makes timezone databases so absurdly large. Timezones are a horror.

Calculate date from numeric value

The number 71867806 represents the present day, with the smallest unit of days.
Sorry guy's, caching owned me, it's actually milliseconds!
How can I
calculate the currente date from it?
(or) convert it into an Unix timestamp?
Solution shouldn't use language depending features.
Thanks!
This depends on:
What unit this number represents (days, seconds, milliseconds, ticks?)
When the starting date was
In general I would discourage you from trying to reinvent the wheel here, since you will have to handle every single exception in regards to dates yourself.
If it's truly an integer number of days, and the number you've given is for today (April 21, 2010, for me as I'm reading this), then the "zero day" (the epoch) was obviously enough 71867806 days ago. I can't quite imagine why somebody would pick that though -- it works out to roughly 196,763 years ago (~194,753 BC, if you prefer). That seems like a strange enough time to pick that I'm going to guess that there's more to this than what you've told us (perhaps more than you know about).
It seems to me the first thing to do is verify that the number does increase by one every 24 hours. If at all possible keep track of the exact time when it does increment.
First, you have only one point, and that's not quite enough. Get the number for "tomorrow" and see if that's 71867806+1. If it is, then you can safely bet that +1 means +1 day. If it's something like tomorrow-today = 24, then odds are +1 means +1 hour, and the logic to display days only shows you the "day" part. If it's something else check to see if it's near (24*60, which would be minutes), (24*60*60, which would be seconds), or (24*60*60*1000, which would be milliseconds).
Once you have an idea of what kind of units you are using, you can estimate how many years ago the "start" date of 0 was. See if that aligns with any of the common calendar systems located at http://en.wikipedia.org/wiki/List_of_calendars. Odds are that the calendar you are using isn't a truly new creation, but a reimplementation of an existing calendar. If it seems very far back, it might be an Julian Date, which has day 0 equivalent to BCE 4713 January 01 12:00:00.0 UT Monday. Julian Dates and Modified Julian dates are often used in astronomy calculations.
The next major goal is to find Jan 1, 1970 00:00:00. If you can find the number that represents that date, then you simply subtract it from this foreign calendar system and convert the remainder from the discovered units to milliseconds. That will give you UNIX time which you can then use with the standard UNIX utilities to convert to a time in any time zone you like.
In the end, you might not be able to be 100% certain that your conversion is exactly the same as the hand implemented system, but if you can test your assumptions about the calendar by plugging in numbers and seeing if they display as you predicted. Use this technique to create a battery of tests which will help you determine how this system handles leap years, etc. Remember, it might not handle them at all!
What time is: 71,867,806 miliseconds from midnight?
There are:
- 86,400,000 ms/day
- 3,600,000 ms/hour
- 60,000 ms/minute
- 1,000 ms/second
Remove and tally these units until you have the time, as follows:
How many days? None because 71,867,806 is less than 86,400,000
How many hours? Maximum times 3,600,000 can be removed is 19 times
71,867,806 - (3,600,000 * 19) = 3,467,806 ms left.
How many minutes? Maximum times 60,000 can be removed is 57 times.
3,467,806 - (60,000 * 57) = 47,806 ms left
How many seconds? Maximum times 1,000 can be removed is 47 times.
47,806 - (1,000 * 47) = 806
So the time is: 19:57:47.806
It is indeed a fairly long time ago if the smallest number is in days. However, assuming you're sure about it I could suggest the following shell command which would be obviously not valid for dates before 1st Jan. 1970:
date -d "#$(echo '(71867806-71853086)*3600*24'|bc)" +%D
or without bc:
date -d "#$(((71867806 - 71853086) * 3600 * 24))" +%D
Sorry again for the messy question, i got the solution now. In js it looks like that:
var dayZero = new Date(new Date().getTime() - 71867806 * 1000);