Checking Whether Daylight Saving Time Is in Effect
Problem
You want to see whether the current time in your locale is normal time or Daylight Saving/Summer Time.
Solution
Create a Time object and check its isdst method:
Time.local(2006, 1, 1) # => Sun Jan 01 00:00:00 EST 2006 Time.local(2006, 1, 1). isdst # => false Time.local(2006, 10, 1) # => Sun Oct 01 00:00:00 EDT 2006 Time.local(2006, 10, 1).isdst # => true
Discussion
Time objects representing UTC times will always return false when isdst is called, because UTC is the same year-round. Other Time objects will consult the daylight saving time rules for the time locale used to create the Time object. This is usually the sysem locale on the computer you used to create it: see Recipe 3.7 for information on changing it. The following code demonstrates some of the rules pertaining to Daylight Saving Time across the United States:
eastern = Time.local(2006, 10, 1) # => Sun Oct 01 00:00:00 EDT 2006 eastern.isdst # => true ENV['TZ'] = 'US/Pacific' pacific = Time.local(2006, 10, 1) # => Sun Oct 01 00:00:00 PDT 2006 pacific.isdst # => true # Except for the Navajo Nation, Arizona doesn't use Daylight Saving Time. ENV['TZ'] = 'America/Phoenix' arizona = Time.local(2006, 10, 1) # => Sun Oct 01 00:00:00 MST 2006 arizona.isdst # => false # Finally, restore the original time zone. ENV['TZ'] = nil
The C library on which Ruby's Time class is based handles the complex rules for Daylight Saving Time across the history of a particular time zone or locale. For instance,
Daylight Saving Time was mandated across the U.S. in 1918, but abandoned in most locales shortly afterwards. The "zoneinfo" file used by the C library contains this information, along with many other rules:
# Daylight saving first took effect on March 31, 1918. Time.local(1918, 3, 31).isdst # => false Time.local(1918, 4, 1).isdst # => true Time.local(1919, 4, 1).isdst # => true # The federal law was repealed later in 1919, but some places # continued to use Daylight Saving Time. ENV['TZ'] = 'US/Pacific' Time.local(1920, 4, 1) # => Thu Apr 01 00:00:00 PST 1920 ENV['TZ'] = nil Time.local(1920, 4, 1) # => Thu Apr 01 00:00:00 EDT 1920 # Daylight Saving Time was reintroduced during the Second World War. Time.local(1942,2,9) # => Mon Feb 09 00:00:00 EST 1942 Time.local(1942,2,10) # => Tue Feb 10 00:00:00 EWT 1942 # EWT stands for "Eastern War Time"
A U.S. law passed in 2005 expands Daylight Saving Time into March and November, beginning in 2007. Depending on how old your zoneinfo file is, Time objects you create for dates in 2007 and beyond might or might not reflect the new law.
Time.local(2007, 3, 13) # => Tue Mar 13 00:00:00 EDT 2007 # Your computer may incorrectly claim this time is EST.
This illustrates a general point. There's nothing your elected officials love more than passing laws, so you shouldn't rely on isdst to be accurate for any Time objects that represent times a year or more into the future. When that time actually comes around, Daylight Saving Time might obey different rules in your locale.
The Date class isn't based on the C library, and knows nothing about time zones or locales, so it also knows nothing about Daylight Saving Time.
See Also
- Recipe 3.7, " Converting Between Time Zones"
- Information on the "zoneinfo" database (http://www.twinsun.com/tz/tz-link.htm)