I have 2 dates in the database. One is in the past, and other is in the future. I want to check if the current time is between those two dates. Everything works locally, but not on the server.
The server is in a different timezone, but if I echo the results (in comments), everything shows as it should. Dates in the database are saved in the correct timezone, so I do not apply setTimezone to those.
$timezone = new DateTimeZone('Europe/Belgrade');
$start_date = new DateTime($popup_start);
$end_date = new DateTime($popup_end);
$current_date = new DateTime();
$current_date->setTimezone($timezone);
//echo $start_date->format('Y-m-d H:i:s') .'<br>';
//echo $end_date->format('Y-m-d H:i:s') .'<br>';
//echo $current_date->format('Y-m-d H:i:s') .'<br>';
if($start_date < $current_date AND $end_date > $current_date) {
echo 'true';
}
else {
echo 'false';
}
The code above always goes to false for some reason.
Any help is appreciated
DateTime() is compared in UTC time reference (not based on format('Y-m-d H:i:s')).
The universal time reference (probably Unix Epoch seconds) is set on the DataTime instancing and does not change by ->setTimeZone(), that just affects the output, but it's still the same UTC time.
You have no TZ reference in the DB, so $start_date gets your local TZ when parsed. Let's say TZ_REMOTE is the timezone of the datestimes in the DB, and TZ_LOCAL is the local TZ. Then what happens is (pseudocode):
$start_date <- (($popup_start TZ_LOCAL)=>UTC)
$current_date <- (now()=>UTC)
So you have not gotten rid of the TZ difference in any way, it's still TZ_LOCAL dates.
What you can do is compare the textual representations, not the DateTimes:
if($popup_start < $current_date->format('Y-m-d H:I:s') && $popup_end > $current_date->format('Y-m-d H:I:s'))
Because, like I said, ->setTimeZone() will not alter the actual time, but it will alter the output of ->format() to convert the UTC datetime to the specified TZ.
Related
I have a UTC timestamp value 1615958170523 and I want to convert it into our local timezone.
I have tried this method:
The timestamp is in milliseconds that's why firstly I have converted in seconds and then used the below method.
$Date = date('m-d-Y H:i:s', 1615958170523/1000);
It always returns the time ~6hours ago i.e 03-17-2021 05:16:10 (Considering current time here), I don't want to add +5:30 hours to do the same.
Is it possible that we can use a standard method that means in-built functions which may be provided by Cakephp or PHP so that I can get the answer for the same?
I have also tried this one:
$gmtTimezone = new \DateTimeZone('GMT');
$myDateTime = new \DateTime(1615958170523/1000, $gmtTimezone);
It returns the same as I have used the date function.
You need to change the timezone after to define the timestamp in GMT.
$timestamp = 1615958170523/1000;
$myDateTime = \DateTime::createFromFormat('U', (int)$timestamp);
echo $myDateTime->format('Y-m-d H:i:s'), PHP_EOL; // 2021-03-17 05:16:10
$myDateTime->setTimezone(new \DateTimeZone('Europe/Paris'));
echo $myDateTime->format('Y-m-d H:i:s'), PHP_EOL; // 2021-03-17 06:16:10
$myDateTime->setTimezone(new \DateTimeZone('America/Denver'));
echo $myDateTime->format('Y-m-d H:i:s'), PHP_EOL; // 2021-03-16 23:16:10
See DateTime::setTimezone() documentation
You should use the FrozenTime which will use the default Timezone you set in your config/app.php
I have these two functions:
function time_is_older_than($timestamp, $time_string)
{
if (strtotime($timestamp) < strtotime('-' . $time_string))
return true;
return false;
}
function time_is_younger_than($timestamp, $time_string)
{
if (strtotime($timestamp) > strtotime('-' . $time_string))
return true;
return false;
}
They enable me to do neat things like:
if (time_is_older_than($last_time_some_action_happened, '5 minutes'))
do_it_again();
They normally work, except for during one hour every six months, when my timezone switches over to "summer time" or "winter time". This means that the clocks are increased or put back one hour at midnight (according to this timezone).
The PHP manual states this for strtotime:
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.
However, if I provide the exact same date/time string, with "+08:00" added in the end versus "+00:00", for example, I get different numbers of seconds returned. So strtotime() does understand timezones when it parses the provided time, even if the returned integer obviously doesn't contain this information. (Nor is it expected or required to by me.)
I've spent countless hours trying to debug this, testing countless things, and just sitting here thinking, but I can't figure out what exactly would make the code I have fail, specifically for one hour. And especially what about it I need to change. Setting the second parameter for strtotime() seems likely, but I just couldn't make it work correctly.
My hottest "lead" for quite some time was that the strtotime('-' . $time_string) part is ending up using a different timezone than the timestamp strings provided, but I do provide timezone data to it most of the time! An example of $last_time_some_action_happened might be something like 2020-10-28 02:22:41.123456+01.
I set the timezone with date_default_timezone_set().
I suspect that I only need to make some very minor change, but I've been experimenting so much and so long now, even taking rests in between, that my brain can no longer see this clearly. I bet the solution is something awfully simple.
Please don't tell me to use DateTimeImmutable. This would fundamentally change my entire structure and require me to do things very differently. Perhaps I should, and even will, at some point, but for now, I just wish to fix this rare but still very annoying bug in my existing code. (If it's possible at all, which I very much believe is the case.)
I'm able to reproduce the issue you are having:
date_default_timezone_set('Pacific/Auckland');
// Daylight saving time 2020 in New Zealand began at 2:00am on Sunday, 27 September
$current = strtotime('2020-09-27 02:04:00');
$d1 = strtotime('2020-09-27 02:05:00', $current);
$d2 = strtotime('-5 minutes', $current);
var_dump($d1 > $d2); // false
var_dump(date('Y-m-d H:i:s', $d1)); // 2020-09-27 03:05:00
var_dump(date('Y-m-d H:i:s', $d2)); // 2020-09-27 03:59:00
This person looks to be having the same issue as you and may appear to be a bug.
DateTime::modify and DST switch
The solution is to convert the dates to UTC then compare:
// Convert to UTC and compare
$d1 = new \DateTime('2020-09-27 02:05:00', new \DateTimeZone('Pacific/Auckland'));
$d2 = new \DateTime('2020-09-27 02:04:00', new \DateTimeZone('Pacific/Auckland'));
$d2->setTimezone(new \DateTimeZone('UTC'));
$d2->modify('-5 minutes');
$d2->setTimezone(new \DateTimeZone('Pacific/Auckland'));
var_dump($d1 > $d2); // true
var_dump($d1->format(\DateTimeInterface::RFC3339_EXTENDED)); // 2020-09-27T03:05:00.000+13:00
var_dump($d2->format(\DateTimeInterface::RFC3339_EXTENDED)); // 2020-09-27T01:59:00.000+12:00
I've updated your functions:
function time_is_older_than($datetime, $time_string)
{
$d1 = new \DateTime($datetime);
$d1->setTimezone(new \DateTimeZone('UTC'));
$d2 = new \DateTime();
$d2->setTimezone(new \DateTimeZone('UTC'));
$d2->modify('-' . $time_string);
return $d1 < $d2;
}
function time_is_younger_than($datetime, $time_string)
{
$d1 = new \DateTime($datetime);
$d1->setTimezone(new \DateTimeZone('UTC'));
$d2 = new \DateTime();
$d2->setTimezone(new \DateTimeZone('UTC'));
$d2->modify('-' . $time_string);
return $d1 > $d2;
}
Could you consider a solution:
In the timestamp string(like Thu, 21 Dec 2000 16:01:07 +0200), add a timezone tag which specify timezone without difference of daylight saving time.
I have one page in that I have two textboxes where user will enter unix timestamp and datetime, I have to compare that both timestamp and datetime but in php the timezone giving different timestamp as per time zone so the code doesn't working in all places where time zones are different.
Please help on this I had used..
strtotime(),mktime(),getTimestamp() in php,
also used my sql for this..
SELECT UNIX_TIMESTAMP() but all are giving different time stamps.
$sql = "SELECT UNIX_TIMESTAMP('date time from text box') as timeStampfromdb";
$result = mysql_query($sql);
while($row = mysql_fetch_array($result))
{
$timeStampFromDateTime = $row["timeStampfromdb"];
}
if($timeStampFromDateTime == timestamp textbox value)
{
matched
}
else
{
not matched
}
You can set php timezone in php.ini file, for GMT you need "GMT".
You can also try in your code:
echo date('Y-m-d H:i:s T', time()) . "<br>\n";
date_default_timezone_set('GMT');
echo date('Y-m-d H:i:s T', time()) . "<br>\n";
time() should return the current unix timestamp.
If you are working with dates and times across time zones you should work with everything in GMT to avoid time zone issues. If you need to display a date and time at some point that is the place to do any time zone conversion that may be necessary.
Is there a way to convert an input time string (ex: 01:13) to a Zend date object, so that I store it later in a timestamp column in a Mysql database.
Examples:
If the current datetime is 2013-07-15 17:33:07 and the user inputs 18:05 the output should be 2013-07-15 18:05:00.
If the current datetime is 2013-07-15 17:33:07 and the user inputs 02:09 the output should be 2013-07-16 02:09:00. Notice that since the time entered was lower than the current time, so it was treated as tomorrows time.
I simply want to get the next point in time that satisfies the entered time. I'm open for solution using plain PHP or Zend_Date.
I think you should compare the current time with the time entered by the user and create a DateTime object of either "today" or "tomorrow". DateTime accepts strtotime() relative time parameters.
Quick hack. Works as of today, 15.07.2013 23:58 local time:
$nextTime = new DateTime('today 18:10');
if ($nextTime < new DateTime('now')) { // DateTime comparison works since 5.2.2
$nextTime = new DateTime('tomorrow 18:10');
}
echo $nextTime->format('d.m.Y H:i:s');
here is working example for you just add your dynamic variable to check date with user inputs
You can use mktime function to manage your date.
$input_date = date("Y-m-d H:i:s",mktime(18,05,0,date("m"),date("d"),date("Y")));
echo "current time".$current_time = date('Y-m-d H:m:s');
echo "<br>User input is ".$input_date;
if(strtotime($current_time) > strtotime($input_date)){
$input_date = date("Y-m-d H:i:s",mktime(18,05,0,date("m"),date("d")+1,date("Y")));
echo "in";
}else{
// nothing to do
}
echo "<br> result->".$input_date;
i hope it will sure solve your issue
I am trying to compare the current datetime, with a datetime from the database using string, as the following:
$today = new DateTime("now");
$todayString = $today->format('Y-m-d H:i:s');
if($todayString >= $rows["PrioritizationDueDate"])
{...}
$todayString keeps giving me the time 7 hours earlier (i.e now its 11:03pm, its giving me 16:04).
More, is it better to compare this way, or should i compare using datetime objects?
$todayString keeps giving me the time 7 hours earlier
you have to setup a timezone for the DateTime object I believe.
is it better to compare this way
I doubt so.
The general way is to compare in the query, using SQL to do all date calculations and return only matching rows.
Set a correct timezone in the constructor to DateTime.
$today = new DateTime("now", new DateTimeZone('TimezoneString'));
Where TimezoneString is a valid timezone string.
Edit: For a more complete example using DateTime objects, I would use DateTime::diff in conjunction with DateTime::createFromFormat.
$rows["PrioritizationDueDate"] = '2011-11-20 10:30:00';
$today = new DateTime("now", new DateTimeZone('America/New_York'));
$row_date = DateTime::createFromFormat( 'Y-m-d H:i:s', $rows["PrioritizationDueDate"], new DateTimeZone('America/New_York'));
if( $row_date->diff( $today)->format('%a') > 1)
{
echo 'The row timestamp is more than one day in the past from now.';
}
Demo
First set time zone using this function
date_default_timezone_set('UTC');
Then either you can use function strtotime() or get difference directly...