How can I change the timezone of a date string? - php

I would like to change the timezone of a time like:
2015-08-24 01:30:40
so that it's in the America/Los_Angeles timezone, but the code below isn't working as expected:
$timedate = date_timezone_set(
date_create_from_format('Y-m-d h:i:s A', $row[timezone]),
new DateTimeZone('America/Los Angeles')
);
$row[timezone] successfully returns 2015-08-24 01:30:40 on it's own, but when I do it like this to try to change the timezone, it doesn't work.
All PHP code after that doesn't run. I have done lots of searching, but I can't figure out how to get this to work properly so can someone tell me what I am doing wrong?

Your call to date_create_from_format includes an A at the end of the format string - that looks specious to me, given that your value doesn't end with am or pm. Your use of h looks unlikely to be correct too, as that's for a 12-hour hour-of-day, which isn't useful when you don't have an am/pm indicator. I suspect you want a format of
Y-m-d H:i:s
That appears to match your sample string better...
Additionally, as noted in comments, your time zone ID should be 'America/Los_Angeles' rather than 'America/Los Angeles'.
I would also separate the various calls you have in this single large line of code, to make it easier to diagnose - that way you could tell that it's the parsing that's failing, rather than anything to do with the time zone. You have three separate operations here:
Parse a string to a datetime
Create a time zone object
Set the time zone in the datetime
Keeping those three in separate statements will make the code easier to read and easier to maintain. (In particular, you'd be able to find and correct these two problems independently...)

Related

Convert From MediaWiki Time Format To Unix Timestamp In PHP [duplicate]

This question already has answers here:
Convert one date format into another in PHP
(17 answers)
Closed 15 days ago.
MediaWiki (the free software behind Wikipedia) stores database timestamps in a unique binary(14) format for fields of the database. This is described further in their timestamp documentation.
The format of timestamps used in MediaWiki URLs and in some of the
MediaWiki database fields is yyyymmddhhmmss. For example, the
timestamp for 2023-01-20 17:12:22 (UTC) is 20230120171222. The
timezone for these timestamps is UTC.
I have also seen a similar timestamp format in other places such as URLs for the Internet Archive. I am regularly needing to compare these timestamps against timestamps which are stored in a standard Unix timestamp format (seconds from the Unix epoch). I believe this should be a common format so it surprises me that I can't find a ready-made solution to easily convert from the MediaWiki format to a Unix timestamp.
What I'm most interested in is the best way to do this conversion. That is:
Relatively short/simple to understand code.
Most efficient algorithm.
Does detect errors in original format.
There is apparently a function that MediaWiki includes for conversion named "wfTimestamp" however I haven't been able to locate this function itself or the source code online and I understand it has a large number of unnecessary features beyond the simple conversion. One potential solution may be to remove other parts of that function, but I still don't know if that function is the optimal solution or if there's a better way. There are lots of questions on the more general conversion to timestamps but I'm hoping for something specific to this format. I've thought of a lot of ways to solve it such as a regular expression, mktime after string split, strtotime, etc... but I'm not sure which will be fastest for this particular task/time format if it had to be done a lot of times. I am assuming since this format exists in at least two places, an optimal solution for this specific format conversion could be useful for others as well. Thanks.
I think this is what you're probably looking:
$timestamp = strtotime("20230120171222");
// 1674234742
The Unix timestamp that this function returns does not contain information about time zones. In order to do calculations with date/time information, you should use the more capable DateTimeImmutable.
Please see here: https://www.php.net/manual/en/function.strtotime.php
You can use DateTime::createFromFormat function with specified format.
$date = DateTime::createFromFormat("YmdHis", "20230120171222", new \DateTimeZone('UTC'));
$timestamp = $date->getTimestamp();
I'm not sure that you can find more optimised way, because even if you will parse this manually, you have to consider that there are leap years and not every day has exactly 24 hours. PHP does it for you.
In order to interpret the string "20230120171222" as UTC time, the time zone must be specified with strtotime or the default time zone must be set to UTC.
$dateStr = "20230120171222";
$timestamp = strtotime($dateStr.' UTC');
var_dump($timestamp); //int(1674234742)
See this example for comparison.

Date() returns a year in future instead of correct year

date('Y-m-d H:i:s','1345453380000'); should return 2012-08-20 09:03:00 but instead it returns 44605-09-21 02:00:00
I understand the time difference of one day may be due to me not specifically setting timezone in the conversion, but 38k years in the future is a bit off, where am I doing it wrong?
Is it the trailing zeros?
I appreciate any pointers... (BTW That timestamp is how certain apps deliver them, I did not craft it myself)
When I getdate() that same timestamp the same issue happens, so I don't think my code is wrong, rather something is problematic with the trailing 0's...
But even if I use the from human to timestamp converted, with epoch converter, I get wrong results.
ONLY if I remove ALL zeros it seems to return a proper date.
Why?
Note again, the timestamp is how it comes from an online "diary" App, and Epoch converter IS able to read it!
(https://www.epochconverter.com/)
What is happening here is that the timestamp is in milliseconds, but PHP expects seconds. Epoch converter works fine with both seconds and milliseconds. What you have to do is call date('Y-m-d H:i:s', ($timestamp/1000));
Look at this demo.
date('Y-m-d H:i:s',(1345453380000/1000));
Above code converts milliseconds to seconds.

Half hour time zone designations when parsing input strings

My Php server app receives data from a mobile application, including date/time strings.
One of these strings recently caused an exception when parsing the string into a DateTime instance because the timezone was formatted like this:
2017-03-14 17:56:42GMT+05.500
strtotime("2017-03-14 17:56:42GMT+05.500")
returns false, while
strtotime("2017-03-14 17:56:42GMT+05")
returns a epoch timestamp.
What is the best practice for handling such strings?
I could grep replace and offset by half an hour on the resulting timestamp, then designate a valid (by php standards) timezone.
It feels like I'm heading for a big pile of mud - maybe some kind person have a composer library to the rescue
So the problem was that my php app couldn't understand the 'GMT+05.500' time zone part, but can understand 'GMT+0530'.
I can use the regular expression below to find out if my input needs some string replacing and convert any decimal to the relevant offset in minutes
if(preg_match('/\+0?[\d]([,.:;_ ])([\d]{3})$/', $datetime, $matches){
//... convert 'GMT+05.500' to 'GMT+0530' by using a switch or actual calculation
Currently I haven't been able to find out if user-agents will use a locale/cultural specific separator character, so I assume a range og possibilities (the ',.;:_ ' part of the regexp). Maybe there is an ISO standard for how to format this, but user-agents being user-agents... :)
'GMT+0530' will also affect the resulting epoch timestamp when using strtotime() by the proper 30 minutes, so no data is lost.

Yii custom date format (pattern)

Is there a way to specify your own date pattern besides the included ones (small, medium, full). The main point here is that it should work with i18n. I've tried a couple of things but I couldn't get it to work...
Yii::app()->dateFormatter->format("l d/m/Y",$slide->date_start);
I know about strftime but the problem here is that different hosting providers use different locale string... and you have to customize it...
I'm looking for an elegant way of doing this.
I'd like to display the date in l d/m/Y form...
Update:
Never mind... I've just found out that dateFormatter doesn't use standard php date format...
I think you should measure time solely in Unix Time because Timezones & date formats are a presentation-layer problem. Unix time is always UTC & It's a single number, so easier to pass around in code.
As far the problem of "hosting providers use different locale string", just ask the user his timezone & display according to that. far less error-prone than trying to guess.
For date formatting, have a look at YII's format()
Hope it answers your question
Here's a related yii forum discussion
The yii forum solution worked for me to avoid raw SQL NOW() statements but still produce database-friendly date strings with PHP date() and time() functions which otherwise return integers.
In protected/config/main.php:
...
'params'=>array(
'mysqlDateTimeFormat' => 'Y-m-d H:i:s', # ':u' adds microsecond precision,
...
Then, wherever you want to put a date-time string into a model field use
$myModel->myDate = date(Yii::app()->params['mysqlDateTimeFormat']);
Obviously you can enter the date/time format into the date (or time) functions directly if you prefer.

big values for strtotime()

I tried
echo strtotime('129:00');
but it will have an empty output.
This
echo strtotime('03:00');
will have 1288339200 as the output.
I guess strtotime() won't accept huge values?? What's the alternative for strtotime() that will accept 129:00.
The alternative is to give strtotime() a time that actually means something. I know of no clocks that go up to 129 o'clock myself.
That's not to say there aren't any but I'm pretty old and I've traveled a bit. I'm sure I would have noticed something like this :-)
See the docs, which state:
The function expects to be given a string containing a US English date format
and end up pointing you here for valid time formats.
strtotime parses a date or a time (of the day, 24h clock) into UNIX timestamps. 129:00 is neither a date nor a time, so it returns false. It's not "too big", it's simply invalid input.

Categories