Convert atom timestamp with timezone in php - php

I have some json data which contains timestamps in atom format.
Some examples of timestamps:
2020-04-12T04:05:08.92949232Z
2020-03-24T22:59:13.447142853+01:00
I'm trying to convert these with 'date("Y-m-d g:i:s",strtotime($atom)' but It seems to have problems with the +timezone format.
It works fine with $atom = "2020-04-12T04:05:08.92949232Z".
But if $atom = "2020-03-24T22:59:13.447142853+01:00" I get 1970-01-01 12:00:00.
I've played around with DateTime::createFromFormat but I just cant get it to work.
Is this possible to parse without to much effort or do I have to shoot the guy creating the json files?

DateTime causes problems if there are more than 6 digits after the period.
You must limit the digits to a maximum of 6 after the decimal point, then the expressions will be accepted.
$strDate = '2020-03-24T22:59:13.447142853+01:00';
//reduce microseconds to a maximum of 6
$strDate = preg_replace_callback('~\.\d{7,}~',function($match){
return ltrim(sprintf('%0.6F',$match[0]),'0');
},$strDate);
$d = date_create($strDate);
var_dump($d);
//object(DateTime)#2 (3) { ["date"]=> string(26) "2020-03-24 22:59:13.447143" ["timezone_type"]=> int(1) ["timezone"]=> string(6) "+01:00" }

Related

Convert String to date (european to american) [duplicate]

This question already has answers here:
Convert one date format into another in PHP
(17 answers)
Closed 6 years ago.
I have a String on the form: "dd/mm-yyyy", where dd is day of the month with two digits, mm is the month represented with two digits, and yyyy is the year with four digits.
I need to store this in my database. Ive tried
$dato = date('d/m-Y' ,strtotime($_POST['dag'] )
But that clearly doesnt work. In my database the date displays as yyyy-mm-dd. How do I properly convert the String to the correct format?
strtotime not accept your time string format, so it return false. You can use DateTime::createFromFormat or date_create_from_format, manual here.
DateTime::createFromFormat('d/m-Y', $_POST['dag']);
check the live demo
<?php
var_dump(DateTime::createFromFormat('d/m-Y', '11/01-2017'));
putput:
object(DateTime)#1 (3) {
["date"]=>
string(26) "2017-01-11 14:34:53.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(3) "UTC"
}
Try to replace the / with a - like so:
$date = "02/04-2016";
$dateNew = str_replace("/","-",$date);
You can use DateTime::createFromFormat:
$time = '12/3-1987';
$data = DateTime::createFromFormat('d/m-Y', $time);
echo $data->format('Y-m-d'); //1987-03-12
sandbox

Why convert Timestamp '2016-10-06T09:50:54.000Z' with php

This code :
$timestamp = 2016-10-06T09:50:54.000Z;
How do I separate or convert from the timestamp into a date and time?
example :
TimeStamp 2016-10-06T09:50:54.000Z
Date 2016-10-06
Jam(GMT +7) 04:55:45
Please help to solve this problem. Thanks
$d = new DateTime('2016-10-06T09:50:54.000Z');
echo $d->format('Y-m-d\TH:i:s.u'); // 2016-10-06T09:50:54.000000
echo $d->format('Y-m-d'); // 2016-10-06
// convert to GMT+7 timezone
$d->setTimezone(new DateTimeZone('GMT+7'));
echo $d->format('h:i:s'); // 04:50:54
<?php
$timestamp = "2016-10-06T09:50:54.000Z";
$datetime = new Datetime('2016-10-06T09:50:54.000Z');
echo "Date".$datetime->format('Y-m-d')."<br>";
echo "Jam".$datetime->format('H:i:s');
?>
Take a look at this short example:
<?php
$datetime = new Datetime('2016-10-06T09:50:54.000Z');
var_dump($datetime->format('Y-m-d H:i:s'));
The output obviously is: string(19) "2016-10-06 09:50:54"
Using different format strings you can convert your date time object into whatever representation you want to. 'Y-m-d' will give the date in international format for example.
Take a look at the great documentation: http://php.net/manual/en/class.datetime.php
Not much of a mystery:
<?php
$timestamp = '2016-10-06T09:50:54.000Z';
$dt = new DateTime($timestamp);
var_dump($dt);
$dt->setTimezone(new DateTimeZone('Asia/Jakarta'));
var_dump($dt);
object(DateTime)#1 (3) {
["date"]=>
string(26) "2016-10-06 09:50:54.000000"
["timezone_type"]=>
int(2)
["timezone"]=>
string(1) "Z"
}
object(DateTime)#1 (3) {
["date"]=>
string(26) "2016-10-06 16:50:54.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(12) "Asia/Jakarta"
}
Unlike strings, giving format to a proper date is trivial.
I don't know what time zone Jam is but I suggest you assign a city so you can account for DST (I've used Asia/Jakarta in my sample code, the complete list can be found at List of Supported Timezones). Just relying on a UTC offset like +7 may make your code unreliable during the summer.

Why does DateTime::createFromFormat() fails and returns a boolean in my second example?

When I run this the first one is correctly created into a date. The second one fails, returning a boolean and so I cannot format. Is the time out of range?
//works correctly
$startDate = "2015-05-06 10:49:20.637133";
$start = DateTime::createFromFormat('Y-m-d h:m:s.u',$startDate);
echo $start->format('m/d/y');
//doesn't work correctly
$startDate = "2015-05-12 15:49:06.821289";
$start = DateTime::createFromFormat('Y-m-d h:m:s.u',$startDate);
echo $start->format('m/d/y');
Code to reproduce the error
Check DateTime::getLastErrors():
php > var_dump(DateTime::createFromFormat('Y-m-d h:m:s',"2015-05-12 15:49:06"));
bool(false)
php > var_dump(DateTime::getLastErrors());
array(4) {
["warning_count"]=>
int(1)
["warnings"]=>
array(1) {
[19]=>
string(27) "The parsed date was invalid"
}
["error_count"]=>
int(1)
["errors"]=>
array(1) {
[11]=>
string(30) "Hour can not be higher than 12"
Change the h to a big H, since the small one is 12-hours format and the big one is 24-hours format.
You can see all formats in the manual. And a quote from there:
h 12-hour format of an hour with leading zeros 01 through 12
H 24-hour format of an hour with leading zeros 00 through 23
Means right now your code fails, because there is no 15 in the 12 hour format.
In addition to the other answers, for standard formats understood by DateTime you don't need to create from a format:
$startDate = "2015-05-12 15:49:06.821289";
$start = new DateTime($startDate);
echo $start->format('m/d/y');

compare datetime with different timezone_type php

I'm trying to compare to DateTime objects in PHP.
$Time1 = DateTime::createFromFormat('UP', '1409900072+0200');
$Time2 = new DateTime('2014-09-05 07:54:32');
The Time2 use the defoult which is Europe/Copenhagen, comparing yields the following
if ($Time2 > $Time1){
echo "true \n";
} else {
echo "false \n";
}
true
object(DateTime)#1 (3) {
["date"]=>
string(19) "2014-09-05 06:54:32"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+02:00"
}
object(DateTime)#2 (3) {
["date"]=>
string(19) "2014-09-05 07:54:32"
["timezone_type"]=>
int(3)
["timezone"]=>
string(17) "Europe/Copenhagen"
}
The way I understand it is the actual local time for Time1 is 08:54:32, so how can I get the comparison at the same timezone?
Thanks in advance
The really weird part is your initial value of 1409900072+0200. If 1409900072 is a UNIX timestamp, passing a particular timezone with it makes little sense. And it seems to cause PHP to create the instance incorrectly; it creates the instance with the time set to the UTC value (6:54), but the timezone offset of +0200 (where the time should actually be 8:54).
Arguably this should be filed as a bug report; but arguably the input data is nonsensical to begin with.
If you're feeding in a UNIX timestamp, then ignore any timezone information it may contain and explicitly set the timezone to UTC, then it all works as expected:
$t1 = DateTime::createFromFormat('U+', '1409900072+0200', new DateTimeZone('UTC'));
$t2 = new DateTime('2014-09-05 07:54:32', new DateTimeZone('Europe/Copenhagen'));
var_dump($t1 > $t2); // true
Note that PHP before 5.3.9 seems to have problems with the createFromFormat call; you'll probably have to filter out the trailing timezone by hand if you need to support those versions.
Convert both DateTimes to UTC (setTimeZone('UTC')) and then compare them.
<?php
$Time1 = DateTime::createFromFormat('UP', '1409900072+0200');
$Time2 = new DateTime('2014-09-05 07:54:32');
// convert
$utc = new DateTimeZone('UTC');
$time1_utc = clone $Time1;
$time1_utc->setTimeZone($utc);
$time2_utc = clone $Time2;
$time2_utc->setTimeZone($utc);
var_dump($Time1,$Time2);
var_dump($time1_utc,$time2_utc);

date_create_from_format php on certain month and date does not return correct date

I have a function in php that uses the date_create_from_format function to convert dates in format 'Ym' to datetime. It works correctly except in one case I found today and I cant find the problem. The situation is the following:
Current date: 07/31/2014.
$period value: '201409' (as the month I want to do some calc on)
$newDateCreated = date_create_from_format('Ym', $period);
This returns a new datetime created but with the value of 10/01/2014 instead of 09/01/2014
If instead of setting the value 201409 I put 201411 or 201408 the new datetime is created correctly.
The only solution I found to this was to replace
$newDateCreated = date_create_from_format('Ym', $period);
for
$newDateCreated = date_create_from_format('Ymd', $period.'01');
I believe that this have to be something with the day of the month but I cant find the real problem. Any ideas about this?
Thanks in advance.
As from the manual:
If format does not contain the character ! then portions of the
generated time which are not specified in format will be set to the
current system time.
If format contains the character !, then portions of the generated
time not provided in format, as well as values to the left-hand side
of the !, will be set to corresponding values from the Unix epoch.
The Unix epoch is 1970-01-01 00:00:00 UTC.
Example
date_create_from_format('Ym', '201409');
// Tries '2014-09-31 15:59:45', but since that date doesn't exists
// that becomes '2014-10-01':
// object(DateTime)#62 (3) {
// ["date"] => string(19) "2014-10-01 15:59:45"
// ["timezone_type"] => int(3)
// ["timezone"] => string(16) "Europe/Amsterdam"
// }
date_create_from_format('!Ym', '201409');
// object(DateTime)#62 (3) {
// ["date"] => string(19) "2014-09-01 00:00:00"
// ["timezone_type"] => int(3)
// ["timezone"] => string(16) "Europe/Amsterdam"
// }

Categories