Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correctly format times between client (javascript) and the server (PHP)

I have a date object in javascript that goes as follows:

var date = 2014-12-01T00:00:00.000Z

And if I do:

var date = new Date(date);
date.setUTCMonth(date.getUTCMonth()+1);

Then the toISOString() method shows the expected value:

2015-01-01T00:00:00.000Z

But when I send that date time string through a POST to a PHP script and parse it back to a date using the DateTime class, I get this:

2014-12-31 19:00:00 -0500

I have tried setting the timezone using the DateTimeZone class and setting the timezone to my own and UTC without luck:

new DateTime($_POST['DateTime'],new DateTimeZone('America/Mexico_City'));
new DateTime($_POST['DateTime'],new DateTimeZone('UTC'));

Is there a way to set the timezone in javascript, using the Date class? Is there another way to work around this? I have small if not zero experience at all dealing with timezones.

Update:

Here's my ISO-formatted time string as per the toISOString() method (javascript):

2014-09-01T00:00:00.000Z

And here are the contents of my $_POST var as per print_r():

Array (
    [DateTime] => 2014-09-01T00:00:00.000Z
)

Here's the output of my formatter function, using the '%c' format (es_MX locale):

dom 31 ago 2014 19:00:00 CDT

And the mentioned formatter function:

function formatDate($date) {
    return utf8_encode(strftime('%c', $date->getTimestamp()));
}
like image 447
arielnmz Avatar asked Apr 14 '26 13:04

arielnmz


2 Answers

I think when you send the date-string, it's somehow in different format. At least when I tested this, it works as expected:

$a = new DateTime('2015-01-01T00:00:00.000Z');
echo $a->format('Y-m-d H:i:s'); // Outputs '2015-01-01 00:00:00'

Demo here.

like image 141
nhaa123 Avatar answered Apr 17 '26 02:04

nhaa123


The issue you are getting is that when you use the following format

$date = '2015-01-01T00:00:00.000Z'; 

You are specifying a timezone.

Notice the "Z" at the end of your date, using it is the equivalent of "nautical timezone (GMT)"

Therefore when you try to run this code, you will get the exact same date which is not what you expect even when you have specified the DateTimeZone as a constructor parameter.

$dateTime = new DateTime($date, new DateTimeZone('America/Mexico_City')); 
echo $dateTime->format('c'). "\n"; // 2015-01-01T00:00:00+00:00

$dateTime = new DateTime($date, new DateTimeZone('UTC')); 
echo $dateTime->format('c'). "\n"; //2015-01-01T00:00:00+00:00

This is expected PHP behavior and is documented in the DateTime::__construct documentation under the $timezone parameter:

Note:

The $timezone parameter and the current timezone are ignored when the $time parameter either is a UNIX timestamp (e.g. @946684800) or specifies a timezone (e.g. 2010-01-28T15:00:00+02:00).

In your case you are specifying a timezone directly with in your date (the "Z") and this is why the DateTimeZone object is ignored.

To avoid this and set a custom time zone either set it in the date time string or get rid of the Z.:

$date = '2015-01-01T00:00:00.000';
$dateTime = new DateTime($date, new DateTimeZone('America/Mexico_City'));
echo $dateTime->format('c'). "\n"; // 2015-01-01T00:00:00-06:00

$dateTime = new DateTime($date, new DateTimeZone('UTC')); 
echo $dateTime->format('c'). "\n"; // 2015-01-01T00:00:00+00:00

$date = '2015-01-01T00:00:00.000 America/Mexico_City';
$dateTime = new DateTime($date);
echo $dateTime->format('c'). "\n"; //2015-01-01T00:00:00-06:00

See the code working for different versions of PHP here: Demo

Also take a look at this related question I asked recently: PHP DateTime Timezones - Constructor vs Setter method

like image 25
Onema Avatar answered Apr 17 '26 02:04

Onema



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!