Convert a String with GMT to DateTime Format - php [duplicate] - php

This question already has answers here:
Convert one date format into another in PHP
(17 answers)
Closed 3 years ago.
I face this problem to integrate bKash Online Payment Gateway API.
The Documentation is here - https://developer.bka.sh/docs/create-payment-1.
In 'Create Payment' section bKash return paymentCreateTime string as following format.
2020-01-07T11:55:34:438 GMT+0600
How can I convert it to 2020-01-07 11:55:34 to save in MySQL?
I find a solution like following way.
$input = "2020-01-07T11:55:34:438 GMT+0600" // "2020-01-07T11:55:34:438 GMT+0600"
$timestamp = substr($input,0,19); // "2020-01-07T11:55:34"
$mysql = date_format(date_create($timestamp),'Y-m-d H:i:s'); // "2020-01-07 11:55:34"
But I need a solution without substr() function.

You can use createFromFormat() to directly parse your string.
Importantly, you'll need to escape T and GMT.
Everything else in https://www.php.net/manual/en/datetime.createfromformat.php
$input = '2020-01-07T11:55:34:438 GMT+0600';
$date = DateTime::createFromFormat('Y-m-d\Th:i:s:u \G\M\TO', $input);
echo $date->format('Y-m-d h:i:s');
This will cleanly deliver an object that you can format however you like.
Here is a demonstration:
$date = new DateTime("now");
echo $date->format('Y-m-d\Th:i:s:u \G\M\TO');
echo "\n---\n";
$input = '2020-01-07T11:55:34:438 GMT+0600';
echo $input;
echo "\n---\n";
$date = DateTime::createFromFormat('Y-m-d\Th:i:s:u \G\M\TO', $input);
echo $date->format('Y-m-d h:i:s');
echo "\n===\n";
var_dump($date);
Demonstration Output:
2020-01-07T10:12:53:000245 GMT+0100
---
2020-01-07T11:55:34:438 GMT+0600
---
2020-01-07 11:55:34
===
object(DateTime)#2 (3) {
["date"]=>
string(26) "2020-01-07 11:55:34.438000"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+06:00"
}

You can use it like this
date_default_timezone_set("Asia/Dhaka");
$mysql1 = date_format(date_create(strtotime($input)),'Y-m-d H:i:s');
it will print 2020-01-07 09:17:23

Related

parse int to datetime with carbon

I have an example value of : 20160530105130
Which I want to convert to a datetime.
I have tried Carbon::createFromFormat('Ym',$value)
But that just errors.
I also tried with timestamp, but again error.
Anyone have an idea how I can achive this?
Create a DateTime or Carbon object from the string and use the year and month there.
$str = '20160530105130';
$dt = DateTime::createFromFormat('!Ym????????',$str);
var_dump($dt);
//object(DateTime)#2 (3) { ["date"]=> string(26) "2016-05-01 00:00:00.000000"
Demo: https://3v4l.org/bOJdU
With carbon:
$str = '20160530105130';
$dt = Carbon::createFromFormat('!Ym????????',$str);
echo $dt; //2016-05-01 00:00:00
Alternatively, the string can also be completely parsed with DateTime. The day and time can then be set to the desired values using the modify method. This variant makes it easier to read what is being done.
$str = '20160530105130';
$dt = date_create($str)->modify('first day of this month 00:00');
//object(DateTime)#2 (3) { ["date"]=> string(26) "2016-05-01 00:00:00.000000"
Carbon::createFromFormat('YmdHis', "$value")

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

PHP converting unknown datetime string to datetime object

I am having trouble with the following string which is supposed to be a datetime (response from an api).
2013-03-08T19:11:11.234+0000
I need to convert the string to ISO 8601.
The exact format should look like:
2016-03-01T12:00:00+00:00
If someone could help me do this in php would be great but I would be already more than happy if someone could identify the format (like yyyy-mm-ddThh:mm:ss).
It seems the API returns the time with milliseconds.
Try this:
$date = '2013-03-08T19:11:11.234+0000';
$format = 'Y-m-d\TH:i:s.uO';
$dt = DateTime::createFromFormat($format, $date);
echo $dt->format(DateTime::ISO8601);
Result:
2013-03-08T19:11:11+0000
EDIT
Based on comments on your answer, you need to convert such a time:
2016-03-01T11:01:51.126044 00:00
Since it's not possible to parse this format with DateTime, you need to make it readable first.
There are many ways to do this. What we need is to add a + before timezone, so that my code above work.
If you are sure the date you get from the API is always this format, and that there will always be only 1 space in the string, just replace the string with a space:
$date = '2016-03-01T11:01:51.126044 00:00';
str_replace(' ', '+', $date);
$format = 'Y-m-d\TH:i:s.uP';
$dt = DateTime::createFromFormat($format, $date);
echo $dt->format(DateTime::ISO8601);
This should work (note that here the timezone mask is P since there is a colon)
You can also use preg_replace() instead of DateTime, if you don't need the date for calculations:
$date = '2016-03-01T11:01:51.126044 00:00';
$date = preg_replace('`(\.[0-9]+\s)`', '+', $date);
echo $date;
This produces:
2016-03-01T11:01:51+00:00
If you need the date for calculation, just convert it to DateTime after:
$date = '2016-03-01T11:01:51.126044 00:00';
$date = preg_replace('`(\.[0-9]+\s)`', '+', $date);
$date = DateTime::createFromFormat(DateTime::ISO8601, $date);
var_dump($date);
This produces:
object(DateTime)#1 (3) {
["date"]=>
string(26) "2016-03-01 11:01:51.000000"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}
I suggest you to use Carbon: http://carbon.nesbot.com/docs/
echo Carbon::parse('2013-03-08T19:11:11.234+0000')->toAtomString();
Also, the format you want is ATOM, not ISO 8601. You could do #Arcesilas way, it should work too.

php/mysql: strToTime error manipulating dates

I have some code for rendering dates that was working great for a couple of years and is now broken. I don't know if it has something to do with my host changing version of PHP or somehow an error crept in.
Basically, dates such as 11/30/15 are now getting rendered as 11/30/-1
Here is an example of what is going on:
$olddate = $row['date'];//in database this looks like:0000-00-00 00:00:00
$newdate = nicedate($olddate);
echo "starting date time: ".$olddate;//displays as 'starting date time: 0000-00-00 00:00:00'
echo "after transforming it with nice date: ".$newdate; //displays as 'after transforming it with nice date: 11/30/-1'
I also tried just running strtotime and get this:
echo "after transforming it with strtotime: ".nicedate($row['starttime']);//-62169966000
// gets nice data
function nicedate($datetime) {
$niceDate = strtotime($datetime);
$niceDate = date("m/d/y",$niceDate);
return $niceDate;
}
As you can see here https://3v4l.org/8gqCK it really depends on which PHP version you are using.
PHP will render the string 0000-00-00 00:00:00 to -0001-11-30 00:00:00.000000
This is an example output from DateTime:
object(DateTime)#1 (3) {
["date"]=>
string(27) "-0001-11-30 00:00:00.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(13) "Europe/Berlin"
}
The OUTPUT also depends on the time zone:
object(DateTime)#1 (3) {
["date"]=>
string(27) "-0001-11-29 23:06:32.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(3) "UTC"
}
This would output:
...with nice date: 11/29/-1
And here strtotime():
int(-62169987208)
So you see the date function were changed on different version, what you can do now ist just to check if the date is 0000-00-00 00:00:00:
function nicedate ( $datetime ) {
if( $datetime == "0000-00-00 00:00:00" ) return "Some value or false?";
...
...
}
You also have a look at the MySQL mode: NO_ZERO_IN_DATE
Updated approach due to the comments below:
function nicedate( $datetime ) {
if( !validateDate( $datetime ) ) return "something";
$dateTimeObject = DateTime::createFromFormat('Y-m-d H:i:s', $datetime );
return $dateTimeObject->format( "m/d/y" );
}
function validateDate($date) {
$d = DateTime::createFromFormat('Y-m-d H:i:s', $date);
return $d && $d->format('Y-m-d H:i:s') == $date;
}
function was copied from this answer or php.net
This is because 0000-00-00.... is not a valid date. What happens is simple, from year, month, day,... is alway one (1) substracted from the last.
0000 -1 = -1// year
00 - 1 = 11// month, because 12 is the highest value that datetime recognizes as month
00 - 1 = 30// day, because 31 is the highest value that datetime recognizes as day
For hours, minutes, seconds,.. it's ok, because zero is a valid value for time.
That's why it is rendered like this: -0001-11-30 00:00:00.000000

PHP DateTime::createFromFormat doesn't parse ISO 8601 date time

Code speaks a million words:
php > echo strtotime("2010-12-07T23:00:00.000Z");
1291762800
echo date('c', 1291762800);
2010-12-08T00:00:00+01:00
php > var_dump(DateTime::createFromFormat('c', "2010-12-07T23:00:00.000Z"));
bool(false)
php > var_dump(DateTime::createFromFormat(DateTime::ISO8601, "2010-12-07T23:00:00.000Z"));
bool(false)
Any idea what's going on?
Btw, yes, new DateTime("2010-12-07T23:00:00.000Z") works fine. But I prefer to know what input I am getting.
There's a bug report that exactly describes your problem :)
https://bugs.php.net/bug.php?id=51950
Since 2016-08-07, the bug report has been marked as "not a bug". You need to use strtotime or new DateTime instead.
The constants that have been defined apply to both formatting and parsing in the same way, which forces your ways.
Parsing ISO8601 date, and also switching timezone:
// create ISO8601 dateTime
$date = DateTime::createFromFormat(DateTime::ISO8601, '2016-07-27T19:30:00Z');
// set to user's timezone
$date -> setTimeZone('Asia/Singapore');
echo $date -> format(DateTime::ISO8601);
// prints '2016-07-28T03:30:00+0800'
Nobody mentioned to use DATE_ATOM which is as far as i know phps most correct implementation of ISO 8601. It should at least work for the last 3 of these:
<?php
$dates = array(
"2010-12-07T23:00:00.000Z",
"2010-12-07T23:00:00",
"2010-12-07T23:00:00Z",
"2010-12-07T23:00:00+01:00",
(new \DateTime("now"))->format(DATE_ATOM)
);
foreach($dates as $d) {
$res = \DateTime::createFromFormat(DATE_ATOM, $d);
echo "try $d: \n";
var_dump($res);
echo "\n\n";
}
?>
To be able to parse all of them i wrote a tiny function:
<?php
function parse_iso_8601($iso_8601_string) {
$results = array();
$results[] = \DateTime::createFromFormat("Y-m-d\TH:i:s",$iso_8601_string);
$results[] = \DateTime::createFromFormat("Y-m-d\TH:i:s.u",$iso_8601_string);
$results[] = \DateTime::createFromFormat("Y-m-d\TH:i:s.uP",$iso_8601_string);
$results[] = \DateTime::createFromFormat("Y-m-d\TH:i:sP",$iso_8601_string);
$results[] = \DateTime::createFromFormat(DATE_ATOM,$iso_8601_string);
$success = array_values(array_filter($results));
if(count($success) > 0) {
return $success[0];
}
return false;
}
// Test
$dates = array(
"2010-12-07T23:00:00.000Z",
"2010-12-07T23:00:00",
"2010-12-07T23:00:00Z",
"2010-12-07T23:00:00+01:00",
(new \DateTime("now"))->format(DATE_ATOM)
);
foreach($dates as $d) {
$res = parse_iso_8601($d);
echo "try $d: \n";
var_dump($res);
echo "\n\n";
}
?>
As #Glutexo mentioned it works only if there are only 1 to 6 precision digits for the decimal part, too. Feel free to improve it.
try this:
DateTime::createFromFormat('Y-m-d\TH:i:sP', $date)
It is very strange and disappointing that this bug is still actual.
Here is a right pattern for parsing date with microseconds in decimal part of seconds:
Y-m-d\TH:i:s.uO
Usage:
$dateStr = '2015-04-29T11:42:56.000+0400'
$ISO = 'Y-m-d\TH:i:s.uO'
$date = DateTime::createFromFormat($ISO, $dateStr)
Simply :
$dt = new DateTime('2018-04-07T16:32:44Z');
$dt->format('Ymd'); // 20180407
Use DATE_ATOM rather than 'c' when formatting like #Steven said. This is how you work with ISO 8601 in PHP.
<?php
$now_date = new DateTime();
$now_iso_8601 = $now_date->format(DATE_ATOM);
echo "Now in ISO 8601 format: {$now_iso_8601}\n";
$date_from_string_and_format = date_create_from_format(DATE_ATOM, $now_iso_8601);
echo "ISO 8601 formatted string, back to DateTime object:\n";
var_dump($date_from_string_and_format);
prints
Now in ISO 8601 format: 2018-09-05T08:17:35-10:00
ISO 8601 formatted string, back to DateTime object:
object(DateTime)#2 (3) {
["date"]=>
string(26) "2018-09-05 08:17:35.000000"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "-10:00"
}
For the answer listed here https://stackoverflow.com/a/14849503/2425651
we can use this format "Y-m-d\TH: i: s.u+" to keep the microseconds.
$format = 'Y-m-d\TH:i:s.u+';
$value = '2017-09-21T10:11:19.026Z'; // jsDate.toUTCString();
var_dump(\DateTime::createFromFormat($format, $value));
This one works for me:
$date = (new DateTime)->setTimestamp(strtotime('2017-12-31T23:00:00.000Z'));
I've experienced this issue with POSTGRES default Time with timezone format and this was the format that fixed it for me:
Y-m-d H:i:s.uO
This works for me:
$timeStamp = "2020-12-10T14:54:25.618Z";
var_dump(DateTime::createFromFormat('Y-m-d\TH:i:s.v\Z', $timeStamp));
object(DateTime)#1 (3) {
["date"]=>
string(26) "2020-12-10 14:54:25.618000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(3) "UTC"
}
I am using follow function that allow multiple ISO8601 formats:
function fromISO8601($time, \DateTimeZone $timezone = null) {
// valid ISO time 2019-04-01T00:00:00.000+02:00
$t = \DateTime::createFromFormat('Y-m-d\TH:i:s.uO', $time) or
// ISO time without millis 2019-04-01T00:00:00+02:00
$t = \DateTime::createFromFormat('Y-m-d\TH:i:sO', $time) or
// ISO time without timezone 2019-04-01T00:00:00.000
$t = \DateTime::createFromFormat('Y-m-d\TH:i:s.u', $time, $timezone) or
// ISO time without millis and timezone 2019-04-01T00:00:00.000+02:00
$t = \DateTime::createFromFormat('Y-m-d\TH:i:s', $time, $timezone);
return $t;
}
here are all supported dates
var_dump(
fromISO8601('2019-04-01T00:00:00.000+02:00'),
fromISO8601('2019-04-01T00:00:00+02:00'),
fromISO8601('2019-04-01T00:00:00.000'),
fromISO8601('2019-04-01T00:00:00')
);
This code is benevolent for missing timezone and milliseconds and works in older php versions.

Categories