as microseconds form the Unix Epoch – (January 1, 1970 00:00:00 UTC) – Some systems allow it to be negative. (A non-portable feature) • UTC stands for “Coordinated Universal Time” – It replaced the designation of GMT (Greenwich Mean Time)
and machine, unambiguous, and sortable as a string. It is the format used in the microformats.org specification • UTC 'timezone' designator is "Z" e.g 1994-11-05T13:15:30Z corresponds to 1994-11-05T08:15:30-05:00 • Use ‘tzinfo’ gem to work with zone • Suggestions – Always store your dates or times as iso8601 xmlschema in UTC see http://devblog.avdi.org/2009/10/25/iso8601-dates-in-ruby/ and note http://www.w3.org/TR/NOTE-datetime
careful with: • Daylight savings – Spring Forward: On the second Sunday in March 2 a.m. becomes 3 a.m. and daylight time begins. 2 a.m. doesn’t exist! – Fall Back: On the first Sunday in November, 2 a.m. becomes 1 a.m. local standard time. 2 a.m. occurs twice! • Using localized times in your app, or in a script – 12 a.m. Wednesday March 28th in Chicago is Tuesday March 27th in Denver and Palo Alto • Leap seconds, or other last minute changes – (next slide) • Fuuuuuu! (h/t Peter Cooper ruby19 walkthrough) – require 'time’; (else get undefined method `parse' for Time:Class) – Time.parse("30/12/2001”): in Ruby 1.8 ArgumentError, '12/30/2001' works – in 1.9.2 parses as dd/mm/yyyy .. was mm/dd/yyyy in 1.8!
Sun Dec 30 00:00:00 -0600 2001 ArgumentError Time.parse(“1/2/2001”) Tue Jan 02 00:00:00 -0600 2001 2001-02-01 00:00:00 -0600 Time.parse('2001-01-02') Tue Jan 02 00:00:00 -0600 2001 2001-01-02 00:00:00 -0600 Gotchas: why we can’t have nice things good times
3 a.m. as that time may not exist • Be careful scheduling cron jobs around midnight that depend on the current date as the current date changes in different time zones
• A 32-bit machine can only go up to 3:14:07 UTC on Tuesday, 19 January 2038 before there’s an integer overflow. Problems began in 2006 in the AOLServer – 64-bit machines should be good until 292 billions years from now • Test your machine bits in ruby – Could be useful if you run specs with dates > 2038 on multiple machines – (1.size*8 == 32)
time_in_zone(time,zone) tzinfo = zone.respond_to?(:current_period) ? zone : TZInfo::Timezone.get(zone) rescue guess_tz(zone) offset = tz_offset(tzinfo) if RUBY_VERSION < '1.9' tzinfo.utc_to_local(time.utc) # Note that the Time returned will look like it is UTC (Time.zone will return "UTC"). This is because it is not currently possible to change the offset of an individual Time instance. else time.localtime(offset) end end def tz_offset(tzinfo) '%.02d:00' % (tzinfo.current_period.utc_total_offset / 60 / 60 ) # e.g. '-06:00' end def guess_tz(zone_guess) guess = zone_guess.to_s.split('/')[-1] TZInfo::Timezone.us_zones.detect {|tz| tz.name =~ /#{guess}/i } end require 'tzinfo' datetime = '2012-11-03T10:00:00-06:00' time = Time.parse(datetime) tzinfo = TZInfo::Timezone.get('Pacific/Honolulu') # #<TZInfo::TimezoneProxy: Pacific/Honolulu> offset = '%.02d:00' % (tzinfo.current_period.utc_total_offset / 60 / 60) # "-10:00" localtime_from_utc = tzinfo.utc_to_local(time.utc) localtime_from_offset = time.localtime(offset) # 1.9 only localtime_from_utc.xmlschema => "2012-11-03T06:00:00Z" localtime_from_offset.xmlschema => "2012-11-03T06:00:00-10:00" # and the time object is changed, too
rails_zone_key,tz_info_name| tz_info_name == 'America/Chicago' }.first – The TimeZone class serves as a wrapper around TZInfo::Timezone instances. It allows us to do the following – Retrieve and display zones with a friendlier name (e.g., “Eastern Time (US & Canada)” instead of “America/New_York”). – Adds Time.zone etc • ActiveSupport::TimeWithZone – A Time-like class that can represent a time in any time zone. Necessary because standard Ruby Time instances are limited to UTC and the system’s ENV[‘TZ’] zone. – You shouldn’t ever need to create a TimeWithZone instance directly