Converting between illogically formatted dates (changing /slash/ to -dash- ) - php

I am rebuilding a web application from an old one with many inconsistencies. I have to migrate all the data over from the old database to our new structure.
In the old database, dates were stored in the MySQL DB as VARCHAR. We are based in the UK, so dates were written in the format DD/MM/YYYY. I need to convert these dates to MySQL's native DATE() format.
Problem is this - PHP defaults to assuming the dates are in 'American' format (MM/DD/YYYY) because they were originally split with / rather than - - and - forces PHP to assume they are 'European' format.
I am doing this so far to convert them:
$start_date = date('Y-m-d', strtotime($query->row('startdate')));
Where $query->row('startdate') is the column in the old database which was storing the dates. Problem is, I need to first switch all the 21/03/1994s to 21-03-1994.
How can I do this?

$start_date = date('Y-m-d', strtotime(str_replace('/', '-', $query->row('startdate'))));
Or better yet - just change the data in the database:
UPDATE `table` SET `startdate` = REPLACE(`startdate`, '/', '-');
... and then convert the field to type DATE.
---- EDIT ----
Actually, Col. Shrapnel has a point ... I'd overlooked the fact that the date needs reversing as well so it's YYYY-MM-DD; assuming the original date is in the format DD/MM/YYYY a better query might be something like:
UPDATE `table` SET `date` = CONCAT(SUBSTRING(`date`, 7), '-', SUBSTRING(`date`, 4, 2), '-', SUBSTRING(`date`, 1, 2))
Which will reverse the component parts into a string that can be converted to a DATE ... it won't quite work if the original date string doesn't use leading zeroes 1/6/2011 for instance... would need to do something a little cleverer in that case.

WHY bother with all this date time stuff when you need mere a simplest string manipulation of 2 moves long?
$tmp = explode("/",$query->row('startdate'));
$date = "$tmp[2]-$tmp[1]-$tmp[0]";
but, as chris said, you dno't have to involve PHP in this operation as you can convert it using single SQL query using similar string manipulations in the query.

MySQL has a Replace() function that may be the easiest way to do this.
This is the 5.0 API reference:
http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_replace

Use str_replace like this:
$start_date = date('Y-m-d', strtotime(str_replace('-','/',$query->row('startdate'))));
That is of course ugly and quick solution - YMMV.

If you're bound to PHP, why not parse the data, normalize it and then continue? E.g. with sscanf:
$r = sscanf($varcharDate, '%d/%d/%d', $day, $month, $year);
if ($r !== 3)
{
throw new Exception(sprintf('Invalid date format given: %s', $varcharDate));
}

Related

PHP DateTime from integer values

If have $day, $month, and $year as integer values and want to create a DateTime object in PHP 7.
Creating a string representation to let it parse into a date, such as:
$date = new DateTime("$year-$month-$day");
looks quite ridiculous to me. I tried to set the date after creation, such as:
$date = (new DateTime())->setDate($year, $month, $day);
but since new DateTime() uses the current timestamp the time part of the object is still set to the current time (instead of 00:00:00). So I'd have to set the time value as well, what seems inefficcient to me as well:
$date = (new DateTime())->setDate($year, $month, $day)->setTime(0, 0);
What is therefore the best (i.e. most performant) way to create a new DateTime instance for a date when I already have day, month and year as integer values?
UPDATE
For some users seem to misinterpret my question: I'm asking rather for a performant than for an aesthetic solution. ;-)
Yes new DateTime("$year-$month-$day") is short and nice, but is it the recommended way to let PHP parse a date string I already have split to its int values?
I understand the concern, converting integers into a string which is then parsed by some automagic as some matching date format does seem somewhere between inefficient and insane to instantiate DateTime objects from what are already integers. Alas, there's no alternative constructor in standard PHP DateTime classes that would offer any alternative.
Personally I always feel icky letting PHP auto-parse any sort of date string to hope it gets it right, so I'd actually prefer the more explicit alternative:
DateTime::createFromFormat('Y-m-d', "$year-$month-$day")
But that is mostly personal preference, new DateTime("$year-$month-$day") should accomplish exactly the same thing as long as your variables actually contain the values you think they do.
If you're only after a conversion to UNIX timestamps, there's mktime which accepts explicit integer arguments, albeit it in a weird order:
mktime(0, 0, 0, $month, $day, $year)

Convert mm/dd/yyyy into mysql timestamp?

I've been trying for about two hours to get this working with no luck. I'm trying to convert a date that's entered like 11/18/2012 into a mysql timestamp but everything I've tried just ends up as either 0000-00-00 00:00:00 or NULL in the database :( I'm using PHP + MYSQL so a solution in either would be great
Try This
$release_date=$_POST['release_date'];
echo date("Y-m-d H:i:s",strtotime($release_date));
PHP's DateTime to the rescue!
$datetime = new DateTime($alternativeFormat);
echo $datetime->format('Y-m-d H:i:s'); // mysql format
It's also possible to leave the altering of the data by MySQL, but I advice against it. By using the DateTime object you leave your query open to support other formats aswell.
Use STR_TO_DATE:
SELECT TIMESTAMP(STR_TO_DATE('11/18/2012','%m/%d/%Y'))
http://sqlfiddle.com/#!2/d41d8/4363/0
You stated that you tried:
UNIX_TIMESTAMP(STR_TO_DATE('$release_date','%m/%d/%y'))
The reason this doesn't work is because UNIX_TIMESTAMP's return type is unsigned integer, not TIMESTAMP. This is why you can't insert it into a TIMESTAMP column
Have you tried strtotime(): http://php.net/manual/en/function.strtotime.php
Or exploding on '/' and then using mktime(): http://php.net/manual/en/function.mktime.php
$parts = explode('/', $date);
$timestamp = mktime(0, 0, 0, $parts[0], $parts[1], $parts[2]);
Or any of the other suggestions in answers posted here?
My favorite method:
$date = '10/1/2012';
$mysqlDate = date('Y-m-d', strtotime($date));
I would try something like this.
$sDate = '11/18/2012';
$aDate = explode('/', $sDate);
$sMySQLTimestamp = sprintf(
'%s-%s-%s 00:00:00',
$aDate[2],
$aDate[0],
$aDate[1]
);
var_dump($sMySQLTimestamp);
> string(19) "2012-11-18 00:00:00"
The correct answer will depend upon exactly what you're trying to do, but in most cases it is a combination of these things:
Use a DateTime object, rather than a string, to represent the timestamp in PHP. (Convert it on input rather than when writing to the database).
Use a database interface that has placeholders, and when filling in a value that's a DateTime, automatically converts them to the appropriate string format
This keeps you from having to convert to, or even know, the native format expected by MySQL.
can you enter that example date as 2012/11/18 ?
if yes use
select convert('2012/11/18' ,DATETIME)
or you can use
select convert(str_to_date('11/18/2012','%m/%d/%Y'),DATETIME)

How do I compare a user passed y/m/d string to date time in mysql?

I have a variable that a user specifies $start_date in format of y-m-d.
so let's say for example $start_date = '2011-10-27';
In my database I have a DATETIME field, let's call it sample_date that looks like this
2011-10-27 14:15:20
When I run sql query using $start_date.. do I have to convert to compare the dates such as
SELECT * from content WHERE sample_date >= $start_date
or should I convert it somehow first
You don't need to convert the value as long as you've validated the format, but you should definitely sanitize the input to prevent XSS attacks and other nastiness. A calendar drop-down would be good here as well.
EDIT:
Whoa now... I see you've edited your question and the formats are different. That changes everything! Michael's comment is the correct answer, use strtotime() function to convert the date to a unix timestamp, then recreate the date in the proper format needed... like so... date('Y-m-d', strtotime($start_date))
Simply replace slashes with dashes.
$start_date = str_replace('/','-',$start_date);
$start_date = mysql_real_escape_string($start_date);
Just append some zeros onto this:
$start_date = "2010-10-27";
$start_date .= " 00:00:00";
EDIT: Testing confirms that this is unnecessary. As long as the mysql column is DATETIME formatted, it understands "2010-10-27".
HOWEVER! Your example will throw an error, as Greater Than or Equal to should be written ">=", not "=>"

Shortest way to compare 2 dates in dd/mm/yyyy format

can anyone suggest the neatest way to do this comparison? I need to test if a date provided in dd/mm/yyyy format is less than a fixed date, e.g 01/05/2009 - I know I can convert these to unix time format using strtotime, then make the comparison, but I'm curious if there is a quicker way to do it - many thanks, just looking for a hint to improve my code!
One option is just to reverse the format - create a string of the form
yyyy/mm/dd
That's a sortable format, so you can just do an ordinal string comparison. Of course, this means you won't detect invalid data etc.
There's probably not a shorter way code wise, and I wouldn't bother optimizing this unless you're sure it's a bottleneck.
However, as long as you're sure it will always be the exact same format (including 2 digits for month and day and with 0s) you should be able to reorder the string to put the year first, then the month, and then the day, and then just compare the strings.
However, I'm not sure this would be faster than just letting the libraries convert to unix time and then comparing those.
If you can change the format that the dates are stored in, you could define them as yyyy/mm/dd and then just compare the strings.
I think that your solution of converting it to Epoch then doing a comparison is as fast and as clean as your going to get.
if you want to improve your code, I would suggest you to use DateTime class. It's been introduced in php 5.2.0 (so, it still might not be supported on all servers)
in php 5.3.0 you can write something like this:
$d1 = DateTime::createFromFormat('d/m/Y', '02/03/2009');
$d2 = DateTime::createFromFormat('d/m/Y', '02/05/2009');
$interval = $d1->diff($d2);
echo $interval->format('%R%d days');
Well, you could use the PHP date class, but I am not sure it would be any better than you current solution...
http://php.net/manual/en/book.datetime.php
use this method
yearmonthday
you have 01.05.2010 and 03.07.2010
and to compare : 20100501 <= or => 20100703
$fixedDate = '01/05/2009';
$variableDate = '28/04/2010';
// Now we do our timestamping magic!
$fixedDate = implode('', array_reverse(explode('/', $fixedDate)));
$variableDate = implode('', array_reverse(explode('/', $variableDate)));
if ($variableDate < $fixedDate) // 20100428 < 20090501
{
// there you go
}

PHP function to get the date format?

I know how to use date format strings, to turn date('Y/m/d H:i:s'); into 2009/12/18 11:37:45.
I would like a function that can do the opposite - look at a formatted date then return the format. Is there one in PHP?
The reason is we have timestamps saved in our database in a variety of formats and I am writing a tool processing all of our old tables and analyzing the date entries.
EDIT: so I guess there isn't a straight-forward way to do this. I was thinking I could use strftime(), which returns the time in seconds since the epoch. So a better question is can I use that time in seconds in the timestamp fields in the mySQL database? I would guess this would work if the table is structured as a timestamp and not a varchar,which is sometimes is.
No, there isn't such a function. You'll need to write a set of regular expression matches which express all the possible variations, e.g.
$variations = array (
'^([0-9]{4})/[0-9]{2}/[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{4}2$' => 'Y/m/d H:i:s',
// more here
);
foreach ($dateFromDatabase as $date) {
foreach ($variations as $regexp => $dateFormat) {
if (preg_match ('|' . $regexp . '|', $date)) {
$matches[$dateFromDatabase] = $dateFormat;
break;
}
}
}
// $matches now consists of an array of dates => format
Yes, there does exist a function for this: strtotime()
strtotime — Parse about any English textual datetime description into a Unix timestamp
EDIT: Okay, the function might not return the formatting used, but you will get the timestamp, and then you're able to store it in any format.
Take a look into strptime().
You could use regexp to identifiy specific date formats. You could add to your regexp list until you have 100% coverage.
if(preg_match('/^\d{4}\/\d{2}\/\d{2} \d{2}:\d{2}:\d{2}$/', $Date))
$Format = 'Y/m/d H:i:s';
etc...
You dont need to get the date into m/d/Y format. You can use strtotime to turn any valid date into any other date format you want.
date( 'format', strtotime($date) );
Maybe its a better idea to save them all as unix timestamps then you can format them on the fly very easily depending on what your users want to see.

Categories