Created
September 7, 2012 18:20
-
-
Save bf4/3668333 to your computer and use it in GitHub Desktop.
Ruby Time and Timezone walkthrough
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'pathname' | |
root = Pathname File.expand_path('..', __FILE__) | |
require root.join('timezone_converter') | |
require 'erb' | |
@converter = TimezoneConverter.new | |
@template = ERB.new(root.join("index.html.erb").read) | |
# def time_in_zone(time, zone) | |
# TimezoneConverter::BadZone | |
run ->(env){ | |
request = Rack::Request.new(env) | |
time, zone = request.params.values_at("time", "zone") | |
if time and zone | |
begin | |
@time = "#{@converter.time_in_zone(time, zone)}, is localtime #{time} in #{zone}" | |
rescue TimezoneConverter::BadZone => e | |
@time = e.inspect | |
end | |
else | |
@time = '' | |
end | |
@local_time = Time.now.localtime | |
@local_zone = @local_time.zone || 'Unknown' | |
[ 200, | |
{ 'Content-Type' => 'text/html', }, [@template.result(binding)] | |
] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
source "https://rubygems.org" | |
gem "rack" | |
gem "tzinfo" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
GEM | |
remote: https://rubygems.org/ | |
specs: | |
rack (1.5.2) | |
thread_safe (0.3.4) | |
tzinfo (1.2.1) | |
thread_safe (~> 0.1) | |
PLATFORMS | |
ruby | |
DEPENDENCIES | |
rack | |
tzinfo |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<body> | |
It is now <%= @local_time %> in <%= @local_zone %><br> | |
<%= @time %><br> | |
<form> | |
<label for="time">Local time:</label> | |
<input name="time" type="text"> | |
<label for"zone">Zone you want the time converted to:</label> | |
<input name="zone" type="text"> | |
<input type="submit"> | |
</form> | |
<p>Known zones:</p> | |
<% @converter.zones_mapping.each do |simple_zone| %> | |
<%= simple_zone.to_s %><br> | |
<% end %> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
web: bundle exec rackup config.ru -p $PORT |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# see https://gist.github.com/bf4/3668333 | |
require 'active_support/time' | |
# require 'active_support/core_ext/time' | |
# require 'active_support/core_ext/date' | |
# require 'active_support/core_ext/date_time' | |
# require 'active_support/time_with_zone' | |
class RailsSimpleZone | |
def self.all | |
ActiveSupport::TimeZone::MAPPING.values.map do |tz_info_name| | |
tz = ActiveSupport::TimeZone[tz_info_name] | |
new(tz) | |
end | |
end | |
def rails_friendly_name_zone_from_tz(tz='America/Chicago') | |
ActiveSupport::TimeZone::MAPPING.detect {|rails_zone_key,tz_info_name| tz_info_name == tz }.first | |
end | |
def self.tz_offset(tzinfo) | |
if tzinfo.respond_to?(:formatted_offset) | |
tzinfo.formatted_offset | |
else | |
total_offset = tzinfo.to_i | |
offset = '%.2d:00' % total_offset | |
offset.start_with?('-') ? offset : "+#{offset}" | |
end | |
end | |
attr_reader :name, :offset | |
def initialize(tz) | |
@name = tz.name | |
@offset = self.class.tz_offset(tz) | |
end | |
def to_str | |
"Zone: #{name}. Offset: #{offset}" | |
end | |
def to_s | |
to_str | |
end | |
def inspect | |
"<#SimpleZone #{name}. Offset: #{offset}>" | |
end | |
end | |
class RailsTimezoneConverter | |
BadZone = Class.new(StandardError) | |
def time_in_zone(time, zone) | |
zone = Zone(zone) | |
time = Time(time) | |
zone.parse(time) | |
end | |
def Zone(zone) | |
if zone.respond_to?(:formatted_offset) | |
zone | |
elsif zone.respond_to?(:current_period) | |
ActiveSupport::TimeZone[zone.name] | |
else | |
ActiveSupport::TimeZone[zone] || guess_tz(zone) | |
end | |
end | |
def Time(time) | |
if time.respond_to?(:strftime) | |
time | |
else | |
Time.parse(time) | |
end | |
end | |
def guess_tz(zone_guess) | |
raise bad_zone_error(zone_guess) if zone_guess.to_s.size.zero? | |
guess = zone_guess.to_s.split('/')[-1].downcase | |
zm = zones_mapping.find do |tz| | |
tz.name.downcase.include?(guess) || | |
matching_offset?(tz.offset, guess) | |
end | |
if zm | |
ActiveSupport::TimeZone[zm.name] | |
else | |
raise bad_zone_error(zone_guess) | |
end | |
end | |
def bad_zone_error(zone) | |
BadZone.new("Need a zone to convert to. Got #{zone.inspect}") | |
end | |
def matching_offset?(reference,guess) | |
reference == (guess.to_i.zero? ? guess : RailsSimpleZone.tz_offset(guess)) | |
end | |
def zones_mapping | |
@zones_mapping ||= RailsSimpleZone.all | |
end | |
end | |
if $0 == __FILE__ | |
require 'rspec/autorun' | |
describe RailsTimezoneConverter do | |
context 'Zone()' do | |
let(:tz) { ActiveSupport::TimeZone['America/Chicago'] } | |
example do | |
expect(tz.name).to eq('America/Chicago') | |
end | |
it 'returns the time zone passed in' do | |
expect(subject.Zone(tz)).to eq(tz) | |
end | |
it 'returns the timezone for a valid identifier' do | |
expect(subject.Zone(tz.name)).to eq(tz) | |
end | |
it 'guessed the timezone from an imprecise identifier' do | |
expect(subject.Zone('Chicago')).to eq(tz) | |
end | |
end | |
context 'Time()' do | |
let(:time) { Time.now } | |
example do | |
expect(time).to respond_to(:strftime) | |
end | |
it 'returns the time passed in' do | |
expect(subject.Time(time)).to eq(time) | |
end | |
it 'returns a parsed time object when passed a string' do | |
time_string = time.xmlschema | |
expect(subject.Time(time_string).xmlschema).to eq(time_string) | |
end | |
end | |
describe "#tz_offset" do | |
it 'returns a UTC offset of +00:00 for UTC' do | |
tz = ActiveSupport::TimeZone['UTC'] | |
expected = '+00:00' | |
expect(RailsSimpleZone.tz_offset(tz)).to eq(expected) | |
end | |
it 'returns +00:00 for +00:00' do | |
offset = '+00:00' | |
expected = '+00:00' | |
expect(RailsSimpleZone.tz_offset(offset)).to eq(expected) | |
end | |
it 'returns +00:00 for 0' do | |
offset = 0 | |
expected = '+00:00' | |
expect(RailsSimpleZone.tz_offset(offset)).to eq(expected) | |
end | |
it 'returns +05:00 for 5' do | |
offset = 5 | |
expected = '+05:00' | |
expect(RailsSimpleZone.tz_offset(offset)).to eq(expected) | |
end | |
it 'returns -05:00 for -5' do | |
offset = -5 | |
expected = '-05:00' | |
expect(RailsSimpleZone.tz_offset(offset)).to eq(expected) | |
end | |
it 'returns +00:00 for -0' do | |
offset = -0 | |
expected = '+00:00' | |
expect(RailsSimpleZone.tz_offset(offset)).to eq(expected) | |
end | |
end | |
describe '#matching_offset?' do | |
it 'matches 5 to +05:00' do | |
reference = '+05:00' | |
guess = 5 | |
expect( | |
subject.matching_offset?(reference,guess) | |
).to be_true | |
end | |
end | |
describe "#guess_tz" do | |
let(:tz) { ActiveSupport::TimeZone['America/Chicago'] } | |
it 'returns a timezone with a matching identifier' do | |
expect(subject.guess_tz('Chicago')).to eq(tz) | |
end | |
it 'returns a timezone with a matching offset' do | |
offset = '-05:00' | |
tz = subject.guess_tz('-05:00') | |
expect(RailsSimpleZone.tz_offset(tz)).to eq(offset) | |
end | |
end | |
describe "#zones_mapping" do | |
it 'is an array of objects with the tz name and offset' do | |
expect(subject.zones_mapping. | |
find{|zm| zm.name == 'Etc/UTC'}. | |
offset | |
).to eq('+00:00') | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
=begin | |
see | |
http://time.is/ | |
http://strfti.me/ | |
=end | |
# | |
=begin | |
t = Time.now | |
# fails undefined method `xmlschema' | |
t.xmlschema | |
require 'time' | |
# or require 'tzinfo' | |
# works "2012-09-07T08:32:03-05:00" | |
t.xmlschema | |
=end | |
# Time.local('America/Chicago') | |
=begin | |
# http://tzinfo.rubyforge.org/doc/files/README.html | |
# to get the right xmlschema | |
require 'time' | |
require 'rubygems' | |
require 'tzinfo' | |
def 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) | |
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 | |
start_datetime = '2012-11-03T10:00:00-06:00' | |
time = Time.parse(start_datetime) | |
tzinfo = guess_tz('honolulu') | |
offset = tz_offset(tzinfo) | |
localtime = time_in_zone(time,guess_tz('honolulu')) | |
localtime.xmlschema | |
=> "2012-11-03T06:00:00-10:00" # and the time object is changed, too | |
tzinfo.utc_to_local(time.utc).xmlschema | |
=> "2012-11-03T06:00:00Z" | |
# 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. | |
tzinfo.current_period.utc_total_offset | |
tzinfo.current_period.utc_offset === utc_offset + std_offset. | |
http://stackoverflow.com/questions/9962038/how-do-i-calculate-the-offset-in-hours-of-a-given-timezone-from-utc-in-ruby | |
current.dst? | |
#=> true | |
To get the base offset of the timezone from UTC in seconds: | |
current.utc_offset | |
#=> -28800 which is -8 hours; this does NOT include daylight savings | |
To get the daylight savings offset from standard time: | |
current.std_offset | |
#=> 3600 which is 1 hour; this is because right now we're in daylight savings | |
To get the total offset from UTC: | |
current.utc_total_offset | |
#=> -25200 which is -7 hours | |
Time.mktime(sec, min, hour, day, month, year, wday, yday, isdst, tz) | |
Time.utc(sec, min, hour, day, month, year, wday, yday, isdst, tz) | |
Time.gm(sec, min, hour, day, month, year, wday, yday, isdst, tz) | |
Time.local(sec, min, hour, day, month, year, wday, yday, isdst, tz) | |
Time.new(year, month=nil, day=nil, hour=nil, min=nil, sec=nil, utc_offset=nil) | |
Time.new(2007,11,5,13,45,0, "-05:00") # EST (Detroit) | |
starts_at.localtime('-06:00') | |
Time.zone_offset('CDT') | |
tzinfo.current_period.zone_identifier == :PDT | |
DateTime rfc2822, rfc3339, rfc3339, rfc822 | |
starts_at.gmt_offset | |
starts_at.getlocal | |
=end | |
class ShowTime | |
def timezone_from_tz(tz='America/Chicago') | |
TZInfo::Timezone.get(tz) | |
end | |
# utc = tz.local_to_utc(local) | |
# period = tz.period_for_utc(DateTime.new(2005,8,29,15,35,0)) | |
# id = period.zone_identifier | |
# us = TZInfo::Country.get('US') | |
# timezones = us.zone_identifiers | |
# The zone_info method of Country provides an additional description and location for each Timezone in the Country. | |
def demonstrate(time) | |
puts "#{desc('default:')}\t#{time}" | |
[:to_i, :utc, :xmlschema, :rfc2822, :httpdate, :iso8601].each do |meth| | |
puts "#{desc meth}:\t#{time.method(meth).call}" | |
end | |
describe_time(time) | |
# Rails Time.zone | |
demonstrate_zone(time,Time.zone) if defined?(TZInfo) | |
end | |
def describe_time(time) | |
puts "#{desc 'Zone:'}\t#{time.zone.inspect}" | |
puts "#{desc 'Strftime:'}\t#{time.strftime("%c").inspect}" | |
end | |
def desc(s) | |
"%10s" % s.to_s | |
end | |
require 'timecop' | |
def with_time(time,&block) | |
Timecop.freeze(time) | |
block.call | |
Timecop.return # "turn off" Timecop | |
end | |
def midnight_in_chicago | |
Time.local(2012, 03, 28, 0, 0, 0) | |
end | |
def spring_forward_2012 | |
Time.local(2012, 03, 10, 2, 0, 0) | |
end | |
def fall_back_2012 | |
Time.local(2012, 11, 03, 2, 0, 0) | |
end | |
module Rails | |
# activesupport: Time.zone | |
def demonstrate_rails_start_of_day(time) | |
puts 3.days.from_now.utc.beginning_of_day | |
puts Time.now.utc.beginning_of_day + 3.days #end_of_day | |
end | |
def get_tzinfo_zone_from_rails(tz ='America/Chicago') | |
zone = rails_friendly_name_zone_from_tz(tz) | |
Time.zone = zone | |
# Time.zone.class => ActiveSupport::TimeZone | |
Time.zone | |
end | |
def rails_friendly_name_zone_from_tz(tz='America/Chicago') | |
ActiveSupport::TimeZone::MAPPING.detect {|rails_zone_key,tz_info_name| tz_info_name == tz }.first | |
end | |
def demonstrate_zone(time,tz_info) | |
Time.zone = nil | |
puts "I got #{time.xmlschema}\t zone #{Time.zone.inspect}" | |
puts "\tsetting Time.zone to #{tz_info}" | |
Time.zone = tz_info | |
puts "\tHey, Time.zone #{Time.zone.inspect}" | |
rails_friendly_name = rails_friendly_name_from_tz(tz_info) | |
puts "\tsetting Time.zone to #{rails_friendly_name}" | |
Time.zone = rails_friendly_name | |
puts "I got #{time.xmlschema}\t zone #{Time.zone.inspect}" | |
puts "Getting the ActiveSupport::Timezone" | |
zone = the_zone_i_need(rails_friendly_name) | |
puts "Trying one.parse(time)" | |
puts zone.parse(time).xmlschema | |
end | |
def demonstrate_to_s(time,format = :db) | |
time.to_s(format) #uses utc.to_s(:db) | |
end | |
def the_zone_i_need(rails_friendly_name) | |
Time.zone = rails_friendly_name | |
Time.zone | |
end | |
# * Create ActiveSupport::TimeWithZone instances via TimeZone's +local+, +parse+, +at+ and +now+ methods. | |
# * t.to_s(:rfc822) | |
# * def to_s(format = :default) | |
# if format == :db | |
# utc.to_s(format) | |
# * ActiveSupport::TimeWithZone | |
# begin | |
# @time_zone.period_for_local(@time) | |
# rescue ::TZInfo::PeriodNotFound | |
# # time is in the "spring forward" hour gap, so we're moving the time forward one hour and trying again | |
# @time += 1.hour | |
# retry | |
# end | |
# end | |
end | |
end | |
# # leap second | |
=begin | |
* 12 a.m. Wednesday March 28th in Chicago is Tuesday March 27th in Denver and Palo Alto | |
* 2004-04-01T16:32:45-06:00 | |
* Note that iso8601 is the both human-readable and machine, unambiguous, and sortable as a string. It is the format used in the microformats | |
* UTC 'timezone' designator is "Z" e.g 1994-11-05T13:15:30Z corresponds to 1994-11-05T08:15:30-05:00 | |
=end | |
=begin | |
time = midnight_in_chicago | |
ShowTime::Rails.demonstrate_rails_beginning_of_day(time) | |
tz = 'America/Phoenix' | |
tzinf = timezone_from_tz(tz) | |
rails_friendly_name = ShowTime::Rails.rails_friendly_name_zone_from_tz(tz) | |
zone = Showtime::Rails.get_tzinfo_zone_from_rails(tz) | |
Time.zone = zone | |
Time.zone.parse("2012-09-07 13:15") | |
# Time.zone = zone | |
# ActiveSupport::TimeWithZone.new(rails_friendly_name) | |
# Showtime:Rails.demonstrate | |
=end | |
# make it 10am in chicago, palo alto, madrid | |
# Time | |
# - require 'time'; Time.parse("30/12/2001") .. in 1.9.2 parses as dd/mm/yyyy .. was mm/dd/yyyy in 1.8! | |
=begin | |
TODO: | |
Date vs. Time vs. DateTime | |
with require 'time' | |
with require 'tzinfo' | |
with require 'activesupport' | |
Compare 1.hour to Date.civil( | |
ActiveSupport | |
rails 3.1 | |
require 'active_support/time/autoload.rb' | |
loads 'active_support/duration' | |
loads 'active_support/time_with_zone' | |
loads 'active_support/values/time_zone' | |
rails 2.3 | |
require 'active_support/values/time_zone.rb' | |
ActiveSupport::TimeZone | |
active_support/core_ext/time/behavior | |
active_support/core_ext/time/calculations | |
active_support/core_ext/time/conversions | |
=end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# see https://gist.github.com/bf4/3668333 | |
# http://tzinfo.rubyforge.org/doc/files/README.html | |
# to get the right xmlschema | |
require 'time' | |
require 'rubygems' | |
require 'tzinfo' | |
class SimpleZone | |
def self.all | |
TZInfo::Timezone.all_country_zones.map do |tz| | |
new(tz) | |
end | |
end | |
def self.tz_offset(tzinfo) | |
if tzinfo.respond_to?(:current_period) | |
total_offset = (tzinfo.current_period.utc_total_offset / 60 / 60 ) # e.g. '-06:00' | |
else | |
total_offset = tzinfo.to_i | |
end | |
offset = '%.2d:00' % total_offset | |
offset.start_with?('-') ? offset : "+#{offset}" | |
end | |
attr_reader :name, :offset | |
def initialize(tz) | |
@name = tz.name | |
@offset = self.class.tz_offset(tz) | |
end | |
def to_str | |
"Zone: #{name}. Offset: #{offset}" | |
end | |
def to_s | |
to_str | |
end | |
def inspect | |
"<#SimpleZone #{name}. Offset: #{offset}>" | |
end | |
end | |
class TimezoneConverter | |
BadZone = Class.new(StandardError) | |
def time_in_zone(time, zone) | |
zone = Zone(zone) | |
time = Time(time) | |
offset = SimpleZone.tz_offset(zone) | |
if RUBY_VERSION < '1.9' | |
zone.utc_to_local(time.utc) | |
else | |
time.localtime(offset) | |
end | |
end | |
def Zone(zone) | |
if zone.respond_to?(:current_period) | |
zone | |
else | |
begin | |
TZInfo::Timezone.get(zone) | |
rescue TZInfo::InvalidTimezoneIdentifier | |
guess_tz(zone) | |
end | |
end | |
end | |
def Time(time) | |
if time.respond_to?(:strftime) | |
time | |
else | |
Time.parse(time) | |
end | |
end | |
def guess_tz(zone_guess) | |
raise bad_zone_error(zone_guess) if zone_guess.to_s.size.zero? | |
guess = zone_guess.to_s.split('/')[-1].downcase | |
zm = zones_mapping.find do |tz| | |
tz.name.downcase.include?(guess) || | |
matching_offset?(tz.offset, guess) | |
end | |
if zm | |
TZInfo::Timezone.get(zm.name) | |
else | |
raise bad_zone_error(zone_guess) | |
end | |
end | |
def bad_zone_error(zone) | |
BadZone.new("Need a zone to convert to. Got #{zone.inspect}") | |
end | |
# if guess is text, match exact, else try to convert to offset | |
def matching_offset?(reference,guess) | |
reference == (guess.to_i.zero? ? guess : SimpleZone.tz_offset(guess)) | |
end | |
def zones_mapping | |
@zones_mapping ||= SimpleZone.all | |
end | |
end | |
if $0 == __FILE__ | |
require 'rspec/autorun' | |
describe TimezoneConverter do | |
context 'Zone()' do | |
let(:tz) { TZInfo::Timezone.get('America/Chicago') } | |
example do | |
expect(tz.name).to eq('America/Chicago') | |
end | |
it 'returns the time zone passed in' do | |
expect(subject.Zone(tz)).to eq(tz) | |
end | |
it 'returns the timezone for a valid identifier' do | |
expect(subject.Zone(tz.name)).to eq(tz) | |
end | |
it 'guessed the timezone from an imprecise identifier' do | |
expect(subject.Zone('Chicago')).to eq(tz) | |
end | |
end | |
context 'Time()' do | |
let(:time) { Time.now } | |
example do | |
expect(time).to respond_to(:strftime) | |
end | |
it 'returns the time passed in' do | |
expect(subject.Time(time)).to eq(time) | |
end | |
it 'returns a parsed time object when passed a string' do | |
time_string = time.xmlschema | |
expect(subject.Time(time_string).xmlschema).to eq(time_string) | |
end | |
end | |
describe "#tz_offset" do | |
it 'returns a UTC offset of +00:00 for UTC' do | |
tz = TZInfo::Timezone.get('UTC') | |
expected = '+00:00' | |
expect(SimpleZone.tz_offset(tz)).to eq(expected) | |
end | |
it 'returns +00:00 for +00:00' do | |
offset = '+00:00' | |
expected = '+00:00' | |
expect(SimpleZone.tz_offset(offset)).to eq(expected) | |
end | |
it 'returns +00:00 for 0' do | |
offset = 0 | |
expected = '+00:00' | |
expect(SimpleZone.tz_offset(offset)).to eq(expected) | |
end | |
it 'returns +05:00 for 5' do | |
offset = 5 | |
expected = '+05:00' | |
expect(SimpleZone.tz_offset(offset)).to eq(expected) | |
end | |
it 'returns -05:00 for -5' do | |
offset = -5 | |
expected = '-05:00' | |
expect(SimpleZone.tz_offset(offset)).to eq(expected) | |
end | |
it 'returns +00:00 for -0' do | |
offset = -0 | |
expected = '+00:00' | |
expect(SimpleZone.tz_offset(offset)).to eq(expected) | |
end | |
end | |
describe '#matching_offset?' do | |
it 'matches 5 to +05:00' do | |
reference = '+05:00' | |
guess = 5 | |
expect( | |
subject.matching_offset?(reference,guess) | |
).to be_true | |
end | |
end | |
describe "#guess_tz" do | |
let(:tz) { TZInfo::Timezone.get('America/Chicago') } | |
it 'returns a timezone with a matching identifier' do | |
expect(subject.guess_tz('Chicago')).to eq(tz) | |
end | |
it 'returns a timezone with a matching offset' do | |
offset = '-05:00' | |
tz = subject.guess_tz('-05:00') | |
expect(SimpleZone.tz_offset(tz)).to eq(offset) | |
end | |
end | |
describe "#zones_mapping" do | |
it 'is an array of objects with the tz name and offset' do | |
expect(subject.zones_mapping. | |
find{|zm| zm.name == 'America/Chicago'}. | |
offset | |
).to eq('-05:00') | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment