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.
Related
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.
I have a script which is fed dates in numerous different formats.
I want to save these dates as timestamps so they can easily be manipulated/ordered.
When i try an convert a mm-dd-yyyy type date to a timestamp, it fails.
When the script runs, it does not know what format it will be fed, and as such this cannot be specified. Near all other formats of date seem to be converted fine.
Could anyone advise how to fix this, or alternatively an alternative way that all date formats can be converted to an orderable, consistent format that can be manipulated?
Many Thanks
It sees strings with - in them as dd-mm-yyyy and / as mm/dd/yyyy.
See also this question and the comments on the documentation.
Possible solutions / workarounds:
on php 5.3, use date_create_from_format
on older php and not on windows, use strptime
if neither can be used, either replace the - to / when necessary, or use one of the regexes suggested you can find through the linked question.
Note however that at some time you do need to know what the format is to start with. Computers are not mindreaders. They can't, and never will be able to, distinguish between mm-dd-yyyy and dd-mm-yyyy in the overlap ranges (both mm and dd <= 12) if you don't provide the distinction.
I have an application that uses time() to record the time a topic was posted. I have done this for a long time and the only glitch i ever had with the method was that the time was always off by an hour (mainly a DST issue i never looked into).
I'm want to switch to the DateTime method, since I'm also switching to Twig, which uses that date format when setting a timezone.
But from what I can see, you can't use timestamps to parse the date. my question is, how do you input a date and parse it and what format are they looking for if it isn't time()?
By the sounds of it your server's default timezone is UTC. I suggest you try changing the default_timezone setting in php.ini to something that applies DST. This will mean that when you use date(), the resulting output will be correctly adjusted for DST.
you can't use timestamps to parse the date
There is a way, if your php version is >=5.3 :
$time = time();//or other time
$date = DateTime::createFromFormat('U',$time);
but as a matter of fact it is somewhat weird to use timestamp as DateTime does not rely on it. You can parse a date string directly with the datetime constructor if your date is english or "french" (i.e d/m/y). You can also create your custom format.
how do you input a date and parse it and what format are they looking for if it isn't time()
if it is a a standard format date :
$date = new DateTime($yourString);//would throw an exception if the format is wrong
if it is a custom format, like DD/MM/YYYY 14h32mins
$date = DateTime::createFromFormat('d/m/Y h\hi\m\i\n\s',$yourString);
if($date === false){//if format does not fit
exit('Your wrong !');
}
I have an application that uses time() to record the time a topic was posted.
Very bad practice. In MySQL you have DateTime format (and each relational data base system has his own equivalent) to store date times and there are fully compatible with the DateTime constructor in PHP so migrate to it (use FROM_TIMESTAMP to change into DateTime).
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.
strtotime("25/03/1957") returns false. what will satisfy all of these date formats? i can't imagine how long it would take to actually make my own, so i hope there's already one out there you know of.
thanks!
Considering some dates are valid but can point to two different actual dates, no function will ever be able to "guess" the right format at all times...
To help with that, with PHP >= 5.3, a new function has been added : date_create_from_format -- but it doesn't exist with PHP < 5.3, unfortunately...
(See also DateTime::createFromFormat)
Still, in the example you took, the year 1957 is a possible source of problems : PHP generally works with UNIX Timestamps, when it comes to dates...
And, at least on 32-bits systems, those can only represent dates between 1970 and 2038 -- as they count the number of seconds since 1970-01-01.
To avoid this problem, it's often a good idea to use the DateTime class, with which (quoting) :
The date and time information is
internally stored as an 64-bit number
so all imaginable dates (including
negative years) are supported. The
range is from about 292 billion years
in the past to the same in the future.
(It will not solve the parsing problems with PHP < 5.3 ; but it'll solve the date-range problem...)
I've found that dateTime objects support a wider range of formats than the strtotime() function, and the timezone settings of your server also make a difference; but I ended up building a function that would replace '/' with '-' before using the string to date methods. I also test for valid, then try swapping the apparent dd and mm (25-03-2001 => 03-25-2001) if invalid before testing again.