php mktime gives different results for same date? - php

the following code:
// settings 1st alternative
$season = 2011;
$startweek = 36;
// calculation, 1st alternative
// in any case Jan 1st is in 1. week
$firstweekuniversal = mktime(0,0,0,1,4,$season);
// I'd like to calculate monday 0:00 of the given week.
// date(...) computes to monday of the calculated week.
$startday1 = $firstweekuniversal + 86400 * (7*($startweek-1) - date('w', $firstweekuniversal)+1);
// settings 2nd alternative
$StartingDate = "KW36 - 5.09.2011 (Mo)";
// calculation, 2nd alternative
$firstparts = explode(" ", $StartingDate);
$secparts = explode(".", $firstparts[2]);
$startday2 = mktime(0,0,0,intval($secparts[1]),intval($secparts[0]),intval($secparts[2]));
// Output
echo "Start: \$startday1=".$startday1.", Timestamp=\"".date("d.m.Y - H:i:s", $startday1)."\"<br>\n";
echo "Start: \$startday2=".$startday2.", Timestamp=\"".date("d.m.Y - H:i:s", $startday2)."\"<br>\n";
leads to this output:
Start: $startday1=1315177200, Timestamp="05.09.2011 - 01:00:00"
Start: $startday2=1315173600, Timestamp="05.09.2011 - 00:00:00"
where is the 1h difference coming from? It can't be summertime issues, in that case the 1h had to be the other way round, or am I wrong?
There's no difference, when I'm trying with my environment (localhost), but on the server of my prvider there is.
Can anyone explain this to me? I'm totally puzzled here.
Thanks in advance,

My understanding of daylight savings is that at a certain point between winter and summer the sun is starting to rise earlier, so at 8am it would feel like it should be 9am ... and that's exactly what the clock does, it moves forward making it later (by one hour typically). This is also why it's such a good excuse for being late at school :)
In any case, the timezone setting of your local php is probably UTC (or some other "neutral" timezone) but the server timezone setting honors daylight savings.

Related

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.

php giving wrong answer when using time zone Australia/Sydney

I am developing an website to run in Australia.
so i have set the time zone as follows.
date_default_timezone_set('Australia/Sydney');
I need to calculate number of days between two dates.
I found a strange behavior in the month of October.
$now = strtotime('2013-10-06'); // or your date as well
$your_date = strtotime('2013-10-01');
$datediff = $now - $your_date;
echo floor($datediff/(60*60*24));//gives output 5, this is right
$now = strtotime('2013-10-07'); // or your date as well
$your_date = strtotime('2013-10-01');
$datediff = $now - $your_date;
echo floor($datediff/(60*60*24));//gives output 5, this is wrong, but it should be 6 here
after 2013-10-07 it always give one day less in answer.
Its fine with other timezones. May be its due to daylight saving. But whats the solution for this.
Please help.
Thanks
Why it says 5, and why this is technically correct
In Sydney, DST begins at 2013-10-06 02:00:00 - so you lose an hour in dates straddling that.
When you call strtime, it will interpret the time as a Sydney time, but return a Unix timestamp. If you converted the second set of timestamps to UTC, you'd get a range from 2013-09-30 14:00:00 to 2013-10-06 13:00:00, which isn't quite 6 days, so gets rounded down to 5.
How to get the time difference ignoring DST transitions
Try using DateTime objects instead, e.g.
$tz=new DateTimeZone('Australia/Sydney');
$start=new DateTime('2013-10-01', $tz);
$end=new DateTime('2013-10-07', $tz);
$diff=$end->diff($start);
//displays 6
echo "difference in days is ".$diff->d."\n";
Why does DateTime::diff work differently?
You might ask "why does that work?" - after all, there really isn't 6 days between those times, it's 5 days and 23 hours.
The reason is that DateTime::diff actually corrects for DST transitions. I had to read the source to figure that out - the correction happens inside the internal timelib_diff function. This correction happens if all the following are true
each DateTime uses the same timezone
the timezone must be geographic id and not an abbreviation like GMT
each DateTime must have different DST offsets (i.e. one in DST and one not)
To illustrate this point, here's what happens if we use two times just a few hours either side of the switch to DST
$tz=new DateTimeZone('Australia/Sydney');
$start=new DateTime('2013-10-06 00:00:00', $tz);
$end=new DateTime('2013-10-06 04:00:00', $tz);
//diff will correct for the DST transition
$diffApparent=$end->diff($start);
//but timestamps represent the reality
$diffActual=($end->getTimestamp() - $start->getTimestamp()) / 3600;
echo "Apparent difference is {$diffApparent->h} hours\n";
echo "Actual difference is {$diffActual} hours\n";
This outputs
Apparent difference is 4 hours
Actual difference is 3 hours

Understanding date processing with strtotime

I'm trying to get my head round someone else's code which they've written for handling the dates of when news stories are published. The problem has come up because they are using this line -
$date = strtotime("midnight", strtotime($dateString));
to process a date selected using a jquery calendar widget. This works fine for future dates, but when you try to use a date which is in the previous calendar year, it uses the current year instead. I think this is due to "midnight" finding the closest instance of the selected day and month.
I could remove the "midnight", but I'm not sure what the repercussions of this would be - is there a reason that the midnight could be there?
EDIT: this is the full block of code which handles the date. The date contains the time, which allows the user to publish an item at a specific time.
$array['display_date'] = '24 October, 2011 17:30';
$string = $array['display_date'];
$dateString = substr($string, 0, -5);
$timeArray = explode(':', substr($string, -5));
$hours_in_secs = 60 * 60 * $timeArray[0];
$mins_in_secs = $timeArray[1];
$date = strtotime("midnight", strtotime($dateString));
$timestamp = $date + $hours_in_secs + $mins_in_secs;
//assign timestamp to validation array
$array['display_date'] = $timestamp;
echo $array['display_date']; // Output = 1351094430 (Oct 24 2012 17:00:30)
This really depends on what $dateString contains. Assuming your jQuery widget delivered the time portion as well, your colleague likely wanted to remove the time portion. Compare the following:
echo date(DATE_ATOM, strtotime('2010-10-01 17:32:00'));
// 2010-10-01T17:32:00+02:00
echo date(DATE_ATOM, strtotime("midnight", strtotime('2010-10-01 17:32:00')));
// 2010-10-01T00:00:00+02:00
If your widget doesnt return the time portion, I dont see any reason for setting the date to midnight, because it will be midnight automatically:
echo date(DATE_ATOM, strtotime('2010-10-01'));
// 2010-10-01T00:00:00+02:00
Note that all these are dates in the past and they will result in the given year in the past, not the current year like you say. If they do in your code, the cause must be somewhere else.
Will there be repercussions when you change the code? We cannot know. This is just one line of code and we have no idea of any context. Your unit-tests should tell you when something breaks when you change code.
EDIT after update
The codeblock you show makes no sense whatsoever. Ask the guy who wrote it what it is supposed to do. Not only will it falsely return the current year for past years, but it will also give incorrect results for the minutes, e.g.
24 March, 2010 17:30 will be 2012-03-24T17:00:30+01:00
I assume this was an attempt at turning 24 March, 2010 17:30 into a valid timestamp, which is in a format strtotime does not recognize. But the approach is broken. When you are on PHP5.3 use
$dt = DateTime::createFromFormat('d F, Y H:i', '24 March, 2010 17:30');
echo $dt->format(DATE_ATOM); // 2010-03-24T17:30:00+01:00
If you are not on 5.3 yet, go through https://stackoverflow.com/search?q=createFromFormat+php for alternate solutions. There is a couple in there.

understanding gmtime return value

I can't understand why gmdate() and date() reutrn the same values if my server is not configured to be on Greenwich Mean Time.
Why is this?
echo time(); // 1311011114
echo date("U"); // 1311011114
echo gmdate("U"); // 1311011114
echo date("j-m-y H:m:s"); // 18-07-11 12:07:14
echo date("e"); // America/Chicago
echo date("O"); // -0500
echo date("T"); // CDT
UPDATE
how do I obtain current time on Greenwich? calculating with date("O")? is there other way?
Because time never changes -- it is always seconds since epoch (GMT).
Time is always the same. It is just your time-zone is different and that is how display date differs.
You can change your timezone in order to see time in the different zones.
See here for all the Date/Time functions
So a long time ago, people needed a way to determine time across multiple computing systems that was uniformed. The Computing Syndicate Council of Wise Elders (CSCWE for short) of the pre-Internet age were the ones that decided upon this. A secret ballot decided the arbitrary beginning point would be 1970 to herald a more advance computing age. So from that moment onwards, an unending march of seconds through the decades began, a new time for computing revolution with the steady beat of the seconds.
From this arbitrarily defined beginning, all computing time can be determined by running mathematical wizardry against this ever increasing number of seconds and then factoring in the timezones.
It is already answered but if you want to get local time and UTC time;
date_default_timezone_set('America/Chicago');
$format = 'Y-m-d H:i:s';
$time1 = time();
$time2 = strtotime(gmdate($format));
print date($format, $time1);
print date($format, $time2);
// 2014-07-24 17:31:23
// 2014-07-24 22:31:23

March 14th not 86400 seconds long?

In my web application, I have users input a date in a simple textbox. That input (after being sanitized, of course), is run through strtotime(), and 86399 is added to it, to make that timestamp the end of the day written (11:59:59). This is for due date purposes (so if the date passes, the application raises a flag)
For the days I tested, it worked...
January 5th saved as january 5th, at the end of the day.
March 13th saved as March 13th
March 15th saved as March 15th
March 14th, for whatever reason, saved itself as March 15th.
Is March 14th mysteriously a couple seconds short or something??
Update: Thanks to oezi for the solution - worked like a charm. Code as requested:
Old code:
if ($_POST['dateto'] != '') {
$dateto = strtotime(mysql_real_escape_string($_POST['dateto'])) + 86399;
}
New code:
# Offset to "end of day"
list($y,$m,$d) = explode('-',date("Y-m-d",strtotime($_POST['dateto'])));
$d++;
$dateto = strtotime($y . '-' . $m . '-' . $d) - 1;
March 14, 2010 is the day Daylight Saving Time begins in the United States. So if you're doing math in the local time zone, March 14 is only 23 hours long.
I would assume because this is the beginning of daylight savings time
Like others said, this is because of daylight saving time. To solve this problem, you could do this:
<?php
list($y,$m,$d) = explode('-',date("Y-m-d",strtotime($date_from_user)));
$h = 23;
$i = 59;
$s = 59;
$mytimestamp = "$y-$m-$d $h:$i:$s";
?>
What database are you using? there has to be a better way to do this (most date manipulation commands are database specific). In SQL Server, I'd just add 1 day to the date and then subtract 1 second:
DECLARE #YourDate datetime
SET #YourDate='2010-03-14'
SELECT DATEADD(ss,-1,#YourDate+1)
OUTPUT:
-----------------------
2010-03-14 23:59:59.000
(1 row(s) affected)
for what it is worth, I'd much prefer to have a condition: < NextDay than <=CurrentDay12_59_59
In all time zones that "support" daylight savings time, you'll get two days a year that don't have 24h. They'll have 25h or 23h respectively. And don't even think of hardcoding those dates. They change every year, and between time zones.
Oh, and here's a list of 34 other reasons that you hadn't thought about, and why you shouldn't do what you're doing.
http://tycho.usno.navy.mil/leapsec.html
Not all days are 86400 seconds long.
This is a rare event. And (historically) never scheduled in March.

Categories