Hey, long story short I have inherited some terrible code. As a result a string comparison is buggy when comparing dates due to the format of the date. I am trying to convert the date to a valid DateFormat syntax so I can run a proper comparison.
These are some samples of the current format:
12/01/10 at 8:00PM
12/31/10 at 12:00PM
12/10/09 at 5:00AM
and so forth. I'd like to convert this to a YYYYMMDDHHMM format i.e 201012012000 for comparison purposes. If anyone can give me a quick regex snippet to do this that'd be appreciated as right now i'm hitting a brick wall for a regex. I can do it by exploding the string over several times etc but I'd rather do it in a more efficient manner.
Thanks!
Working with dates in strange formats is very easy with the DateTime class which was built into PHP 5.3.
No need for regex or anything fancy:
$date = DateTime::createFromFormat('m/d/y \a\t g:iA', '12/10/09 at 5:00AM');
print_r($date);
Once it is a date object you can have it in any format you want.
Related
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.
I am trying to get the date out of sentences in php.. so for example
I am trying to get 10/8/2006 out of
"This building was cleaned on the 8th of October 2006 after a huge storm."
There is a github function for it
https://github.com/etiennetremel/PHP-Find-Date-in-String but it fails in dates such as 1/5/2012.
I realize that given the varied nature of date strings, finding a date string in strings is so much tougher than just simple REGEX for a specific format, or simply strototiming a given string input..
does anyone have any good ideas?
Firstly, I would start by looking for a few basic patterns and extracting them with a few passes of regular expression (mm/dd/yy and mm/dd/yyyy with \d{2]/\d{2}/\d{2,4}, then look for others, like \d{1,2}(th|st|rd)? Jan(uary)?|Feb(ruary)?|Mar(ch)?|Apr(il)?|May|Jun(e)?|Jul(y)?|Aug(ust)?|Sep(tember)?|Oct(ober)|Nov(ember)?|Dec(ember) etc)
It will almost certainly be quicker to write a few regular expressions and do it in passes than write one massive one.
Then, pass the stuff you extracted in to strtotime to get yourself a usable unix timestamp and do with what you need from that.
Caveats:
I haven't tried the regexes, there are obvious optimisations
Works on the assumption that your dates will always be USA style (mm/dd/yy, and not dd/mm/yy)
I don't think there is a working solution because 10/8/2010 is not telling too much... it can be 10 day or month... I think you can proceed with your regex :)
i think it will be more simple with regex.
the problem is that aher ary many options of how the date is writen.
Good evŠµning!
echo date('r', strtotime('10.01.11'));
Prints: Sun, 05 Feb 2012 10:01:11
Expected: Mon, 10 Jan 2011 00:00:00
How do I force strtotime() to parse the input string as a date only? I have to convert a bunch of dates in different format. DateTime::format is not an option since I don't know all the formats the script will run into, and it's not even installed on the server (and i don't have privileges to do it).
Tried
strtotime('day 10.01.11'),
strtotime('10.01.11 00:00:00'),
strtotime('10.01.11 midnight')
- nothing worked.
Any help is much appreciated
How do I force strtotime() to parse the input string as a date only?
You don't. strtotime uses very well-defined parsing formats. What it generates will depend entirely on what you give it.
'10.01.11' is parsed as a time format, as it will always interpret three pairs of digits separated by periods as a time. It will recognize dates when separated by dashes, slashes or spaces. Annoyingly, there's an example there on the date format page that uses dots, but there doesn't seem to be a sure-fire way to force date parsing instead of time parsing. Sigh, PHP.
If you need that specific format to be interpreted as a date instead of a time, you have two options.
First, you can use a different date parsing method. If the expected format never changed, you could use DateTime::createFromFormat() or the horrifying strptime. You've indicated in comments that the format will vary and your PHP version is old enough not to have DateTime, so this might not work for you.
Second, you can pre-process the data. At least in this example, a conversion of . to / may do the trick, though 10/01/11 can be ambiguous as a date to humans. There's nothing wrong with a little regex sniffing to determine how to best process data.
There's also a third option: if you're getting this information from users, make your application begin forcing users to enter dates in a normal, consistent, parseable format. It may take some time to train your users to use YYYY-MM-DD, but it's probably the most sane long-term bet.
Is modifying the input an option for you?
$str = '10.01.11';
$str = str_replace('.', '/', $str);
echo date('r', strtotime($str));
However, this will still output Sat, 01 Oct 2011 00:00:00, according to the MM.DD.YY pattern (US standard).
EDIT: Depending on you usage, you might consider creating a list of regex patterns and parse the date accordingly. It is very hard to make a code like this to be open to all possibilities.
Tested, this works:
$date = DateTime::createFromFormat('d.m.y', '10.01.11');
echo $date->format('r');
http://codepad.viper-7.com/OH7Kyn
why don't you add the time set to 00:00:00 by default?
e.g.
echo date('D, d M Y H:i:s', strtotime('10.01.11'));
also strtotime uses the american date format so this will be translated into 1st of october 2011. it's easier to use the iso date format
I don't think strtotime knows how to parse those dates. To avoid potential ambiguity, it's best to use ISO 8601 (YYYY-MM-DD) dates.
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've been using PHP's strtotime() method to accept a date field on a form. I love how powerful it is, in how it will accept "Tomorrow", "Next Thursday", or (supposedly) any date representation and convert it to the Unix timestamp.
It's been working great -- until yesterday. Someone entered "2-4-10" and instead of logging Feb 4th, 2010, it logged April 10, 2002! So it expected Y-M-D instead of M-D-Y.
I thought maybe the problem was just using a 2-digit year, so we tried again with "2-4-2010". That logged April 2nd, 2010! At that point I just don't understand what strtotime() is doing. PHP.net says it expects a US English date format. Why then would it assume D-M-Y?
Is there a way around this? Or do I have to stop using strtotime()?
Note: I just now did a test. When you use slashes instead of hyphen/dashes, it works fine, even with 2/4/10. Why on earth does that matter? And if that's all it is, should I just run str_replace("-", "/", $input) on the form input before passing it to strtotime()?
The - indicates an ISO Date:
03-02-01 => 1. february 2003 (ISO)
01.02.03 => 1. february 2003 (European)
02/01/03 => 1. february 2003 (US)
The behavior of strtotime() is based largely on the GNU date input formats spec. But as powerful as it is, it shouldn't be expected to read minds. Allowing free-form user date input is asking for perpetual trouble.
I had this problem and solved it by doing exactly what you suggested - do a str_replace on the user-entered date to replace the dashes with slashes. This prevents strtotime from using an ISO date and solves the problem.
strtotime is by its very nature fuzzy, so you can't assume that it will always do what you want. If you enter 2010-04-02 then you would expect that to return 2nd April 2010, which is what strottime is trying to do. Running an str_replace from hyphens to slashes might mean that people entering in that format get the wrong date.
If you're running PHP 5.3 or above, consider date_parse_from_format() or for PHP 5.1 and above on Unix consider strptime(). Both functions take a format, so remove potential ambiguity (if you tell users what format you are expecting - if you're running an international site and have a text box labelled date which the user enters 2/4/2010 into then there is no way to know what their intended date is).