- Notifications
You must be signed in to change notification settings - Fork100
TZInfo - Ruby Timezone Library
License
tzinfo/tzinfo
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
TZInfo is a Ruby library that provides access totime zone data and allows times to be converted using time zone rules.
TZInfo requires a source of time zone data. There are two options:
- A zoneinfo directory containing timezone definition files. These files aregenerated from theIANA Time Zone Databaseusing the
zic
utility. Most Unix-like systems include a zoneinfo directory. - The TZInfo::Data library (the tzinfo-data gem). TZInfo::Data contains a setof Ruby modules that are also generated from the IANA Time Zone Database.
By default, TZInfo will attempt to use TZInfo::Data. If TZInfo::Data is notavailable (i.e. ifrequire 'tzinfo/data'
fails), then TZInfo will search for azoneinfo directory instead (by checking the directories specified byTZInfo::DataSources::ZoneinfoDataSource.search_path
in turn).
If no data source can be found, aTZInfo::DataSourceNotFound
exception will beraised when TZInfo is used. Further information is availablein the wiki to help resolveTZInfo::DataSourceNotFound
errors.
The default data source selection can be overridden by callingTZInfo::DataSource.set
.
Custom data sources can also be used. See theTZInfo::DataSource.set
documentation for further details.
The TZInfo gem can be installed by runninggem install tzinfo
or by addinggem 'tzinfo'
to yourGemfile
and runningbundle install
.
To use the Ruby modules as the data source, TZInfo::Data will also need to beinstalled by runninggem install tzinfo-data
or by addinggem 'tzinfo-data'
to yourGemfile
.
The data returned and used by TZInfo is sourced from theIANA Time Zone Database. TheTheory and pragmatics of the tz code and datadocument gives details of how the data is organized and managed.
To use TZInfo, it must first be required with:
require'tzinfo'
TheTZInfo::Timezone
class provides access to time zone data and methods forconverting times.
Theall_identifiers
method returns a list of valid time zone identifiers:
identifiers=TZInfo::Timezone.all_identifiers# => ["Africa/Abidjan", "Africa/Accra", ..., "Zulu"]
ATZInfo::Timezone
instance representing an individual time zone can beobtained withTZInfo::Timezone.get
:
tz=TZInfo::Timezone.get('America/New_York')# => #<TZInfo::DataTimezone: America/New_York>
A time can be converted to the local time of the time zone withto_local
:
tz.to_local(Time.utc(2018,2,1,12,30,0))# => 2018-02-01 07:30:00 -0500tz.to_local(Time.utc(2018,7,1,12,30,0))# => 2018-07-01 08:30:00 -0400tz.to_local(Time.new(2018,7,1,13,30,0,'+01:00'))# => 2018-07-01 08:30:00 -0400
Local times with the appropriate offset for the time zone can be constructedwithlocal_time
:
tz.local_time(2018,2,1,7,30,0)# => 2018-02-01 07:30:00 -0500tz.local_time(2018,7,1,8,30,0)# => 2018-07-01 08:30:00 -0400
Local times can be converted to UTC by usinglocal_time
and callingutc
onthe result:
tz.local_time(2018,2,1,7,30,0).utc# => 2018-02-01 12:30:00 UTCtz.local_time(2018,7,1,8,30,0).utc# => 2018-07-01 12:30:00 UTC
Thelocal_to_utc
method can also be used to convert a time object to UTC. Theoffset of the time is ignored - it is treated as if it were a local time for thetime zone:
tz.local_to_utc(Time.utc(2018,2,1,7,30,0))# => 2018-02-01 12:30:00 UTCtz.local_to_utc(Time.new(2018,2,1,7,30,0,'+01:00'))# => 2018-02-01 12:30:00 UTC
Information about the time zone can be obtained from returned local times:
local_time=tz.to_local(Time.utc(2018,2,1,12,30,0))local_time.utc_offset# => -18000local_time.dst?# => falselocal_time.zone# => "EST"local_time=tz.to_local(Time.utc(2018,7,1,12,30,0))local_time.utc_offset# => -14400local_time.dst?# => truelocal_time.zone# => "EDT"
Time zone information can be included when formatting times withstrftime
using the%z
and%Z
directives:
tz.to_local(Time.utc(2018,2,1,12,30,0)).strftime('%Y-%m-%d %H:%M:%S %z %Z')# => "2018-02-01 07:30:00 -0500 EST"tz.to_local(Time.utc(2018,7,1,12,30,0)).strftime('%Y-%m-%d %H:%M:%S %z %Z')# => "2018-07-01 08:30:00 -0400 EDT"
Theperiod_for
method can be used to obtain information about the observedtime zone information at a particular time as aTZInfo::TimezonePeriod
object:
period=tz.period_for(Time.utc(2018,7,1,12,30,0))period.base_utc_offset# => -18000period.std_offset# => 3600period.observed_utc_offset# => -14400period.abbreviation# => "EDT"period.dst?# => trueperiod.local_starts_at.to_time# => 2018-03-11 03:00:00 -0400period.local_ends_at.to_time# => 2018-11-04 02:00:00 -0400
A list of transitions between periods where different rules are observed can beobtained with thetransitions_up_to
method. The result is returned as anArray
ofTZInfo::TimezoneTransition
objects:
transitions=tz.transitions_up_to(Time.utc(2019,1,1),Time.utc(2017,1,1))transitions.mapdo |t|[t.local_end_at.to_time,t.offset.observed_utc_offset,t.offset.abbreviation]end# => [[2017-03-12 02:00:00 -0500, -14400, "EDT"],# [2017-11-05 02:00:00 -0400, -18000, "EST"],# [2018-03-11 02:00:00 -0500, -14400, "EDT"],# [2018-11-04 02:00:00 -0400, -18000, "EST"]]
A list of the unique offsets used by a time zone can be obtained with theoffsets_up_to
method. The result is returned as anArray
ofTZInfo::TimezoneOffset
objects:
offsets=tz.offsets_up_to(Time.utc(2019,1,1))offsets.map{|o|[o.observed_utc_offset,o.abbreviation]}# => [[-17762, "LMT"],# [-18000, "EST"],# [-14400, "EDT"],# [-14400, "EWT"],# [-14400, "EPT"]]
AllTZInfo::Timezone
methods that accept a time as a parameter can be usedwith either instances ofTime
,DateTime
orTZInfo::Timestamp
. ArbitraryTime
-like objects that respond to bothto_i
andsubsec
and optionallyutc_offset
will be treated as if they are instances ofTime
.
TZInfo::Timezone
methods that both accept and return times will return anobject with a type matching that of the parameter (actually aTZInfo::TimeWithOffset
,TZInfo::DateTimeWithOffset
orTZInfo::TimestampWithOffset
subclass when returning a local time):
tz.to_local(Time.utc(2018,7,1,12,30,0))# => 2018-07-01 08:30:00 -0400tz.to_local(DateTime.new(2018,7,1,12,30,0))# => #<TZInfo::DateTimeWithOffset: 2018-07-01T08:30:00-04:00 ((2458301j,45000s,0n),-14400s,2299161j)>tz.to_local(TZInfo::Timestamp.create(2018,7,1,12,30,0,0,:utc))# => #<TZInfo::TimestampWithOffset: @value=1530448200, @sub_second=0, @utc_offset=-14400, @utc=false>
In addition tolocal_time
, which returnsTime
instances, thelocal_datetime
andlocal_timestamp
methods can be used to construct localDateTime
andTZInfo::Timestamp
instances with the appropriate offset:
tz.local_time(2018,2,1,7,30,0)# => 2018-02-01 07:30:00 -0500tz.local_datetime(2018,2,1,7,30,0)# => #<TZInfo::DateTimeWithOffset: 2018-02-01T07:30:00-05:00 ((2458151j,45000s,0n),-18000s,2299161j)>tz.local_timestamp(2018,2,1,7,30,0)# => #<TZInfo::TimestampWithOffset: @value=1517488200, @sub_second=0, @utc_offset=-18000, @utc=false>
Thelocal_to_utc
,local_time
,local_datetime
andlocal_timestamp
methodsmay raise aTZInfo::PeriodNotFound
or aTZInfo::AmbiguousTime
exception.TZInfo::PeriodNotFound
signals that there is no equivalent UTC time (forexample, during the transition from standard time to daylight savings time whenthe clocks are moved forward and an hour is skipped).TZInfo::AmbiguousTime
signals that there is more than one equivalent UTC time (for example, during thetransition from daylight savings time to standard time where the clocks aremoved back and an hour is repeated):
tz.local_time(2018,3,11,2,30,0,0)# raises TZInfo::PeriodNotFound (2018-03-11 02:30:00 is an invalid local time.)tz.local_time(2018,11,4,1,30,0,0)# raises TZInfo::AmbiguousTime (2018-11-04 01:30:00 is an ambiguous local time.)
TZInfo::PeriodNotFound
exceptions can only be resolved by adjusting the time,for example, by advancing an hour:
tz.local_time(2018,3,11,3,30,0,0)# => 2018-03-11 03:30:00 -0400
TZInfo::AmbiguousTime
exceptions can be resolved by setting thedst
parameter and/or specifying a block to choose one of the interpretations:
tz.local_time(2018,11,4,1,30,0,0,true)# => 2018-11-04 01:30:00 -0400tz.local_time(2018,11,4,1,30,0,0,false)# => 2018-11-04 01:30:00 -0500tz.local_time(2018,11,4,1,30,0,0){|p|p.first}# => 2018-11-04 01:30:00 -0400tz.local_time(2018,11,4,1,30,0,0){|p|p.last}# => 2018-11-04 01:30:00 -0500
The default value of thedst
parameter can also be set globally:
TZInfo::Timezone.default_dst=truetz.local_time(2018,11,4,1,30,0,0)# => 2018-11-04 01:30:00 -0400TZInfo::Timezone.default_dst=falsetz.local_time(2018,11,4,1,30,0,0)# => 2018-11-04 01:30:00 -0500
TZInfo also provides information aboutISO 3166-1 countries andtheir associated time zones via theTZInfo::Country
class.
A list of valid ISO 3166-1 (alpha-2) country codes can be obtained by callingTZInfo::Country.all_codes
:
TZInfo::Country.all_codes# => ["AD", "AE", ..., "ZW"]
ATZInfo::Country
instance representing an individual time zone can beobtained withTZInfo::Country.get
:
c=TZInfo::Country.get('US')# => #<TZInfo::Country: US>c.name# => "United States"
Thezone_identifiers
method returns a list of the time zone identifiers usedin a country:
c.zone_identifiers# => ["America/New_York", "America/Detroit", ..., "Pacific/Honolulu"]
Thezone_info
method returns further information about the time zones used ina country as anArray
ofTZInfo::CountryTimezone
instances:
zi=c.zone_info.firstzi.identifier# => "America/New_York"zi.latitude.to_f.round(5)# => 40.71417zi.longitude.to_f.round(5)# => -74.00639zi.description# => "Eastern (most areas)"
Thezones
method returns anArray
ofTZInfo::Timezone
instances for acountry. ATZInfo::Timezone
instance can be obtained from aTZInfo::CountryTimezone
using thetimezone
method:
zi.timezone.to_local(Time.utc(2018,2,1,12,30,0))# => 2018-02-01 07:30:00 -0500
For further detail, please refer to the API documentation for theTZInfo::Timezone
andTZInfo::Country
classes.
The Time Zone Database maintainers recommend that time zone identifiers are notmade visible to end-users (seeNames oftimezones).
Instead of displaying a list of time zone identifiers, time zones can beselected by the user's country. CallTZInfo::Country.all
to obtain a list ofTZInfo::Country
objects, each with a uniquecode
and aname
that can beused for display purposes.
Most countries have a single time zone. When choosing such a country, the timezone can be inferred and selected automatically.
croatia=TZInfo::Country.get('HR')# => #<TZInfo::Country: HR>croatia.zone_info.length# => 1croatia.zone_info[0].identifier# => "Europe/Belgrade"
Some countries have multiple time zones. Thezone_info
method can be usedto obtain a list of user-friendly descriptions of the available options:
australia=TZInfo::Country.get('AU')# => #<TZInfo::Country: AU>australia.zone_info.length# => 13australia.zone_info.map{|i|[i.identifier,i.description]}# => [["Australia/Lord_Howe", "Lord Howe Island"],# ["Antarctica/Macquarie", "Macquarie Island"],# ...# ["Australia/Eucla", "Western Australia (Eucla)"]]
Please note that country information available through TZInfo is intended as anaid to help users select a time zone data appropriate for their practical needs.It is not intended to take or endorse any position on legal or territorialclaims.
TZInfo v2.0.0 requires a minimum of Ruby MRI 1.9.3 or JRuby 1.7 (in 1.9 mode orlater).
TheTZInfo::Country
andTZInfo::Timezone
classes are thread-safe. It is safeto use class and instance methods ofTZInfo::Country
andTZInfo::Timezone
inconcurrently executing threads. Instances of both classes can be shared acrossthread boundaries.
API documentation for TZInfo is available onRubyDoc.info.
TZInfo is released under the MIT license, see LICENSE for details.
Source code for TZInfo is available onGitHub.
Please post any bugs, issues, feature requests or questions about TZInfo to theGitHub issue tracker.
Issues with the underlying time zone data should be raised on theTime Zone Database Discussion mailing list.
About
TZInfo - Ruby Timezone Library