Check if time is between two times, gives false answers - php

<?php
$saturday = array(
'00:00 - 01:00' => 'Nightshow',
'01:00 - 02:00' => 'Nightshow',
'02:00 - 03:00' => 'Nightshow',
'03:00 - 04:00' => 'Nightshow',
'04:00 - 05:00' => 'Nightshow',
'05:00 - 06:00' => 'Early birds',
'06:00 - 07:00' => 'Early birds',
'07:00 - 08:00' => 'Cox n Crendor in the morning',
'08:00 - 09:00' => 'Cox n Crendor in the morning',
...
'23:00 - 24:00' => 'John late night'
);
foreach($saturday as $timeD => $show){
if(!empty($timeD) && isset($timeD)){
$timesplit = explode(' -', $timeD);
if (time() > strtotime('today '. $timesplit[0]) && time() < strtotime('today '. $timesplit[1])) {
echo $show;
}
}
}
?>
Hello again Stackoverflow!
I have an array, containing times of the day (24h format) that represents a schedule. What I'm trying to do, is check wich show is currently on. What I've tried above didn't work - Times turned out to be a few hours off or they would be completely wrong, not even in a certain order. I don't understand what's wrong. How do I solve this?
Thanks in advance!

I believe you ran into some basic timezone problem.
Timezone Basic
Timezone conversion could be frustrating, but once you get used to it, it's pretty straight forward.
When we deal with time, we also need to be careful with functions like strtotime() and date(). These two functions are affected by timezone settings. When I say timezone setting, I mean the value date.timezone in your php.ini.
Take, for example, I set date.timezone = Asia/Singapore, and it's a UTC+8 timezone:
Let's say UTC time now is 2013-02-05 00:00:00 UTC and timestamp should be 1360022400:
time() will gives me 1360022400
strtotime('2013-02-05 00:00:00') will gives me 1359993600 (or -28800, or -8 hours!)
Notice how strtotime behaves? It actually uses the fact that the PHP environment is in UTC+8 timezone and thinks that the datetime you had specified is in a +8 timezone, and hence it pushed back 8 hours for you, to correctly represent it in UTC timestamp. This is where the problem is.
Solution
Usually, what I will do (perhaps someone can offer a better solution?) is to hard append a UTC behind the ambiguous datetime and force us to calculate everything in UTC timezone. So simply do this:
strtotime('2013-02-05 00:00:00 UTC')
will now gives you 1360022400, or exactly 00:00:00 in UTC time. This is especially good when you do time sensitive calculation when time() is returning you a real UTC timestamp.
Some notes:
time() will always give you UTC timestamp regardless of timezone setting.
strtotime() will always affected by timezone setting so if you are doing time sensitive comparison, try to make sure they are all in UTC.
date() as well, affected by timezone setting, where date('Y-m-d H:i:s', 1360022400) will gives you 2013-02-05 08:00:00 and to overcome this we use gmdate('Y-m-d H:i:s', 1360022400) instead.
Your Question
So since it seems like you are dealing with time-sensitive decision here, one question, do I need to see the same result as you if I live in a different timezone with you?
If we (I and you) need to see the exact same result, then you should do this:
//Let's say the timezone required for that decision made is UTC+6
$event_timezone_offset = 6 * 3600;
foreach($saturday as $timeD => $show){
if(!empty($timeD)){ //you don't need isset here as !empty taken care of it
list($startTime, $endTime) = explode(' - ', $timeD);
$start = strtotime('today '.$startTime.' UTC') - $event_timezone_offset;
$end = strtotime('today '.$endTime.' UTC') - $event_timezone_offset;
$now = time();
if ($start <= $now && $now < $end) { //notice the inclusive <=
echo $show;
}
}
For the line strtotime('today '.$startTime.' UTC') - $event_timezone_offset;, let's step through:
Let's assume the local time now is 07:00 (UTC+6) and you should see 'Cox n Crendor..':
time() will gives you the exact UTC timestamp of 2013-09-21 01:00:00 UTC
strtotime('today 07:00 UTC') will gives you the timestamp of 2013-09-21 07:00:00 UTC
and once you do - $event_timezone_offset, you get a time of 2013-09-21 01:00:00 UTC
so if ($start <= $now) will then be true, and you should see 'Cox n Crendor..'
If I and you need to get a different result based on our respective local timestamp, you will then need to either sniff user's timezone using javascript, or ask them to set a timezone through some backend settings, and use the same logic to determine the result, by setting $event_timezone_offset = $user_timezone_offset.
I hope this is not too confusing but it's really fun dealing with all these maths.

(You will have to replace $fake_timestamp with the current timestamp time() later in your script ... but I needed it that way for testing.)
<?php
$saturday = array(
'00:00 - 01:00' => 'Nightshow',
'01:00 - 02:00' => 'Nightshow',
'02:00 - 03:00' => 'Nightshow',
'03:00 - 04:00' => 'Nightshow',
'04:00 - 05:00' => 'Nightshow',
'05:00 - 06:00' => 'Early birds',
'06:00 - 07:00' => 'Early birds',
'07:00 - 08:00' => 'Cox n Crendor in the morning',
'08:00 - 09:00' => 'Cox n Crendor in the morning',
'23:00 - 24:00' => 'John late night'
);
//$current_day_timestamp = gettimeofday(); //bug? returns time(), not day!time
$current_day_timestamp = strtotime('TODAY');
//print 'Current day time: '.$current_day_timestamp.'<br />';
//Trying to "find" Early birds 05:00-06.00, setting "current time" to 05:30
$fake_timestamp = $current_day_timestamp + 5.5 * 3600;
//print 'fake time: '.$fake_timestamp.'<br />';
foreach ($saturday AS $hours => $show) {
$hours = explode(' - ', $hours);
$show_start = strtotime($hours[0]);
$show_end = strtotime($hours[1]);
if ($show_start < $fake_timestamp AND $show_end > $fake_timestamp) {
print $show;
}
//print $show.'<hr />';
//print 'show start: '.$show_start.'<br />';
//print 'show end: '.$show_end.'<br /><br />';
}
?>

Related

Convert GMT date to other timezone date using offset [duplicate]

A head scratcher for you.
I am grabbing geo IP data from IPInfoDB's API and it returns a timezone offset from UTC including DST (if currently reflected).
For example, I live in EST (-5) and currently it's DST, so the geo IP API returns (-04:00) as the offset.
This is wonderful since DST is a freaking headache. But to my surprise, it caused another headache.
I load this data in PHP to be passed via AJAX to the application. I would like to have the live local time of the IP address on the app.
I have that all set perfectly, but I am going crazy trying to figure out how to set the PHP timezone to match the offset so I can just grab the current hours date('H'); and minutes date('i'); to pass to via AJAX.
I am unsure if there is a specific function that can just give me the current hours and minutes based on that offset or if there is a practical way to set the timezone based on the offset (which will have DST already applied if is in effect).
I've been searching and searching Google to find an answer to this, but what I am doing is more specific since DST is already applied.
I found one function on PHP.net that seems to do the trick (it works for my timezone and returns the correct time) although for other timezones such as PST, it's returning 1 hour later than it should be even though the offset is correct (-07:00 with DST).
The timezone returned from the function is Chile/EasterIsland which I have a feeling is the cause. If I could, I would make this only work for the USA, but I do need it to be worldwide.
This is the function I have now. Please excuse the extremely messy code. I have been playing around with tons of things over the last few hours trying to figure out a solution.
Most of the functionality was found online.
function offsetToTZ($offset) {
switch((string) $offset) {
case '-04:30' : return 'America/Caracas'; break;
case '-03:30' : return 'Canada/Newfoundland'; break;
case '+03:30' : return 'Asia/Tehran'; break;
case '+04:30' : return 'Asia/Kabul'; break;
case '+05:30' : return 'Asia/Kolkata'; break;
case '+05:45' : return 'Asia/Kathmandu'; break;
case '+09:30' : return 'Australia/Darwin'; break;
}
$offset = (int) str_replace(array('0',0,':00',00,'30',30,'45',45,':','+'),'', (string) $offset);
$offset = $offset*60*60;
$abbrarray = timezone_abbreviations_list();
foreach ($abbrarray as $abbr) {
foreach($abbr as $city) {
if($city['offset'] == $offset) {
return $city['timezone_id'];
}
}
}
return false;
}
I included the switch/case for certain timezones that are :30 and :45 out there. There may be a way to include that also without the need of the switch/case.
NOTE: The offsets are always returned as such +00:00 or -00:00 from the geo IP API.
I would appreciate any help or a point in the right direction. I'm not very novice with PHP, but offsets are a new story for me. Thanks!
It can be done quite simply, by turning the offset into seconds and passing it to timezone_name_from_abbr:
<?php
$offset = '-7:00';
// Calculate seconds from offset
list($hours, $minutes) = explode(':', $offset);
$seconds = $hours * 60 * 60 + $minutes * 60;
// Get timezone name from seconds
$tz = timezone_name_from_abbr('', $seconds, 1);
// Workaround for bug #44780
if($tz === false) $tz = timezone_name_from_abbr('', $seconds, 0);
// Set timezone
date_default_timezone_set($tz);
echo $tz . ': ' . date('r');
Demo
The third parameter of timezone_name_from_abbr controls whether to adjust for daylight saving time or not.
Bug #44780:
timezone_name_from_abbr() will return false on some time zone
offsets. In particular - Hawaii, which has a -10 from GMT offset, -36000
seconds.
References:
timezone_name_from_abbr
date_default_timezone_set
date
date_default_timezone_set('UTC');
$timezones = array();
foreach (DateTimeZone::listAbbreviations() as $key => $array)
{
$timezones = array_merge($timezones, $array);
}
$utc = new DateTimeZone('UTC');
$timezone_offset = '+02:00'; # 2H
$sign = substr($timezone_offset, 0, 1) == '+'? '': '-';
$offset = substr($timezone_offset, 1, 2) . 'H' . substr($timezone_offset, 4, 2) . 'M';
$operation = $sign == ''? 'add': 'sub';
$start = new DateTime('', $utc);
$date = new DateTime('', $utc);
$date->{$operation}(new DateInterval("PT{$offset}"));
$offset = $start->diff($date)->format('%r') . ($start->diff($date)->h * 3600 + $start->diff($date)->m * 60 + $start->diff($date)->s); # 7200 (2H)
echo $offset, PHP_EOL;
echo $date->format('Y-m-d H:i:s'), PHP_EOL;
foreach($timezones as $timezone)
{
if($timezone['offset'] == $offset)
{
echo $timezone['timezone_id'], PHP_EOL;
}
}
I might have misunderstood you in some parts, but I hope it helps, if you could be more specific, I might be more helpful.
For Chile I get:
-25200 (-7h)
2012-08-07 18:05:24 (current time 2012-08-08 01:05:24)
Chile/EasterIsland
Output of the example above:
7200
2012-08-08 02:49:56
Europe/London
Europe/Belfast
Europe/Gibraltar
Europe/Guernsey
Europe/Isle_of_Man
Europe/Jersey
GB
Africa/Khartoum
Africa/Blantyre
Africa/Bujumbura
Africa/Gaborone
Africa/Harare
Africa/Kigali
Africa/Lubumbashi
Africa/Lusaka
Africa/Maputo
Africa/Windhoek
Europe/Berlin
Africa/Algiers
Africa/Ceuta
Africa/Tripoli
Africa/Tunis
Arctic/Longyearbyen
Atlantic/Jan_Mayen
CET
Europe/Amsterdam
Europe/Andorra
Europe/Athens
Europe/Belgrade
Europe/Bratislava
Europe/Brussels
Europe/Budapest
Europe/Chisinau
Europe/Copenhagen
Europe/Gibraltar
Europe/Kaliningrad
Europe/Kiev
Europe/Lisbon
Europe/Ljubljana
Europe/Luxembourg
Europe/Madrid
Europe/Malta
Europe/Minsk
Europe/Monaco
Europe/Oslo
Europe/Paris
Europe/Podgorica
Europe/Prague
Europe/Riga
Europe/Rome
Europe/San_Marino
Europe/Sarajevo
Europe/Simferopol
Europe/Skopje
Europe/Sofia
Europe/Stockholm
Europe/Tallinn
Europe/Tirane
Europe/Tiraspol
Europe/Uzhgorod
Europe/Vaduz
Europe/Vatican
Europe/Vienna
Europe/Vilnius
Europe/Warsaw
Europe/Zagreb
Europe/Zaporozhye
Europe/Zurich
WET
Europe/Kaliningrad
Europe/Helsinki
Africa/Cairo
Africa/Tripoli
Asia/Amman
Asia/Beirut
Asia/Damascus
Asia/Gaza
Asia/Istanbul
Asia/Nicosia
EET
Europe/Athens
Europe/Bucharest
Europe/Chisinau
Europe/Istanbul
Europe/Kaliningrad
Europe/Kiev
Europe/Mariehamn
Europe/Minsk
Europe/Moscow
Europe/Nicosia
Europe/Riga
Europe/Simferopol
Europe/Sofia
Europe/Tallinn
Europe/Tiraspol
Europe/Uzhgorod
Europe/Vilnius
Europe/Warsaw
Europe/Zaporozhye
Asia/Jerusalem
Asia/Gaza
Asia/Tel_Aviv
MET
Africa/Johannesburg
Africa/Maseru
Africa/Mbabane
Africa/Windhoek
Africa/Windhoek
Africa/Ndjamena
Europe/Lisbon
Europe/Madrid
Europe/Monaco
Europe/Paris
WET
Europe/Luxembourg
Which nails my timezone.
$UTC_offset = '+03:00';
$date = new \DateTime('now', 'UTC');
var_dump($date);
$timezone = new \DateTimeZone(str_replace(':', '', $UTC_offset));
$date->setTimezone($timezone);
var_dump($date);
Results:
class DateTime#205 (3) {
public $date =>
string(26) "2015-01-20 06:00:00.000000"
public $timezone_type =>
int(3)
public $timezone =>
string(3) "UTC"
}
class DateTime#205 (3) {
public $date =>
string(26) "2015-01-20 09:00:00.000000"
public $timezone_type =>
int(1)
public $timezone =>
string(6) "+03:00"
}
It is unadvised to map time zone offsets back to a time zone identifier. Many time zones share the same offset.
Even within a single country, this is problematic. Consider that in the United States, the -5 offset is used by both Central Standard Time (America/Chicago) and Eastern Daylight Time (America/New_York) at different times of the year.
Also consider that there are times where BOTH of those time zones use -5 at the same time. For example, Sunday November 3rd 2013 at 1:00 AM in UTC-5 could be either in CDT or EST. You'd have no way to distinguish just by -5 which time zone it was.
Details here.
Nowadays the DateTimeZone constructor can explicitly accept a UTC offset, which I understand you have.
So just:
$timeZone = new DateTimeZone('+0100');
Documentation:
http://php.net/manual/en/datetimezone.construct.php
Note: per that documentation link, this new constructor usage has been available since PHP version 5.5.10.
You might want to have a look at DateTime PHP extension (it's enabled & included by default in all PHP versions >= 5.2.0, unless it was specifically disabled at compile time).
It does everything you need here quite well.
You can use GMT time also and convert it to your requirement afterwards
<?php
echo gmdate("M d Y H:i:s", mktime(0, 0, 0, 1, 1, 1998));
?>
GMT refers Greenwich Mean Time which is common all over the world.
This work for me:
function Get_Offset_Date($Offset, $Unixtime = false, $Date_Format = 'Y.m.d,H:i')
{
try
{
$date = new DateTime("now",new DateTimeZone($Offset));
if($Unixtime)
{
$date->setTimestamp($Unixtime);
}
$Unixtime = $date->getTimestamp();
return $date->format($Date_Format);
}
catch(Exception $e)
{
return false;
}
}
To use it just call this to get current time:
echo Get_Offset_Date('+2:00');
And this for get Offset date (input is unixtime)
echo Get_Offset_Date('+2:00',1524783867);

UTC time to time based by timezone offset

I am saving all the times in MySQL in UTC(0), so I could change them later while I'm showing the times for the users with different time zones, for saving into db, I use:
function get_utc(){
date_default_timezone_set('UTC');
return date("Y-m-d H:i:s");
}
$now = get_utc();
And now I want to convert those times into different timezones based by timezones offset, I am using this function:
function utc_and_timezone($utc_time, $offset) {
return date("Y-m-d H:i:s", strtotime($offset, strtotime($utc_time)));
}
So for example, if the UTC time is: 2013-01-30 21:06:29
Applying the +5 timezone on that time is easy to find:
$new_time = utc_and_timezone("2013-01-30 21:06:29", "+5 hours"); // Works Fine
It works JUST fine with offsets like 5,6 or other integers, BUT with some other like +3.5, +2.5 this is not working:
$new_time = utc_and_timezone("2013-01-30 21:06:29", "+5.5 hours"); // NOT WORKING
Anyone knows why?!
Any better solutions for making UTC times in different timezones...?
Thanks
SHORT QUESTION:
I want to show a UTC time like 2013-01-30 21:06:29 in +3.5 timezone, how is that possible?
On the PHP side, you can try:
$utc_time = '2013-01-30 21:06:29';
$offset = '3.5';
echo date("Y-m-d H:i:s", strtotime($utc_time) + (3600 * $offset) );
//Returns 2013-01-31 00:36:29
$utc_time = '2013-01-30 21:06:29';
$offset = '-5.5';
echo date("Y-m-d H:i:s", strtotime($utc_time) + (3600 * $offset) );
//Returns 2013-01-30 15:36:29
On the MySQL side, you can just use CONVERT_TZ:
SELECT CONVERT_TZ('2013-01-30 21:06:29','+00:00','+03:30');
//Returns January, 31 2013 00:56:29+0000
SELECT CONVERT_TZ('2013-01-30 21:06:29','+00:00','-05:50');
//Returns January, 30 2013 15:16:29+0000

Convert UTC offset to timezone or date

A head scratcher for you.
I am grabbing geo IP data from IPInfoDB's API and it returns a timezone offset from UTC including DST (if currently reflected).
For example, I live in EST (-5) and currently it's DST, so the geo IP API returns (-04:00) as the offset.
This is wonderful since DST is a freaking headache. But to my surprise, it caused another headache.
I load this data in PHP to be passed via AJAX to the application. I would like to have the live local time of the IP address on the app.
I have that all set perfectly, but I am going crazy trying to figure out how to set the PHP timezone to match the offset so I can just grab the current hours date('H'); and minutes date('i'); to pass to via AJAX.
I am unsure if there is a specific function that can just give me the current hours and minutes based on that offset or if there is a practical way to set the timezone based on the offset (which will have DST already applied if is in effect).
I've been searching and searching Google to find an answer to this, but what I am doing is more specific since DST is already applied.
I found one function on PHP.net that seems to do the trick (it works for my timezone and returns the correct time) although for other timezones such as PST, it's returning 1 hour later than it should be even though the offset is correct (-07:00 with DST).
The timezone returned from the function is Chile/EasterIsland which I have a feeling is the cause. If I could, I would make this only work for the USA, but I do need it to be worldwide.
This is the function I have now. Please excuse the extremely messy code. I have been playing around with tons of things over the last few hours trying to figure out a solution.
Most of the functionality was found online.
function offsetToTZ($offset) {
switch((string) $offset) {
case '-04:30' : return 'America/Caracas'; break;
case '-03:30' : return 'Canada/Newfoundland'; break;
case '+03:30' : return 'Asia/Tehran'; break;
case '+04:30' : return 'Asia/Kabul'; break;
case '+05:30' : return 'Asia/Kolkata'; break;
case '+05:45' : return 'Asia/Kathmandu'; break;
case '+09:30' : return 'Australia/Darwin'; break;
}
$offset = (int) str_replace(array('0',0,':00',00,'30',30,'45',45,':','+'),'', (string) $offset);
$offset = $offset*60*60;
$abbrarray = timezone_abbreviations_list();
foreach ($abbrarray as $abbr) {
foreach($abbr as $city) {
if($city['offset'] == $offset) {
return $city['timezone_id'];
}
}
}
return false;
}
I included the switch/case for certain timezones that are :30 and :45 out there. There may be a way to include that also without the need of the switch/case.
NOTE: The offsets are always returned as such +00:00 or -00:00 from the geo IP API.
I would appreciate any help or a point in the right direction. I'm not very novice with PHP, but offsets are a new story for me. Thanks!
It can be done quite simply, by turning the offset into seconds and passing it to timezone_name_from_abbr:
<?php
$offset = '-7:00';
// Calculate seconds from offset
list($hours, $minutes) = explode(':', $offset);
$seconds = $hours * 60 * 60 + $minutes * 60;
// Get timezone name from seconds
$tz = timezone_name_from_abbr('', $seconds, 1);
// Workaround for bug #44780
if($tz === false) $tz = timezone_name_from_abbr('', $seconds, 0);
// Set timezone
date_default_timezone_set($tz);
echo $tz . ': ' . date('r');
Demo
The third parameter of timezone_name_from_abbr controls whether to adjust for daylight saving time or not.
Bug #44780:
timezone_name_from_abbr() will return false on some time zone
offsets. In particular - Hawaii, which has a -10 from GMT offset, -36000
seconds.
References:
timezone_name_from_abbr
date_default_timezone_set
date
date_default_timezone_set('UTC');
$timezones = array();
foreach (DateTimeZone::listAbbreviations() as $key => $array)
{
$timezones = array_merge($timezones, $array);
}
$utc = new DateTimeZone('UTC');
$timezone_offset = '+02:00'; # 2H
$sign = substr($timezone_offset, 0, 1) == '+'? '': '-';
$offset = substr($timezone_offset, 1, 2) . 'H' . substr($timezone_offset, 4, 2) . 'M';
$operation = $sign == ''? 'add': 'sub';
$start = new DateTime('', $utc);
$date = new DateTime('', $utc);
$date->{$operation}(new DateInterval("PT{$offset}"));
$offset = $start->diff($date)->format('%r') . ($start->diff($date)->h * 3600 + $start->diff($date)->m * 60 + $start->diff($date)->s); # 7200 (2H)
echo $offset, PHP_EOL;
echo $date->format('Y-m-d H:i:s'), PHP_EOL;
foreach($timezones as $timezone)
{
if($timezone['offset'] == $offset)
{
echo $timezone['timezone_id'], PHP_EOL;
}
}
I might have misunderstood you in some parts, but I hope it helps, if you could be more specific, I might be more helpful.
For Chile I get:
-25200 (-7h)
2012-08-07 18:05:24 (current time 2012-08-08 01:05:24)
Chile/EasterIsland
Output of the example above:
7200
2012-08-08 02:49:56
Europe/London
Europe/Belfast
Europe/Gibraltar
Europe/Guernsey
Europe/Isle_of_Man
Europe/Jersey
GB
Africa/Khartoum
Africa/Blantyre
Africa/Bujumbura
Africa/Gaborone
Africa/Harare
Africa/Kigali
Africa/Lubumbashi
Africa/Lusaka
Africa/Maputo
Africa/Windhoek
Europe/Berlin
Africa/Algiers
Africa/Ceuta
Africa/Tripoli
Africa/Tunis
Arctic/Longyearbyen
Atlantic/Jan_Mayen
CET
Europe/Amsterdam
Europe/Andorra
Europe/Athens
Europe/Belgrade
Europe/Bratislava
Europe/Brussels
Europe/Budapest
Europe/Chisinau
Europe/Copenhagen
Europe/Gibraltar
Europe/Kaliningrad
Europe/Kiev
Europe/Lisbon
Europe/Ljubljana
Europe/Luxembourg
Europe/Madrid
Europe/Malta
Europe/Minsk
Europe/Monaco
Europe/Oslo
Europe/Paris
Europe/Podgorica
Europe/Prague
Europe/Riga
Europe/Rome
Europe/San_Marino
Europe/Sarajevo
Europe/Simferopol
Europe/Skopje
Europe/Sofia
Europe/Stockholm
Europe/Tallinn
Europe/Tirane
Europe/Tiraspol
Europe/Uzhgorod
Europe/Vaduz
Europe/Vatican
Europe/Vienna
Europe/Vilnius
Europe/Warsaw
Europe/Zagreb
Europe/Zaporozhye
Europe/Zurich
WET
Europe/Kaliningrad
Europe/Helsinki
Africa/Cairo
Africa/Tripoli
Asia/Amman
Asia/Beirut
Asia/Damascus
Asia/Gaza
Asia/Istanbul
Asia/Nicosia
EET
Europe/Athens
Europe/Bucharest
Europe/Chisinau
Europe/Istanbul
Europe/Kaliningrad
Europe/Kiev
Europe/Mariehamn
Europe/Minsk
Europe/Moscow
Europe/Nicosia
Europe/Riga
Europe/Simferopol
Europe/Sofia
Europe/Tallinn
Europe/Tiraspol
Europe/Uzhgorod
Europe/Vilnius
Europe/Warsaw
Europe/Zaporozhye
Asia/Jerusalem
Asia/Gaza
Asia/Tel_Aviv
MET
Africa/Johannesburg
Africa/Maseru
Africa/Mbabane
Africa/Windhoek
Africa/Windhoek
Africa/Ndjamena
Europe/Lisbon
Europe/Madrid
Europe/Monaco
Europe/Paris
WET
Europe/Luxembourg
Which nails my timezone.
$UTC_offset = '+03:00';
$date = new \DateTime('now', 'UTC');
var_dump($date);
$timezone = new \DateTimeZone(str_replace(':', '', $UTC_offset));
$date->setTimezone($timezone);
var_dump($date);
Results:
class DateTime#205 (3) {
public $date =>
string(26) "2015-01-20 06:00:00.000000"
public $timezone_type =>
int(3)
public $timezone =>
string(3) "UTC"
}
class DateTime#205 (3) {
public $date =>
string(26) "2015-01-20 09:00:00.000000"
public $timezone_type =>
int(1)
public $timezone =>
string(6) "+03:00"
}
It is unadvised to map time zone offsets back to a time zone identifier. Many time zones share the same offset.
Even within a single country, this is problematic. Consider that in the United States, the -5 offset is used by both Central Standard Time (America/Chicago) and Eastern Daylight Time (America/New_York) at different times of the year.
Also consider that there are times where BOTH of those time zones use -5 at the same time. For example, Sunday November 3rd 2013 at 1:00 AM in UTC-5 could be either in CDT or EST. You'd have no way to distinguish just by -5 which time zone it was.
Details here.
Nowadays the DateTimeZone constructor can explicitly accept a UTC offset, which I understand you have.
So just:
$timeZone = new DateTimeZone('+0100');
Documentation:
http://php.net/manual/en/datetimezone.construct.php
Note: per that documentation link, this new constructor usage has been available since PHP version 5.5.10.
You might want to have a look at DateTime PHP extension (it's enabled & included by default in all PHP versions >= 5.2.0, unless it was specifically disabled at compile time).
It does everything you need here quite well.
You can use GMT time also and convert it to your requirement afterwards
<?php
echo gmdate("M d Y H:i:s", mktime(0, 0, 0, 1, 1, 1998));
?>
GMT refers Greenwich Mean Time which is common all over the world.
This work for me:
function Get_Offset_Date($Offset, $Unixtime = false, $Date_Format = 'Y.m.d,H:i')
{
try
{
$date = new DateTime("now",new DateTimeZone($Offset));
if($Unixtime)
{
$date->setTimestamp($Unixtime);
}
$Unixtime = $date->getTimestamp();
return $date->format($Date_Format);
}
catch(Exception $e)
{
return false;
}
}
To use it just call this to get current time:
echo Get_Offset_Date('+2:00');
And this for get Offset date (input is unixtime)
echo Get_Offset_Date('+2:00',1524783867);

How to convert datetime to GMT in php

Alright, so i'm not sure if im converting user input time to GMT properly. I will be having users across several timezones entering "events" and they will have to be able to see "how long untill" or "how long since" the current time();
This is how I was planning to convert the time they input. It will start as something like 07/21/2011 01:30 am Then,
echo gmdate('Y-m-d H:i:s',strtotime('07/21/2011 01:30 am'));
gives me 2011-07-21 08:30:00
So I was planning to take the value of gmdate('Y-m-d H:i:s',strtotime('07/21/2011 01:30 am')); then take time() and display "how long until this event" to users. But it seems like there is always 10 hours added onto the result, so if if i was scheduling an event 30 min from now it would say 10 hours 30 min from now. So, im thinking im not converting the local time correctly or something.
What am I missing? Maybe I just dont properly understand GMT. How can I make sure all the times involved are GMT so all times are universal to all the users on the website?
Other info if it helps:
The server timezone is America/Los_Angeles
EDIT:
After everyones suggestions i've tried setting this at the top of my php code:
date_default_timezone_set("GMT");
and I tried using date('Y-m-d H:i:s') to do the comparison to figure out the diff, but its saying "3 hours ago" rather than the 10 hours from now. So this definately changed things.
But still not correct.
I've confirmed date('Y-m-d H:i:s') is returning the correct and current GMT. So thats good.
But the user input date is off. How am I converting it incorrectly?
EDIT AGAIN(including some test results after Salman A's suggestions):
2:55am - my current local time EST
date('Y-m-d H:i:s') shows up as 2011-07-21 06:56:43 - which is correct
3:00am EST is the time in the future I submitted as 07/21/2011 03:00 am
Here's how I get the time "convert it" and submit it to my DB:
$time = $_POST['time'];
//there is where im assuming it turns my EST time to the GMT equivalent.
$the_date = strtotime($time . ' GMT');
$utctime = gmdate('Y-m-d H:i:s',$the_date);
I'm expecting my function to tell me the event is 5 minutes from now, but its hours off.
just to make sure the user submitted time was actually converted to GMT i display $utctime and it shows up as 2011-07-21 03:00:00 - which is not 08:00 or 07:00 (which i think one of those would be the GMT equivalent)
So how do I convert it?
So, what im seeing is strtotime($time . ' GMT'); doesn't seem to be applying the GMT to the local time I supply. On a side note: somone suggested I have date_default_timezone_set("GMT"); in my code, so i have it at the top. Should I remove it? but i noticed if i remove it the GMT is incorrect. So thats why I left it.
If you simply need to calculate the difference between two time values:
<?php
$time = '07/21/2011 11:30 am';
$timeleft = strtotime($time) - time();
// target time....: 2011-07-21 11:30:00
// current time...: 2011-07-21 11:13:45
// difference.....: 975 seconds (16 min, 15 seconds)
The above example assumes that $time has same timezone as that used by the time() function i.e. the server's timezone.
If the timezones differ, you must normalize them in order for subtraction to work as expected. So for example if you're storing GMT date/time in your database then the above example becomes:
<?php
$time = '07/21/2011 06:30 am';
$timeleft = strtotime($time . ' GMT') - time();
// target time............: 2011-07-21 06:30:00 GMT
// converted local time...: 2011-07-21 11:30:00 PKT
// current time...........: 2011-07-21 11:34:48 PKT
// difference.............: -288 seconds (minus 4 minutes, 48 seconds)
Edit 1
Regarding this code:
$time = $_POST['time'];
If your users are from various parts of the world, you should either:
ask them to enter the date/time in GMT
ask them to enter a timezone for the date entered
You can later convert the date on server side and store it in database:
<?php
$source_time = '2011-07-21 17:00';
$source_offset = '-0700'; // PDT
$local_timestamp = strtotime($source_time . ' ' . $source_offset); // 2011-07-22 05:00 PKT (SERVER TIME)
list(
$temp_hh,
$temp_mm
) = explode(':', date('P')); // returns difference between SERVER TIME and GMT
$local_offset = $temp_hh * 3600 + $temp_mm * 60;
$gmt_timestamp = $local_timestamp + $local_offset;
echo date("Y-m-d H:i:s", $gmt_timestamp); // 2011-07-21 10:00:00
// THIS is what you store in your database
// Same as 2011-07-21 17:00:00 minus 7 hours
Without the timezone information your calculations will be unreliable.
Edit #2
Actually... it is much simpler:
<?php
$source_time = '2011-07-21 17:00';
$source_offset = -7.0; // -0700
echo date("Y-m-d H:i:s", strtotime($source_time) + $source_offset * 3600);
// 2011-07-21 10:00:00
// THIS is what you store in your database
Edit #3
<input type="text" name="time" id="time" value="07/21/2011 17:00">
<input type="text" name="offset" id="offset">
<script type="text/javascript">
document.getElementById("time").onchange = function(){
var d = new Date(this.value);
alert('Date entered: ' + d + '\nDate to GMT: ' + d.toUTCString());
}
document.getElementById("offset").value = (new Date()).getTimezoneOffset() / 60;
</script>
Demo here
A good idea is to explicitly set the timezone for your scripts. For example:
date_default_timezone_set('Europe/London');
This will make all date functions returns dates in GMT, and I believe accounting for BST too.
Hello I am living in Poland and we have a CET time.
To convert CET to GMT I am using function:
function convertCETtoGMT($timeCET)
{
date_default_timezone_set('EUROPE/London');
$time = $timeCET." CET";
$timeGMT = date('Y-m-d H:i:s', strtotime($time));
date_default_timezone_set('EUROPE/Warsaw'); //set back to CET
return $timeGMT;
}

check time for time difference in 24hr

In php i get the variable $date_time in this format -- 11-01-2010 20:48:25 . This time is GMT time. I have a 2 hour flexibility and if it exceeds 2 hours then i have to reject it. I am set in EST, but i want to do the check based on GMT only so that there is no errors in the time difference. How can i set to GMT in my php code and how do i check for the 2 hours flexible time difference? like for this example it is acceptable for any time between 11-01-2010 18:48:25 and 11-01-2010 22:48:25. Also will it be an issue if $date_time is 11-01-2010 23:48:23?
Clarification
I am doing a $date_time=$_GET['date_time'];. Then i need to check if this new $date_time if within 2 hours range of the current GMT time. if it is in the range, then i will proceed to execute that code, else i will show an error or do something else. I wanted to know how i am going to check this 2 hours range for this $date_time variable.
Here is a way how to convert your time format into a UNIX timestamp:
$date = strptime($date_time, "%m-%d-%Y %T");
$ut = mktime($date['tm_hour'], $date['tm_min'], $date['tm_sec'], 1 + $date['tm_mon'], $date['tm_mday'], 1900 + $date['tm_year']);
$now = time();
if($ut >= $now && $ut <= ($now + 7200)) { // 7200 = 2 * 60 * 60 seconds
// allowed
}
Reference: strptime, mktime, time.
Note: time() always returns the UNIX timestamp in UTC (regardless of time settings). So this assumes that the $date_time timestamp is a GMT time.
Working example (of course you have to provide a valid GMT time for $date_time).
Note 2: If the input time is not in GMT, you can set the timezone with date_default_timezone_set (affects mktime but not time).
Working example (change time and timezone accordingly)
If PHP >= 5.3 (you've got a seriously weird format BTW):
date_default_timezone_set('EST');
$inputtime = DateTime::createFromFormat('m-d-Y H:i:s','11-01-2010 20:48:25',new DateTimeZone("GMT"));
$diff = $inputtime->getTimestamp() - time();
if(abs($diff) > 7200){
//more then 2 hours difference.
}
If you run on PHP > 5.3, you can use DateTime for this :
$my_date = "11-01-2010 20:48:25";
$date = DateTime::createFromFormat('m-d-Y H:i:s', $my_date);
$date_lower = DateTime::createFromFormat('m-d-Y H:i:s', $my_date);
$date_upper = DateTime::createFromFormat('m-d-Y H:i:s', $my_date);
$date_lower->sub(new DateInterval('PT2H'));
$date_upper->add(new DateInterval('PT2H'));
var_dump($date >= $date_lower && $date <= $date_upper); // bool(true)
I find it more readable.
You can also use another timezone if necessary, check the third argument of createFromFormat.
I suggest you to never pass times and dates with format string. Just convert it later. You just pass the timestamp as a get variable and then you format it in the script.
It's the best solution and also the cleanest.
Then use the following code:
$flexibility = X seconds;
if ($date_time < time() - $flexibility or $date_time > time() + $flexibility)
{ /*Error*/ }

Categories