Convert user input to my date format - php

User enters the date as 8/1/11 or 08/1/11. Regardless of how the user inputs the date in my text field, I want to convert what they enter to my format of mm/dd/yyyy
So if the user enters 8/1/11 it would convert it to 08/01/2011.

Use strtotime() to transfer it into a time value, and then mktime() to transfer it to whatever format you want.
EDIT: Turns out it's not that simple.
You can't just print any date you'd like and transfer it to another, it'll be best to use some sort of UI on the client side to ensure the input matches, a great example is jQueryUI Datepicker

Check this.
It also checks if the date is valid (with checkdate) and converts years from short to long. When using short years, 0-69 is converted to 2000-2069 and 70-99 is converted to 1970-1999.
<?php
function cleanDate($input)
{
$parts = explode('/', $input);
if(count($parts) != 3) return false;
$month = (int)$parts[0];
$day = (int)$parts[1];
$year = (int)$parts[2];
if($year < 100)
{
if($year < 70)
{
$year += 2000;
}
else
{
$year += 1900;
}
}
if(!checkdate($month, $day, $year)) return false;
return sprintf('%02d/%02d/%d', $month, $day, $year);
// OR
$time = mktime(0, 0, 0, $month, $day, $year);
return date('m/d/Y', $time);
}
$test = array(
'08/01/2011', '8/1/11', '08/01/11', // Should all return 08/01/2011
'08/1/87', // Should return 08/01/1987
'32/1/93', '13', // Should fail: invalid dates
'02/29/2011', // Should fail: 2011 is not a leap year
'2/29/08'); // Should return 02/29/2008 (2008 is a leap year)
foreach($test as $t)
{
echo $t.' : '.(cleanDate($t) ?: 'false')."\n";
}
?>
Result:
08/01/2011 : 08/01/2011
8/1/11 : 08/01/2011
08/01/11 : 08/01/2011
08/1/87 : 08/01/1987
32/1/93 : false
13 : false
02/29/2011 : false
2/29/08 : 02/29/2008

<?php
$userInput = '08/1/11'; // or = '8/1/11' or = '08/01/11' or = '01/8/11'
$arr = explode('/', $userInput);
$formatted = sprintf("%1$02d", $arr[0]) . '/' . sprintf("%1$02d", $arr[1]) . '/20' . $arr[2];
?>

<?php
preg_match('#^(0?[1-9]|1[0-2])/(0?[1-9]|[12][0-9]|3[01])/(\d{2})$#',trim($date),$matches);
$month=str_pad($matches[1],2,'0',STR_PAD_LEFT);
$day=str_pad($matches[2],2,'0',STR_PAD_LEFT);
$year=$matches[3];
$result="{$month}/{$day}/{$year}";
?>

While #Truth is right that the user can do a lot to make it difficult, there IS actually a way to do a fairly decent job of parsing a date input box to work. It takes into account a variety of user input issues that may come up.
Note that it does make two assumptions:
That the local uses a date format of m/d/y
If the year is entered in short form, we are dealing with a 2000+ year
<?php
// Trim spaces from beginning/end
$date = trim(request($field));
// Allow for the user to have separated by spaces
$date = str_replace(" ", "/", $date);
// Allow for the user to have separated by dashes or periods
$date = str_replace("-", "/", str_replace(".", "/", trim($date)));
// Explode the date parts out to ensure a year
// Granted, this is geo-centric - you could adjust based on your locale
$dateparts = explode("/", $date);
// Check for a year. If not entered, assume this year
if (!isset($dateparts[2])) {$dateparts[2] = date("Y");}
// Force year to integer for comparison
$dateparts[2] = (int)$dateparts[2];
// Allow for user to use short year. Assumes all dates will be in the year 2000+
if ($dateparts[2] < 2000) {$dateparts[2]+= 2000;}
// Re-assemble the date to a string
$date = implode("/", $dateparts);
// Utilize strtotime and date to convert date to standard format
$date = date("m/d/Y", strtotime($date));
?>
Disclaimer: Yes, this is the verbose way of doing this, however I did so for clarity of the example, not for efficiency.

Related

Verifiying 2 date to make sure they're valid dates

I am working with a date which is formatted like so:
25/02/1994 - 15/03/2000
To get each date I am using the explode function to separate each date between dash
$newdate = explode("-",$olddate);
Now my problem is, if it was just one date I could split it up in to 3 parts, the day, month, year and use the checkdate function to validate the month, but because I am using explode I cannot split it up like that (to my knowledge)
What would be the best way to validate the date for legitimacy?
You have a good start, after you exploded your string by -, just simply loop through each date with array_reduce() and reduce it to 1 value.
In the anonymous function you just explode() each date and check with checkdate() if it is a valid date, e.g.
<?php
$str = "25/02/1994 - 15/03/2000";
$dates = explode("-", $str);
if(array_reduce($dates, function($keep, $date){
list($day, $month, $year) = array_map("trim",explode("/", $date));
if(!checkdate($month, $day, $year))
return $keep = FALSE;
return $keep;
}, TRUE)) {
echo "all valid dates";
}
?>
$date = '25/02/1994 - 15/03/2000';
$date_array = explode("-", $date);
$first_date = explode("/", trim($date_array[0]));
$second_date = explode("/", trim($date_array[1]));
if(checkdate($first_date[1],$first_date[0],$first_date[2])){
//do stuff
}
if(checkdate($second_date[1],$second_date[0],$second_date[2])){
//do stuff
}
or, what Daan suggested using the DateTime object.
$date = '25/02/1994 - 15/03/2000';
$date_array = explode("-", $date);
$date1 = DateTime::createFromFormat('j-M-Y', $date_array[0]);
$date2 = DateTime::createFromFormat('j-M-Y', $date_array[1]);
if($date1){
//do stuff
}
if($date2){
//do stuff
}

converting m/d/yy to mm/dd/yyyy in php

Im pulling column from excel with dates, and with the code i have to verify if row has date in it works fine for when dates in mm/dd/yyyy (07/05/2015) format. it passes date verify function and I'm able to grab that date and store it in mysql date formate column. but problem comes in when I'm reading excel file that has date format m/d/yy (7/5/15) I'm not sure at what point its failing but when i look at it database the dates are converted to weird dates and its skipping most of the dates from failing at date verify function. what i would like to do is convert the string I'm fetching from excel from m/d/yy to mm/dd/yyyy before it gets to date verify function. can anyone tell me how can i achieve that?
this is my function to verify if its date.
public function is_date( $str ) /// function to check if its date
{
$stamp = strtotime( $str );
if (!is_numeric($stamp))
return FALSE;
$month = date( 'm', $stamp );
$day = date( 'd', $stamp );
$year = date( 'Y', $stamp );
if (checkdate($month, $day, $year))
return TRUE;
return FALSE;
}
this is the part where it gets the date and sends to database
foreach(array_slice($sheetData, $dateRow-1) as $item)
{
$value = trim($item["{$revCol}"], "$");
$value = str_replace(",", "", $value);
$value = str_replace("?", "", $value);
//check if its date or garbage data
if ($this->is_date( $item["{$dateCol}"]) /* && $this->isCurrency($temp) */)
{
$key = $item["{$dateCol}"];
$key = date('Y-m-d', strtotime($key));
$sold = $item["{$soldCol}"];
$params = array('key' => $key);
$oldVal->execute($params);
$results = $oldVal->fetch(); // fetch old value before replacing with new
$old_rev = $results['rev'];
$old_sold = $results['sold'];
$diff_rev = $value - $old_rev;
$diff_rev = number_format($diff_rev, 2, '.', '');
$diff_sold = $sold - $old_sold;
//$insertDiff->execute(array($key, $diff_rev, $diff_sold));
$newVal->execute(array($key, $value, $diff_rev, $sold, $diff_sold));
}
}
Try this code to convert it ...
$date = "7/5/15";
$your_date = date("m/d/Y", strtotime($date));
echo $your_date;
It will echo 07/05/2015
Here you have the example online
You can format the column in Excel as a date with leading zeroes. That seems the quickest solution.
is this what you want? strtotime undestands such format
$str = '7/5/15';
echo date("m/d/Y", strtotime($str)); // 07/05/2015
strtotime should do the work.
Try replacing '/' by '-'
$stamp = strtotime( str_replace('/', '-' ,$str ) );
If not, the problem happen all time with the format m/d/yy or just in some cases (for example for days greater than 12 or something like that ?

Validate date month and year

I have a date in the form MM-YYYY (e.g: 04-2000). I exploded the date into month and year and am now trying to check certain conditions on the month:
between 1 and 12
formed of 2 digits)
and on the year:
formed of 4 digits
Is my syntax correct?
list($name_month, $name_year) = explode('-', $name_date, 2);
if(($name_month < 1 || $name_month > 12 || $name_month ) || ($name_year)) {
echo "<br><br>Wrong date";
$uploadOk = 0;}
You can use the DateTime object and createFromFormat() to validate your date:
$date = '04-2000';
// Create a DateTime object pointing to the 1st of your given month and year
$d = DateTime::createFromFormat('d-m-Y', '01-' . $date);
if($d && $d->format('m-Y') == $date){
echo 'Valid date';
}
Eval.in
This should work, if seprator is always -
$date = '04-2000';
if($date == date('m-Y', strtotime('01-'.$date)))
{
echo 'Valid date';
}
As commented, there are several was to do this. What first comes to mind is checkdate() and createFromFormat().
The catch is, you need to be mindful what is injected for the day part since your format does not include day.
Since createFromFormat() injects the day part from the current date, it is not a viable option. George's code will fail for a format of 02-2015 on days after 28.
As such, I would use checkdate():
$date = '04-2000';
list($month, $year) = explode('-', $date);
if (checkdate($month, 1, $year)) {
echo 'Valid date';
}

Start Date and Start Time Less than End Date and End Time Validation

Start Time, End Date and End Time variables.
The Date Variables are formatted yyyy-mm-dd
The Time Variables are formatted hh-mm (however only on hour numbers are usable, e.g Minutes is always 00)
I can insert these variables into my database no problem, however before I do I want to check that the start date and time is before the end date and time. I know how to check if the time is earlier, and the date is earlier, but I cannot check the time and date together and I would appreciate any help?
$_POST['start_time']
$_POST['end_time']
$_POST['start_date']
$_POST['end_date']
are the variables and how I am grabbing them.
Use DateTime objects to make life simple for yourself:
<?php
// assuming the following values...
$_POST['start_time'] = '06:00';
$_POST['end_time'] = '10:00';
$_POST['start_date'] = '2012-01-01';
$_POST['end_date'] = '2013-06-02';
//set up two DateTime objects
$start = DateTime::createFromFormat('Y-m-d H-i', $_POST['start_date'] . ' ' . $_POST['start_time']);
$end = DateTime::createFromFormat('Y-m-d H-i', $_POST['end_date'] . ' ' . $_POST['end_time']);
// check if they're valid
if ($start < $end) {
echo 'We are good...';
} else {
echo 'Something bad happened...';
}
Bear in mind that this assumes that your $_POSTed values are valid. If you haven't sanitized them already, wrap it in a try/catch at least.
function getTime ($ymd, $hi) {
return strtotime($ymd." ".$hi);
}
if (getTime($_POST['start_date'], $_POST['start_time']) < getTime($_POST['end_date'], $_POST['end_time'])) {
echo "Ok!";
}
Simply convert it to an Unix-timestamp and then compare.
I would use DateTime::createFromFormat() for it. Like this:
$start = DateTime::createFromFormat('Y-m-d H-i',
$_POST['start_date'] . ' ' . $_POST['start_time']);
Try exploding the arrays and then using mktime() function to pass the date to seconds. Then, just compare both dates, the bigger in seconds is the later.
list($strHour, $strMin) = explode('-', $_POST['start_time']);
list($endHour, $endMin) = explode('-', $_POST['end_time']);
list($strYear, $strMonth, $strDay) = explode('-', $_POST['start_date']);
list($endYear, $endMonth, $endDay) = explode('-', $_POST['end_date']);
$startSeconds = mktime($strHour, $strMin, 0, $strMonth, $strDay, $strYear);
$endSeconds = mktime($endHour, $endMin, 0, $endMonth, $endDay, $endYear);
if ($startSeconds > $endSeconds) {
echo 'Start is bigger';
}

php check for a valid date, weird date conversions

Is there a way to check to see if a date/time is valid you would think these would be easy to check:
$date = '0000-00-00';
$time = '00:00:00';
$dateTime = $date . ' ' . $time;
if(strtotime($dateTime)) {
// why is this valid?
}
what really gets me is this:
echo date('Y-m-d', strtotime($date));
results in: "1999-11-30",
huh? i went from 0000-00-00 to 1999-11-30 ???
I know i could do comparison to see if the date is either of those values is equal to the date i have but it isn't a very robust way to check. Is there a good way to check to see if i have a valid date? Anyone have a good function to check this?
Edit:
People are asking what i'm running:
Running PHP 5.2.5 (cli) (built: Jul 23 2008 11:32:27) on Linux localhost 2.6.18-53.1.14.el5 #1 SMP Wed Mar 5 11:36:49 EST 2008 i686 i686 i386 GNU/Linux
From php.net
<?php
function isValidDateTime($dateTime)
{
if (preg_match("/^(\d{4})-(\d{2})-(\d{2}) ([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/", $dateTime, $matches)) {
if (checkdate($matches[2], $matches[3], $matches[1])) {
return true;
}
}
return false;
}
?>
As mentioned here: https://bugs.php.net/bug.php?id=45647
There is no bug here, 00-00-00 means 2000-00-00, which is 1999-12-00,
which is 1999-11-30. No bug, perfectly normal.
And as shown with a few tests, rolling backwards is expected behavior, if a little unsettling:
>> date('Y-m-d', strtotime('2012-03-00'))
string: '2012-02-29'
>> date('Y-m-d', strtotime('2012-02-00'))
string: '2012-01-31'
>> date('Y-m-d', strtotime('2012-01-00'))
string: '2011-12-31'
>> date('Y-m-d', strtotime('2012-00-00'))
string: '2011-11-30'
echo date('Y-m-d', strtotime($date));
results in: "1999-11-30"
The result of strtotime is 943920000 - this is the number of seconds, roughly, between the Unix epoch (base from which time is measured) to 1999-11-30.
There is a documented mysql bug on mktime(), localtime(), strtotime() all returning this odd value when you try a pre-epoch time (including "0000-00-00 00:00:00"). There's some debate on the linked thread as to whether this is actually a bug:
Since the time stamp is started from 1970, I don't think it supposed to
work in anyways.
Below is a function that I use for converting dateTimes such as the above to a timestamp for comparisons, etc, which may be of some use to you, for dates beyond "0000-00-00 00:00:00"
/**
* Converts strings of the format "YYYY-MM-DD HH:MM:SS" into php dates
*/
function convert_date_string($date_string)
{
list($date, $time) = explode(" ", $date_string);
list($hours, $minutes, $seconds) = explode(":", $time);
list($year, $month, $day) = explode("-", $date);
return mktime($hours, $minutes, $seconds, $month, $day, $year);
}
Don't expect coherent results when you're out of range:
cf strtotime
cf Gnu Calendar-date-items.html
"For numeric months, the ISO 8601
format ‘year-month-day’ is allowed,
where year is any positive number,
month is a number between 01
and 12, and day is a
number between 01 and 31. A
leading zero must be present if a
number is less than ten."
So '0000-00-00' gives weird results, that's logical!
"Additionally, not all
platforms support negative timestamps,
therefore your date range may be
limited to no earlier than the Unix
epoch. This means that e.g.
%e, %T, %R and %D (there might be
more) and dates prior to Jan
1, 1970 will not work on Windows, some
Linux distributions, and a few other
operating systems."
cf strftime
Use checkdate function instead (more robust):
month:
The month is between 1 and 12 inclusive.
day:
The day is within the allowed number of days for the given
month. Leap year s are taken
into consideration.
year:
The year is between 1 and 32767 inclusive.
This version allows for the field to be empty, has dates in mm/dd/yy or mm/dd/yyyy format, allow for single digit hours, adds optional am/pm, and corrects some subtle flaws in the time match.
Still allows some pathological times like '23:14 AM'.
function isValidDateTime($dateTime) {
if (trim($dateTime) == '') {
return true;
}
if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{2,4})(\s+(([01]?[0-9])|(2[0-3]))(:[0-5][0-9]){0,2}(\s+(am|pm))?)?$/i', $dateTime, $matches)) {
list($all,$mm,$dd,$year) = $matches;
if ($year <= 99) {
$year += 2000;
}
return checkdate($mm, $dd, $year);
}
return false;
}
If you just want to handle a date conversion without the time for a mysql date field, you can modify this great code as I did.
On my version of PHP without performing this function I get "0000-00-00" every time. Annoying.
function ConvertDateString ($DateString)
{
list($year, $month, $day) = explode("-", $DateString);
return date ("Y-m-d, mktime (0, 0, 0, $month, $day, $year));
}
<?php
function is_valid_date($user_date=false, $valid_date = "1900-01-01") {
$user_date = date("Y-m-d H:i:s",strtotime($user_date));
return strtotime($user_date) >= strtotime($valid_date) ? true : false;
}
echo is_valid_date("00-00-00") ? 1 : 0; // return 0
echo is_valid_date("3/5/2011") ? 1 : 0; // return 1
I have been just changing the martin answer above, which will validate any type of date and return in the format you like.
Just change the format by editing below line of script
strftime("10-10-2012", strtotime($dt));
<?php
echo is_date("13/04/10");
function is_date( $str ) {
$flag = strpos($str, '/');
if(intval($flag)<=0){
$stamp = strtotime( $str );
} else {
list($d, $m, $y) = explode('/', $str);
$stamp = strtotime("$d-$m-$y");
}
//var_dump($stamp) ;
if (!is_numeric($stamp)) {
//echo "ho" ;
return "not a date" ;
}
$month = date( 'n', $stamp ); // use n to get date in correct format
$day = date( 'd', $stamp );
$year = date( 'Y', $stamp );
if (checkdate($month, $day, $year)) {
$dt = "$year-$month-$day" ;
return strftime("%d-%b-%Y", strtotime($dt));
//return TRUE;
} else {
return "not a date" ;
}
}
?>
I have used the following code to validate dates coming from ExtJS applications.
function check_sql_date_format($date) {
$date = substr($date, 0, 10);
list($year, $month, $day) = explode('-', $date);
if (!is_numeric($year) || !is_numeric($month) || !is_numeric($day)) {
return false;
}
return checkdate($month, $day, $year);
}
<?php
function is_date( $str ) {
$stamp = strtotime( $str );
if (!is_numeric($stamp)) {
return FALSE;
}
$month = date( 'm', $stamp );
$day = date( 'd', $stamp );
$year = date( 'Y', $stamp );
if (checkdate($month, $day, $year)) {
return TRUE;
}
return FALSE;
}
?>

Categories