Forum Moderators: coopster

Message Too Old, No Replies

Subtracting unixtime formatted dates renders remainders

unix timestamp, time stamp, add dates, subtract dates, remainder

         

elbowlobstercowstand

5:56 pm on May 21, 2009 (gmt 0)

10+ Year Member



I'm just starting to learn about date calculations. I'm curious to know why I SOMETIMES get a remainder from the following code, where I'm subtracting unix timestamps.

The code block below outputs:

days between 2009-01-01 and 2009-01-11 = 10 
days between 2009-01-01 and 2009-02-11 = 41
days between 2009-01-01 and 2009-03-11 = 68.9583333333


#Why the remainder?

//first an example that works as expected, within the same month
$day1 = '2009-01-01';
$day2 = '2009-01-11';
//convert to unixtime
$day1_unixtime = strtotime($day1);
$day2_unixtime = strtotime($day2);
//subtract
$seconds_between = $day2_unixtime - $day1_unixtime;
//now convert that into days
$days_between = $seconds_between * (1/60) * (1/60) * (1/24);
//and the answer is...
echo "days between $day1 and $day2 = $days_between\n";
//outputs: 10 AS EXPECTED

//second an example that works as expected, between months
$day1 = '2009-01-01';
$day2 = '2009-02-11';
//convert to unixtime
$day1_unixtime = strtotime($day1);
$day2_unixtime = strtotime($day2);
//subtract
$seconds_between = $day2_unixtime - $day1_unixtime;
//now convert that into days
$days_between = $seconds_between * (1/60) * (1/60) * (1/24);
//and the answer is...
echo "days between $day1 and $day2 = $days_between\n";
//outputs: 41 AS EXPECTED

//third: why the remainder?!
//second an example that works as expected, between months
$day1 = '2009-01-01';
$day2 = '2009-03-11';
//convert to unixtime
$day1_unixtime = strtotime($day1);
$day2_unixtime = strtotime($day2);
//subtract
$seconds_between = $day2_unixtime - $day1_unixtime;
//now convert that into days
$days_between = $seconds_between * (1/60) * (1/60) * (1/24);
//and the answer is...
echo "days between $day1 and $day2 = $days_between\n";
//outputs: 68.9583333333 (NOT EXPECTED)

Maybe there is a better way to add/subtract dates and I don't know it. Regardless, I'm curious as to WHY a remainder exists. I'm thinking it has something to d with the calender not being perfect or something.

clkdesign

7:17 pm on May 21, 2009 (gmt 0)

10+ Year Member



Daylight savings time was March 8th, if you are not accounting for the lost time, this might be why you are getting a remainder?

clkdesign

7:43 pm on May 21, 2009 (gmt 0)

10+ Year Member



Just checked this, and it is daylight savings time that is messing with your code, so:

before march 9th = no remainder
between march 9th and october 31stb = no remainder
march 8th and to November 2nd = no remainder

days between 2009-11-01 and 2009-12-31 = 60.0416666667
after november 1st = no remainder.

You'll have to write an exception that includes these dates and add the appropriate time to even out the numbers.

penders

10:58 pm on May 21, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Daylight savings time was March 8th...

Ah, but this depends where you are in the world (or rather where your server is, or what the default timezone is). Using your code, the days between 2009-01-01 and 2009-03-11 comes out at a nice round 69 over here (but we change our clocks on 29 March)!

You'll have to write an exception that includes these dates and add the appropriate time to even out the numbers.

Or you could just round() the result, now that you know what the reason is.

However, if you keep your dates relative to UTC/GMT then you shouldn't get this problem. May be set date_default_timezone_set('UTC') at the start of your script? Or perhaps consider using gmmktime() instead of converting strings, unless that is a requirement. (Although the default timezone should be set somewhere.)

elbowlobstercowstand

12:24 am on May 22, 2009 (gmt 0)

10+ Year Member



Thanks SO much for nailing that down guys. That makes sense. I didn't think of daylight savings because a) I'm dumb and b) I live in AZ, which is MST, which has NO daylight savings time. However, I do notice that when displaying the timezone portion of dates, I get "MDT" which I believe stands for mountain daylight time. Which likely has daylight savings time in it.

I need to find a way to check my server time, the time php is synced to, and mysql for that matter. I'm on apache. Time to google. Or if someone sees this, feel free to respond.

PS: And can I just add that whoever came up with daylight savings time should be tarred and feathered?

elbowlobstercowstand

2:13 am on May 22, 2009 (gmt 0)

10+ Year Member



post for webmaster world

K. I found out my mysql timezone is this using mysql monitor:


mysql> show variables like '%zone%';
+------------------+--------+
¦ Variable_name ¦ Value ¦
+------------------+--------+
¦ system_time_zone ¦ MST ¦
¦ time_zone ¦ SYSTEM ¦
+------------------+--------+
2 rows in set (0.00 sec)

And using phpinfo() function, my php timezone is this:

Default timezone America/Denver
(which corresponds to MDT)

Although I can't find this setting in php.ini. So I created it:

date.timezone = "America/Phoenix"

I thought PHP and mysql would both sync to the same thing in apache, of which, I'm thinking HAS a default timezone, I'm just not sure where to look for it. Wait. the httpd.conf file. I'm on it...

Nope. Nothing in there related to the term "zone" (which is hard to believe), but I'll simply change.

BOTTOM LINE
After changing the php.ini file to MST, I reran the code block, as suggested by PENDERS, and there were no round numbers! Thanks again everyone, so much!

[edited by: coopster at 12:07 pm (utc) on May 22, 2009]
[edit reason] removed non-authoritative url [/edit]

g1smd

2:23 am on May 22, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



There's something to be said for using UTC all year round for storage of data, and then let user apply their standard offset and then also adjust for DST at their end for display purposes only.

elbowlobstercowstand

2:35 am on May 22, 2009 (gmt 0)

10+ Year Member



Great idea... but for some reason, I'm scared to change all my databases, server settings, etc (with current date info stored as MST)... I mean, what if everything blows up?!

And... do you have functions written that make this simpler?

I'm not sure why, but dates and timezones have always scared the crap out of me. Wish there was a comprehensive tutorial out there regarding best practices. But do share yours. Well. I guess you did. But if you want to share more detail, would love to hear it.

coopster

12:41 pm on May 22, 2009 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



Here are a couple of old threads on the subject that may be helpful. The first asks the same question you originally asked and the second link is to the original introduction of the new configuration directive:

change apache timezone via htaccess? [webmasterworld.com]
[webmasterworld.com...]

However, the best resource is still the manual page for the date.timezone [php.net] configuration directive which offers this direction:

The default timezone used by all date/time functions if the TZ environment variable isn't set. The precedence order is described in the date_default_timezone_get() [php.net] page. See List of Supported Timezones [php.net] for a list of supported timezones.

elbowlobstercowstand

5:20 am on May 25, 2009 (gmt 0)

10+ Year Member



Hey Coopster... awesome links. Many virtual chocolate bars to you for your reply. You've always been incredibly helpful!