Convert GMT time to Day light saving countries Timezone - php

I am working on project in which i am converting the time according to user location. i.e if user belongs to ALASKA then then all the information will be shown according to his countries timezone.I did some conversion but i am getting wrong time in case of user has a Daylight timezone (DST) which changes frequently.
Here is my code snippet.
date_default_timezone_set('UTC');
$offset=$_SESSION['gmtoffset'];
echo date('Y-m-d H:i:s',strtotime(date('Y-m-d H:i:s'))-(-$offset));
So in this case how do i maintain this timezone? what is the exact way for this time related conversions?
Any guidance and idea will be appreciated.
Thanks

Here's a simple solution
Javascript:
var timeZone = new Date().getTimezoneOffset();
document.cookie="tz=" + (timeZone/(-60));
Then PHP:
if(!empty($_COOKIE['tz']) && $_COOKIE['tz']>=-12 && $_COOKIE['tz']<=13){
$offset = $_COOKIE['tz'];
$tz = timezone_name_from_abbr(null, $offset * 3600, true);
if($tz === false) $tz = timezone_name_from_abbr(null, $offset * 3600, false);
date_default_timezone_set($tz);
}else{
date_default_timezone_set('UTC');
}

I am a bit uncertain to what in particular you are asking, but hopefully this will help.
If your question is regarding detecting that the user is in the Alaska time zone, then read:
How to detect user's timezone?
If your question is about picking a time zone by country, then read:
In PHP, how can I get Timezone from offset and country?
If you are wanting to understand Alaskan time zones, recognize that there are three different legal zones, and seven different IANA/Olson/TZ time zones (that PHP can use):
http://en.wikipedia.org/wiki/Time_in_Alaska
Don't try to treat a time zone as a numeric value. See "TimeZone != Offset" in the timezone tag wiki.
If you are wanting to manipulate dates with time zones in PHP, see the example in the PHP documentation for date_default_timezone_set.
If you just want to work with UTC, then there's no reason to do anything with time zones at all. The browser can always convert UTC to and from the user's local time zone, whatever that might be. Just create your JavaScript Date objects with a UTC timestamp integer, or parse from a UTC format, such as YYYY-MM-DDTHH:MM:SSZ.
To eliminate browser inconsistencies, you might want to use a library instead, such as moment.js:
// here's one way
var m = moment('2013-05-31T12:34:56Z');
// here's another
var m = moment.utc('2013-05-31 12:34:56','YYYY-MM-DD HH:mm:ss');
// pretty much anything else you might want to do...

Related

How to set php timezone by offset value in hh:mm, minuts or seconds?

My online application gets users timezone offset in + or - value in minutes. I want to set this value in server.
MySQL / MariaDB accepts timezone values and works perfectly
SET time_zone = "+0:15";
But php only accepts timezone string like this
date_default_timezone_set("Asia/Karachi"); // Works Perfectly
And does not set time in offset value
date_default_timezone_set("+0:15"); // Error
Is there any way to set php time with offset value?
After reading the documentation for the date_default_timezone_set() php function, this seems to be a common issue.
I'm sure there may be alternatives if you choose to use other date functions in php, however, to be able to set the timezone by an offset, you would require a helper function to do this.
I've copied and modified a helper function posted on the php doc page here
function setTimezoneByOffset($offset)
{
$testTimestamp = time();
date_default_timezone_set('UTC');
$testLocaltime = localtime($testTimestamp,true);
$testHour = $testLocaltime['tm_hour'];
$abbrarray = timezone_abbreviations_list();
foreach ($abbrarray as $abbr)
{
//$abbr."<br>";
foreach ($abbr as $city)
{
date_default_timezone_set($city['timezone_id']);
$testLocaltime = localtime($testTimestamp,true);
$hour = $testLocaltime['tm_hour'];
$testOffset = $hour - $testHour;
if($testOffset == $offset)
{
return $city['timezone_id'];
}
}
}
return false;
}
Where the parameter $offset is a string representation of the offset (ie. '+0:15'), which returns the timezone id of the timezone which matches that of your input.
My online application gets users timezone offset in + or - value in minutes.
This is problematic, because a time zone offset is not the same thing as a time zone. Consider that one cannot take the current offset and assume it is the correct offset to apply for any given date and time. Many time zones use more than one offset depending on time of year, and many time zones have had changes to their standard time offsets at different points in history. For more on this, see "Time Zone != Offset" in the timezone tag wiki.
As an example, you might be using a JavaScript function like new Date().getTimezoneOffset(). However, this returns the offset for the Date object returned by new Date() - which is the current date. For me, in the US Pacific time zone, it will return 480 (UTC-8) when run in the winter during standard time, but 420 (UTC-7) when run in the summer during daylight saving time.
Instead, have your front-end call Intl.DateTimeFormat().resolvedOptions().timeZone in JavaScript to return the time zone identifier, which for me returns "America/Los_Angeles". You can pass that to your back-end and use it with PHP.
As a side note, there are no time zones in the world that use or have ever used UTC+0:15. The closest to that would have been UTC+0:20 used in the Netherlands from 1 May 1909 to 16 May 1940. This is already captured in the history of "Europe/Amsterdam".

A Need To Check For Daylight Saving Time

What i am trying to archive is what time exactly a post was posted based on the users default timezone via there IP.
What i am worried about is daylight saving time so say if it's 1:46PM now then if daylight saving time in effect it might still post a update as 1:46PM instead of the exact time 3:46PM
The question is does PHP automatically check against that? or is there anything I need to do to see if daylight saving is in effect or not
$timezone = '+0:00';
$timezone = preg_replace('/[^0-9]/', '', $timezone) * 36;
$timezone_name = timezone_name_from_abbr(null, $timezone, true);
date_default_timezone_set($timezone_name);
echo date('D d M Y H:i:s');
Thanks :)
Just checking as everything needs to be 100% accurate
The answer is yes, PHP can give you the precise time based on timezone, regardless of DST. For example, if a user's IP tells you that they're in New York, you could do
$date = date_create('now America/New_York');
to create a DateTime object with the current time in New York.
echo $date->format('h:i:s');
Incidentally, DST is currently in effect, and this code prints the correct current time of 12:21:32.
EDIT
In response to your follow-up question, yes, the time that you save is the time that you will retrieve. For example,
$timestamp = (int) $date->format('U');
would save the absolute unix time of 12:21:32 (or whenever you run this code), regardless of timezone or DST. Another DateTime object will yield the same time:
$retrieved = new DateTime;
$retrieved->setTimestamp($timestamp);
echo $retrieved->format('h:i:s'); // outputs '12:21:32'
Hope that helps.
EDIT 2
To answer your next question, it is indeed possible to adjust a DateTime you've saved to a different timezone. First, set your script's default timezone to UTC.
date_default_timezone_set('UTC');
Then, you can save your timestamps as shown above (except, don't specify a timezone), and when you retrieve them, you can adjust them to where your users are:
echo $retrieved->format('h:i:s'); // Outputs UTC time of 5:21:32
$retrieved->setTimezone(new DateTimeZone('America/New_York'));
echo $retrieved->format('h:i:s'); // Outputs correct New York time of 12:21:32
Even after DST ends, this code would still display 12:21:32 (or, again, whatever time at which you run it)
Hope that helps, again!
EDIT 3
To address your most recent question, you can always just adjust the DateTime object based on the user's settings. For example, if they decide to override DST to off, then you should
// Change your default timezone to that of your user
date_default_timezone_set('America/New_York');
// Check for daylight savings time with date('I')
if (date('I', $timestamp) == 1) $retrieved->modify('-1 hour');
And that should do it!

how to convert PHP timezone string(e.g Europe/Berlin) to codeigniter timezone(e.g. UP1)

In a short if i have to ask this question is just the vice verse of this link question .
I am using a javscript library which automcatically detects the timezone and returns the time zone name in PHP format i.e 'Europe/Berlin' format.
But I make use of Codeigniters timezone_menu which gives a drop down box of time timezones and I am wondering how can i convert this php time zone (i.e 'Europe/Berlin' ) to codeigniters timezone format i.e UP1.?
It appears from the CodeIgniter documentation that they are treating time zones as fixed offsets. Their convention is fairly straight forward:
UTC to represent exactly UTC.
or
U to represent UTC
M or P for Minus or Plus
A number to describe the offset
A single digit for whole hour offsets
Two digits when there are half-hour offsets, but these are shifted funky (you would think +05:30 would be represented by UP55, but its actually UP45
So why did they do this? Who knows. It's not a standard thing, it's a CodeIgnitor special format. Normally an offset is just represented like +05:30 or +0530.
Using an offset to represent a whole time zone is out of sync with reality. If it was that easy, then we wouldn't need the IANA time zones like Europe/Berlin in the first place. You can see in the time zone list here that Europe/Berlin alternates between +01:00 and +02:00. Code Ignitor might say that it is UP1, but then that wouldn't ever take into account the daylight time offset. (Daylight saving time is different all over the world, so you can't just augment this with a checkbox and expect to be reliable.)
So, if you must have CodeIgnitor's strange form of time zone representation, then take the base offset of the IANA zone and apply their funky formula (as dev-null-dweller showed in his answer). Just don't expect it to be accurate.
And if you're in zone with a :45 offset, then you're out of luck. That would be Pacific/Chatham or Asia/Kathmandu.
You can read more in the timezone tag wiki under "Time Zone != Offset"
Just to add something actually constructive to to this answer, I recommend not using CodeIgnitor's time zones. Just stick with the IANA zones as provided for you by PHP. They are even kept up to date via timezondb in the PECL.
I don't know CI that much, but from quick look at the date helper documentation, it looks like it can be created from offset:
$now = new DateTime('now', new DateTimeZone('UTC'));
$tz = new DateTimeZone('America/Argentina/Buenos_Aires');
$offset = $tz->getOffset($now) / 3600;
$ci_tz = 'U';
if($offset) {
if($offset < 0) {
$ci_tz .= 'M';
$offset = abs($offset);
} else {
$ci_tz .= 'P';
}
if(is_float($offset)) {
$offset = $offset * 10 - 10;
}
$ci_tz .= (string)$offset;
} else {
$ci_tz .= 'TC';
}
var_dump($ci_tz); // UM3 = UTC Minus 3 hours

PHP & MySQL: Converting Stored TIMESTAMP into User's Local Timezone

So I have a site with a comments feature where the timestamp of the comment is stored in a MySQL database. From what I understand, the timestamp is converted to UTC when stored, then converted back to the default timezone when retrieved. In my case, my server is in the Central Daylight Time timezone (CDT).
I have a plan to get the timezone from each user via entry form. I just wanted to know how to convert the TIMESTAMP value into the user's timezone.
First, would I convert from UTC to local timezone? Or CDT to local timezone?
Secondly, how would I go about doing that in PHP? Would I just do:
$userTimezone = new DateTimeZone($userSubmittedTimezoneString);
$myDateTime = new DateTime($storedTimestamp, $userTimezone);
...or is that not correct?
Date/time/datetime values are stored in MySQL as you supply them. I.e. if you INSERT the string 2012-04-17 12:03:23 into a DATETIME column, that's the value that will be stored. It will be converted internally into a timestamp which may or may not be accurate (see below), but when you query for the value again, you'll get the same value back out; the roundtrip is transparent.
Problems may occur if you try to do time calculations inside SQL. I.e. any operation that requires SQL to take the timezone and/or the server time into account. For example, using NOW(). For any of those operations, the timezone and/or server time should be set correctly. See Time Zone Problems.
If that doesn't concern you and you only need to do calculations in PHP, you only need to make sure you know from which timezone to which timezone you want to convert. For that purpose it can be convenient to standardize all times to UTC, but it is not necessary, as timezone conversions from any timezone to any other timezone work just as well, as long as you're clear about which timezone you're converting from and to.
date_default_timezone_set('Asia/Tokyo'); // your reference timezone here
$date = date('Y-m-d H:i:s');
/* INSERT $date INTO database */;
$date = /* SELECT date FROM database */;
$usersTimezone = new DateTimeZone('America/Vancouver');
$l10nDate = new DateTime($date);
$l10nDate->setTimeZone($usersTimezone);
echo $l10nDate->format('Y-m-d H:i:s');
There is no reliable way to get the user's timezone. Timezone information is not sent in HTTP headers. The best that you could do is either:
Match the IP address againsta geographic database
-or-
Use Javascript to get the time set on the user's computer and either send that to the server (AJAX) or make the time string on the client.
$timezone = new DateTimeZone('America/Vancouver');
$date = new DateTime(date('m/d/Y h:i:s a', time()));
$date->setTimeZone($timezone);
echo $date->format('l F j Y g:i:s A')."\n";
Replace new DateTime(date('m/d/Y h:i:s a', time())); with new DateTime("UTC Time");
You can create a new DateTimeZone() object for each user input.
The way to do it is by using javascript. I think the best way to do it is by storing the users GMT into his cookies, and retrieving it on the PHP process form.
<script language="javascript">
function TimeZoneCookie()
{
var u_gmt = (-(new Date().getTimezoneOffset()))/60;
var o_date = new Date("December 31, 2025");
var v_cookie_date = o_date.toGMTString();
var str_cookie = "utimezone="+u_gmt;
str_cookie += ";expires=" + v_cookie_date;
document.cookie=str_cookie;
}
//---------------------
TimeZoneCookie();
</script>
u_gmt explained:
Date().getTimezoneOffset() returns the offset to GMT-0 in minutes
Since getTimezoneOffset() will return the offset to GMT-0 and not from GMT-0 we'll need to turn it around. How? simple, just by knowing that -*-=+ & -*+=-. If you know basic math, you already know this principle.
As I said in step 1 getTimezoneOffset() will return the offset in minutes, so we just divide it by 60, so we can get the gmt offset format.
Result: (-(new Date().getTimezoneOffset()))/60
Now retrieve the cookie in PHP:
<?php
$user_timezone = $_COOKIE['utimezone'];
?>

advice with php date and timestamps

We have a battle system where people can pick a match time to challenge another player. To create a match the user needs to pick a date. Currently a user picks the day, hour, minute, and pm/am from a dropdown list. If the user selects 5/20/2012 # 1PM, the system adds the hours and minutes from the start of the day. Here's a quick sample to get a better understanding of what I'm talking about:
$time = strtotime('today', $inputdate);
$time = $time + $hours + $minutes;
the value of $hours changes if the users selects AM or PM. It's pretty basic:
Everything was working fine until people started have timezone issues. For example, if player A creates a match at 1:PM, then player B will see the match starts at 1:PM, but he/she will have different timezones!
The problem is that I don't know the problem :/
I don't know how to fix the timezone issue. I have been creating functions in the hopes that everything will fall together, but no luck.
What I have:
User profiles have a timezone options.
A function that gets the raw timestamp and returns the formatted time based on the user's timezone.
A function that gets a timestamp and converts it to another timestamp
based on the user's timezone.
I'm lost and I can't seem to fix the issue, I can code, but right now I'm not thinking logical. I took me one hour to write this and try to explain it how I could, since I myself don't know how to make it work. Some advice is appreciated.
I need a function to convert a timestamp to UTC-5:
function input_date($timestamp)
{
global $vbulletin;
$timestamp = (int)$timestamp;
if (strlen((string)$timestamp) == 10)
{
$hour = 3600.00;
$offset = $vbulletin->userinfo['timezoneoffset'];//sample -8
$ds = (int)$vbulletin->userinfo['dstonoff'];//DST
$fluff = $hour*($offset+5.00);
$timestamp = $timestamp+$fluff+($ds*$hour);
return $timestamp;//return timestamp in UTC-5 format..
}
else
{
return 0;
}
}
Essentially everything in the database should be stored using a single timezone, preferably one which is not affected by DST. The standard option here is UTC.
If you know the user's timezone by its name, you can use that to generate your time:
// Player A creates match at 1PM Europe/London
$timezone = 'Europe/London';
$localTime = '2012-03-01 13:00:00';
// work out UNIX timestamp using that timezone (making it timezone independent)
date_default_timezone_set($timezone);
$timestamp = strtotime($localTime);
// store $timestamp in the database
// Player B views the timestamp with timezone America/Los_Angeles
$timezone = 'America/Los_Angeles';
date_default_timezone_set($timezone);
var_dump(date('c', $timestamp)); // see manual for more output formats
If you have the timezones stored as their abbreviations (e.g. "CET", "GMT"), then use timezone_name_from_abbr to get the correct timezone name.

Categories