1

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!

scapegoat17
  • 5,509
  • 14
  • 55
  • 90
  • What's the function supposed to do? I honestly cannot deduce it from current code and your textual description is quite vague. – Álvaro González Nov 04 '13 at 17:08
  • What's the output of `echo $timezone;`? – geomagas Nov 04 '13 at 17:08
  • 2
    check out this answer => http://stackoverflow.com/questions/1586552/how-to-tell-if-a-timezone-observes-daylight-saving-at-any-time-of-the-year – PlantTheIdea Nov 04 '13 at 17:09
  • @geomagas - I was unable to get anything to output in my chrome console when I added `echo $timezone;`. Do you have any ideas? – scapegoat17 Nov 04 '13 at 18:11
  • @ÁlvaroG.Vicario - Please see my edit above. Hopefully this makes more sense with what I am trying to do.Please let me know if I am still being too vague. – scapegoat17 Nov 04 '13 at 18:45
  • Sorry but I can't figure out that "transfer times for DST" means. Your code appears to calculate the difference in hours between DST and regular time for the server's time zone, which is probably a constant `1`. What's the use case for that? If you have "1st Jan, 18:30 +0100", do you want back `1st Aug, 19:30 +0200` instead of `18:30` or something like that? Are you trying to calculate the exact time when DST starts and ends? – Álvaro González Nov 05 '13 at 08:26
  • @ÁlvaroG.Vicario - Essentially, yes. What I want is a way to have the function recognize between DST and regular time - eliminating the reason for somebody to have to go in and comment/uncomment code every time. I am not a regular PHP coder and have not worked with it much at all. i am used to using Dot NET and C# in there you can use `TimeZoneInfo` and that will account for DST/Regular time changes. – scapegoat17 Nov 05 '13 at 22:17
  • You're already aware of [DateTimeZone::getTransitions()](http://us2.php.net/manual/en/datetimezone.gettransitions.php)—the time info is in the `time` key (rather than `offset`). But I'm pretty sure this is an [X-Y problem](http://mywiki.wooledge.org/XyProblem). I can't think of any real time situation where you need to know that your server in Madrid will switch to summer time on 30 Mar 2014 01:00:00 UTC. – Álvaro González Nov 06 '13 at 08:33
  • @ÁlvaroG.Vicario - I am trying to see how I turned this into an X-Y problem... Would you be able to elaborate more on what your are trying to explain to me (for a solution) - if you are trying to "help" me with my problem I am not understanding what your are actually saying. Perhaps we can start over with a clean slate. I changed my edit above to better explain my problem the best way I can. I am open to all suggestions that you may have. I am really just wondering if what I am asking for is feasible. If it is feasible, how would I go about it? Thank you for your patience thus far. – scapegoat17 Nov 06 '13 at 16:39

1 Answers1

3

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:

  1. $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.

  2. 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.

Álvaro González
  • 142,137
  • 41
  • 261
  • 360
  • Thank you, I really appreciate your help. My only followup question to this is: By setting the `$start` and `$end` dates as you have above, would that mean I would need to go in manually every year and change the date to the correct DST dates? If so, is there a way around doing something like that? – scapegoat17 Nov 06 '13 at 18:16
  • @scapegoat17 - I've edited my answer but I don't really understand what your follow-up question means. Do you have prior experience with another programming language? Perhaps you should explain how you'd do it with in that other lang and we can help you to port it to PHP. But my code complies exactly with what I assume to be your requirement: calculate the difference between two dates. If you need further clarifications to understand how it works feel free to ask but hard-coding DST stuff is crazy since PHP can do it for you. – Álvaro González Nov 07 '13 at 08:25
  • I think that what I said earlier may have come our wrong. I just wanted to make sure that it wasn't something hard coded and that I would not have to change the date every year. For example, this year DST ended `2013-11-03 2:00:00' and next year it will be `2013-11-02 2:00:00' so would i have to change the `$start` and `$end` dates every year due to the actual dates changing every year? I am sorry for my inexperience with doing something like this... I am just trying to better understand how this works and learn how to do this properly. And to answer your question I have done something similar – scapegoat17 Nov 07 '13 at 15:22
  • to this once before with C#/Dot NET. Where I had to parse an XML file and converted the format of the date from GMT to EST. This seemed to account for DST automatically with `TimeZoneInfo`. Other than that, I have had little experience dealing with DST in coding which is why my questions may sound silly/noobish. – scapegoat17 Nov 07 '13 at 15:25
  • @scapegoat17 - See my second edit (I don't explain how to parse XML but I understand you aren't asking that). – Álvaro González Nov 07 '13 at 16:36
  • Thank you for all of your help. That makes complete sense now. Sorry for the long drawn out questions. Again, I really appreciate your help and patience! – scapegoat17 Nov 07 '13 at 19:06