I am pretty sure that at some point in your programming career you will have to mess with dates. This is normally not a big deal, as a date is a date is a date. But then, you will get into more complicated date structures and algorithms involving timezones and daylight savings time. This is about when your hair will start to fall out and you start running around like an idiot screaming at the walls. I know, because I was doing almost this exact thing yesterday.
What happened:
I started with a date, made a timestamp, and then wanted to loop through all dates less than today. I was doing some data scrubbing based on these dates. The issue was that when I went to graph the data based on these dates, I was missing data for Oct 30 and March 11. The more observant programmer, the person who read the title, or someone not blinded by their own code would have noticed that those are the days when we Americans celebrate Daylight savings (celebrate being a relative term). Much like Y2K, DST causes many programmers much anguish.
For example, if I start looping from January 1, 2006 to today, my code looked something like this:
-
$timestamp = 1136132724; //gmt for jan 01, 2006 + some hours
-
//scrub the date to just the Year, month and day – scrub the hours, minutes and seconds off
-
$date = date('Y-m-d', $timestamp);
-
$minDate = strtotime($date);
-
while ($minDate < time()) {
-
//do some code
-
//increment the date by 24hrs worth of seconds
-
$minDate += 86400;
-
}
By all accounts, whether this code is ugly or not, this loop will allow you to run some code for every day between the initial date and today. Except one thing, DST.
What happens is that on the code where we do this:
-
$date = date('Y-m-d', $timestamp);
We are essentially asking for the same thing as:
-
$date = date('Y-m-d 00:00:00', $timestamp);
or
-
$date = date('Y-m-d', $timestamp).' 00:00:00';
Which is midnight of the day we are starting on. Still, we should be fine, right?
Nope.
What happens here is that on October 29, 2006 when we add 86400 seconds, we do not get the timestamp of:
-
2006-10-30 00:00:00
we in fact get:
-
2006-10-29 23:00:00
because of DST. Fun, right!?
The Solution:
What we can do is actually initialize the original date variable to be at noon on the initial date. This means that whether the time goes forward in the spring to 1pm, backwards to 11am, or stays at noon we are ALWAYS talking about the same day. Whereas, 11pm, 12am and 1am are not on the same days.
The code looks like this:
-
$timestamp = 1136132724; //gmt for jan 01, 2006 + some hours
-
//scrub the date to just the Year, month and day – scrub the hours, minutes and seconds off
-
$date = date('Y-m-d', $timestamp);
-
$minDate = (strtotime($date) + 43200);
-
while ($minDate < time()) {
-
//do some code
-
//increment the date by 24hrs worth of seconds
-
$minDate += 86400;
-
}
Where we essentially just added 12 hours to the scrubbed date. This gives us exactly 12pm.
Caveats:
This code sort of assumes that all of your timestamps were recorded in the same time zone. Between PHP and MySQL you can get some squirley date issues. The best solution here is to record all timestamps in GMT and then adjust them in one place only, either as you pull them from MySQL or in the PHP. DO NOT try to adjust sometimes in one place and other times in the other, it is too easy to get confused.
The other thing to realize is that your users may be pulling data from across the globe, which means that the timezones are way different. This also means that 12pm your time may be 12am their time, which can put you in the same predicament. I believe it is better to run date-based system critical data in a single timezone and do not run it from random or different timezones, just in case.
Questions, Comments, Suggestions? Please leave them as a comment below this post!
Sphere: Related Content
