You may think to yourself, Oh I understand timezone, I fly a lot and timezone is easy to me. Try to think deeper and answer the question that no one can answer: What is time
Time is not a thing, it is actually an imaginary system we create to keep track things and collaborate. In fact the time system has been always developed and updated through human history.
The current system we all use is solar calendar base on solar year. One solar year is 365 days, 5 hours, 48 minutes, 45 seconds. No it is not 365 days exactly. There fore for every 4 years we get an extra day on 29th February to make up the difference (Leap year). As for the year we are in 2019, why? year 0 is the year of Christ
I am a software developer, in computer since we also have our own significant time 00:00:00 Thursday, 1 January 1970 UTC. It is the start of UNIX time. UTC (Coordinated Universal Time) is a standard used to divide world into zones. It has 24 zones. The time of GMT (Greenwich Mean Time) is used as the reference point for zone 0. zones to the east can be represented as GMT +N. Zones to the west can be represented as GMT -N
So at a single point of time on earth. When the time on GMT is 2019-05-01 12:00:00, Time in Beijing is 2019-05-01 20:00:00 GMT+8
Ok enough background knowledge. Let’s get to the real problem.
Imagine you have a online chat room, messages need to be tracked with time. A person in New York send a message to another person in Sydney. Your server is in Singapore. Message is send across almost intently. And you need to store a time on both the server and user device.
For example the client is using JavaScript. It is a web application.
var unixTime = Date.now();
//1558941152248
var current = new Date(unixTime);
console.log(current.toString());
//'Mon May 27 2019 17:12:58 GMT+1000 (Australian Eastern Standard Time)'
console.log(current.toUTCString());
//'Mon, 27 May 2019 07:13:34 GMT'
console.log(current.toISOString());
//'2019-05-27T07:13:46.994Z'
console.log(current.getTimezoneOffset());
//-10
So you can use toString() to display time in local time zone, and use toUTCString() ti display GMT+0 timezome. toISOSting() is the international standard to display date and time, also in UTC
An important method is Date.parse(), it return the UNIX time and converting timezone according to the string format.
var GTMTimeStamp = Date.parse('2019-05-27T07:00:00.000+0000');
console.log(GTMTimeStamp);
//1558941101866
var GTMTime = new Date(GTMTimeStamp)
//When create from timestamp, it always assume in UTC
console.log(GTMTime.toString());
//Mon May 27 2019 17:00:00 GMT+1000 (Australian Eastern Standard Time)
Another interesting function to know is getTimezoneOffset(), which returns your time zone offset in minus. However you can not set you timezone. This is because when JavaScript operates on Browser, the current time and timezone is base on your system time. you can still change the timezone by changing you system or browser setting. And if you really need to play with timezone, there are libraries that allows your to do it, eg Moment.js
Now we can send time across the internet. Let all those formats settle in for a minute before we make a decision. Ok, let’s use the international standard toISOString() because it sounds official. (Huge mistake!)
2019-05-27T07:13:46.994Z
This is format. it always refers to GMT +0000. when the message receive on the server, we can start to process it.
All through the server is in Singapore, we want to save the date in database in UTC, not Singapore local time zone. If we ever need to migrate our server to another place, this is one less thing to worry about.
Now let parse the ISO string we sent from JavaScript in PHP
DateTime is the class php handles date and time. It provides a function to convert string into php DateTime object.
If a timezone is not set, the function will parse it using default system timezone on your server. usually set in php.ini
$date = DateTime::createFromFormat(DateTime::ISO8601,'2019-05-27T07:13:46.994Z');
Boom! There is an error. The function createFromFormat() return false. what Happened?
It turns out that DateTime::ISO8601 format is not actual ISO, what? PHP.net actually has it documented
Note: This format is not compatible with ISO-8601, but is left this way for backward compatibility reasons. Use
DateTime::ATOM
orDATE_ATOM
for compatibility with ISO-8601 instead.
The format is still wrong! No one have told you that the format from js toISOString() will match PHP DateTime::ISO8601 format.
OK let’s dig out about the format.
The standard in JavaScript is called ISO-8601 and the format is: YYYY-MM-DDTHH:mm:ss.sssZ
However you can not copy paste this format here, it is not in php representation. Finally after another hour of reading https://www.php.net/manual/en/datetime.createfromformat.php. you find out the format you need!
Y-m-d\TH:i:s.uP
$date = DateTime::createFromFormat("Y-m-d\TH:i:s.uP",'2019-05-27T07:13:46.994Z');
echo $date->format(DateTime::ATOM);
//2019-05-27T07:13:46+00:00
After all of this, It makes me feel bad about both Javascript and PHP, and makes me wonder how other languages handle those international standard?