Managing date formats differences between PHP and MySQL - php

I'm writing my first PHP app that has to directly deal with dates, and thus to directly deal with the fact that PHP and MySQL have different date formats.
My question is: what's the most elegant way to manage this difference?
I have the following two functions to manage the difference using php:
function mysql_date($php_date) {
return date( 'Y-m-d H:i:s', $php_date );
}
function php_date($mysql_date) {
$val = explode(" ",$mysql_date);
$date = explode("-",$val[0]);
$time = explode(":",$val[1]);
return mktime($time[0],$time[1],$time[2],$date[1],$date[2],$date[0]);
}
is there a simpler way to manage this directly within my SQL queries?
Or could you suggest any other more elegant way to manage this?

Since (around) PHP 5.2, PHP has had a built in class/object for dealing with Dates and Times, called DateTime. In a void, it's always better to use a built-in than to wrangle with the messy details yourself.
The DateTime constructor (or the date_create function) accepts a date in any format understood by strToTime. All you need to know about strToTime is it's magic voodoo that will correctly recognize a date in almost any string format. When I first encountered strToTime I had the same internal reaction you're having now ("that's bullshit/seems unreliable"). It's not. It Just Works in a way that your own fragile understanding of dates never will (and if you think you understand dates, you don't. Trust Me.)
So, pull the information from MySQL as a Date/Time string, and immediately create a PHP date Object. Use the date_format method (with some handy constants) when/if you need the date again as a string.

You can replace php_date with strtotime.
$php = strtotime($mysql);
The MySQL equivalent would be UNIX_TIMESTAMP.
Though, if you want to handle formatting in SQL, try MySQL's DATE_FORMAT.

Store everything in the database in a datetime field in UTC. For PHP manipulation, use the PEAR Date library. I'm not a big PEAR user, but this library is fantastic and will handle all of annoying date conversion issues that you should not be spending your time worrying about.

I would recommend you keep everything in mysql format until you need to display it to the user, then use strtotime() to get a unix timestamp and date() to format it.
If you throw in some Hungarian Notation it's even harder to go wrong:
$ymdDateAdded = date('Y-m-d');
$timeDateAdded = strtotime($ymdDateAdded);
$userDateadded = date('j F Y', $timeDateAdded);

I think it would be a better ideea to store unix timestamps in the DB field. When you need to display dates to human language, you can always use php's date() function. For everything else, just use the numeric timestamp.

You could make a small date object which simply converts the date as you need it
$Date_p = new MagicDate($php_date);
$Date_m = new MagicDate($mysql_date);
The $Date_p and $Date_m are just showing that you can seed the object anyway you need to. When you want a mysql date you would have code like. Realistically it would be something pretty generic like $Date.
$query = "UPDATE SET Date='".$Date_p->toMysql()."' "...
and vice versa when you need the opposite. You can use the functions you've already created. Just add a "sniffer" in the construct method like:
public function __construct($date)
{
$phpdate = strtotime($date);
if($phpdate)
{
$this->phpdate = $phpdate;
$this->mysqldate = $this->mysql_date($phpdate);
}
else
{
$this->phpdate = $this->php_date($phpdate);
$this->mysqldate = $phpdate;
}
}
Throw some error handling in to catch the things that go bad. Add the getter for the two dates. And it's a set it and forget it situation. Just pull the right date out when you need it.
There could be some optimizations, but this is to just show you how it could work.

It is best way to save time and date as unix timestamp rather than other formats.
I have created a class to handle date and time in php. Its easy to use and very very useful
<?php
define("NEW_LINE", "</BR>");
class scTimestamp
{
private $timestamp;
private $year;
private $month;
private $day;
private $hour;
private $minute;
private $second;
public function __construct()
{
register_shutdown_function(array($this,'__destruct'));
$this->setTimestamp($_SERVER['REQUEST_TIME']);
}
public function __destruct()
{
unset($this->timestamp);
unset($this->year);
unset($this->month);
unset($this->day);
unset($this->hour);
unset($this->minute);
unset($this->second);
}
private function rebuildTimestampFromDate()
{
$this->timestamp=mktime($this->hour,$this->minute,$this->second,$this->month,$this->day,$this->year);
}
private function rebuildDateFromTimestamp()
{
$this->day=date('j',$this->timestamp);
$this->month=date('n',$this->timestamp);
$this->year=date('Y',$this->timestamp);
$this->hour=date('g',$this->timestamp);
$this->minute=date('G',$this->timestamp);
$this->second=date('s',$this->timestamp);
}
public function setTimestamp($tempTimestamp)
{
$this->timestamp=$tempTimestamp;
$this->rebuildDateFromTimestamp();
}
public function getTimestamp()
{
return $this->timestamp;
}
public function setYear($tempYear)
{
$this->year = $tempYear;
$this->rebuildTimestampFromDate();
}
public function getYear()
{
return $this->year;
}
public function setMonth($tempMonth)
{
$this->month = $tempMonth;
$this->rebuildTimestampFromDate();
}
public function getMonth()
{
return $this->month;
}
public function setDay($tempDay)
{
$this->day=$tempDay;
$this->rebuildTimestampFromDate();
}
public function getDay()
{
return $this->day;
}
public function setHour($tempHour)
{
$this->hour = $tempHour;
$this->rebuildTimestampFromDate();
}
public function getHour()
{
return $this->hour;
}
public function setMinute($tempMinute)
{
$this->minute = $tempMinute;
$this->rebuildTimestampFromDate();
}
public function getMinute()
{
return $this->minute;
}
public function setSecond($tempSecond)
{
$this->second = $tempSecond;
$this->rebuildTimestampFromDate();
}
public function getSecond()
{
return $this->second;
}
public function getDateDifferenceFromNow()
{
return $this->getDateDifferenceFrom($_SERVER['REQUEST_TIME']);
}
public function getDateDifferenceFrom($fromDate)
{
$return="";
$sec=" Second";
$min=" Minute";
$hrs=" Hour";
$before=" Before";
$difference=$fromDate-$this->getTimestamp();
if($difference<0)
$return.="In the Future";
else if($difference<60)
{
if($difference>1)
$sec.="s";
$return.= $difference.$sec.$before;
}
else if($difference<3600)
{
$difference=intval($difference/60);
if($difference>1)
$min.="s";
$return.=$difference.$min.$before;
}
else if($difference<86400)
{
$difference=intval($difference/3600);
if($difference>1)
$hrs.="s";
$return= $difference.$hrs.$before;
}
else if($difference<604800)
{
$return.= date("l g:i a",$this->getTimestamp());
}
else if($difference<28512000)
{
$return.= date("F j",$this->getTimestamp());
}
else
{
$return.= date("F j, Y, g:i a",$this->getTimestamp());
}
return $return;
}
public function getDateAsString()
{
return date("F j, Y",$this->getTimestamp());
}
public function getDateTimeAsString()
{
return date("F j, Y, g:i a",$this->getTimestamp());
}
public function __toString()
{
$return = NEW_LINE."^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^";
$return.= NEW_LINE." ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^".NEW_LINE;
$return.= NEW_LINE."## Timestamp: ".$this->getTimestamp()." ##".NEW_LINE;
$return.= NEW_LINE."## Date: ".$this->getDateTimeAsString()." ##".NEW_LINE;
$return.= NEW_LINE." ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^".NEW_LINE;
return $return;
}
}
?>
once it is included it can be used as follow
include_once("scTimestamp.php");
$test=new scTimestamp();
echo $test->getDateAsString();
$test->setTimestamp(1210203200);
echo $test->getDateDifferenceFromNow();
echo $test;
$test->setTimestamp(121020320022);
echo $test->getYear();
echo $test;
And the result would like this.
June 26, 2015May 7, 2008, 11:33 pm
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
## Timestamp: 1210203200 ##
## Date: May 7, 2008, 11:33 pm ##
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5804
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
## Timestamp: 121020320022 ##
## Date: December 25, 5804, 3:33 am ##
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This class can be used as per needs

Related

Why is recursive static function is not behaving like expected?

The function below should return the next working day. It takes into account holidays and weekends.
The problem is the weird behaviour at the end (see image below code)
class test{
private static $i;
static function getNextWorkingDay(DateTimeInterface $dateTime) {
self::$i++;
dump("Iteration n°: ".self::$i. " Date: ".$dateTime->format('d/m/Y'));
$dateTime = (new DateTime())->setTimestamp($dateTime->getTimestamp());
if (self::isWeekend($dateTime)) {
dump("Iteration n°: ".self::$i." Weekend");
self::getNextWorkingDay($dateTime->modify('next monday'));
}
if (self::isNotWorkable($dateTime)) {
dump("Iteration n°: ".self::$i." Not workable");
self::getNextWorkingDay($dateTime->modify('next day'));
 }
dump("Iteration n°: ".self::$i. " This date should be returned and end the function: ".$dateTime->format('d/m/Y'));
return $dateTime;
}
}
Testing with date = 2020-05-01
I expect 2020-05-04 but it returns 2020-05-02

MySQL database and importing dates problems

Okay,so in my mysql database I use a date field. Using PHP I check if the user is 18 years of age or not. Then I try to enter all the form information to my MySQL database to make a user. I keep getting a blank screen (besides my navbar and footer) The user is not being saved into the database, and the error log shows this error: PHP Recoverable fatal error: Object of class DateTime could not be converted to string in ....
$age = checkAge($_POST["birthday"]);
if($age != false)
{
$ageSuc = "All Good!";
}
else ....
function checkAge ($data)
{
$dateObj = new DateTime($data);
$ageLimit = new DateTime('-18 years');
if ($dateObj > $ageLimit)
{
return false;
}
else
{
$dateObj->format('Y-m-d');
return $dateObj;
}
}
So the question is, do I need to convert the dateTime Obj into a string before MySQL will accept it? The field is set to hold 'dates' so I thought the date obj would be the same thing? How does one change it to a string.
You are returning the DateTime object, because the format function returns a string, it doesn't change the object. Try returning the result of the format function which is the formatted string.
return $dateObj->format('Y-m-d');
$age = checkAge($_POST["birthday"]);
if($age != false)
{
$ageSuc = "All Good!";
}
else ....
function checkAge ($data)
{
$dateObj = new DateTime($data);
$ageLimit = new DateTime('-18 years');
if ($dateObj > $ageLimit)
{
return false;
}
else
{
return $dateObj->format('Y-m-d');
}
}
If you want a string result, you have to return the format() result, not the object itself.
But the error you have specified is not triggered directly in this code, but somewhere in the else, where you try to convert the result to string.

PHP check date difference for backward date

I have checked that the input date is a valid date, now need to check for backward date where date_start must be before date_end.
I have tried several other option to no avail, I really dont want to compare the substring of the input if possible.
The input are from html5 date using chrome with format dd/mm/yyyy
class MY_Form_validation extends CI_Form_validation {
public $CI;
public function date_format($date) {
if (($timestamp = strtotime($date)) === false) {
return false;
}
}
//error message stored in caller module language folder
public function backward_date($date_start, $date_end) {
$date_1 = new DateTime($date_start);
$date_2 = new DateTime($date_end);
if ($date_1 > $date_2 == true) {
return false;
}
else {
return true;
}
}
}
try this one
public function backward_date($date_start, $date_end) {
$ts1 = strtotime($date_start);
$ts2 = strtotime($date_end);
$seconds_diff = $ts2 - $ts1;
return ($seconds_diff>0) ? true : false;
}
The problem here is that DateTime is not able to parse the string from 'dd/mm/yyyy' to a valid DateTime Object.
Here is the received error :
PHP Warning: Uncaught Exception: DateTime::__construct(): Failed to parse time string (27/10/2017)
In order to fix this, you could use the createFromFormat() method from the DateTime model to parse your string with a specified format.
$date_1 = DateTime::createFromFormat('d/m/Y', $date_start);
So your method would be like :
public function backward_date($date_start, $date_end)
{
$date_1 = DateTime::createFromFormat('d/m/Y', $date_start);
$date_2 = DateTime::createFromFormat('d/m/Y', $date_end);
return $date_1 <= $date_2;
}
Hope it helps.
Try to this ... Working for me.
function date_calculate($start_date, $end_date) {
$dStart = new DateTime($start_date);
$dEnd = new DateTime($end_date);
$days=0;
if ($dStart < $dEnd) {
$dDiff = $dStart->diff($dEnd);
$dDiff->format('%R');
$days = $dDiff->days;
return $days;
} else {
return $days;
}
}

PHP Format date yyyy-mm-ddThh:ii:ss to Y-m-d h:i:s [duplicate]

This question already has answers here:
Convert a date format in PHP [duplicate]
(18 answers)
Closed 5 years ago.
i need to convert a date with this format (2017-06-14T08:22:29.296-03:00) to Y-m-d H:i:s. I take that date from an xml response from a soap service, And i need to check if the expiration date is less than the actual date.
I have this and works OK on localhost, but when is uploaded to other server, i have validation problems:
if($wsaa->get_expiration() < date("Y-m-d h:m:i")) {
if ($wsaa->generar_TA()) {
echo '<br>Nuevo Ticket de Acceso Generado';
} else {
echo '<br>No se pudo obtener ticket de acceso';
}
} else {
echo '<br>TA expira:' . $wsaa->get_expiration();
}
$wsaa->get_expiration() return 2017-06-14T08:22:29.296-03:00
I tried to format the date but return with a few minutes of diff.
You can use date function for format and use strtotime to convert current date to timestamp that date function needed:
$datetime = '2017-06-14T08:22:29.296-03:00';
$format_date = date('Y-m-d H:i:s', strtotime($datetime));
An alternative solution in OOP using Carbon from http://carbon.nesbot.com. If you run my example, you might notice that solution1() is an hour behind. That's the reason why I recommend Carbon is that it plays really well with time-zones.
First run "composer require nesbot/carbon";
<?php
require 'vendor/autoload.php';
use Carbon\Carbon;
class FormatDate
{
protected $dateTime;
protected $newFormat;
public function __construct($dateTime, $newFormat)
{
$this->dateTime = $dateTime;
$this->newFormat = $newFormat;
}
// Solution 1
public function solution1()
{
$format_date = date($this->newFormat, strtotime($this->dateTime));
return $format_date;
}
// Solution 2
public function solution2()
{
$date = Carbon::parse($this->dateTime)->format($this->newFormat);
return $date;
}
}
$datetime = '2017-06-14T08:22:29.296-03:00';
$newFormat = 'Y-m-d H:i:s';
// Solution 1
echo (new FormatDate($datetime, $newFormat))->solution1();
echo '----------------------------';
// Solution 2
echo (new FormatDate($datetime, $newFormat))->solution2();

Is it possible to change the system date for php (only)

Is it possible to change the system date for php (only).
I want this for debugging/testing purpose.
//Test 1 (2010-01-01)
$datetime = new DateTime(); //(2010-01-01)
//Test 2 (2010-02-01)
$datetime = new DateTime(); //(2010-02-01)
I can't really change the real system clock, because other developers are working on the same system (well I could but still).
I'm just hoping this is possible, or that someone knows a nice trick.
When I print the phpinfo(); I see the following line:
Timezone Database internal
Maybe it's changeable to something like "manual" and ad a timezone with +120
Thanks!
This sounds like an encapsulation issue -- why not search for all mentions of date() or time() and replace them with $site->getDisplayedDate(), or something else appropriate to your code?
I feel your pain, but I don't think there's any way to do this. Think about it this way... how would you feel if, in some unrelated code, you called time() and it gave you some date 3 weeks in the future?
You can change only timezone (and ofcourse only couple hours forward / backward; and not whole day forward), but thats not correct solution...
You could create your own DateTime class that extends the default DateTime and hence change the behaviour:
<?php
class CustomDateTimeVariables {
public static $date = 'now';
}
class CustomDateTime extends DateTime {
public function __construct($time = null, DateTimeZone $timezone = null) {
if ($time === null) {
$time = CustomDateTimeVariables::$date;
}
if ($timezone !== null) {
parent::__construct($time, $timezone);
} else {
parent::__construct($time);
}
}
}
CustomDateTimeVariables::$date = '2010-01-01';
$datetime1 = new CustomDateTime();
CustomDateTimeVariables::$date = '2010-01-02';
$datetime2 = new CustomDateTime();
var_dump($datetime1->Format('Y-m-d H:i:s')); //"2010-01-01 00:00:00"
var_dump($datetime2->Format('Y-m-d H:i:s')); //"2010-01-02 00:00:00"
?>
DEMO
This way you can also set the default time very easily (check CustomDateTimeVariables):
<?php
class CustomDateTimeVariables {
public static $date = 'now +120 hours';
}
class CustomDateTime extends DateTime {
public function __construct($time = null, DateTimeZone $timezone = null) {
if ($time === null) {
$time = CustomDateTimeVariables::$date;
}
if ($timezone !== null) {
parent::__construct($time, $timezone);
} else {
parent::__construct($time);
}
}
}
$datetime = new CustomDateTime();
var_dump($datetime->Format('Y-m-d H:i:s')); //"2013-10-29 13:37:39"
?>
..and when it goes live, you can simply change the default back to now.

Categories