
Mark was inspired on Friday and wrote this lovely piece of code for detecting whether daylight savings time is enabled, which he is particularly proud of.
I have found it tends to be quite difficult to define what people mean when they specify a date and time.
* Do they mean GMT time? Unless they are living within the GMT timezone, more likely is that they mean their local time.
* What is the effect of daylight saving? It may or may not be in effect at a particular point in time, and possibly not even being used in the local timezone.
Javascript gives us the Date.getOffsetTimezone however AFAIK there is nothing similar for DST. The following Date protoype extension (based on the technique by Josh Frasher) detects whether DST is enabled:
Date.prototype.getDST() = function() {
var now_local = this;
var jan_local = new Date(now_local.getFullYear(), 0, 1, 0, 0, 0, 0, 0);
var jun_local = new Date(now_local.getFullYear(), 5, 1, 0, 0, 0, 0, 0);
var now_utc = new Date.UTC(now_local.getFullYear(), now_local.getMonth(), now_local.getDate(), now_local.getHours(), now_local.getMinutes(), now_local.getSeconds(), now_local.getMilliseconds());
var jan_utc = new Date.UTC(jan_local.getFullYear(), jan_local.getMonth(), jan_local.getDate(), jan_local.getHours(), jan_local.getMinutes(), jan_local.getSeconds()), jun_local.getMilliseconds();
var jun_utc = new Date.UTC(jun_local.getFullYear(), jun_local.getMonth(), jun_local.getDate(), jun_local.getHours(), jun_local.getMinutes(), jun_local.getSeconds(), jan_local.getMilliseconds());
var now_diff = Math.round((now_utc - now_local.getTime()) / (1000 * 3600));
var jan_diff = Math.round((jan_utc - jan_local.getTime()) / (1000 * 3600));
var jun_diff = Math.round((jun_utc - jun_local.getTime()) / (1000 * 3600));
return jan_diff != jun_diff && now_diff == Math.max(jan_diff, jun_diff);
}
Feel free to use/modify this code as you see fit.
Update: l8nite (see comment #1 below) pointed out a few errors when the times are right on the cusp of a DST update. This was down to the Date object doing internal conversions based on the user’s timezone (thus messing up the UTC times being passed in).
Update 2: Unfortunately this code relies on the operating system’s timezone settings and whether DST patches (DST changes all the time!) have been applied. Having done some testing in Win XP SP3 it seems that DST settings for the U.S. are a bit messed up.
Update 3: Updated to use UTC method from the class rather than a new object and added milliseconds (thanks l8nite comment #6)
Update 4: Using Math.round rather than parseInt to avoid rounding issues (thanks Eyal comment #7)
« Mega Monday lives up to the hype
Oban releases top secret project details to ITP.net »
Thanks for the fix! Is there a particular license on this code?
Actually, same results with the new code. Here’s what I’m using to test it:
/* unit tests */
var aDSTTests = [
// U.S.: 1987 - 2006
[ "Apr 02, 2006 01:59:00", false ],
[ "Apr 02, 2006 02:00:00", true ],
[ "Oct 29, 2006 01:59:00", true ],
[ "Oct 29, 2006 02:00:00", false ],
// U.S.: 2007 -
[ "Mar 11, 2007 01:59:00", false ],
[ "Mar 11, 2007 02:00:00", true ],
[ "Nov 04, 2007 01:59:00", true ],
[ "Nov 04, 2007 02:00:00", false ],
];
for (var i = 0; i < aDSTTests.length; i++)
{
var sDate = aDSTTests[i][0];
var bFlag = aDSTTests[i][1];
var oDate = new Date(sDate);
print(oDate);
if (oDate.getDST() != bFlag) {
print("FAIL: " + sDate + ", expected " + (bFlag ? 'on' : 'off'));
}
else {
print("PASS: " + sDate + ", expected " + (bFlag ? 'on' : 'off'));
}
if (i != aDSTTests.length – 1) {
print();
}
}
/* unit tests */
var aDSTTests = [
// U.S.: 1987 - 2006
[ "Apr 02, 2006 01:59:00", false ],
[ "Apr 02, 2006 02:00:00", true ],
[ "Oct 29, 2006 01:59:00", true ],
[ "Oct 29, 2006 02:00:00", false ],
// U.S.: 2007 -
[ "Mar 11, 2007 01:59:00", false ],
[ "Mar 11, 2007 02:00:00", true ],
[ "Nov 04, 2007 01:59:00", true ],
[ "Nov 04, 2007 02:00:00", false ],
];
for (var i = 0; i < aDSTTests.length; i++)
{
var sDate = aDSTTests[i][0];
var bFlag = aDSTTests[i][1];
var oDate = new Date(sDate);
print(oDate);
if (oDate.getDST() != bFlag) {
print("FAIL: " + sDate + ", expected " + (bFlag ? 'on' : 'off'));
}
else {
print("PASS: " + sDate + ", expected " + (bFlag ? 'on' : 'off'));
}
if (i != aDSTTests.length – 1) {
print();
}
}
Actually, now it doesn’t seem to work for any valid DST datetime…
After debugging a little I think you just need to change “new Date.UTC(…)” to “Date.UTC(…)”. I also added Milliseconds, since the Date object supports it.
Hi,
There is a potential problem (that unfortunately happened to me), with the float calculations.
If for example (now_utc – now_local.getTime()) / (1000 * 3600)
results in 4.9999, parseInt would result in now_diff=4 instead of the desired 5. I changed it to Math.round and it seemed to solve the problem.












FAIL: Mar 11, 2007 01:59:00, expected off
PASS: Mar 11, 2007 02:00:00, expected on
FAIL: Nov 04, 2007 01:59:00, expected on
PASS: Nov 04, 2007 02:00:00, expected off