PHP daylight saving time detection - php

I need to send an email to users based wherever in the world at 9:00 am local time. The server is in the UK. What I can do is set up a time difference between each user and the server's time, which would then perfectly work if DST didn't exist.
Here's an example to illustrate it:
John works in New York, -5 hours from the server (UK) time
Richard works in London, UK, so 0 hour difference with the server.
When the server goes from GMT to GMT +1 (BST) at 2:00am on a certain Sunday, this means that John now has a -6H time difference now.
This scenario I can still handle by updating all the users outside the server's local time, but once I've moved forward/backward the time of all the other users, I still need a way to detect when (time and date) the users living outside the UK will (or will not) change their local time to a probable DST one.
I need a PHP method to know/detect when other parts of the world will enter/exit DST.

Do you need to know all the details of DST transition yourself? or do you just need to know when is 9:00 am in a given timezone?
If it's the latter, PHP can use your operating system's timezone database to do that for you. The strtotime() function is remarkably good at "figuring out" what you mean:
echo strtotime("today 9:00 am America/New_York"); // prints "1306501200"
echo strtotime("today 9:00 am Europe/London"); // prints "1306483200"
Just make sure you're using one of the PHP supported timezones.

As Jimmy points out you can use timezone transitions, but this is not available on PHP <5.3. as dateTimeZone() is PHP>=5.2.2 but getTransitions() with arguments is not! In that case here is a function that can give you timezone data, including whether in DST or not.
function timezonez($timezone = 'Europe/London'){
$tz = new DateTimeZone($timezone);
$transitions = $tz->getTransitions();
if (is_array($transitions)){
foreach ($transitions as $k => $t){
// look for current year
if (substr($t['time'],0,4) == date('Y')){
$trans = $t;
break;
}
}
}
return (isset($trans)) ? $trans : false;
}
Having said that, there is a simpler method using date() if you just need to know whether a timezone is in DST. For example if you want to know if UK is in DST you can do this:
date_default_timezone_set('Europe/London');
$bool = date('I'); // this will be 1 in DST or else 0
... or supply a timestamp as a second arg to date() if you want to specify a datetime other than your current server time.

Changing my answer a bit: DateTimeZone::getTransitions looks like it will do what you need, provided you have PHP >= 5.2.
From a comment in the documentation:
<?php
$theTime = time(); // specific date/time we're checking, in epoch seconds.
$tz = new DateTimeZone('America/Los_Angeles');
$transition = $tz->getTransitions($theTime, $theTime);
// only one array should be returned into $transition. Now get the data:
$offset = $transition[0]['offset'];
$abbr = $transition[0]['abbr'];
?>
So here, all we need to do is pass in the timezone we want to check and we can know if that timezone is in DST/what the offset is. You'll then need to check the offset against GMT to see if you want to send your e-mail now, or not now.

I created this PHP function to see if a time value is BST or not:
<?php
function isBST($timestamp)
{
$baseDate = date("m/d/Y H:i:s", $timestamp);
$clocktime=strtotime($baseDate." Europe/London")."\n";
$utctime=strtotime($baseDate." UTC")."\n";
//echo "$a \n$b \n";
if ($clocktime!=$utctime)
{
return true;
}
else
{
return false;
}
}
?>

Related

How to get the UK timezone in PHP and detect midnight?

I am learning some PHP. I have a script which checks to see if a JSON file exists. If it does not exist; it will populate it with some YQL and some data. If it exists, it will not do anything as it is better for cache and speed.
In my code; I have this line (currently only doing every 3 hours (10800)):
if ( !file_exists($cache) || filemtime($cache) < ( time() - 10800 ) ) {
What I want do is, despite the server time, I want to use the UK GMT timezone and check to see if it is 00.01 past midnight, if it is, that is when I want to update the script. Every day at 00.01 midnight in the UK. Now I have heard PHP supports timezone but I only want it on this script?
This is what I have tried.
// TIMEZONE
date_default_timezone_set("Europe/London");
$date = $date();
$timestr = $time();
$timestamp = strtotime('today midnight');
// VARS
$cache = '../media/js/data.json';
// VALIDATION
// -- The cache is new
if ( !file_exists($cache) || filemtime($cache) < ( time() - timestamp ) ) {
another approach would be as mentioned would be cron jobs. you mentioned you want uk time zone , in that case please set your php.ini time zone to UK. this is how you do it
//add this line or replace within your php.ini file
; Defines the default timezone used by the date functions
date.timezone = "Europe/London"
and then set the cron job.
I'm using some stuff like that
$timezone = "Your timezone";
$tmpTZ = date_default_timezone_get();
date_default_timezone_set($timezone);
// some code to generate the date
date_default_timezone_set($tmpTZ);
Putting that in a small function an your ready to go.
The easiest solution will be usage of Cron, just calculate the difference between 2 timezones, and add task on the calculated time
http://www.thegeekstuff.com/2009/06/15-practical-crontab-examples/

Automatically calculate is daylight savings from timezone offset in php [duplicate]

I need to send an email to users based wherever in the world at 9:00 am local time. The server is in the UK. What I can do is set up a time difference between each user and the server's time, which would then perfectly work if DST didn't exist.
Here's an example to illustrate it:
John works in New York, -5 hours from the server (UK) time
Richard works in London, UK, so 0 hour difference with the server.
When the server goes from GMT to GMT +1 (BST) at 2:00am on a certain Sunday, this means that John now has a -6H time difference now.
This scenario I can still handle by updating all the users outside the server's local time, but once I've moved forward/backward the time of all the other users, I still need a way to detect when (time and date) the users living outside the UK will (or will not) change their local time to a probable DST one.
I need a PHP method to know/detect when other parts of the world will enter/exit DST.
Do you need to know all the details of DST transition yourself? or do you just need to know when is 9:00 am in a given timezone?
If it's the latter, PHP can use your operating system's timezone database to do that for you. The strtotime() function is remarkably good at "figuring out" what you mean:
echo strtotime("today 9:00 am America/New_York"); // prints "1306501200"
echo strtotime("today 9:00 am Europe/London"); // prints "1306483200"
Just make sure you're using one of the PHP supported timezones.
As Jimmy points out you can use timezone transitions, but this is not available on PHP <5.3. as dateTimeZone() is PHP>=5.2.2 but getTransitions() with arguments is not! In that case here is a function that can give you timezone data, including whether in DST or not.
function timezonez($timezone = 'Europe/London'){
$tz = new DateTimeZone($timezone);
$transitions = $tz->getTransitions();
if (is_array($transitions)){
foreach ($transitions as $k => $t){
// look for current year
if (substr($t['time'],0,4) == date('Y')){
$trans = $t;
break;
}
}
}
return (isset($trans)) ? $trans : false;
}
Having said that, there is a simpler method using date() if you just need to know whether a timezone is in DST. For example if you want to know if UK is in DST you can do this:
date_default_timezone_set('Europe/London');
$bool = date('I'); // this will be 1 in DST or else 0
... or supply a timestamp as a second arg to date() if you want to specify a datetime other than your current server time.
Changing my answer a bit: DateTimeZone::getTransitions looks like it will do what you need, provided you have PHP >= 5.2.
From a comment in the documentation:
<?php
$theTime = time(); // specific date/time we're checking, in epoch seconds.
$tz = new DateTimeZone('America/Los_Angeles');
$transition = $tz->getTransitions($theTime, $theTime);
// only one array should be returned into $transition. Now get the data:
$offset = $transition[0]['offset'];
$abbr = $transition[0]['abbr'];
?>
So here, all we need to do is pass in the timezone we want to check and we can know if that timezone is in DST/what the offset is. You'll then need to check the offset against GMT to see if you want to send your e-mail now, or not now.
I created this PHP function to see if a time value is BST or not:
<?php
function isBST($timestamp)
{
$baseDate = date("m/d/Y H:i:s", $timestamp);
$clocktime=strtotime($baseDate." Europe/London")."\n";
$utctime=strtotime($baseDate." UTC")."\n";
//echo "$a \n$b \n";
if ($clocktime!=$utctime)
{
return true;
}
else
{
return false;
}
}
?>

PHP Daylight Savings Time Issue

I have the following function that is used to get the correct time and is used for my website.
Unfortunately, It doesn't check for daylight savings time and is causing a time error. I was wondering if anyone would have a possible solution or help me out with my issue?
I am very new to PHP coding and am still getting my footing with it. It would be really helpful if someone would be able to help me with a way to have it automatically make the switch for in the future.
Here is the function:
function getDSTDifference() {
$timezone = date_default_timezone_get();
$newTZ = new DateTimeZone($timezone);
$trans = $newTZ->getTransitions();
$offset = $trans[0]['offset'] /60 /60;
return $offeset;
}
---EDIT---
To better clarify what I am trying to say:
I have a website that monitors call times. These call times become off by an hour during the switch between DST and Regular Time (and vice versa). For example this past weekend caused times to show up like this: -57:01:23. Instead of have the function the way that it is - where I would have to manually go in and uncomment/comment out the two lines of code every time DST and Regular Time switch, is there a possible solution to making the function be able to do this automatically? Kinda like a more permanent solution. To me it just seems like redundant coding to have to constantly revisit that function to make what seems like a simple change over and over again. Again, I have not done a lot of work with PHP code before, therefore I am not familiar with built in functions that can be used or if I would have to create this on my own. If anybody would have some information/help to go about this, it would be much appreciated.
function getDSTDifference() {
$timezone = date_default_timezone_get();
$NewTZ = new DateTimeZone($timezone);
$transition = $NewTZ->getTransitions();
$offset = $transition[0]['offset'] /60 /60;
//The following two lines need to be commented out when it is
//daylight savings time
//They need to be uncommented when Daylight Savings Time ends
$dst = $transition[0]['isdst'];
$offset = $offset - $dst;
return $offset;
}
Hopefully that makes more sense!
Thanks in advance for the help!
One possibility to calculate the difference between two given hours is to use DateTime::diff(). At the time of writing this answer there was a PHP bug and you had to convert to UTC before:
<?php
$zone = new DateTimeZone('Europe/Madrid');
$start = new DateTime('2013-03-31 1:59:00 ', $zone);
$end = new DateTime('2013-03-31 3:00:00', $zone);
// Workaround for bug #63953
// No longer required since PHP/5.6.0, PHP/5.5.8 or PHP/5.4.24
$start->setTimeZone(new DateTimeZone('UTC'));
$end->setTimeZone(new DateTimeZone('UTC'));
$difference = $start->diff($end);
echo $difference->format('%H:%I:%S');
... prints 00:01:00 because that's when DST started in Western Europe.
You can also use Unix timestamps, which represent a fixed moment in time thus do not depend on time zones:
<?php
$zone = new DateTimeZone('Europe/Madrid');
$start = new DateTime('2013-03-31 1:59:00 ', $zone);
$end = new DateTime('2013-03-31 3:00:00', $zone);
$difference = $end->format('U') - $start->format('U');
echo "$difference seconds";
... prints 60 seconds.
Edit #1: What do you mean? My snippet contains sample data so you can test it—in real code you'll use your real data. You can (and should) set the correct time zone as default so you don't need to specify it every time. But even if you don't, the server's time zone will never change—even if you decide to physically move the computer to another state or country several times a year you can still opt for a fixed time zone of your choice (your app's time zone can be different from your server's).
If you really want a solution that requires you to change the code manually twice a year (for whatever the reason, maybe to charge maintenance fees), you'd better skip date/time functions and use strings; otherwise you'll risk PHP doing the calculations for you.
Edit #2:
$start and $end represent your data. I chose sample data one minute before DST just to illustrate that the diff code works fine. It's the same as when you see <?php echo "Hello, World!"; ?> in a PHP tutorial: Hello, World! is sample data to illustrate how echo works but you don't have to use Hello, World! when you write your app.
To convert from GMT to EST with PHP you create a date that belongs to GMT:
$date = new DateTime('14:30', new DateTimeZone('GMT'));
echo 'GMT: ' . $date->format('r') . PHP_EOL;
// GMT: Thu, 07 Nov 2013 14:30:00 +0000
... and then switch to EST:
$date->setTimeZone(new DateTimeZone('EST'));
echo 'EST: ' . $date->format('r') . PHP_EOL;
// EST: Thu, 07 Nov 2013 09:30:00 -0500
However, if your original dates are in GMT, converting them to EST before substracting them does not provide any benefit.

How to get time at midnight of an user from my server?

I have an user with the timezone (for example: +7 GMT).
In PHP language:
My server is set timezone at 0-GMT.
How could I know from my server that now is midnight of that user?
Assuming you have the timezine of the user saved (I'll use America/Los_Angeles since that is currently GMT -7 right now)
$user_tz = 'America/Los_Angeles'; // get from your db
$dt = new DateTime();
$dt->setTimeZone(new DateTimeZone($user_tz))
if ($dt->format('g') == 0 && $dt->format('i') == '00')
{
echo "it's midnight";
}
You can't with PHP since it isn't running on the users computer, another option wold be using the getTimezoneOffset() in javascript.

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