diff -Nru ruby-tzinfo-1.2.6/appveyor.yml ruby-tzinfo-2.0.4/appveyor.yml --- ruby-tzinfo-1.2.6/appveyor.yml 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/appveyor.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1,94 +0,0 @@ -version: "{build}-{branch}" - -cache: - - vendor/bundle - -environment: - TESTOPTS: --verbose - - matrix: - # Ruby 1.8.7 isn't available on AppVeyor. - - - RUBY_ENGINE: ruby - RUBY_VERSION: 193 - SSL_CERT_FILE: C:\Ruby193\lib\ruby\1.9.1\rubygems\ssl_certs\ca-bundle.pem - - - RUBY_ENGINE: ruby - RUBY_VERSION: 200 - - - RUBY_ENGINE: ruby - RUBY_VERSION: 200-x64 - - - RUBY_ENGINE: ruby - RUBY_VERSION: 21 - - - RUBY_ENGINE: ruby - RUBY_VERSION: 21-x64 - - - RUBY_ENGINE: ruby - RUBY_VERSION: 22 - - - RUBY_ENGINE: ruby - RUBY_VERSION: 22-x64 - - - RUBY_ENGINE: ruby - RUBY_VERSION: 23 - - - RUBY_ENGINE: ruby - RUBY_VERSION: 23-x64 - - - RUBY_ENGINE: ruby - RUBY_VERSION: 24 - - - RUBY_ENGINE: ruby - RUBY_VERSION: 24-x64 - - - RUBY_ENGINE: ruby - RUBY_VERSION: 25 - - - RUBY_ENGINE: ruby - RUBY_VERSION: 25-x64 - - - RUBY_ENGINE: ruby - RUBY_VERSION: 26 - - - RUBY_ENGINE: ruby - RUBY_VERSION: 26-x64 - - - RUBY_ENGINE: jruby - JRUBY_VERSION: 1.7.27 - - - RUBY_ENGINE: jruby - JRUBY_VERSION: 9.1.17.0 - - - RUBY_ENGINE: jruby - JRUBY_VERSION: 9.2.9.0 - -install: - - if not exist vendor mkdir vendor - - if %RUBY_ENGINE%==jruby appveyor DownloadFile https://repo1.maven.org/maven2/org/jruby/jruby-dist/%JRUBY_VERSION%/jruby-dist-%JRUBY_VERSION%-bin.zip -FileName vendor\jruby-dist-%JRUBY_VERSION%-bin.zip - - if %RUBY_ENGINE%==jruby 7z x vendor\jruby-dist-%JRUBY_VERSION%-bin.zip -ovendor -y - - if %RUBY_ENGINE%==jruby set PATH=C:\projects\tzinfo\vendor\jruby-%JRUBY_VERSION%\bin;%PATH% - - if %RUBY_ENGINE%==jruby if "%JRUBY_VERSION:~0,2%"=="1." gem install bundler --version "~> 1.17" - - if %RUBY_ENGINE%==jruby if not "%JRUBY_VERSION:~0,2%"=="1." gem install bundler - - if v%RUBY_VERSION%==v193 appveyor DownloadFile https://github.com/philr/rubyinstaller/releases/download/1.9.3-p551-openssl-tls-1.1-1.2/ruby-1.9.3-p551-i386-mingw32.7z -FileName vendor\ruby-1.9.3-p551-i386-mingw32.7z - - if v%RUBY_VERSION%==v193 7z e vendor\ruby-1.9.3-p551-i386-mingw32.7z -ovendor ruby-1.9.3-p551-i386-mingw32\bin\libeay32.dll ruby-1.9.3-p551-i386-mingw32\bin\ssleay32.dll ruby-1.9.3-p551-i386-mingw32\lib\ruby\1.9.1\i386-mingw32\openssl.so ruby-1.9.3-p551-i386-mingw32\lib\ruby\1.9.1\rubygems\ssl_certs\ca-bundle.pem - - if v%RUBY_VERSION%==v193 copy /Y vendor\*eay32.dll C:\Ruby193\bin - - if v%RUBY_VERSION%==v193 copy /Y vendor\openssl.so C:\Ruby193\lib\ruby\1.9.1\i386-mingw32 - - if v%RUBY_VERSION%==v193 copy /Y vendor\ca-bundle.pem C:\Ruby193\lib\ruby\1.9.1\rubygems\ssl_certs - - if %RUBY_ENGINE%==ruby set PATH=C:\Ruby%RUBY_VERSION%\bin;%PATH% - - bundle config --local path vendor/bundle - - bundle update - -build: off - -before_test: - - "%RUBY_ENGINE% -v" - - gem -v - - bundle -v - -test_script: - - bundle exec rake test - -after_test: - - bundle clean diff -Nru ruby-tzinfo-1.2.6/CHANGES.md ruby-tzinfo-2.0.4/CHANGES.md --- ruby-tzinfo-1.2.6/CHANGES.md 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/CHANGES.md 2020-12-30 06:49:15.000000000 +0000 @@ -1,64 +1,267 @@ -Version 1.2.6 - 24-Dec-2019 ---------------------------- +# Changes -* Timezone#strftime('%s', time) will now return the correct number of seconds +## Version 2.0.4 - 16-Dec-2020 + +* Fixed an incorrect InvalidTimezoneIdentifier exception raised when loading a + zoneinfo file that includes rules specifying an additional transition to the + final defined offset (for example, Africa/Casablanca in version 2018e of the + Time Zone Database). #123. + + +## Version 2.0.3 - 8-Nov-2020 + +* Added support for handling "slim" format zoneinfo files that are produced by + default by zic version 2020b and later. The POSIX-style TZ string is now used + calculate DST transition times after the final defined transition in the file. + #120. +* Fixed `TimeWithOffset#getlocal` returning a `TimeWithOffset` with the + `timezone_offset` still assigned when called with an offset argument on JRuby + 9.3. +* Rubinius is no longer supported. + + +## Version 2.0.2 - 2-Apr-2020 + +* Fixed 'wrong number of arguments' errors when running on JRuby 9.0. #114. +* Fixed warnings when running on Ruby 2.8. #113. + + +## Version 2.0.1 - 24-Dec-2019 + +* Fixed "SecurityError: Insecure operation - require" exceptions when loading + data with recent Ruby releases in safe mode. #100. +* Fixed warnings when running on Ruby 2.7. #109. +* Added a `TZInfo::Timezone#=~` method that performs a regex match on the time + zone identifier. #99. +* Added a `TZInfo::Country#=~` method that performs a regex match on the country + code. + + +## Version 2.0.0 - 26-Dec-2018 + +### Added + +* `to_local` and `period_for` instance methods have been added to + `TZInfo::Timezone`. These are similar to `utc_to_local` and `period_for_utc`, + but take the UTC offset of the given time into account. +* `abbreviation`, `dst?`, `base_utc_offset` and `observed_utc_offset` instance + methods have been added to `TZInfo::Timezone`, returning the abbreviation, + whether daylight savings time is in effect and the UTC offset of the time zone + at a specified time. +* A `TZInfo::Timestamp` class has been added. It can be used with + `TZInfo::Timezone` in place of a `Time` or `DateTime`. +* `local_time`, `local_datetime` and `local_timestamp` instance methods have + been added to `TZInfo::Timezone`. These methods construct local `Time`, + `DateTime` and `TZInfo::Timestamp` instances with the correct UTC offset and + abbreviation for the time zone. +* Support for a (yet to be released) version 2 of tzinfo-data has been added, in + addition to support for version 1. The new version will remove the (no longer + needed) `DateTime` parameters from transition times, reduce memory consumption + and improve the efficiency of loading timezone and country indexes. +* A `TZInfo::VERSION` constant has been added, indicating the TZInfo version + number. + +### Changed + +* The minimum supported Ruby versions are now Ruby MRI 1.9.3, JRuby 1.7 (in 1.9 + or later mode) and Rubinius 3. +* Local times are now returned using the correct UTC offset (instead of using + UTC). #49 and #52. +* Local times are returned as instances of `TimeWithOffset`, + `DateTimeWithOffset` or `TZInfo::TimestampWithOffset`. These classes subclass + `Time`, `DateTime` and `TZInfo::Timestamp` respectively. They override the + default behaviour of the base classes to return information about the observed + offset at the indicated time. For example, the zone abbreviation is returned + when using the `%Z` directive with `strftime`. +* The `transitions_up_to`, `offsets_up_to` and `strftime` instance methods of + `TZInfo::Timezone` now take the UTC offsets of given times into account + (instead of ignoring them as was previously the case). +* The `TZInfo::TimezonePeriod` class has been split into two subclasses: + `TZInfo::OffsetTimezonePeriod` and `TZInfo::TransitionsTimezonePeriod`. + `TZInfo::OffsetTimezonePeriod` is returned for time zones that only have a + single offset. `TZInfo::TransitionsTimezonePeriod` is returned for periods + that start or end with a transition. +* `TZInfo::TimezoneOffset#abbreviation`, `TZInfo::TimezonePeriod#abbreviation` + and `TZInfo::TimezonePeriod#zone_identifier` now return frozen `String` + instances instead of instances of `Symbol`. +* The `utc_offset` and `utc_total_offset` attributes of `TZInfo::TimezonePeriod` + and `TZInfo::TimezoneOffset` have been renamed `base_utc_offset` and + `observed_utc_offset` respectively. The former names have been retained as + aliases. +* `TZInfo::Timezone.get`, `TZInfo::Timezone.get_proxy` and `TZInfo::Country.get` + can now be used with strings having any encoding. Previously, only encodings + that are directly comparable with UTF-8 were supported. +* The requested identifier is included in `TZInfo::InvalidTimezoneIdentifier` + exception messages. +* The requested country code is included in `TZInfo::InvalidCountryCode` + exception messages. +* The full range of transitions is now loaded from zoneinfo files. Zoneinfo + files produced with version 2014c of the `zic` tool contain an initial + transition `2**63` seconds before the epoch. Zoneinfo files produced with + version 2014d or later of `zic` contain an initial transition `2**59` seconds + before the epoch. These transitions would previously have been ignored, but + are now returned in methods such as `TZInfo::Timezone#transitions_up_to`. +* The `TZInfo::RubyDataSource` and `TZInfo::ZoneinfoDataSource` classes have + been moved into a new `TZInfo::DataSources` module. Code that is setting + `TZInfo::ZoneinfoDataSource.search_path` or + `TZInfo::ZoneinfoDataSource.alternate_iso3166_tab_search_path` will need to be + updated accordingly. +* The `TZInfo::InvalidZoneinfoDirectory` and `TZInfo::ZoneinfoDirectoryNotFound` + exception classes raised by `TZInfo::DataSources::ZoneinfoDataSource` have + been moved into the `TZInfo::DataSources` module. +* Setting the data source to `:ruby` or instantiating + `TZInfo::DataSources::RubyDataSource` will now immediately raise a + `TZInfo::DataSources::TZInfoDataNotFound` exception if `require 'tzinfo/data'` + fails. Previously, a failure would only occur later when accessing an index or + loading a timezone or country. +* The `DEFAULT_SEARCH_PATH` and `DEFAULT_ALTERNATE_ISO3166_TAB_SEARCH_PATH` + constants of `TZInfo::DataSources::ZoneinfoDataSource` have been made private. +* The `TZInfo::Country.data_source`, + `TZInfo::DataSource.create_default_data_source`, + `TZInfo::DataSources::ZoneinfoDataSource.process_search_path`, + `TZInfo::Timezone.get_proxies` and `TZInfo::Timezone.data_source` methods have + been made private. +* The performance of loading zoneinfo files and the associated indexes has been + improved. +* Memory use has been decreased by deduplicating `String` instances when loading + country and time zone data. +* The dependency on the deprecated thread_safe gem as been removed and replaced + by concurrent-ruby. +* The Info classes used to return time zone and country information from + `TZInfo::DataSource` implementations have been moved into the + `TZInfo::DataSources` module. +* The `TZInfo::TransitionDataTimezoneInfo` class has been removed and replaced + with `TZInfo::DataSources::TransitionsDataTimezoneInfo` and + `TZInfo::DataSources::ConstantOffsetDataTimezoneInfo`. + `TZInfo::DataSources::TransitionsDataTimezoneInfo` is constructed with an + `Array` of `TZInfo::TimezoneTransition` instances representing times when the + offset changes. `TZInfo::DataSources::ConstantOffsetDataTimezoneInfo` is + constructed with a `TZInfo::TimezoneOffset` instance representing the offset + constantly observed in a time zone. +* The `TZInfo::DataSource#timezone_identifiers` method should no longer be + overridden in custom data source implementations. The implementation in the + base class now calculates a result from + `TZInfo::DataSource#data_timezone_identifiers` and + `TZInfo::DataSource#linked_timezone_identifiers`. +* The results of the `TZInfo::DataSources::RubyDataSource` `to_s` and `inspect` + methods now include the time zone database and tzinfo-data versions. + + +### Removed + +* Methods of `TZInfo::Timezone` that accept time arguments no longer allow + `Integer` timestamp values. `Time`, `DateTime` or `TZInfo::Timestamp` values + or objects that respond to `to_i`, `subsec` and optionally `utc_offset` must + be used instead. +* The `%:::z` format directive can now only be used with + `TZInfo::Timezone#strftime` if it is supported by `Time#strftime` on the + runtime platform. +* Using `TZInfo::Timezone.new(identifier)` and `TZInfo::Country.new(code)` to + obtain a specific `TZInfo::Timezone` or `TZInfo::Country` will no longer work. + `TZInfo::Timezone.get(identifier)` and `TZInfo::Country.get(code)` should be + used instead. +* The `TZInfo::TimeOrDateTime` class has been removed. +* The `valid_for_utc?`, `utc_after_start?`, `utc_before_end?`, + `valid_for_local?`, `local_after_start?` and `local_before_end?` instance + methods of `TZInfo::TimezonePeriod` have been removed. Comparisons can be + performed with the results of the `starts_at`, `ends_at`, `local_starts_at` + and `local_ends_at` methods instead. +* The `to_local` and `to_utc` instance methods of `TZInfo::TimezonePeriod` and + `TZInfo::TimezoneOffset` have been removed. Conversions should be performed + using the `TZInfo::Timezone` class instead. +* The `TZInfo::TimezonePeriod#utc_total_offset_rational` method has been + removed. Equivalent information can be obtained using the + `TZInfo::TimezonePeriod#observed_utc_offset` method. +* The `datetime`, `time`, `local_end`, `local_end_time`, `local_start` and + `local_start_time` instance methods of `TZInfo::TimezoneTransition` have been + removed. The `at`, `local_end_at` and `local_start_at` methods should be used + instead and the result (a `TZInfo::TimestampWithOffset`) converted to either a + `DateTime` or `Time` by calling `to_datetime` or `to_time` on the result. +* The `us_zones` and `us_zone_identifiers` class methods of `TZInfo::Timezone` + have been removed. `TZInfo::Country.get('US').zones` and + `TZInfo::Country.get('US').zone_identifiers` should be used instead. + + +## Version 1.2.9 - 16-Dec-2020 + +* Fixed an incorrect InvalidTimezoneIdentifier exception raised when loading a + zoneinfo file that includes rules specifying an additional transition to the + final defined offset (for example, Africa/Casablanca in version 2018e of the + Time Zone Database). #123. + + +## Version 1.2.8 - 8-Nov-2020 + +* Added support for handling "slim" format zoneinfo files that are produced by + default by zic version 2020b and later. The POSIX-style TZ string is now used + calculate DST transition times after the final defined transition in the file. + The 64-bit section is now always used regardless of whether Time has support + for 64-bit times. #120. +* Rubinius is no longer supported. + + +## Version 1.2.7 - 2-Apr-2020 + +* Fixed 'wrong number of arguments' errors when running on JRuby 9.0. #114. +* Fixed warnings when running on Ruby 2.8. #112. + + +## Version 1.2.6 - 24-Dec-2019 + +* `Timezone#strftime('%s', time)` will now return the correct number of seconds since the epoch. #91. -* Removed the unused TZInfo::RubyDataSource::REQUIRE_PATH constant. +* Removed the unused `TZInfo::RubyDataSource::REQUIRE_PATH` constant. * Fixed "SecurityError: Insecure operation - require" exceptions when loading data with recent Ruby releases in safe mode. * Fixed warnings when running on Ruby 2.7. #106 and #111. -Version 1.2.5 - 4-Feb-2018 --------------------------- +## Version 1.2.5 - 4-Feb-2018 -* Support recursively (deep) freezing Country and Timezone instances. #80. +* Support recursively (deep) freezing `Country` and `Timezone` instances. #80. * Allow negative daylight savings time offsets to be derived when reading from zoneinfo files. The utc_offset and std_offset are now derived correctly for Europe/Dublin in the 2018a and 2018b releases of the Time Zone Database. -Version 1.2.4 - 26-Oct-2017 ---------------------------- +## Version 1.2.4 - 26-Oct-2017 * Ignore the leapseconds file that is included in zoneinfo directories installed with version 2017c and later of the Time Zone Database. -Version 1.2.3 - 25-Mar-2017 ---------------------------- +## Version 1.2.3 - 25-Mar-2017 -* Reduce the number of String objects allocated when loading zoneinfo files. +* Reduce the number of `String` objects allocated when loading zoneinfo files. #54. -* Make Timezone#friendly_identifier compatible with frozen string literals. -* Improve the algorithm for deriving the utc_offset from zoneinfo files. This +* Make `Timezone#friendly_identifier` compatible with frozen string literals. +* Improve the algorithm for deriving the `utc_offset` from zoneinfo files. This now correctly handles Pacific/Apia switching from one side of the International Date Line to the other whilst observing daylight savings time. #66. -* Fix an UnknownTimezone exception when calling transitions_up_to or - offsets_up_to on a TimezoneProxy instance obtained from Timezone.get_proxy. +* Fix an `UnknownTimezone` exception when calling transitions_up_to or + offsets_up_to on a `TimezoneProxy` instance obtained from + `Timezone.get_proxy`. * Allow the Factory zone to be obtained from the Zoneinfo data source. * Ignore the /usr/share/zoneinfo/timeconfig symlink included in Slackware distributions. #64. -* Fix Timezone#strftime handling of %Z expansion when %Z is prefixed with more - than one percent. #31. -* Support expansion of %z, %:z, %::z and %:::z to the UTC offset of the time - zone in Timezone#strftime. #31 and #67. +* Fix `Timezone#strftime` handling of `%Z` expansion when `%Z` is prefixed with + more than one percent. #31. +* Support expansion of `%z`, `%:z`, `%::z` and `%:::z` to the UTC offset of the + time zone in `Timezone#strftime`. #31 and #67. -Version 1.2.2 - 8-Aug-2014 --------------------------- +## Version 1.2.2 - 8-Aug-2014 -* Fix an error with duplicates being returned by Timezone#all_country_zones - and Timezone#all_country_zone_identifiers when used with tzinfo-data +* Fix an error with duplicates being returned by `Timezone#all_country_zones` + and `Timezone#all_country_zone_identifiers` when used with tzinfo-data v1.2014.6 or later. * Use the zone1970.tab file for country timezone data if it is found in the zoneinfo directory (and fallback to zone.tab if not). zone1970.tab was added in tzdata 2014f. zone.tab is now deprecated. -Version 1.2.1 - 1-Jun-2014 --------------------------- +## Version 1.2.1 - 1-Jun-2014 * Support zoneinfo files generated with zic version 2014c and later. * On platforms that only support positive 32-bit timestamps, ensure that @@ -67,55 +270,52 @@ * Minor documentation improvements. -Version 1.2.0 - 26-May-2014 ---------------------------- +## Version 1.2.0 - 26-May-2014 * Raise the minimum supported Ruby version to 1.8.7. * Support loading system zoneinfo data on FreeBSD, OpenBSD and Solaris. Resolves #15. -* Add canonical_identifier and canonical_zone methods to Timezone. Resolves #16. -* Add a link to a DataSourceNotFound help page in the TZInfo::DataSourceNotFound - exception message. +* Add `canonical_identifier` and `canonical_zone` methods to `Timezone`. + Resolves #16. +* Add a link to a `DataSourceNotFound` help page in the + `TZInfo::DataSourceNotFound` exception message. * Load iso3166.tab and zone.tab files as UTF-8. -* Fix Timezone#local_to_utc returning local Time instances on systems using UTC - as the local time zone. Resolves #13. -* Fix == methods raising an exception when passed an instance of a different - class by making <=> return nil if passed a non-comparable argument. -* Eliminate "require 'rational'" warnings. Resolves #10. +* Fix `Timezone#local_to_utc` returning local `Time` instances on systems using + UTC as the local time zone. Resolves #13. +* Fix `==` methods raising an exception when passed an instance of a different + class by making `<=>` return `nil` if passed a non-comparable argument. +* Eliminate `require 'rational'` warnings. Resolves #10. * Eliminate "assigned but unused variable - info" warnings. Resolves #11. * Switch to minitest v5 for unit tests. Resolves #18. -Version 1.1.0 - 25-Sep-2013 ---------------------------- +## Version 1.1.0 - 25-Sep-2013 -* TZInfo is now thread safe. ThreadSafe::Cache is now used instead of Hash - to cache Timezone and Country instances returned by Timezone.get and - Country.get. The tzinfo gem now depends on thread_safe ~> 0.1. -* Added a transitions_up_to method to Timezone that returns a list of the times - where the UTC offset of the timezone changes. -* Added an offsets_up_to method to Timezone that returns the set of offsets +* TZInfo is now thread safe. `ThreadSafe::Cache` is now used instead of `Hash` + to cache `Timezone` and `Country` instances returned by `Timezone.get` and + `Country.get`. The tzinfo gem now depends on thread_safe ~> 0.1. +* Added a `transitions_up_to` method to `Timezone` that returns a list of the + times where the UTC offset of the timezone changes. +* Added an `offsets_up_to` method to `Timezone` that returns the set of offsets that have been observed in a defined timezone. -* Fixed a "can't modify frozen String" error when loading a Timezone from a - zoneinfo file using an identifier String that is both tainted and frozen. +* Fixed a "can't modify frozen String" error when loading a `Timezone` from a + zoneinfo file using an identifier `String` that is both tainted and frozen. Resolves #3. * Support TZif3 format zoneinfo files (now produced by zic from tzcode version 2013e onwards). * Support using YARD to generate documentation (added a .yardopts file). * Ignore the +VERSION file included in the zoneinfo directory on Mac OS X. -* Added a note to the documentation concerning 32-bit zoneinfo files (as +* Added a note to the documentation concerning 32-bit zoneinfo files (as included with Mac OS X). -Version 1.0.1 - 22-Jun-2013 ---------------------------- +## Version 1.0.1 - 22-Jun-2013 * Fix a test case failure when tests are run from a directory that contains a dot in the path (issue #29751). -Version 1.0.0 - 2-Jun-2013 --------------------------- +## Version 1.0.0 - 2-Jun-2013 * Allow TZInfo to be used with different data sources instead of just the built-in Ruby module data files. @@ -124,73 +324,95 @@ distributions. * Remove the definition and index Ruby modules from TZInfo and move them into a separate TZInfo::Data library (available as the tzinfo-data gem). -* Default to using the TZInfo::Data library as the data source if it is +* Default to using the TZInfo::Data library as the data source if it is installed, otherwise use zoneinfo files instead. -* Preserve the nanoseconds of local timezone Time objects when performing +* Preserve the nanoseconds of local timezone Time objects when performing conversions (issue #29705). * Don't add the tzinfo lib directory to the search path when requiring 'tzinfo'. The tzinfo lib directory must now be in the search path before 'tzinfo' is required. -* Add utc_start_time, utc_end_time, local_start_time and local_end_time instance - methods to TimezonePeriod. These return an identical value as the existing - utc_start, utc_end, local_start and local_end methods, but return Time - instances instead of DateTime. -* Make the start_transition, end_transition and offset properties of - TimezonePeriod protected. To access properties of the period, callers should - use other TimezonePeriod instance methods instead (issue #7655). +* Add `utc_start_time`, `utc_end_time`, `local_start_time` and `local_end_time` + instance methods to `TimezonePeriod`. These return an identical value as the + existing `utc_start`, `utc_end`, `local_start` and `local_end` methods, but + return `Time` instances instead of `DateTime`. +* Make the `start_transition`, `end_transition` and `offset` properties of + `TimezonePeriod` protected. To access properties of the period, callers should + use other `TimezonePeriod` instance methods instead (issue #7655). + + +## Version 0.3.58 (tzdata v2020d) - 8-Nov-2020 + +* Updated to tzdata version 2020d + (https://mm.icann.org/pipermail/tz-announce/2020-October/000062.html). -Version 0.3.53 (tzdata v2017b) - 23-Mar-2017 --------------------------------------------- +## Version 0.3.57 (tzdata v2020a) - 17-May-2020 + +* Updated to tzdata version 2020a + (). + + +## Version 0.3.56 (tzdata v2019c) - 1-Nov-2019 + +* Updated to tzdata version 2019c + (). + + +## Version 0.3.55 (tzdata v2018g) - 27-Oct-2018 + +* Updated to tzdata version 2018g + (). + + +## Version 0.3.54 (tzdata v2018d) - 25-Mar-2018 + +* Updated to tzdata version 2018d + (). + + +## Version 0.3.53 (tzdata v2017b) - 23-Mar-2017 * Updated to tzdata version 2017b - (https://mm.icann.org/pipermail/tz-announce/2017-March/000046.html). + (). -Version 0.3.52 (tzdata v2016h) - 28-Oct-2016 --------------------------------------------- +## Version 0.3.52 (tzdata v2016h) - 28-Oct-2016 * Updated to tzdata version 2016h - (https://mm.icann.org/pipermail/tz-announce/2016-October/000042.html). + (). -Version 0.3.51 (tzdata v2016f) - 5-Jul-2016 -------------------------------------------- +## Version 0.3.51 (tzdata v2016f) - 5-Jul-2016 * Updated to tzdata version 2016f - (https://mm.icann.org/pipermail/tz-announce/2016-July/000040.html). + (). -Version 0.3.50 (tzdata v2016e) - 14-Jun-2016 --------------------------------------------- +## Version 0.3.50 (tzdata v2016e) - 14-Jun-2016 * Updated to tzdata version 2016e - (https://mm.icann.org/pipermail/tz-announce/2016-June/000039.html). + (). -Version 0.3.49 (tzdata v2016d) - 18-Apr-2016 --------------------------------------------- +## Version 0.3.49 (tzdata v2016d) - 18-Apr-2016 * Updated to tzdata version 2016d - (https://mm.icann.org/pipermail/tz-announce/2016-April/000038.html). + (). -Version 0.3.48 (tzdata v2016c) - 23-Mar-2016 --------------------------------------------- +## Version 0.3.48 (tzdata v2016c) - 23-Mar-2016 * Updated to tzdata version 2016c - (https://mm.icann.org/pipermail/tz-announce/2016-March/000037.html). + (). -Version 0.3.47 (tzdata v2016b) - 15-Mar-2016 --------------------------------------------- +## Version 0.3.47 (tzdata v2016b) - 15-Mar-2016 * Updated to tzdata version 2016b - (https://mm.icann.org/pipermail/tz-announce/2016-March/000036.html). + (). -Version 0.3.46 (tzdata v2015g) - 2-Dec-2015 -------------------------------------------- +## Version 0.3.46 (tzdata v2015g) - 2-Dec-2015 * From version 2015e, the IANA time zone database uses non-ASCII characters in country names. Backport the encoding handling from TZInfo::Data to allow @@ -198,425 +420,382 @@ byte sequence error when loading the countries index). Resolves #41. -Version 0.3.45 (tzdata v2015g) - 3-Oct-2015 -------------------------------------------- +## Version 0.3.45 (tzdata v2015g) - 3-Oct-2015 * Updated to tzdata version 2015g - (http://mm.icann.org/pipermail/tz-announce/2015-October/000034.html). + (). -Version 0.3.44 (tzdata v2015d) - 24-Apr-2015 --------------------------------------------- +## Version 0.3.44 (tzdata v2015d) - 24-Apr-2015 * Updated to tzdata version 2015d - (http://mm.icann.org/pipermail/tz-announce/2015-April/000031.html). + (). -Version 0.3.43 (tzdata v2015a) - 31-Jan-2015 --------------------------------------------- +## Version 0.3.43 (tzdata v2015a) - 31-Jan-2015 * Updated to tzdata version 2015a - (http://mm.icann.org/pipermail/tz-announce/2015-January/000028.html). + (). -Version 0.3.42 (tzdata v2014i) - 23-Oct-2014 --------------------------------------------- +## Version 0.3.42 (tzdata v2014i) - 23-Oct-2014 * Updated to tzdata version 2014i - (http://mm.icann.org/pipermail/tz-announce/2014-October/000026.html). + (). -Version 0.3.41 (tzdata v2014f) - 8-Aug-2014 -------------------------------------------- +## Version 0.3.41 (tzdata v2014f) - 8-Aug-2014 * Updated to tzdata version 2014f - (http://mm.icann.org/pipermail/tz-announce/2014-August/000023.html). + (). -Version 0.3.40 (tzdata v2014e) - 10-Jul-2014 --------------------------------------------- +## Version 0.3.40 (tzdata v2014e) - 10-Jul-2014 * Updated to tzdata version 2014e - (http://mm.icann.org/pipermail/tz-announce/2014-June/000022.html). + (). -Version 0.3.39 (tzdata v2014a) - 9-Mar-2014 -------------------------------------------- +## Version 0.3.39 (tzdata v2014a) - 9-Mar-2014 * Updated to tzdata version 2014a - (http://mm.icann.org/pipermail/tz-announce/2014-March/000018.html). + (). -Version 0.3.38 (tzdata v2013g) - 8-Oct-2013 -------------------------------------------- +## Version 0.3.38 (tzdata v2013g) - 8-Oct-2013 * Updated to tzdata version 2013g - (http://mm.icann.org/pipermail/tz-announce/2013-October/000015.html). + (). -Version 0.3.37 (tzdata v2013b) - 11-Mar-2013 --------------------------------------------- +## Version 0.3.37 (tzdata v2013b) - 11-Mar-2013 * Updated to tzdata version 2013b - (http://mm.icann.org/pipermail/tz-announce/2013-March/000010.html). + (). -Version 0.3.36 (tzdata v2013a) - 3-Mar-2013 -------------------------------------------- +## Version 0.3.36 (tzdata v2013a) - 3-Mar-2013 * Updated to tzdata version 2013a - (http://mm.icann.org/pipermail/tz-announce/2013-March/000009.html). -* Fix TimezoneTransitionInfo#eql? incorrectly returning false when running on + (). +* Fix `TimezoneTransitionInfo#eql?` incorrectly returning false when running on Ruby 2.0. -* Change eql? and == implementations to test the class of the passed in object - instead of checking individual properties with 'respond_to?'. +* Change `eql?` and `==` implementations to test the class of the passed in + object instead of checking individual properties with `respond_to?`. -Version 0.3.35 (tzdata v2012i) - 4-Nov-2012 -------------------------------------------- +## Version 0.3.35 (tzdata v2012i) - 4-Nov-2012 * Updated to tzdata version 2012i - (http://mm.icann.org/pipermail/tz-announce/2012-November/000007.html). + (). -Version 0.3.34 (tzdata v2012h) - 27-Oct-2012 --------------------------------------------- +## Version 0.3.34 (tzdata v2012h) - 27-Oct-2012 * Updated to tzdata version 2012h - (http://mm.icann.org/pipermail/tz-announce/2012-October/000006.html). + (). -Version 0.3.33 (tzdata v2012c) - 8-Apr-2012 -------------------------------------------- +## Version 0.3.33 (tzdata v2012c) - 8-Apr-2012 * Updated to tzdata version 2012c - (http://article.gmane.org/gmane.comp.time.tz/4859). + (). -Version 0.3.32 (tzdata v2012b) - 4-Mar-2012 -------------------------------------------- +## Version 0.3.32 (tzdata v2012b) - 4-Mar-2012 * Updated to tzdata version 2012b - (http://article.gmane.org/gmane.comp.time.tz/4756). + (). -Version 0.3.31 (tzdata v2011n) - 6-Nov-2011 -------------------------------------------- +## Version 0.3.31 (tzdata v2011n) - 6-Nov-2011 * Updated to tzdata version 2011n - (http://article.gmane.org/gmane.comp.time.tz/4434). + (). -Version 0.3.30 (tzdata v2011k) - 29-Sep-2011 --------------------------------------------- +## Version 0.3.30 (tzdata v2011k) - 29-Sep-2011 * Updated to tzdata version 2011k - (http://article.gmane.org/gmane.comp.time.tz/4084). + (). -Version 0.3.29 (tzdata v2011h) - 27-Jun-2011 --------------------------------------------- +## Version 0.3.29 (tzdata v2011h) - 27-Jun-2011 * Updated to tzdata version 2011h - (http://article.gmane.org/gmane.comp.time.tz/3814). -* Allow the default value of the local_to_utc and period_for_local dst - parameter to be specified globally with a Timezone.default_dst attribute. + (). +* Allow the default value of the `local_to_utc` and `period_for_local` `dst` + parameter to be specified globally with a `Timezone.default_dst` attribute. Thanks to Kurt Werle for the suggestion and patch. - Version 0.3.28 (tzdata v2011g) - 13-Jun-2011 ---------------------------------------------- +## Version 0.3.28 (tzdata v2011g) - 13-Jun-2011 -* Add support for Ruby 1.9.3 (trunk revision 31668 and later). Thanks to +* Add support for Ruby 1.9.3 (trunk revision 31668 and later). Thanks to Aaron Patterson for reporting the problems running on the new version. Closes #29233. -Version 0.3.27 (tzdata v2011g) - 26-Apr-2011 --------------------------------------------- +## Version 0.3.27 (tzdata v2011g) - 26-Apr-2011 * Updated to tzdata version 2011g - (http://article.gmane.org/gmane.comp.time.tz/3758). + (). -Version 0.3.26 (tzdata v2011e) - 2-Apr-2011 -------------------------------------------- +## Version 0.3.26 (tzdata v2011e) - 2-Apr-2011 * Updated to tzdata version 2011e - (http://article.gmane.org/gmane.comp.time.tz/3707). + (). -Version 0.3.25 (tzdata v2011d) - 14-Mar-2011 --------------------------------------------- +## Version 0.3.25 (tzdata v2011d) - 14-Mar-2011 * Updated to tzdata version 2011d - (http://article.gmane.org/gmane.comp.time.tz/3662). + (). -Version 0.3.24 (tzdata v2010o) - 15-Jan-2011 --------------------------------------------- +## Version 0.3.24 (tzdata v2010o) - 15-Jan-2011 * Updated to tzdata version 2010o - (http://article.gmane.org/gmane.comp.time.tz/3473). + (). -Version 0.3.23 (tzdata v2010l) - 19-Aug-2010 --------------------------------------------- +## Version 0.3.23 (tzdata v2010l) - 19-Aug-2010 * Updated to tzdata version 2010l - (http://article.gmane.org/gmane.comp.time.tz/3354). + (). -Version 0.3.22 (tzdata v2010j) - 29-May-2010 --------------------------------------------- +## Version 0.3.22 (tzdata v2010j) - 29-May-2010 * Corrected file permissions issue with 0.3.21 release. -Version 0.3.21 (tzdata v2010j) - 28-May-2010 --------------------------------------------- +## Version 0.3.21 (tzdata v2010j) - 28-May-2010 * Updated to tzdata version 2010j - (http://article.gmane.org/gmane.comp.time.tz/3225). + (). * Change invalid timezone check to exclude characters not used in timezone identifiers and avoid 'character class has duplicated range' warnings with Ruby 1.9.2. -* Ruby 1.9.2 has deprecated "require 'rational'", but older versions of +* Ruby 1.9.2 has deprecated `require 'rational'`, but older versions of Ruby need rational to be required. Require rational only when the Rational module has not already been loaded. * Remove circular requires (now a warning in Ruby 1.9.2). Instead of using - requires in each file for dependencies, tzinfo.rb now requires all tzinfo + requires in each file for dependencies, `tzinfo.rb` now requires all tzinfo files. If you were previously requiring files within the tzinfo directory - (e.g. require 'tzinfo/timezone'), then you will now have to - require 'tzinfo' instead. + (e.g. `require 'tzinfo/timezone'`), then you will now have to + `require 'tzinfo'` instead. -Version 0.3.20 (tzdata v2010i) - 19-Apr-2010 --------------------------------------------- +## Version 0.3.20 (tzdata v2010i) - 19-Apr-2010 * Updated to tzdata version 2010i - (http://article.gmane.org/gmane.comp.time.tz/3202). + (). -Version 0.3.19 (tzdata v2010h) - 5-Apr-2010 -------------------------------------------- +## Version 0.3.19 (tzdata v2010h) - 5-Apr-2010 * Updated to tzdata version 2010h - (http://article.gmane.org/gmane.comp.time.tz/3188). + (). -Version 0.3.18 (tzdata v2010g) - 29-Mar-2010 --------------------------------------------- +## Version 0.3.18 (tzdata v2010g) - 29-Mar-2010 * Updated to tzdata version 2010g - (http://article.gmane.org/gmane.comp.time.tz/3172). + (). -Version 0.3.17 (tzdata v2010e) - 8-Mar-2010 -------------------------------------------- +## Version 0.3.17 (tzdata v2010e) - 8-Mar-2010 * Updated to tzdata version 2010e - (http://article.gmane.org/gmane.comp.time.tz/3128). + (). -Version 0.3.16 (tzdata v2009u) - 5-Jan-2010 -------------------------------------------- +## Version 0.3.16 (tzdata v2009u) - 5-Jan-2010 * Support the use of '-' to denote '0' as an offset in the tz data files. Used for the first time in the SAVE field in tzdata v2009u. * Updated to tzdata version 2009u - (http://article.gmane.org/gmane.comp.time.tz/3053). + (). -Version 0.3.15 (tzdata v2009p) - 26-Oct-2009 --------------------------------------------- +## Version 0.3.15 (tzdata v2009p) - 26-Oct-2009 * Updated to tzdata version 2009p - (http://article.gmane.org/gmane.comp.time.tz/2953). + (). * Added a description to the gem spec. * List test files in test_files instead of files in the gem spec. -Version 0.3.14 (tzdata v2009l) - 19-Aug-2009 --------------------------------------------- +## Version 0.3.14 (tzdata v2009l) - 19-Aug-2009 * Updated to tzdata version 2009l - (http://article.gmane.org/gmane.comp.time.tz/2818). + (). * Include current directory in load path to allow running tests on Ruby 1.9.2, which doesn't include it by default any more. -Version 0.3.13 (tzdata v2009f) - 15-Apr-2009 --------------------------------------------- +## Version 0.3.13 (tzdata v2009f) - 15-Apr-2009 * Updated to tzdata version 2009f - (http://article.gmane.org/gmane.comp.time.tz/2668). + (). * Untaint the timezone module filename after validation to allow use - with $SAFE == 1 (e.g. under mod_ruby). Thanks to Dmitry Borodaenko for + with `$SAFE == 1` (e.g. under mod_ruby). Thanks to Dmitry Borodaenko for the suggestion. Closes #25349. -Version 0.3.12 (tzdata v2008i) - 12-Nov-2008 --------------------------------------------- +## Version 0.3.12 (tzdata v2008i) - 12-Nov-2008 * Updated to tzdata version 2008i - (http://article.gmane.org/gmane.comp.time.tz/2440). + (). -Version 0.3.11 (tzdata v2008g) - 7-Oct-2008 -------------------------------------------- +## Version 0.3.11 (tzdata v2008g) - 7-Oct-2008 * Updated to tzdata version 2008g - (http://article.gmane.org/gmane.comp.time.tz/2335). -* Support Ruby 1.9.0-5. Rational.new! has now been removed in Ruby 1.9. - Only use Rational.new! if it is available (it is preferable in Ruby 1.8 + (). +* Support Ruby 1.9.0-5. `Rational.new!` has now been removed in Ruby 1.9. + Only use `Rational.new!` if it is available (it is preferable in Ruby 1.8 for performance reasons). Thanks to Jeremy Kemper and Pratik Naik for reporting this. Closes #22312. * Apply a patch from Pratik Naik to replace assert calls that have been deprecated in the Ruby svn trunk. Closes #22308. -Version 0.3.10 (tzdata v2008f) - 16-Sep-2008 --------------------------------------------- +## Version 0.3.10 (tzdata v2008f) - 16-Sep-2008 * Updated to tzdata version 2008f - (http://article.gmane.org/gmane.comp.time.tz/2293). + (). -Version 0.3.9 (tzdata v2008c) - 27-May-2008 -------------------------------------------- +## Version 0.3.9 (tzdata v2008c) - 27-May-2008 * Updated to tzdata version 2008c - (http://article.gmane.org/gmane.comp.time.tz/2183). + (). * Support loading timezone data in the latest trunk versions of Ruby 1.9. - Rational.new! is now private, so call it using Rational.send :new! instead. - Thanks to Jeremy Kemper and Pratik Naik for spotting this. Closes #19184. + `Rational.new!` is now private, so call it using `Rational.send :new!` + instead. Thanks to Jeremy Kemper and Pratik Naik for spotting this. Closes + #19184. * Prevent warnings from being output when running Ruby with the -v or -w command line options. Thanks to Paul McMahon for the patch. Closes #19719. -Version 0.3.8 (tzdata v2008b) - 24-Mar-2008 -------------------------------------------- +## Version 0.3.8 (tzdata v2008b) - 24-Mar-2008 * Updated to tzdata version 2008b - (http://article.gmane.org/gmane.comp.time.tz/2149). -* Support loading timezone data in Ruby 1.9.0. Use DateTime.new! if it is - available instead of DateTime.new0 when constructing transition times. - DateTime.new! was added in Ruby 1.8.6. DateTime.new0 was removed in + (). +* Support loading timezone data in Ruby 1.9.0. Use `DateTime.new!` if it is + available instead of `DateTime.new0` when constructing transition times. + `DateTime.new!` was added in Ruby 1.8.6. `DateTime.new0` was removed in Ruby 1.9.0. Thanks to Joshua Peek for reporting this. Closes #17606. * Modify some of the equality test cases to cope with the differences between Ruby 1.8.6 and Ruby 1.9.0. -Version 0.3.7 (tzdata v2008a) - 10-Mar-2008 -------------------------------------------- +## Version 0.3.7 (tzdata v2008a) - 10-Mar-2008 * Updated to tzdata version 2008a - (http://article.gmane.org/gmane.comp.time.tz/2071). + (). -Version 0.3.6 (tzdata v2007k) - 1-Jan-2008 ------------------------------------------- +## Version 0.3.6 (tzdata v2007k) - 1-Jan-2008 * Updated to tzdata version 2007k - (http://article.gmane.org/gmane.comp.time.tz/2029). + (). * Removed deprecated RubyGems autorequire option. -Version 0.3.5 (tzdata v2007h) - 1-Oct-2007 ------------------------------------------- +## Version 0.3.5 (tzdata v2007h) - 1-Oct-2007 * Updated to tzdata version 2007h - (http://article.gmane.org/gmane.comp.time.tz/1878). + (). -Version 0.3.4 (tzdata v2007g) - 21-Aug-2007 -------------------------------------------- +## Version 0.3.4 (tzdata v2007g) - 21-Aug-2007 * Updated to tzdata version 2007g - (http://article.gmane.org/gmane.comp.time.tz/1810). + (). -Version 0.3.3 (tzdata v2006p) - 27-Nov-2006 -------------------------------------------- +## Version 0.3.3 (tzdata v2006p) - 27-Nov-2006 * Updated to tzdata version 2006p - (http://article.gmane.org/gmane.comp.time.tz/1358). + (). -Version 0.3.2 (tzdata v2006n) - 11-Oct-2006 -------------------------------------------- +## Version 0.3.2 (tzdata v2006n) - 11-Oct-2006 * Updated to tzdata version 2006n - (http://article.gmane.org/gmane.comp.time.tz/1288). Note that this release of - tzdata removes the country Serbia and Montenegro (CS) and replaces it with - separate Serbia (RS) and Montenegro (ME) entries. + (). Note that this + release of tzdata removes the country Serbia and Montenegro (CS) and replaces + it with separate Serbia (RS) and Montenegro (ME) entries. -Version 0.3.1 (tzdata v2006j) - 21-Aug-2006 -------------------------------------------- +## Version 0.3.1 (tzdata v2006j) - 21-Aug-2006 * Remove colon from case statements to avoid warning in Ruby 1.8.5. #5198. * Use temporary variable to avoid dynamic string warning from rdoc. * Updated to tzdata version 2006j - (http://article.gmane.org/gmane.comp.time.tz/1175). + (). -Version 0.3.0 (tzdata v2006g) - 17-Jul-2006 -------------------------------------------- +## Version 0.3.0 (tzdata v2006g) - 17-Jul-2006 * New timezone data format. Timezone data now occupies less space on disk and takes less memory once loaded. #4142, #4144. -* Timezone data is defined in modules rather than classes. Timezone instances - returned by Timezone.get are no longer instances of data classes, but are - instead instances of new DataTimezone and LinkedTimezone classes. -* Timezone instances can now be used with Marshal.dump and Marshal.load. #4240. -* Added a Timezone.get_proxy method that returns a TimezoneProxy object for a - given identifier. +* Timezone data is defined in modules rather than classes. `Timezone` instances + returned by `Timezone.get` are no longer instances of data classes, but are + instead instances of new `DataTimezone` and `LinkedTimezone` classes. +* `Timezone` instances can now be used with `Marshal.dump` and `Marshal.load`. + #4240. +* Added a `Timezone.get_proxy` method that returns a `TimezoneProxy` object for + a given identifier. * Country index data is now defined in a single module that is independent - of the Country class implementation. -* Country instances can now be used with Marshal.dump and Marshal.load. #4240. -* Country has a new zone_info method that returns CountryTimezone objects - containing additional information (latitude, longitude and a description) - relating to each Timezone. #4140. -* Timezones within a Country are now returned in an order that makes + of the `Country` class implementation. +* `Country` instances can now be used with `Marshal.dump` and `Marshal.load`. + #4240. +* `Country` has a new `zone_info` method that returns `CountryTimezone` objects + containing additional information (latitude, longitude and a description) + relating to each `Timezone`. #4140. +* Time zones within a `Country` are now returned in an order that makes geographic sense. * The zdumptest utility now checks local to utc conversions in addition to utc to local conversions. -* eql? method defined on Country and Timezone that is equivalent to ==. -* The == method of Timezone no longer raises an exception when passed an object - with no identifier method. -* The == method of Country no longer raises an exception when passed an object - with no code method. -* hash method defined on Country that returns the hash of the code. -* hash method defined on Timezone that returns the hash of the identifier. +* `eql?` method defined on `Country` and `Timezone` that is equivalent to `==`. +* The `==` method of `Timezone` no longer raises an exception when passed an + object with no identifier method. +* The `==` method of `Country` no longer raises an exception when passed an + object with no code method. +* `hash` method defined on `Country` that returns the hash of the code. +* `hash` method defined on `Timezone` that returns the hash of the identifier. * Miscellaneous API documentation corrections and improvements. * Timezone definition and indexes are now excluded from rdoc (the contents were - previously ignored with #:nodoc: anyway). -* Removed no longer needed #:nodoc: directives from timezone data files (which + previously ignored with `#:nodoc:` anyway). +* Removed no longer needed `#:nodoc:` directives from timezone data files (which are now excluded from the rdoc build). -* Installation of the gem now causes rdoc API documentation to be generated. +* Installation of the gem now causes rdoc API documentation to be generated. #4905. * When optimizing transitions to generate zone definitions, check the UTC and standard offsets separately rather than just the total offset to UTC. - Fixes an incorrect abbreviation issue with Europe/London, Europe/Dublin and + Fixes an incorrect abbreviation issue with Europe/London, Europe/Dublin and Pacific/Auckland. -* Eliminated unnecessary .nil? calls to give a minor performance gain. -* Timezone.all and Timezone.all_identifiers now return all the - Timezones/identifiers rather than just those associated with countries. #4146. -* Added all_data_zones, all_data_zone_identifiers, all_linked_zones and - all_linked_zone_identifiers class methods to Timezone. -* Added a strftime method to Timezone that converts a time in UTC to local - time and then returns it formatted. %Z is replaced with the Timezone +* Eliminated unnecessary `.nil?` calls to give a minor performance gain. +* `Timezone.all` and `Timezone.all_identifiers` now return all the + `Timezone` instances/identifiers rather than just those associated with + countries. #4146. +* Added `all_data_zones`, `all_data_zone_identifiers`, `all_linked_zones` and + `all_linked_zone_identifiers` class methods to `Timezone`. +* Added a `strftime` method to `Timezone` that converts a time in UTC to local + time and then returns it formatted. `%Z` is replaced with the timezone abbreviation for the given time (for example, EST or EDT). #4143. -* Fix escaping of quotes in TZDataParser. This affected country names and - descriptions of timezones within countries. +* Fix escaping of quotes in `TZDataParser`. This affected country names and + descriptions of time zones within countries. -Version 0.2.2 (tzdata v2006g) - 17-May-2006 -------------------------------------------- +## Version 0.2.2 (tzdata v2006g) - 17-May-2006 -* Use class-scoped instance variables to store the Timezone identifier and +* Use class-scoped instance variables to store the Timezone identifier and singleton instance. Loading a linked zone no longer causes the parent zone's identifier to be changed. The instance method of a linked zone class also now returns an instance of the linked zone class rather than the parent @@ -625,173 +804,170 @@ zone identifier. * The zdumptestall utility now exits if not supplied with enough parameters. * Updated to tzdata version 2006g - (http://article.gmane.org/gmane.comp.time.tz/1008). + (). -Version 0.2.1 (tzdata v2006d) - 17-Apr-2006 -------------------------------------------- +## Version 0.2.1 (tzdata v2006d) - 17-Apr-2006 -* Fix a performance issue caused in 0.2.0 with Timezone.local_to_utc. - Conversions performed on TimeOrDateTime instances passed to <=> are now +* Fix a performance issue caused in 0.2.0 with `Timezone.local_to_utc`. + Conversions performed on `TimeOrDateTime` instances passed to `<=>` are now cached as originally intended. Thanks to Michael Smedberg for spotting this. -* Fix a performance issue with the local_to_utc period search algorithm +* Fix a performance issue with the `local_to_utc` period search algorithm originally implemented in 0.1.0. The condition that was supposed to cause the search to terminate when enough periods had been found was only being - evaluated in a small subset of cases. Thanks to Michael Smedberg and + evaluated in a small subset of cases. Thanks to Michael Smedberg and Jamis Buck for reporting this. -* Added abbreviation as an alias for TimezonePeriod.zone_identifier. +* Added abbreviation as an alias for `TimezonePeriod.zone_identifier`. * Updated to tzdata version 2006d - (http://article.gmane.org/gmane.comp.time.tz/936). -* Ignore any offset in DateTimes passed in (as is already done for Times). - All of the following now refer to the same UTC time (15:40 on 17 April 2006). - Previously, the DateTime in the second line would have been interpreted - as 20:40. - + (). +* Ignore any offset in `DateTime` instances passed in (as is already done for + `Time` instances). All of the following now refer to the same UTC time (15:40 on 17 April 2006). Previously, the `DateTime` in the second line would have been interpreted as 20:40. + + ```ruby tz.utc_to_local(DateTime.new(2006, 4, 17, 15, 40, 0)) tz.utc_to_local(DateTime.new(2006, 4, 17, 15, 40, 0).new_offset(Rational(5, 24))) tz.utc_to_local(Time.utc(2006, 4, 17, 15, 40, 0)) tz.utc_to_local(Time.local(2006, 4, 17, 15, 40, 0)) + ``` -Version 0.2.0 (tzdata v2006c) - 3-Apr-2006 ------------------------------------------- +## Version 0.2.0 (tzdata v2006c) - 3-Apr-2006 -* Use timestamps rather than DateTime objects in zone files for times between - 1970 and 2037 (the range of Time). -* Don't convert passed in Time objects to DateTime in most cases (provides +* Use timestamps rather than `DateTime` objects in zone files for times between + 1970 and 2037 (the range of `Time`). +* Don't convert passed in `Time` objects to `DateTime` in most cases (provides a substantial performance improvement). -* Allow integer timestamps (time in seconds since 1970-1-1) to be used as well - as Time and DateTime objects in all public methods that take times as +* Allow integer timestamps (time in seconds since 1970-1-1) to be used as well + as `Time` and `DateTime` objects in all public methods that take times as parameters. * Tool to compare TZInfo conversions with output from zdump. -* TZDataParser zone generation algorithm rewritten. Now based on the zic code. +* `TZDataParser` zone generation algorithm rewritten. Now based on the zic code. TZInfo is now 100% compatible with zic/zdump output. * Riyadh Solar Time zones now included again (generation time has been reduced - with TZDataParser changes). + with `TZDataParser` changes). * Use binary mode when writing zone and country files to get Unix (\n) new lines. * Omit unnecessary quotes in zone identifier symbols. * Omit the final transition to DST if there is a prior transition in the last year processed to standard time. * Updated to tzdata version 2006c - (http://article.gmane.org/gmane.comp.time.tz/920). + (). -Version 0.1.2 (tzdata v2006a) - 5-Feb-2006 ------------------------------------------- +## Version 0.1.2 (tzdata v2006a) - 5-Feb-2006 * Add lib directory to the load path when tzinfo is required. Makes it easier - to use tzinfo gem when unpacked to vendor directory in rails. -* Updated to tzdata version 2006a - (http://article.gmane.org/gmane.comp.time.tz/738). -* build_tz_classes rake task now handles running svn add and svn delete as new - timezones and countries are added and old ones are removed. -* Return a better error when attempting to use a Timezone instance that was - constructed with Timezone.new(nil). This will occur when using Rails' - composed_of. When the timezone identifier in the database is null, attempting - to use the Timezone will now result in an UnknownTimezone exception rather - than a NameError. + to use tzinfo gem when unpacked to vendor directory in rails. +* Updated to tzdata version 2006a + (). +* `build_tz_classes` rake task now handles running svn add and svn delete as new + time zones and countries are added and old ones are removed. +* Return a better error when attempting to use a `Timezone` instance that was + constructed with `Timezone.new(nil)`. This will occur when using Rails' + `composed_of`. When the timezone identifier in the database is null, + attempting to use the `Timezone` will now result in an `UnknownTimezone` + exception rather than a `NameError`. -Version 0.1.1 (tzdata v2005q) - 18-Dec-2005 -------------------------------------------- +## Version 0.1.1 (tzdata v2005q) - 18-Dec-2005 -* Timezones that are defined by a single unbounded period (e.g. UTC) now +* Time zones that are defined by a single unbounded period (e.g. UTC) now work again. * Updated to tzdata version 2005q. -Version 0.1.0 (tzdata v2005n) - 27-Nov-2005 -------------------------------------------- +## Version 0.1.0 (tzdata v2005n) - 27-Nov-2005 -* period_for_local and local_to_utc now allow resolution of ambiguous - times (e.g. when switching from daylight savings to standard time). +* `period_for_local` and `local_to_utc` now allow resolution of ambiguous + times (e.g. when switching from daylight savings to standard time). The behaviour of these methods when faced with an ambiguous local time has now changed. If you are using these methods you should check the documentation. Thanks to Cliff Matthews for suggesting this change. -* Added require 'date' to timezone.rb (date isn't loaded by default in all +* Added `require 'date'` to `timezone.rb` (date isn't loaded by default in all environments). * Use rake to build packages and documentation. * License file is now included in gem distribution. * Dates in definitions stored as Astronomical Julian Day numbers rather than - as civil dates (improves performance creating DateTime instances). -* Added options to TZDataParser to allow generation of specific zones and + as civil dates (improves performance creating `DateTime` instances). +* Added options to `TZDataParser` to allow generation of specific zones and countries. -* Moved TimezonePeriod class to timezone_period.rb. -* New TimezonePeriodList class to store TimezonePeriods for a timezone and - perform searches for periods. -* Timezones now defined using blocks. TimezonePeriods are only instantiated - when they are needed. Thanks to Jamis Buck for the suggestion. -* Add options to TZDataParser to allow exclusion of specific zones and +* Moved `TimezonePeriod` class to `timezone_period.rb`. +* New `TimezonePeriodList` class to store `TimezonePeriod` instances for a + timezone and perform searches for periods. +* Time zones are now defined using blocks. `TimezonePeriod` instances are only + created when they are needed. Thanks to Jamis Buck for the suggestion. +* Add options to `TZDataParser` to allow exclusion of specific zones and countries. * Exclude the Riyadh Solar Time zones. The rules are only for 1987 to 1989 and take a long time to generate and process. Riyadh Solar Time is no longer observed. -* The last TimezonePeriod for each Timezone is now written out with an +* The last `TimezonePeriod` for each `Timezone` is now written out with an unbounded rather than arbitrary end time. -* Construct the Rational offset in TimezonePeriod once when the TimezonePeriod - is constructed rather than each time it is needed. -* Timezone and Country now keep a cache of loaded instances to avoid running - require which can be slow on some platforms. +* Construct the `Rational` offset in `TimezonePeriod` once when the + `TimezonePeriod` is constructed rather than each time it is needed. +* `Timezone` and `Country` now keep a cache of loaded instances to avoid running + `require` which can be slow on some platforms. * Updated to tzdata version 2005n. -Version 0.0.4 (tzdata v2005m) - 18-Sep-2005 -------------------------------------------- +## Version 0.0.4 (tzdata v2005m) - 18-Sep-2005 * Removed debug output accidentally included in the previous release. * Fixed a bug in the generation of friendly zone identifiers (was inserting apostrophes into UTC, GMT, etc). -* Fixed Country <=> operator (was comparing non-existent attribute) -* Fixed Timezone.period_for_local error when period not found. -* Added testcases for Timezone, TimezoneProxy, TimezonePeriod, Country and - some selected timezones. - - -Version 0.0.3 (tzdata v2005m) - 17-Sep-2005 -------------------------------------------- - -* Reduced visibility of some methods added in Timezone#setup and Country#setup. -* Added name method to Timezone (returns the identifier). -* Added friendly_identifier method to Timezone. Returns a more friendly version - of the identifier. -* Added to_s method to Timezone. Returns the friendly identifier. -* Added == and <=> operators to Timezone (compares identifiers). -* Timezone now includes Comparable. -* Added to_s method to Country. -* Added == and <=> operators to Country (compares ISO 3166 country codes). -* Country now includes Comparable. -* New TimezoneProxy class that behaves the same as a Timezone but doesn't +* Fixed `Country` `<=>` operator (was comparing non-existent attribute) +* Fixed `Timezone.period_for_local` error when period not found. +* Added test cases for `Timezone`, `TimezoneProxy`, `TimezonePeriod`, `Country` + and some selected time zones. + + +## Version 0.0.3 (tzdata v2005m) - 17-Sep-2005 + +* Reduced visibility of some methods added in `Timezone#setup` and + `Country#setup`. +* Added `name` method to `Timezone` (returns the identifier). +* Added `friendly_identifier` method to `Timezone`. Returns a more friendly + version of the identifier. +* Added `to_s` method to `Timezone`. Returns the friendly identifier. +* Added `==` and `<=>` operators to `Timezone` (compares identifiers). +* `Timezone` now includes `Comparable`. +* Added `to_s` method to `Country`. +* Added `==` and `<=>` operators to `Country` (compares ISO 3166 country codes). +* `Country` now includes `Comparable`. +* New `TimezoneProxy` class that behaves the same as a `Timezone` but doesn't actually load in its definition until it is actually required. -* Modified Timezone and Country methods that return Timezones to return - TimezoneProxy instances instead. This makes these methods much quicker. - - In Ruby on Rails, you can now show a drop-down list of all timezones using the - Rails time_zone_select helper method: - - <%= time_zone_select 'user', 'time_zone', TZInfo::Timezone.all.sort, :model => TZInfo::Timezone %> - - -Version 0.0.2 (tzdata v2005m) - 13-Sep-2005 -------------------------------------------- - -* Country and Timezone data is now loaded into class rather than instance - variables. This makes Timezone links more efficient and saves memory if - creating specific Timezone and Country classes directly. -* TimezonePeriod zone_identifier is now defined as a symbol to save memory +* Modified `Timezone` and `Country` methods that return `Timezone` instances to + return `TimezoneProxy` instances instead. This makes these methods much + quicker. + +In Ruby on Rails, you can now show a drop-down list of all time zones using the +Rails `time_zone_select` helper method: + +```ruby +<%= time_zone_select 'user', 'time_zone', TZInfo::Timezone.all.sort, :model => TZInfo::Timezone %> +``` + + +## Version 0.0.2 (tzdata v2005m) - 13-Sep-2005 + +* `Country` and `Timezone` data is now loaded into class rather than instance + variables. This makes `Timezone` links more efficient and saves memory if + creating specific `Timezone` and `Country` classes directly. +* `TimezonePeriod` `zone_identifier` is now defined as a symbol to save memory (was previously a string). -* TimezonePeriod zone_identifiers that were previously '' are now :Unknown. -* Timezones and Countries can now be returned using Timezone.new(identifier) - and Country.new(identifier). When passed an identifier, the new method - calls get to return an instance of the specified timezone or country. -* Added new class methods to Timezone to return sets of zones and identifiers. +* `TimezonePeriod` `zone_identifier`s that were previously `''` are now + `:Unknown`. +* `Timezone` and `Country` instances can now be returned using + `Timezone.new(identifier)` and `Country.new(identifier)`. When passed an + identifier, the `new` method calls `get` to return an instance of the + specified timezone or country. +* Added new class methods to `Timezone` to return sets of zones and identifiers. Thanks to Scott Barron of Lunchbox Software for the suggestions in his -article about using TZInfo with Rails -(http://lunchroom.lunchboxsoftware.com/pages/tzinfo_rails) +article about using TZInfo with Rails +() -Version 0.0.1 (tzdata v2005m) - 29-Aug-2005 -------------------------------------------- +## Version 0.0.1 (tzdata v2005m) - 29-Aug-2005 * First release. diff -Nru ruby-tzinfo-1.2.6/checksums.yaml.gz.sig ruby-tzinfo-2.0.4/checksums.yaml.gz.sig --- ruby-tzinfo-1.2.6/checksums.yaml.gz.sig 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/checksums.yaml.gz.sig 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1 @@ +"/ޗS{2Eq&[ABE/V%:[ʏ%D_ q!]O6*P1j}b5$0Ξc1 fvUd=(AGNȖJ4W{Dl1mN?$,=rFŘ29$ǒ'(u*~2}^aeۆW}w\wy=}`~%4*2roo.D+O \ No newline at end of file Binary files /tmp/tmp1__nrbj3/6KS5sjn70P/ruby-tzinfo-1.2.6/data.tar.gz.sig and /tmp/tmp1__nrbj3/8QcohKxo2Z/ruby-tzinfo-2.0.4/data.tar.gz.sig differ diff -Nru ruby-tzinfo-1.2.6/debian/changelog ruby-tzinfo-2.0.4/debian/changelog --- ruby-tzinfo-1.2.6/debian/changelog 2020-02-07 11:08:12.000000000 +0000 +++ ruby-tzinfo-2.0.4/debian/changelog 2021-12-13 19:47:05.000000000 +0000 @@ -1,3 +1,48 @@ +ruby-tzinfo (2.0.4-3ubuntu1~ppa1) jammy; urgency=medium + + * d/control: remove Breaks: ruby-activesupport (<< 2:6.1~). + + -- Lucas Kanashiro Mon, 13 Dec 2021 16:47:05 -0300 + +ruby-tzinfo (2.0.4-3) unstable; urgency=medium + + * Team upload + * Breaks ruby-activesupport 6.0.x and earlier + + -- Cédric Boutillier Sun, 21 Nov 2021 09:55:20 +0100 + +ruby-tzinfo (2.0.4-2) unstable; urgency=medium + + * Team upload + + [ Debian Janitor ] + * Update watch file format version to 4. + * Bump debhelper from old 12 to 13. + + [ Cédric Boutillier ] + * Update packaging files with dh-make-ruby -w + * Upload to unstable + + Use gem install layout + + Add upstream metadata + + -- Cédric Boutillier Fri, 19 Nov 2021 14:56:45 +0100 + +ruby-tzinfo (2.0.4-1) experimental; urgency=medium + + * Team upload + + [ Debian Janitor ] + * Trim trailing whitespace. + + [ Cédric Boutillier ] + * Update team name + * Add .gitattributes to keep unwanted files out of the source package + + [ Sruthi Chandran ] + * New upstream version 2.0.4 + + -- Sruthi Chandran Wed, 28 Jul 2021 02:54:42 +0530 + ruby-tzinfo (1.2.6-1) unstable; urgency=medium * Team upload @@ -177,4 +222,3 @@ * Initial release (Closes: #499907) -- Roberto C. Sanchez Tue, 23 Sep 2008 11:29:09 -0400 - diff -Nru ruby-tzinfo-1.2.6/debian/control ruby-tzinfo-2.0.4/debian/control --- ruby-tzinfo-1.2.6/debian/control 2020-02-07 11:08:12.000000000 +0000 +++ ruby-tzinfo-2.0.4/debian/control 2021-12-13 19:47:05.000000000 +0000 @@ -1,29 +1,26 @@ Source: ruby-tzinfo Section: ruby Priority: optional -Maintainer: Debian Ruby Extras Maintainers +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Debian Ruby Team Uploaders: Hleb Valoshka <375gnu@gmail.com> -Build-Depends: debhelper-compat (= 12), - gem2deb, - ruby-minitest (>= 5.0~), - ruby-thread-safe (>= 0.1~), +Build-Depends: debhelper-compat (= 13), + gem2deb (>= 1), + ruby-concurrent (>= 1.0), tzdata, - ruby-concurrent -Standards-Version: 4.5.0 +Standards-Version: 4.6.0 Vcs-Git: https://salsa.debian.org/ruby-team/ruby-tzinfo.git Vcs-Browser: https://salsa.debian.org/ruby-team/ruby-tzinfo -Homepage: https://tzinfo.github.io/ +Homepage: https://tzinfo.github.io Testsuite: autopkgtest-pkg-ruby XS-Ruby-Versions: all Rules-Requires-Root: no - Package: ruby-tzinfo Architecture: all XB-Ruby-Versions: ${ruby:Versions} -Depends: ruby-thread-safe (>= 0.1~), - tzdata, - ${misc:Depends}, +Depends: ${misc:Depends}, + ${ruby:Depends}, ${shlibs:Depends} Description: Daylight-savings aware timezone library TZInfo is a Ruby library that uses the standard tz (Olson) database diff -Nru ruby-tzinfo-1.2.6/debian/rules ruby-tzinfo-2.0.4/debian/rules --- ruby-tzinfo-1.2.6/debian/rules 2020-02-07 11:08:12.000000000 +0000 +++ ruby-tzinfo-2.0.4/debian/rules 2021-11-21 08:55:20.000000000 +0000 @@ -1,15 +1,7 @@ #!/usr/bin/make -f -#export DH_VERBOSE=1 -# -# Uncomment to ignore all test failures (but the tests will run anyway) -#export DH_RUBY_IGNORE_TESTS=all -# -# Uncomment to ignore some test failures (but the tests will run anyway). -# Valid values: -#export DH_RUBY_IGNORE_TESTS=ruby1.8 ruby1.9.1 require-rubygems -# -# If you need to specify the .gemspec (eg there is more than one) -#export DH_RUBY_GEMSPEC=gem.gemspec + +export GEM2DEB_TEST_RUNNER = --check-dependencies +export DH_RUBY = --gem-install %: dh $@ --buildsystem=ruby --with ruby diff -Nru ruby-tzinfo-1.2.6/debian/salsa-ci.yml ruby-tzinfo-2.0.4/debian/salsa-ci.yml --- ruby-tzinfo-1.2.6/debian/salsa-ci.yml 2020-02-07 11:08:12.000000000 +0000 +++ ruby-tzinfo-2.0.4/debian/salsa-ci.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ ---- -include: - - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml - - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml diff -Nru ruby-tzinfo-1.2.6/debian/upstream/metadata ruby-tzinfo-2.0.4/debian/upstream/metadata --- ruby-tzinfo-1.2.6/debian/upstream/metadata 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/debian/upstream/metadata 2021-11-21 08:55:20.000000000 +0000 @@ -0,0 +1,7 @@ +--- +Archive: GitHub +Bug-Database: https://tzinfo.github.io/issues +Bug-Submit: https://tzinfo.github.io/issues/new +Changelog: https://tzinfo.github.io/releases +Repository: https://tzinfo.github.io.git +Repository-Browse: https://tzinfo.github.io diff -Nru ruby-tzinfo-1.2.6/debian/watch ruby-tzinfo-2.0.4/debian/watch --- ruby-tzinfo-1.2.6/debian/watch 2020-02-07 11:08:12.000000000 +0000 +++ ruby-tzinfo-2.0.4/debian/watch 2021-11-21 08:55:20.000000000 +0000 @@ -1,2 +1,7 @@ -version=3 -https://pkg-ruby-extras.alioth.debian.org/cgi-bin/gemwatch/tzinfo .*/tzinfo-(.*).tar.gz +version=4 +https://gemwatch.debian.net/tzinfo .*/tzinfo-(.*).tar.gz + +# Use the regex below for github-based sources +# opts=uversionmangle=s/[_.+-]?(rc|pre|dev|beta|alpha|b|a)/~$1/i,\ +# filenamemangle=s%(?:.+/)?v?@ANY_VERSION@(@ARCHIVE_EXT@)%@PACKAGE@-$1$2% \ +# https://github.com///releases .*/v?@ANY_VERSION@@ARCHIVE_EXT@ diff -Nru ruby-tzinfo-1.2.6/Gemfile ruby-tzinfo-2.0.4/Gemfile --- ruby-tzinfo-1.2.6/Gemfile 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/Gemfile 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -source "https://rubygems.org" - -gemspec - -group :test do - gem 'rake', ['>= 10.5', '< 14'] - - # Exclude Minitest v5.12.0. It is only compatible with Ruby >= 1.9.3, but does - # not specify a minimum Ruby version. - gem 'minitest', ['~> 5.11', '!= 5.12.0'] -end diff -Nru ruby-tzinfo-1.2.6/gem-public_cert.pem ruby-tzinfo-2.0.4/gem-public_cert.pem --- ruby-tzinfo-1.2.6/gem-public_cert.pem 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/gem-public_cert.pem 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDPDCCAiSgAwIBAgIBATANBgkqhkiG9w0BAQsFADAkMSIwIAYDVQQDDBlwaGls -LnJvc3MvREM9Z21haWwvREM9Y29tMB4XDTE5MTIyNDE0NTU0N1oXDTM5MTIyNDE0 -NTU0N1owJDEiMCAGA1UEAwwZcGhpbC5yb3NzL0RDPWdtYWlsL0RDPWNvbTCCASIw -DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJGcwfqn4ZsmPl0b1Lt9dCzExrE5 -EeP/CRQjBdGHkF+mSpi69XysxdwLdfg5SPr9LfxthUug4nNFd5fDCiXM8hYe9jQD -TmkIQKNBh4fFpGngn9gyy+SumCXi6b5L6d/aMc59NAOM6LJ88TOdH1648dh5rq3C -ULq82n3gg4+u0HHGjRPuR/pnCFQCZbANYdX+UBWd0qkOJn/EreNKROmEeHr/xKuh -2/GlKFKt9KLcW3hwBB4fHHVYUzRau7D1m9KbEERdg//qNDC4B7fD2BFJuPbM5S7J -41VwDAh1O8B/Qpg0f+S83K4Kodw4MiPGsug55UkNtd3mGR/zZJ9WM03DSwkCAwEA -AaN5MHcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFA+Z8zvfzBuA -esoHIfz7+jxfUOcfMB4GA1UdEQQXMBWBE3BoaWwucm9zc0BnbWFpbC5jb20wHgYD -VR0SBBcwFYETcGhpbC5yb3NzQGdtYWlsLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEA -J80xgZ3gGdQVA8N+8NJANU5HLuZIU9jOaAlziU9ImoTgPiOHKGZC4as1TwT4kBt1 -Qcnu7YSANYRrxP5tpOHsWPF/MQYgerAFCZS5+PzOTudwZ+7OsMW4/EMHy6aCVHEd -c7HzQRC4mSrDRpWxzyBnZ5nX5OAmIkKA8NgeKybT/4Ku6iFPPUQwlyxQaO+Wlxdo -FqHwpjRyoiVSpe4RUTNK3d3qesWPYi7Lxn6k6ZZeEdvG6ya33AXktE3jmmF+jPR1 -J3Zn/kSTjTekiaspyGbczC3PUaeJNxr+yCvR4sk71Xmk/GaKKGOHedJ1uj/LAXrA -MR0mpl7b8zCg0PFC1J73uw== ------END CERTIFICATE----- diff -Nru ruby-tzinfo-1.2.6/.gitignore ruby-tzinfo-2.0.4/.gitignore --- ruby-tzinfo-1.2.6/.gitignore 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/.gitignore 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -doc -Gemfile.lock -pkg -.rbx -.yardoc diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/annual_rules.rb ruby-tzinfo-2.0.4/lib/tzinfo/annual_rules.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/annual_rules.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/annual_rules.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,71 @@ +# encoding: UTF-8 +# frozen_string_literal: true + +module TZInfo + # A set of rules that define when transitions occur in time zones with + # annually occurring daylight savings time. + # + # @private + class AnnualRules #:nodoc: + # @return [TimezoneOffset] the standard offset that applies when daylight + # savings time is not in force. + attr_reader :std_offset + + # @return [TimezoneOffset] the offset that applies when daylight savings + # time is in force. + attr_reader :dst_offset + + # @return [TransitionRule] the rule that determines when daylight savings + # time starts. + attr_reader :dst_start_rule + + # @return [TransitionRule] the rule that determines when daylight savings + # time ends. + attr_reader :dst_end_rule + + # Initializes a new {AnnualRules} instance. + # + # @param std_offset [TimezoneOffset] the standard offset that applies when + # daylight savings time is not in force. + # @param dst_offset [TimezoneOffset] the offset that applies when daylight + # savings time is in force. + # @param dst_start_rule [TransitionRule] the rule that determines when + # daylight savings time starts. + # @param dst_end_rule [TransitionRule] the rule that determines when daylight + # savings time ends. + def initialize(std_offset, dst_offset, dst_start_rule, dst_end_rule) + @std_offset = std_offset + @dst_offset = dst_offset + @dst_start_rule = dst_start_rule + @dst_end_rule = dst_end_rule + end + + # Returns the transitions between standard and daylight savings time for a + # given year. The results are ordered by time of occurrence (earliest to + # latest). + # + # @param year [Integer] the year to calculate transitions for. + # @return [Array] the transitions for the year. + def transitions(year) + start_dst = apply_rule(@dst_start_rule, @std_offset, @dst_offset, year) + end_dst = apply_rule(@dst_end_rule, @dst_offset, @std_offset, year) + + end_dst.timestamp_value < start_dst.timestamp_value ? [end_dst, start_dst] : [start_dst, end_dst] + end + + private + + # Applies a given rule between offsets on a year. + # + # @param rule [TransitionRule] the rule to apply. + # @param from_offset [TimezoneOffset] the offset the rule transitions from. + # @param to_offset [TimezoneOffset] the offset the rule transitions to. + # @param year [Integer] the year when the transition occurs. + # @return [TimezoneTransition] the transition determined by the rule. + def apply_rule(rule, from_offset, to_offset, year) + at = rule.at(from_offset, year) + TimezoneTransition.new(to_offset, from_offset, at.value) + end + end + private_constant :AnnualRules +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/country_index_definition.rb ruby-tzinfo-2.0.4/lib/tzinfo/country_index_definition.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/country_index_definition.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/country_index_definition.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -module TZInfo - # The country index file includes CountryIndexDefinition which provides - # a country method used to define each country in the index. - # - # @private - module CountryIndexDefinition #:nodoc: - def self.append_features(base) - super - base.extend(ClassMethods) - base.instance_eval { @countries = {} } - end - - # Class methods for inclusion. - # - # @private - module ClassMethods #:nodoc: - # Defines a country with an ISO 3166 country code, name and block. The - # block will be evaluated to obtain all the timezones for the country. - # Calls Country.country_defined with the definition of each country. - def country(code, name, &block) - @countries[code] = RubyCountryInfo.new(code, name, &block) - end - - # Returns a frozen hash of all the countries that have been defined in - # the index. - def countries - @countries.freeze - end - end - end -end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/country_info.rb ruby-tzinfo-2.0.4/lib/tzinfo/country_info.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/country_info.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/country_info.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -module TZInfo - # Represents a country and references to its timezones as returned by a - # DataSource. - class CountryInfo - # The ISO 3166 country code. - attr_reader :code - - # The name of the country. - attr_reader :name - - # Constructs a new CountryInfo with an ISO 3166 country code and name - def initialize(code, name) - @code = code - @name = name - end - - # Returns internal object state as a programmer-readable string. - def inspect - "#<#{self.class}: #@code>" - end - - # Returns a frozen array of all the zone identifiers for the country. - # The identifiers are ordered by importance according to the DataSource. - def zone_identifiers - raise_not_implemented('zone_identifiers') - end - - # Returns a frozen array of all the timezones for the for the country as - # CountryTimezone instances. - # - # The timezones are ordered by importance according to the DataSource. - def zones - raise_not_implemented('zones') - end - - private - - def raise_not_implemented(method_name) - raise NotImplementedError, "Subclasses must override #{method_name}" - end - end -end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/country.rb ruby-tzinfo-2.0.4/lib/tzinfo/country.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/country.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/country.rb 2020-12-30 06:49:15.000000000 +0000 @@ -1,104 +1,102 @@ -require 'thread_safe' +# encoding: UTF-8 +# frozen_string_literal: true module TZInfo - # Raised by Country#get if the code given is not valid. + # {InvalidCountryCode} is raised by {Country#get} if the code given is not a + # valid ISO 3166-1 alpha-2 code. class InvalidCountryCode < StandardError end - - # The Country class represents an ISO 3166-1 country. It can be used to - # obtain a list of Timezones for a country. For example: + + # The {Country} class represents an ISO 3166-1 country. It can be used to + # obtain a list of time zones observed by a country. For example: # - # us = Country.get('US') - # us.zone_identifiers - # us.zones - # us.zone_info + # united_states = Country.get('US') + # united_states.zone_identifiers + # united_states.zones + # united_states.zone_info # - # The Country class is thread-safe. It is safe to use class and instance - # methods of Country in concurrently executing threads. Instances of Country - # can be shared across thread boundaries. + # The {Country} class is thread-safe. It is safe to use class and instance + # methods of {Country} in concurrently executing threads. Instances of + # {Country} can be shared across thread boundaries. # - # Country information available through TZInfo is intended as an aid for - # users, to help them select time zone data appropriate for their practical - # needs. It is not intended to take or endorse any position on legal or + # Country information available through TZInfo is intended as an aid for + # users, to help them select time zone data appropriate for their practical + # needs. It is not intended to take or endorse any position on legal or # territorial claims. class Country include Comparable - - # Defined countries. - # - # @!visibility private - @@countries = nil - - # Whether the countries index has been loaded yet. - # - # @!visibility private - @@index_loaded = false - - # Gets a Country by its ISO 3166-1 alpha-2 code. Raises an - # InvalidCountryCode exception if it couldn't be found. - def self.get(identifier) - instance = @@countries[identifier] - - unless instance - # Thread-safety: It is possible that multiple equivalent Country - # instances could be created here in concurrently executing threads. - # The consequences of this are that the data may be loaded more than - # once (depending on the data source) and memoized calculations could - # be discarded. The performance benefit of ensuring that only a single - # instance is created is unlikely to be worth the overhead of only - # allowing one Country to be loaded at a time. - info = data_source.load_country_info(identifier) - instance = Country.new(info) - @@countries[identifier] = instance - end - - instance - end - - # If identifier is a CountryInfo object, initializes the Country instance, - # otherwise calls get(identifier). - def self.new(identifier) - if identifier.kind_of?(CountryInfo) - instance = super() - instance.send :setup, identifier - instance - else - get(identifier) + + class << self + # Gets a {Country} by its ISO 3166-1 alpha-2 code. + # + # The {Country.all_codes} method can be used to obtain a list of valid ISO + # 3166-1 alpha-2 codes. + # + # @param code [String] An ISO 3166-1 alpha-2 code. + # @return [Country] a {Country} instance representing the ISO-3166-1 + # country identified by the `code` parameter. + # @raise [InvalidCountryCode] If {code} is not a valid ISO 3166-1 alpha-2 + # code it couldn't be found. + def get(code) + Country.new(data_source.get_country_info(code)) + end + + # @return [Array] an `Array` containing all the valid ISO 3166-1 + # alpha-2 country codes. + def all_codes + data_source.country_codes + end + + # @return [Array] an `Array` containing one {Country} instance + # for each defined country. + def all + data_source.country_codes.collect {|code| get(code)} + end + + private + + # @return [DataSource] the current DataSource. + def data_source + DataSource.get end end - - # Returns an Array of all the valid country codes. - def self.all_codes - data_source.country_codes - end - - # Returns an Array of all the defined Countries. - def self.all - data_source.country_codes.collect {|code| get(code)} - end - - # The ISO 3166-1 alpha-2 country code. + + # Initializes a new {Country} based upon a {DataSources::CountryInfo} + # instance. + # + # {Country} instances should not normally be constructed directly. Use + # the {Country.get} method to obtain instances instead. + # + # @param info [DataSources::CountryInfo] the data to base the new {Country} + # instance upon. + def initialize(info) + @info = info + end + + # @return [String] the ISO 3166-1 alpha-2 country code. def code @info.code end - - # The name of the country. + + # @return [String] the name of the country. def name @info.name end - - # Alias for name. + + # @return [String] a `String` representation of this {Country} (the name of + # the country). def to_s name end - - # Returns internal object state as a programmer-readable string. + + # @return [String] the internal object state as a programmer-readable + # `String`. def inspect "#<#{self.class}: #{@info.code}>" end - - # Returns a frozen array of all the zone identifiers for the country. These - # are in an order that + + # Returns an `Array` containing the identifier for each time zone observed + # by the country. These are in an order that # # 1. makes some geographical sense, and # 2. puts the most populous zones first, where that does not contradict 1. @@ -107,90 +105,104 @@ # country. This will occur if the zone covers multiple countries. Any zones # referring to a city or region in a different country will be listed after # those relating to this country. + # + # @return [Array] an `Array` containing the identifier for each time + # zone observed by the country def zone_identifiers - @info.zone_identifiers + zone_info.map(&:identifier) end alias zone_names zone_identifiers - - # An array of all the Timezones for this country. Returns TimezoneProxy - # objects to avoid the overhead of loading Timezone definitions until - # a conversion is actually required. The Timezones are returned in an order - # that + + # Returns An `Array` containing a {Timezone} instance for each time zone + # observed by the country. These are in an order that # # 1. makes some geographical sense, and # 2. puts the most populous zones first, where that does not contradict 1. # - # Identifiers of the zones returned may refer to cities and regions outside - # of the country. This will occur if the zone covers multiple countries. Any - # zones referring to a city or region in a different country will be listed - # after those relating to this country. + # The identifiers of the time zones returned may refer to cities and regions + # outside of the country. This will occur if the time zone covers multiple + # countries. Any zones referring to a city or region in a different country + # will be listed after those relating to this country. + # + # The results are actually instances of {TimezoneProxy} in order to defer + # loading of the time zone transition data until it is first needed. + # + # @return [Array] an `Array` containing a {Timezone} instance for + # each time zone observed by the country. def zones - zone_identifiers.collect {|id| - Timezone.get_proxy(id) - } - end - - # Returns a frozen array of all the timezones for the for the country as - # CountryTimezone instances (containing extra information about each zone). - # These are in an order that + zone_info.map(&:timezone) + end + + # Returns a frozen `Array` containing a {CountryTimezone} instance for each + # time zone observed by the country. These are in an order that # # 1. makes some geographical sense, and # 2. puts the most populous zones first, where that does not contradict 1. # - # Identifiers and descriptions of the zones returned may refer to cities and - # regions outside of the country. This will occur if the zone covers - # multiple countries. Any zones referring to a city or region in a different - # country will be listed after those relating to this country. + # The {CountryTimezone} instances can be used to obtain the location and + # descriptions of the observed time zones. + # + # Identifiers and descriptions of the time zones returned may refer to + # cities and regions outside of the country. This will occur if the time + # zone covers multiple countries. Any zones referring to a city or region in + # a different country will be listed after those relating to this country. + # + # @return [Array] a frozen `Array` containing a + # {CountryTimezone} instance for each time zone observed by the country. def zone_info @info.zones end - - # Compare two Countries based on their code. Returns -1 if c is less - # than self, 0 if c is equal to self and +1 if c is greater than self. + + # Compares this {Country} with another based on their {code}. # - # Returns nil if c is not comparable with Country instances. + # @param c [Object] an `Object` to compare this {Country} with. + # @return [Integer] -1 if `c` is less than `self`, 0 if `c` is equal to + # `self` and +1 if `c` is greater than `self`, or `nil` if `c` is not an + # instance of {Country}. def <=>(c) return nil unless c.is_a?(Country) code <=> c.code end - - # Returns true if and only if the code of c is equal to the code of this - # Country. + + # @param c [Object] an `Object` to compare this {Country} with. + # @return [Boolean] `true` if `c` is an instance of {Country} and has the + # same code as `self`, otherwise `false`. def eql?(c) self == c end - - # Returns a hash value for this Country. + + # @return [Integer] a hash based on the {code}. def hash code.hash end - - # Dumps this Country for marshalling. + + # Matches `regexp` against the {code} of this {Country}. + # + # @param regexp [Regexp] a `Regexp` to match against the {code} of + # this {Country}. + # @return [Integer] the position the match starts, or `nil` if there is no + # match. + def =~(regexp) + regexp =~ code + end + + # Returns a serialized representation of this {Country}. This method is + # called when using `Marshal.dump` with an instance of {Country}. + # + # @param limit [Integer] the maximum depth to dump - ignored. + # @return [String] a serialized representation of this {Country}. def _dump(limit) code end - - # Loads a marshalled Country. + + # Loads a {Country} from the serialized representation returned by {_dump}. + # This is method is called when using `Marshal.load` or `Marshal.restore` + # to restore a serialized {Country}. + # + # @param data [String] a serialized representation of a {Country}. + # @return [Country] the result of converting `data` back into a {Country}. def self._load(data) Country.get(data) end - - private - # Called by Country.new to initialize a new Country instance. The info - # parameter is a CountryInfo that defines the country. - def setup(info) - @info = info - end - - # Initializes @@countries. - def self.init_countries - @@countries = ThreadSafe::Cache.new - end - init_countries - - # Returns the current DataSource - def self.data_source - DataSource.get - end - end + end end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/country_timezone.rb ruby-tzinfo-2.0.4/lib/tzinfo/country_timezone.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/country_timezone.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/country_timezone.rb 2020-12-30 06:49:15.000000000 +0000 @@ -1,135 +1,93 @@ +# encoding: UTF-8 + module TZInfo - # A Timezone within a Country. This contains extra information about the - # Timezone that is specific to the Country (a Timezone could be used by - # multiple countries). + # Information about a time zone used by a {Country}. class CountryTimezone - # The zone identifier. - attr_reader :identifier - - # A description of this timezone in relation to the country, e.g. - # "Eastern Time". This is usually nil for countries having only a single - # Timezone. + # @return [String] the identifier of the {Timezone} being described. + attr_reader :identifier + + # The latitude of this time zone in degrees. Positive numbers are degrees + # north and negative numbers are degrees south. + # + # Note that depending on the data source, the position given by {#latitude} + # and {#longitude} may not be within the country. + # + # @return [Rational] the latitude in degrees. + attr_reader :latitude + + # The longitude of this time zone in degrees. Positive numbers are degrees + # east and negative numbers are degrees west. + # + # Note that depending on the data source, the position given by {#latitude} + # and {#longitude} may not be within the country. + # + # @return [Rational] the longitude in degrees. + attr_reader :longitude + + # A description of this time zone in relation to the country, e.g. "Eastern + # Time". This is usually `nil` for countries that have a single time zone. + # + # @return [String] an optional description of the time zone. attr_reader :description - - class << self - # Creates a new CountryTimezone with a timezone identifier, latitude, - # longitude and description. The latitude and longitude are specified as - # rationals - a numerator and denominator. For performance reasons, the - # numerators and denominators must be specified in their lowest form. - # - # For use internally within TZInfo. - # - # @!visibility private - alias :new! :new - - # Creates a new CountryTimezone with a timezone identifier, latitude, - # longitude and description. The latitude and longitude must be specified - # as instances of Rational. - # - # CountryTimezone instances should normally only be constructed when - # creating new DataSource implementations. - def new(identifier, latitude, longitude, description = nil) - super(identifier, latitude, nil, longitude, nil, description) - end - end - - # Creates a new CountryTimezone with a timezone identifier, latitude, - # longitude and description. The latitude and longitude are specified as - # rationals - a numerator and denominator. For performance reasons, the - # numerators and denominators must be specified in their lowest form. - # - # @!visibility private - def initialize(identifier, latitude_numerator, latitude_denominator, - longitude_numerator, longitude_denominator, description = nil) #:nodoc: - @identifier = identifier - - if latitude_numerator.kind_of?(Rational) - @latitude = latitude_numerator - else - @latitude = nil - @latitude_numerator = latitude_numerator - @latitude_denominator = latitude_denominator - end - - if longitude_numerator.kind_of?(Rational) - @longitude = longitude_numerator - else - @longitude = nil - @longitude_numerator = longitude_numerator - @longitude_denominator = longitude_denominator - end - - @description = description + + # Creates a new {CountryTimezone}. + # + # The passed in identifier and description instances will be frozen. + # + # {CountryTimezone} instances should normally only be constructed + # by implementations of {DataSource}. + # + # @param identifier [String] the {Timezone} identifier. + # @param latitude [Rational] the latitude of the time zone. + # @param longitude [Rational] the longitude of the time zone. + # @param description [String] an optional description of the time zone. + def initialize(identifier, latitude, longitude, description = nil) + @identifier = identifier.freeze + @latitude = latitude + @longitude = longitude + @description = description && description.freeze end - - # The Timezone (actually a TimezoneProxy for performance reasons). + + # Returns the associated {Timezone}. + # + # The result is actually an instance of {TimezoneProxy} in order to defer + # loading of the time zone transition data until it is first needed. + # + # @return [Timezone] the associated {Timezone}. def timezone Timezone.get_proxy(@identifier) end - - # if description is not nil, this method returns description; otherwise it - # returns timezone.friendly_identifier(true). + + # @return [String] the {description} if present, otherwise a human-readable + # representation of the identifier (using {Timezone#friendly_identifier}). def description_or_friendly_identifier description || timezone.friendly_identifier(true) end - - # The latitude of this timezone in degrees as a Rational. - def latitude - # Thread-safety: It is possible that the value of @latitude may be - # calculated multiple times in concurrently executing threads. It is not - # worth the overhead of locking to ensure that @latitude is only - # calculated once. - unless @latitude - result = RubyCoreSupport.rational_new!(@latitude_numerator, @latitude_denominator) - return result if frozen? - @latitude = result - end - - @latitude - end - - # The longitude of this timezone in degrees as a Rational. - def longitude - # Thread-safety: It is possible that the value of @longitude may be - # calculated multiple times in concurrently executing threads. It is not - # worth the overhead of locking to ensure that @longitude is only - # calculated once. - unless @longitude - result = RubyCoreSupport.rational_new!(@longitude_numerator, @longitude_denominator) - return result if frozen? - @longitude = result - end - - @longitude - end - - # Returns true if and only if the given CountryTimezone is equal to the - # current CountryTimezone (has the same identifer, latitude, longitude - # and description). + + # Tests if the given object is equal to the current instance (has the same + # identifier, latitude, longitude and description). + # + # @param ct [Object] the object to be compared. + # @return [TrueClass] `true` if `ct` is equal to the current instance. def ==(ct) ct.kind_of?(CountryTimezone) && identifier == ct.identifier && latitude == ct.latitude && - longitude == ct.longitude && description == ct.description + longitude == ct.longitude && description == ct.description end - - # Returns true if and only if the given CountryTimezone is equal to the - # current CountryTimezone (has the same identifer, latitude, longitude - # and description). + + # Tests if the given object is equal to the current instance (has the same + # identifier, latitude, longitude and description). + # + # @param ct [Object] the object to be compared. + # @return [Boolean] `true` if `ct` is equal to the current instance. def eql?(ct) self == ct end - - # Returns a hash of this CountryTimezone. + + # @return [Integer] a hash based on the {identifier}, {latitude}, + # {longitude} and {description}. def hash - @identifier.hash ^ - (@latitude ? @latitude.numerator.hash ^ @latitude.denominator.hash : @latitude_numerator.hash ^ @latitude_denominator.hash) ^ - (@longitude ? @longitude.numerator.hash ^ @longitude.denominator.hash : @longitude_numerator.hash ^ @longitude_denominator.hash) ^ - @description.hash - end - - # Returns internal object state as a programmer-readable string. - def inspect - "#<#{self.class}: #@identifier>" + [@identifier, @latitude, @longitude, @description].hash end end end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/data_source.rb ruby-tzinfo-2.0.4/lib/tzinfo/data_source.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/data_source.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/data_source.rb 2020-12-30 06:49:15.000000000 +0000 @@ -1,190 +1,435 @@ +# encoding: UTF-8 +# frozen_string_literal: true + +require 'concurrent' require 'thread' module TZInfo - # InvalidDataSource is raised if the DataSource is used doesn't implement one - # of the required methods. + # {InvalidDataSource} is raised if the selected {DataSource} doesn't implement + # one of the required methods. class InvalidDataSource < StandardError end - - # DataSourceNotFound is raised if no data source could be found (i.e. - # if 'tzinfo/data' cannot be found on the load path and no valid zoneinfo + + # {DataSourceNotFound} is raised if no data source could be found (i.e. if + # `'tzinfo/data'` cannot be found on the load path and no valid zoneinfo # directory can be found on the system). class DataSourceNotFound < StandardError end - # The base class for data sources of timezone and country data. + # TZInfo can be used with different data sources for time zone and country + # data. Each source of data is implemented as a subclass of {DataSource}. + # + # To choose a data source and override the default selection, use the + # {DataSource.set} method. # - # Use DataSource.set to change the data source being used. + # @abstract To create a custom data source, create a subclass of {DataSource} + # and implement the {load_timezone_info}, {data_timezone_identifiers}, + # {linked_timezone_identifiers}, {load_country_info} and {country_codes} + # methods. class DataSource # The currently selected data source. + # + # @private @@instance = nil - - # Mutex used to ensure the default data source is only created once. + + # A `Mutex` used to ensure the default data source is only created once. + # + # @private @@default_mutex = Mutex.new - - # Returns the currently selected DataSource instance. - def self.get - # If a DataSource hasn't been manually set when the first request is - # made to obtain a DataSource, then a Default data source is created. - - # This is done at the first request rather than when TZInfo is loaded to - # avoid unnecessary (or in some cases potentially harmful) attempts to - # find a suitable DataSource. - - # A Mutex is used to ensure that only a single default instance is - # created (having two different DataSources in use simultaneously could - # cause unexpected results). - - unless @@instance - @@default_mutex.synchronize do - set(create_default_data_source) unless @@instance + + class << self + # @return [DataSource] the currently selected source of data. + def get + # If a DataSource hasn't been manually set when the first request is + # made to obtain a DataSource, then a default data source is created. + # + # This is done at the first request rather than when TZInfo is loaded to + # avoid unnecessary attempts to find a suitable DataSource. + # + # A `Mutex` is used to ensure that only a single default instance is + # created (this avoiding the possibility of retaining two copies of the + # same data in memory). + + unless @@instance + @@default_mutex.synchronize do + set(create_default_data_source) unless @@instance + end end - end - - @@instance - end - - # Sets the currently selected data source for Timezone and Country data. - # - # This should usually be set to one of the two standard data source types: - # - # * +:ruby+ - read data from the Ruby modules included in the TZInfo::Data - # library (tzinfo-data gem). - # * +:zoneinfo+ - read data from the zoneinfo files included with most - # Unix-like operating sytems (e.g. in /usr/share/zoneinfo). - # - # To set TZInfo to use one of the standard data source types, call - # \TZInfo::DataSource.set in one of the following ways: - # - # TZInfo::DataSource.set(:ruby) - # TZInfo::DataSource.set(:zoneinfo) - # TZInfo::DataSource.set(:zoneinfo, zoneinfo_dir) - # TZInfo::DataSource.set(:zoneinfo, zoneinfo_dir, iso3166_tab_file) - # - # \DataSource.set(:zoneinfo) will automatically search for the zoneinfo - # directory by checking the paths specified in - # ZoneinfoDataSource.search_paths. ZoneinfoDirectoryNotFound will be raised - # if no valid zoneinfo directory could be found. - # - # \DataSource.set(:zoneinfo, zoneinfo_dir) uses the specified zoneinfo - # directory as the data source. If the directory is not a valid zoneinfo - # directory, an InvalidZoneinfoDirectory exception will be raised. - # - # \DataSource.set(:zoneinfo, zoneinfo_dir, iso3166_tab_file) uses the - # specified zoneinfo directory as the data source, but loads the iso3166.tab - # file from an alternate path. If the directory is not a valid zoneinfo - # directory, an InvalidZoneinfoDirectory exception will be raised. - # - # Custom data sources can be created by subclassing TZInfo::DataSource and - # implementing the following methods: - # - # * \load_timezone_info - # * \timezone_identifiers - # * \data_timezone_identifiers - # * \linked_timezone_identifiers - # * \load_country_info - # * \country_codes - # - # To have TZInfo use the custom data source, call \DataSource.set - # as follows: - # - # TZInfo::DataSource.set(CustomDataSource.new) - # - # To avoid inconsistent data, \DataSource.set should be called before - # accessing any Timezone or Country data. - # - # If \DataSource.set is not called, TZInfo will by default use TZInfo::Data - # as the data source. If TZInfo::Data is not available (i.e. if require - # 'tzinfo/data' fails), then TZInfo will search for a zoneinfo directory - # instead (using the search path specified by - # TZInfo::ZoneinfoDataSource::DEFAULT_SEARCH_PATH). - def self.set(data_source_or_type, *args) - if data_source_or_type.kind_of?(DataSource) - @@instance = data_source_or_type - elsif data_source_or_type == :ruby - @@instance = RubyDataSource.new - elsif data_source_or_type == :zoneinfo - @@instance = ZoneinfoDataSource.new(*args) - else - raise ArgumentError, 'data_source_or_type must be a DataSource instance or a data source type (:ruby)' - end - end - - # Returns a TimezoneInfo instance for a given identifier. The TimezoneInfo - # instance should derive from either DataTimzoneInfo for timezones that - # define their own data or LinkedTimezoneInfo for links or aliases to - # other timezones. - # - # Raises InvalidTimezoneIdentifier if the timezone is not found or the - # identifier is invalid. - def load_timezone_info(identifier) - raise_invalid_data_source('load_timezone_info') + + @@instance + end + + # Sets the currently selected data source for time zone and country data. + # + # This should usually be set to one of the two standard data source types: + # + # * `:ruby` - read data from the Ruby modules included in the TZInfo::Data + # library (tzinfo-data gem). + # * `:zoneinfo` - read data from the zoneinfo files included with most + # Unix-like operating systems (e.g. in /usr/share/zoneinfo). + # + # To set TZInfo to use one of the standard data source types, call + # `TZInfo::DataSource.set`` in one of the following ways: + # + # TZInfo::DataSource.set(:ruby) + # TZInfo::DataSource.set(:zoneinfo) + # TZInfo::DataSource.set(:zoneinfo, zoneinfo_dir) + # TZInfo::DataSource.set(:zoneinfo, zoneinfo_dir, iso3166_tab_file) + # + # `DataSource.set(:zoneinfo)` will automatically search for the zoneinfo + # directory by checking the paths specified in + # {DataSources::ZoneinfoDataSource.search_path}. + # {DataSources::ZoneinfoDirectoryNotFound} will be raised if no valid + # zoneinfo directory could be found. + # + # `DataSource.set(:zoneinfo, zoneinfo_dir)` uses the specified + # `zoneinfo_dir` directory as the data source. If the directory is not a + # valid zoneinfo directory, a {DataSources::InvalidZoneinfoDirectory} + # exception will be raised. + # + # `DataSource.set(:zoneinfo, zoneinfo_dir, iso3166_tab_file)` uses the + # specified `zoneinfo_dir` directory as the data source, but loads the + # `iso3166.tab` file from the path given by `iso3166_tab_file`. If the + # directory is not a valid zoneinfo directory, a + # {DataSources::InvalidZoneinfoDirectory} exception will be raised. + # + # Custom data sources can be created by subclassing TZInfo::DataSource and + # implementing the following methods: + # + # * {load_timezone_info} + # * {data_timezone_identifiers} + # * {linked_timezone_identifiers} + # * {load_country_info} + # * {country_codes} + # + # To have TZInfo use the custom data source, call {DataSource.set}, + # passing an instance of the custom data source implementation as follows: + # + # TZInfo::DataSource.set(CustomDataSource.new) + # + # Calling {DataSource.set} will only affect instances of {Timezone} and + # {Country} obtained with {Timezone.get} and {Country.get} subsequent to + # the {DataSource.set} call. Existing {Timezone} and {Country} instances + # will be unaffected. + # + # If {DataSource.set} is not called, TZInfo will by default attempt to use + # TZInfo::Data as the data source. If TZInfo::Data is not available (i.e. + # if `require 'tzinfo/data'` fails), then TZInfo will search for a + # zoneinfo directory instead (using the search path specified by + # {DataSources::ZoneinfoDataSource.search_path}). + # + # @param data_source_or_type [Object] either `:ruby`, `:zoneinfo` or an + # instance of a {DataSource}. + # @param args [Array] when `data_source_or_type` is a symbol, + # optional arguments to use when initializing the data source. + # @raise [ArgumentError] if `data_source_or_type` is not `:ruby`, + # `:zoneinfo` or an instance of {DataSource}. + def set(data_source_or_type, *args) + if data_source_or_type.kind_of?(DataSource) + @@instance = data_source_or_type + elsif data_source_or_type == :ruby + @@instance = DataSources::RubyDataSource.new + elsif data_source_or_type == :zoneinfo + @@instance = DataSources::ZoneinfoDataSource.new(*args) + else + raise ArgumentError, 'data_source_or_type must be a DataSource instance or a data source type (:ruby or :zoneinfo)' + end + end + + private + + # Creates a {DataSource} instance for use as the default. Used if no + # preference has been specified manually. + # + # @return [DataSource] the newly created default {DataSource} instance. + def create_default_data_source + has_tzinfo_data = false + + begin + require 'tzinfo/data' + has_tzinfo_data = true + rescue LoadError + end + + return DataSources::RubyDataSource.new if has_tzinfo_data + + begin + return DataSources::ZoneinfoDataSource.new + rescue DataSources::ZoneinfoDirectoryNotFound + raise DataSourceNotFound, "No source of timezone data could be found.\nPlease refer to https://tzinfo.github.io/datasourcenotfound for help resolving this error." + end + end + end + + # Initializes a new {DataSource} instance. Typically only called via + # subclasses of {DataSource}. + def initialize + @timezones = Concurrent::Map.new + end + + # Returns a {DataSources::TimezoneInfo} instance for the given identifier. + # The result will derive from either {DataSources::DataTimezoneInfo} for + # time zones that define their own data or {DataSources::LinkedTimezoneInfo} + # for links or aliases to other time zones. + # + # {get_timezone_info} calls {load_timezone_info} to create the + # {DataSources::TimezoneInfo} instance. The returned instance is cached and + # returned in subsequent calls to {get_timezone_info} for the identifier. + # + # @param identifier [String] A time zone identifier. + # @return [DataSources::TimezoneInfo] a {DataSources::TimezoneInfo} instance + # for a given identifier. + # @raise [InvalidTimezoneIdentifier] if the time zone is not found or the + # identifier is invalid. + def get_timezone_info(identifier) + result = @timezones[identifier] + + unless result + # Thread-safety: It is possible that multiple equivalent TimezoneInfo + # instances could be created here in concurrently executing threads. The + # consequences of this are that the data may be loaded more than once + # (depending on the data source). The performance benefit of ensuring + # that only a single instance is created is unlikely to be worth the + # overhead of only allowing one TimezoneInfo to be loaded at a time. + + result = load_timezone_info(identifier) + @timezones[result.identifier] = result + end + + result end - - # Returns an array of all the available timezone identifiers. + + # @return [Array] a frozen `Array`` of all the available time zone + # identifiers. The identifiers are sorted according to `String#<=>`. def timezone_identifiers - raise_invalid_data_source('timezone_identifiers') + # Thread-safety: It is possible that the value of @timezone_identifiers + # may be calculated multiple times in concurrently executing threads. It + # is not worth the overhead of locking to ensure that + # @timezone_identifiers is only calculated once. + @timezone_identifiers ||= build_timezone_identifiers end - - # Returns an array of all the available timezone identifiers for - # data timezones (i.e. those that actually contain definitions). + + # Returns a frozen `Array` of all the available time zone identifiers for + # data time zones (i.e. those that actually contain definitions). The + # identifiers are sorted according to `String#<=>`. + # + # @return [Array] a frozen `Array` of all the available time zone + # identifiers for data time zones. def data_timezone_identifiers raise_invalid_data_source('data_timezone_identifiers') end - - # Returns an array of all the available timezone identifiers that - # are links to other timezones. + + # Returns a frozen `Array` of all the available time zone identifiers that + # are links to other time zones. The identifiers are sorted according to + # `String#<=>`. + # + # @return [Array] a frozen `Array` of all the available time zone + # identifiers that are links to other time zones. def linked_timezone_identifiers raise_invalid_data_source('linked_timezone_identifiers') end - - # Returns a CountryInfo instance for the given ISO 3166-1 alpha-2 - # country code. Raises InvalidCountryCode if the country could not be found - # or the code is invalid. - def load_country_info(code) - raise_invalid_data_source('load_country_info') + + # @param code [String] an ISO 3166-1 alpha-2 country code. + # @return [DataSources::CountryInfo] a {DataSources::CountryInfo} instance + # for the given ISO 3166-1 alpha-2 country code. + # @raise [InvalidCountryCode] if the country could not be found or the code + # is invalid. + def get_country_info(code) + load_country_info(code) end - - # Returns an array of all the available ISO 3166-1 alpha-2 - # country codes. + + # Returns a frozen `Array` of all the available ISO 3166-1 alpha-2 country + # codes. The identifiers are sorted according to `String#<=>`. + # + # @return [Array] a frozen `Array` of all the available ISO 3166-1 + # alpha-2 country codes. def country_codes raise_invalid_data_source('country_codes') end - - # Returns the name of this DataSource. + + # @return [String] a description of the {DataSource}. def to_s "Default DataSource" end - - # Returns internal object state as a programmer-readable string. + + # @return [String] the internal object state as a programmer-readable + # `String`. def inspect "#<#{self.class}>" end - - private - - # Creates a DataSource instance for use as the default. Used if - # no preference has been specified manually. - def self.create_default_data_source - has_tzinfo_data = false - - begin - require 'tzinfo/data' - has_tzinfo_data = true - rescue LoadError - end - - return RubyDataSource.new if has_tzinfo_data - - begin - return ZoneinfoDataSource.new - rescue ZoneinfoDirectoryNotFound - raise DataSourceNotFound, "No source of timezone data could be found.\nPlease refer to http://tzinfo.github.io/datasourcenotfound for help resolving this error." - end + + protected + + # Returns a {DataSources::TimezoneInfo} instance for the given time zone + # identifier. The result should derive from either + # {DataSources::DataTimezoneInfo} for time zones that define their own data + # or {DataSources::LinkedTimezoneInfo} for links to or aliases for other + # time zones. + # + # @param identifier [String] A time zone identifier. + # @return [DataSources::TimezoneInfo] a {DataSources::TimezoneInfo} instance + # for the given time zone identifier. + # @raise [InvalidTimezoneIdentifier] if the time zone is not found or the + # identifier is invalid. + def load_timezone_info(identifier) + raise_invalid_data_source('load_timezone_info') end + # @param code [String] an ISO 3166-1 alpha-2 country code. + # @return [DataSources::CountryInfo] a {DataSources::CountryInfo} instance + # for the given ISO 3166-1 alpha-2 country code. + # @raise [InvalidCountryCode] if the country could not be found or the code + # is invalid. + def load_country_info(code) + raise_invalid_data_source('load_country_info') + end + + # @return [Encoding] the `Encoding` used by the `String` instances returned + # by {data_timezone_identifiers} and {linked_timezone_identifiers}. + def timezone_identifier_encoding + Encoding::UTF_8 + end + + # Checks that the given identifier is a valid time zone identifier (can be + # found in the {timezone_identifiers} `Array`). If the identifier is valid, + # the `String` instance representing that identifier from + # `timezone_identifiers` is returned. Otherwise an + # {InvalidTimezoneIdentifier} exception is raised. + # + # @param identifier [String] a time zone identifier to be validated. + # @return [String] the `String` instance equivalent to `identifier` from + # {timezone_identifiers}. + # @raise [InvalidTimezoneIdentifier] if `identifier` was not found in + # {timezone_identifiers}. + def validate_timezone_identifier(identifier) + raise InvalidTimezoneIdentifier, "Invalid identifier: #{identifier.nil? ? 'nil' : identifier}" unless identifier.kind_of?(String) + + valid_identifier = try_with_encoding(identifier, timezone_identifier_encoding) {|id| find_timezone_identifier(id) } + return valid_identifier if valid_identifier + + raise InvalidTimezoneIdentifier, "Invalid identifier: #{identifier.encode(Encoding::UTF_8)}" + end + + # Looks up a given code in the given hash of code to + # {DataSources::CountryInfo} mappings. If the code is found the + # {DataSources::CountryInfo} is returned. Otherwise an {InvalidCountryCode} + # exception is raised. + # + # @param hash [String, DataSources::CountryInfo] a mapping from ISO 3166-1 + # alpha-2 country codes to {DataSources::CountryInfo} instances. + # @param code [String] a country code to lookup. + # @param encoding [Encoding] the encoding used for the country codes in + # `hash`. + # @return [DataSources::CountryInfo] the {DataSources::CountryInfo} instance + # corresponding to `code`. + # @raise [InvalidCountryCode] if `code` was not found in `hash`. + def lookup_country_info(hash, code, encoding = Encoding::UTF_8) + raise InvalidCountryCode, "Invalid country code: #{code.nil? ? 'nil' : code}" unless code.kind_of?(String) + + info = try_with_encoding(code, encoding) {|c| hash[c] } + return info if info + + raise InvalidCountryCode, "Invalid country code: #{code.encode(Encoding::UTF_8)}" + end + + private + + # Raises {InvalidDataSource} to indicate that a method has not been + # overridden by a particular data source implementation. + # + # @raise [InvalidDataSource] always. def raise_invalid_data_source(method_name) raise InvalidDataSource, "#{method_name} not defined" end + + # Combines {data_timezone_identifiers} and {linked_timezone_identifiers} + # to create an `Array` containing all valid time zone identifiers. If + # {linked_timezone_identifiers} is empty, the {data_timezone_identifiers} + # instance is returned. + # + # The returned `Array` is frozen. The identifiers are sorted according to + # `String#<=>`. + # + # @return [Array] an `Array` containing all valid time zone + # identifiers. + def build_timezone_identifiers + data = data_timezone_identifiers + linked = linked_timezone_identifiers + linked.empty? ? data : (data + linked).sort!.freeze + end + + if [].respond_to?(:bsearch) + # If the given `identifier` is contained within the {timezone_identifiers} + # `Array`, the `String` instance representing that identifier from + # {timezone_identifiers} is returned. Otherwise, `nil` is returned. + # + # @param identifier [String] A time zone identifier to search for. + # @return [String] the `String` instance representing `identifier` from + # {timezone_identifiers} if found, or `nil` if not found. + # + # :nocov_no_array_bsearch: + def find_timezone_identifier(identifier) + + result = timezone_identifiers.bsearch {|i| i >= identifier } + result == identifier ? result : nil + end + # :nocov_no_array_bsearch: + else + # If the given `identifier` is contained within the {timezone_identifiers} + # `Array`, the `String` instance representing that identifier from + # {timezone_identifiers} is returned. Otherwise, `nil` is returned. + # + # @param identifier [String] A time zone identifier to search for. + # @return [String] the `String` instance representing `identifier` from + # {timezone_identifiers} if found, or `nil` if not found. + # + # :nocov_array_bsearch: + def find_timezone_identifier(identifier) + identifiers = timezone_identifiers + low = 0 + high = identifiers.length + + while low < high do + mid = (low + high).div(2) + mid_identifier = identifiers[mid] + cmp = mid_identifier <=> identifier + + return mid_identifier if cmp == 0 + + if cmp > 0 + high = mid + else + low = mid + 1 + end + end + + nil + end + # :nocov_array_bsearch: + end + + # Tries an operation using `string` directly. If the operation fails, the + # string is copied and encoded with `encoding` and the operation is tried + # again. + # + # @param string [String] The `String` to perform the operation on. + # @param encoding [Encoding] The `Encoding` to use if the initial attempt + # fails. + # @yield [s] the caller will be yielded to once or twice to attempt the + # operation. + # @yieldparam s [String] either `string` or an encoded copy of `string`. + # @yieldreturn [Object] The result of the operation. Must be truthy if + # successful. + # @return [Object] the result of the operation or `nil` if the first attempt + # fails and `string` is already encoded with `encoding`. + def try_with_encoding(string, encoding) + result = yield string + return result if result + + unless encoding == string.encoding + string = string.encode(encoding) + yield string + end + end end end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/data_sources/constant_offset_data_timezone_info.rb ruby-tzinfo-2.0.4/lib/tzinfo/data_sources/constant_offset_data_timezone_info.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/data_sources/constant_offset_data_timezone_info.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/data_sources/constant_offset_data_timezone_info.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,56 @@ +# encoding: UTF-8 +# frozen_string_literal: true + +module TZInfo + module DataSources + # Represents a data time zone defined by a constantly observed offset. + class ConstantOffsetDataTimezoneInfo < DataTimezoneInfo + # @return [TimezoneOffset] the offset that is constantly observed. + attr_reader :constant_offset + + # Initializes a new {ConstantOffsetDataTimezoneInfo}. + # + # The passed in `identifier` instance will be frozen. A reference to the + # passed in {TimezoneOffset} will be retained. + # + # @param identifier [String] the identifier of the time zone. + # @param constant_offset [TimezoneOffset] the constantly observed offset. + # @raise [ArgumentError] if `identifier` or `constant_offset` is `nil`. + def initialize(identifier, constant_offset) + super(identifier) + raise ArgumentError, 'constant_offset must be specified' unless constant_offset + @constant_offset = constant_offset + end + + # @param timestamp [Timestamp] ignored. + # @return [TimezonePeriod] an unbounded {TimezonePeriod} for the time + # zone's constantly observed offset. + def period_for(timestamp) + constant_period + end + + # @param local_timestamp [Timestamp] ignored. + # @return [Array] an `Array` containing a single unbounded + # {TimezonePeriod} for the time zone's constantly observed offset. + def periods_for_local(local_timestamp) + [constant_period] + end + + # @param to_timestamp [Timestamp] ignored. + # @param from_timestamp [Timestamp] ignored. + # @return [Array] an empty `Array`, since there are no transitions in time + # zones that observe a constant offset. + def transitions_up_to(to_timestamp, from_timestamp = nil) + [] + end + + private + + # @return [TimezonePeriod] an unbounded {TimezonePeriod} with the constant + # offset of this timezone. + def constant_period + OffsetTimezonePeriod.new(@constant_offset) + end + end + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/data_sources/country_info.rb ruby-tzinfo-2.0.4/lib/tzinfo/data_sources/country_info.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/data_sources/country_info.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/data_sources/country_info.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,42 @@ +# encoding: UTF-8 +# frozen_string_literal: true + +module TZInfo + module DataSources + # Represents a country and references to its time zones as returned by a + # {DataSource}. + class CountryInfo + # @return [String] the ISO 3166-1 alpha-2 country code. + attr_reader :code + + # @return [String] the name of the country. + attr_reader :name + + # @return [Array] the time zones observed in the country. + attr_reader :zones + + # Initializes a new {CountryInfo}. The passed in `code`, `name` and + # `zones` instances will be frozen. + # + # @param code [String] an ISO 3166-1 alpha-2 country code. + # @param name [String] the name of the country. + # @param zones [Array] the time zones observed in the + # country. + # @raise [ArgumentError] if `code`, `name` or `zones` is `nil`. + def initialize(code, name, zones) + raise ArgumentError, 'code must be specified' unless code + raise ArgumentError, 'name must be specified' unless name + raise ArgumentError, 'zones must be specified' unless zones + @code = code.freeze + @name = name.freeze + @zones = zones.freeze + end + + # @return [String] the internal object state as a programmer-readable + # `String`. + def inspect + "#<#{self.class}: #@code>" + end + end + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/data_sources/data_timezone_info.rb ruby-tzinfo-2.0.4/lib/tzinfo/data_sources/data_timezone_info.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/data_sources/data_timezone_info.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/data_sources/data_timezone_info.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,91 @@ +# encoding: UTF-8 +# frozen_string_literal: true + +module TZInfo + module DataSources + # The base class for time zones defined as either a series of transitions + # ({TransitionsDataTimezoneInfo}) or a constantly observed offset + # ({ConstantOffsetDataTimezoneInfo}). + # + # @abstract Data sources return instances of {DataTimezoneInfo} subclasses. + class DataTimezoneInfo < TimezoneInfo + # @param timestamp [Timestamp] a {Timestamp} with a specified + # {Timestamp#utc_offset utc_offset}. + # @return [TimezonePeriod] the {TimezonePeriod} observed at the time + # specified by `timestamp`. + # @raise [ArgumentError] may be raised if `timestamp` is `nil` or does not + # have a specified {Timestamp#utc_offset utc_offset}. + def period_for(timestamp) + raise_not_implemented('period_for') + end + + # Returns an `Array` containing the {TimezonePeriod TimezonePeriods} that + # could be observed at the local time specified by `local_timestamp`. The + # results are are ordered by increasing UTC start date. An empty `Array` + # is returned if no periods are found for the given local time. + # + # @param local_timestamp [Timestamp] a {Timestamp} representing a local + # time - must have an unspecified {Timestamp#utc_offset utc_offset}. + # @return [Array] an `Array` containing the + # {TimezonePeriod TimezonePeriods} that could be observed at the local + # time specified by `local_timestamp`. + # @raise [ArgumentError] may be raised if `local_timestamp` is `nil`, or + # has a specified {Timestamp#utc_offset utc_offset}. + def periods_for_local(local_timestamp) + raise_not_implemented('periods_for_local') + end + + # Returns an `Array` of {TimezoneTransition} instances representing the + # times where the UTC offset of the time zone changes. + # + # Transitions are returned up to a given {Timestamp} (`to_timestamp`). + # + # A from {Timestamp} may also be supplied using the `from_timestamp` + # parameter. If `from_timestamp` is specified, only transitions from that + # time onwards will be returned. + # + # Comparisons with `to_timestamp` are exclusive. Comparisons with + # `from_timestamp` are inclusive. If a transition falls precisely on + # `to_timestamp`, it will be excluded. If a transition falls on + # `from_timestamp`, it will be included. + # + # Transitions returned are ordered by when they occur, from earliest to + # latest. + # + # @param to_timestamp [Timestamp] a {Timestamp} with a specified + # {Timestamp#utc_offset utc_offset}. Transitions are returned if they + # occur before this time. + # @param from_timestamp [Timestamp] an optional {Timestamp} with a + # specified {Timestamp#utc_offset utc_offset}. If specified, transitions + # are returned if they occur at or after this time. + # @return [Array] an `Array` of {TimezoneTransition} + # instances representing the times where the UTC offset of the time zone + # changes. + # @raise [ArgumentError] may be raised if `to_timestamp` is `nil` or does + # not have a specified {Timestamp#utc_offset utc_offset}. + # @raise [ArgumentError] may be raised if `from_timestamp` is specified + # but does not have a specified {Timestamp#utc_offset utc_offset}. + # @raise [ArgumentError] may be raised if `from_timestamp` is specified + # but is not earlier than or at the same time as `to_timestamp`. + def transitions_up_to(to_timestamp, from_timestamp = nil) + raise_not_implemented('transitions_up_to') + end + + # @return [DataTimezone] a new {DataTimezone} instance for the time zone + # represented by this {DataTimezoneInfo}. + def create_timezone + DataTimezone.new(self) + end + + private + + # Raises a {NotImplementedError} to indicate that the base class is + # incorrectly being used directly. + # + # raise [NotImplementedError] always. + def raise_not_implemented(method_name) + raise NotImplementedError, "Subclasses must override #{method_name}" + end + end + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/data_sources/linked_timezone_info.rb ruby-tzinfo-2.0.4/lib/tzinfo/data_sources/linked_timezone_info.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/data_sources/linked_timezone_info.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/data_sources/linked_timezone_info.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,33 @@ +# encoding: UTF-8 + +module TZInfo + module DataSources + # Represents a time zone that is defined as a link to or alias of another + # zone. + class LinkedTimezoneInfo < TimezoneInfo + # @return [String] the identifier of the time zone that provides the data + # (that this zone links to or is an alias for). + attr_reader :link_to_identifier + + # Initializes a new {LinkedTimezoneInfo}. The passed in `identifier` and + # `link_to_identifier` instances will be frozen. + # + # @param identifier [String] the identifier of the time zone. + # @param link_to_identifier [String] the identifier of the time zone that + # this zone link to. + # @raise [ArgumentError] if `identifier` or `link_to_identifier` are + # `nil`. + def initialize(identifier, link_to_identifier) + super(identifier) + raise ArgumentError, 'link_to_identifier must be specified' unless link_to_identifier + @link_to_identifier = link_to_identifier.freeze + end + + # @return [LinkedTimezone] a new {LinkedTimezone} instance for the time + # zone represented by this {LinkedTimezoneInfo}. + def create_timezone + LinkedTimezone.new(self) + end + end + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/data_sources/posix_time_zone_parser.rb ruby-tzinfo-2.0.4/lib/tzinfo/data_sources/posix_time_zone_parser.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/data_sources/posix_time_zone_parser.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/data_sources/posix_time_zone_parser.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,181 @@ +# encoding: UTF-8 +# frozen_string_literal: true + +require 'strscan' + +module TZInfo + # Use send as a workaround for erroneous 'wrong number of arguments' errors + # with JRuby 9.0.5.0 when calling methods with Java implementations. See #114. + send(:using, UntaintExt) if TZInfo.const_defined?(:UntaintExt) + + module DataSources + # An {InvalidPosixTimeZone} exception is raised if an invalid POSIX-style + # time zone string is encountered. + # + # @private + class InvalidPosixTimeZone < StandardError #:nodoc: + end + private_constant :InvalidPosixTimeZone + + # A parser for POSIX-style TZ strings used in zoneinfo files and specified + # by tzfile.5 and tzset.3. + # + # @private + class PosixTimeZoneParser #:nodoc: + # Initializes a new {PosixTimeZoneParser}. + # + # @param string_deduper [StringDeduper] a {StringDeduper} instance to use + # to dedupe abbreviations. + def initialize(string_deduper) + @string_deduper = string_deduper + end + + # Parses a POSIX-style TZ string. + # + # @param tz_string [String] the string to parse. + # @return [Object] either a {TimezoneOffset} for a constantly applied + # offset or an {AnnualRules} instance representing the rules. + # @raise [InvalidPosixTimeZone] if `tz_string` is not a `String`. + # @raise [InvalidPosixTimeZone] if `tz_string` is is not valid. + def parse(tz_string) + raise InvalidPosixTimeZone unless tz_string.kind_of?(String) + return nil if tz_string.empty? + + s = StringScanner.new(tz_string) + check_scan(s, /([^-+,\d<][^-+,\d]*) | <([^>]+)>/x) + std_abbrev = @string_deduper.dedupe((s[1] || s[2]).untaint) + check_scan(s, /([-+]?\d+)(?::(\d+)(?::(\d+))?)?/) + std_offset = get_offset_from_hms(s[1], s[2], s[3]) + + if s.scan(/([^-+,\d<][^-+,\d]*) | <([^>]+)>/x) + dst_abbrev = @string_deduper.dedupe((s[1] || s[2]).untaint) + + if s.scan(/([-+]?\d+)(?::(\d+)(?::(\d+))?)?/) + dst_offset = get_offset_from_hms(s[1], s[2], s[3]) + else + # POSIX is negative for ahead of UTC. + dst_offset = std_offset - 3600 + end + + dst_difference = std_offset - dst_offset + + start_rule = parse_rule(s, 'start') + end_rule = parse_rule(s, 'end') + + raise InvalidPosixTimeZone, "Expected the end of a POSIX-style time zone string but found '#{s.rest}'." if s.rest? + + if start_rule.is_always_first_day_of_year? && start_rule.transition_at == 0 && + end_rule.is_always_last_day_of_year? && end_rule.transition_at == 86400 + dst_difference + # Constant daylight savings time. + # POSIX is negative for ahead of UTC. + TimezoneOffset.new(-std_offset, dst_difference, dst_abbrev) + else + AnnualRules.new( + TimezoneOffset.new(-std_offset, 0, std_abbrev), + TimezoneOffset.new(-std_offset, dst_difference, dst_abbrev), + start_rule, + end_rule) + end + elsif !s.rest? + # Constant standard time. + # POSIX is negative for ahead of UTC. + TimezoneOffset.new(-std_offset, 0, std_abbrev) + else + raise InvalidPosixTimeZone, "Expected the end of a POSIX-style time zone string but found '#{s.rest}'." + end + end + + private + + # Parses a rule. + # + # @param s [StringScanner] the `StringScanner` to read the rule from. + # @param type [String] the type of rule (either `'start'` or `'end'`). + # @raise [InvalidPosixTimeZone] if the rule is not valid. + # @return [TransitionRule] the parsed rule. + def parse_rule(s, type) + check_scan(s, /,(?: (?: J(\d+) ) | (\d+) | (?: M(\d+)\.(\d)\.(\d) ) )/x) + julian_day_of_year = s[1] + absolute_day_of_year = s[2] + month = s[3] + week = s[4] + day_of_week = s[5] + + if s.scan(/\//) + check_scan(s, /([-+]?\d+)(?::(\d+)(?::(\d+))?)?/) + transition_at = get_seconds_after_midnight_from_hms(s[1], s[2], s[3]) + else + transition_at = 7200 + end + + begin + if julian_day_of_year + JulianDayOfYearTransitionRule.new(julian_day_of_year.to_i, transition_at) + elsif absolute_day_of_year + AbsoluteDayOfYearTransitionRule.new(absolute_day_of_year.to_i, transition_at) + elsif week == '5' + LastDayOfMonthTransitionRule.new(month.to_i, day_of_week.to_i, transition_at) + else + DayOfMonthTransitionRule.new(month.to_i, week.to_i, day_of_week.to_i, transition_at) + end + rescue ArgumentError => e + raise InvalidPosixTimeZone, "Invalid #{type} rule in POSIX-style time zone string: #{e}" + end + end + + # Returns an offset in seconds from hh:mm:ss values. The value can be + # negative. -02:33:12 would represent 2 hours, 33 minutes and 12 seconds + # ahead of UTC. + # + # @param h [String] the hours. + # @param m [String] the minutes. + # @param s [String] the seconds. + # @return [Integer] the offset. + # @raise [InvalidPosixTimeZone] if the mm and ss values are greater than + # 59. + def get_offset_from_hms(h, m, s) + h = h.to_i + m = m.to_i + s = s.to_i + raise InvalidPosixTimeZone, "Invalid minute #{m} in offset for POSIX-style time zone string." if m > 59 + raise InvalidPosixTimeZone, "Invalid second #{s} in offset for POSIX-style time zone string." if s > 59 + magnitude = (h.abs * 60 + m) * 60 + s + h < 0 ? -magnitude : magnitude + end + + # Returns the seconds from midnight from hh:mm:ss values. Hours can exceed + # 24 for a time on the following day. Hours can be negative to subtract + # hours from midnight on the given day. -02:33:12 represents 22:33:12 on + # the prior day. + # + # @param h [String] the hour. + # @param m [String] the minutes past the hour. + # @param s [String] the seconds past the minute. + # @return [Integer] the number of seconds after midnight. + # @raise [InvalidPosixTimeZone] if the mm and ss values are greater than + # 59. + def get_seconds_after_midnight_from_hms(h, m, s) + h = h.to_i + m = m.to_i + s = s.to_i + raise InvalidPosixTimeZone, "Invalid minute #{m} in time for POSIX-style time zone string." if m > 59 + raise InvalidPosixTimeZone, "Invalid second #{s} in time for POSIX-style time zone string." if s > 59 + (h * 3600) + m * 60 + s + end + + # Scans for a pattern and raises an exception if the pattern does not + # match the input. + # + # @param s [StringScanner] the `StringScanner` to scan. + # @param pattern [Regexp] the pattern to match. + # @return [String] the result of the scan. + # @raise [InvalidPosixTimeZone] if the pattern does not match the input. + def check_scan(s, pattern) + result = s.scan(pattern) + raise InvalidPosixTimeZone, "Expected '#{s.rest}' to match #{pattern} in POSIX-style time zone string." unless result + result + end + end + private_constant :PosixTimeZoneParser + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/data_sources/ruby_data_source.rb ruby-tzinfo-2.0.4/lib/tzinfo/data_sources/ruby_data_source.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/data_sources/ruby_data_source.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/data_sources/ruby_data_source.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,145 @@ +# encoding: UTF-8 +# frozen_string_literal: true + +module TZInfo + # Use send as a workaround for erroneous 'wrong number of arguments' errors + # with JRuby 9.0.5.0 when calling methods with Java implementations. See #114. + send(:using, UntaintExt) if TZInfo.const_defined?(:UntaintExt) + + module DataSources + # A {TZInfoDataNotFound} exception is raised if the tzinfo-data gem could + # not be found (i.e. `require 'tzinfo/data'` failed) when selecting the Ruby + # data source. + class TZInfoDataNotFound < StandardError + end + + # A DataSource implementation that loads data from the set of Ruby modules + # included in the tzinfo-data gem. + # + # TZInfo will use {RubyDataSource} by default if the tzinfo-data gem + # is available on the load path. It can also be selected by calling + # {DataSource.set} as follows: + # + # TZInfo::DataSource.set(:ruby) + class RubyDataSource < DataSource + # (see DataSource#data_timezone_identifiers) + attr_reader :data_timezone_identifiers + + # (see DataSource#linked_timezone_identifiers) + attr_reader :linked_timezone_identifiers + + # (see DataSource#country_codes) + attr_reader :country_codes + + # Initializes a new {RubyDataSource} instance. + # + # @raise [TZInfoDataNotFound] if the tzinfo-data gem could not be found + # (i.e. `require 'tzinfo/data'` failed). + def initialize + super + + begin + require('tzinfo/data') + rescue LoadError + raise TZInfoDataNotFound, "The tzinfo-data gem could not be found (require 'tzinfo/data' failed)." + end + + if TZInfo::Data.const_defined?(:LOCATION) + # Format 2 + @base_path = File.join(TZInfo::Data::LOCATION, 'tzinfo', 'data') + else + # Format 1 + data_file = File.join('', 'tzinfo', 'data.rb') + path = $".reverse_each.detect {|p| p.end_with?(data_file) } + if path + @base_path = File.join(File.dirname(path), 'data').untaint + else + @base_path = 'tzinfo/data' + end + end + + require_index('timezones') + require_index('countries') + + @data_timezone_identifiers = Data::Indexes::Timezones.data_timezones + @linked_timezone_identifiers = Data::Indexes::Timezones.linked_timezones + @countries = Data::Indexes::Countries.countries + @country_codes = @countries.keys.sort!.freeze + end + + # (see DataSource#to_s) + def to_s + "Ruby DataSource: #{version_info}" + end + + # (see DataSource#inspect) + def inspect + "#" + end + + protected + + # Returns a {TimezoneInfo} instance for the given time zone identifier. + # The result will either be a {ConstantOffsetDataTimezoneInfo}, a + # {TransitionsDataTimezoneInfo} or a {LinkedTimezoneInfo} depending on the + # type of time zone. + # + # @param identifier [String] A time zone identifier. + # @return [TimezoneInfo] a {TimezoneInfo} instance for the given time zone + # identifier. + # @raise [InvalidTimezoneIdentifier] if the time zone is not found or the + # identifier is invalid. + def load_timezone_info(identifier) + valid_identifier = validate_timezone_identifier(identifier) + split_identifier = valid_identifier.gsub(/-/, '__m__').gsub(/\+/, '__p__').split('/') + + begin + require_definition(split_identifier) + + m = Data::Definitions + split_identifier.each {|part| m = m.const_get(part) } + m.get + rescue LoadError, NameError => e + raise InvalidTimezoneIdentifier, "#{e.message.encode(Encoding::UTF_8)} (loading #{valid_identifier})" + end + end + + # (see DataSource#load_country_info) + def load_country_info(code) + lookup_country_info(@countries, code) + end + + private + + # Requires a zone definition by its identifier (split on /). + # + # @param identifier [Array] the component parts of a time zone + # identifier (split on /). This must have already been validated. + def require_definition(identifier) + require_data(*(['definitions'] + identifier)) + end + + # Requires an index by its name. + # + # @param name [String] an index name. + def require_index(name) + require_data(*['indexes', name]) + end + + # Requires a file from tzinfo/data. + # + # @param file [Array] a relative path to a file to be required. + def require_data(*file) + require(File.join(@base_path, *file)) + end + + # @return [String] a `String` containing TZInfo::Data version infomation + # for inclusion in the #to_s and #inspect output. + def version_info + # The TZInfo::Data::VERSION constant is only available from v1.2014.8 + # onwards. + "tzdb v#{TZInfo::Data::Version::TZDATA}#{TZInfo::Data.const_defined?(:VERSION) ? ", tzinfo-data v#{TZInfo::Data::VERSION}" : ''}" + end + end + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/data_sources/timezone_info.rb ruby-tzinfo-2.0.4/lib/tzinfo/data_sources/timezone_info.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/data_sources/timezone_info.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/data_sources/timezone_info.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,47 @@ +# encoding: UTF-8 +# frozen_string_literal: true + +module TZInfo + module DataSources + # Represents a time zone defined by a data source. + # + # @abstract Data sources return instances of {TimezoneInfo} subclasses. + class TimezoneInfo + # @return [String] the identifier of the time zone. + attr_reader :identifier + + # Initializes a new TimezoneInfo. The passed in `identifier` instance will + # be frozen. + # + # @param identifier [String] the identifier of the time zone. + # @raise [ArgumentError] if `identifier` is `nil`. + def initialize(identifier) + raise ArgumentError, 'identifier must be specified' unless identifier + @identifier = identifier.freeze + end + + # @return [String] the internal object state as a programmer-readable + # `String`. + def inspect + "#<#{self.class}: #@identifier>" + end + + # @return [Timezone] a new {Timezone} instance for the time zone + # represented by this {TimezoneInfo}. + def create_timezone + raise_not_implemented('create_timezone') + end + + private + + # Raises a {NotImplementedError}. + # + # @param method_name [String] the name of the method that must be + # overridden. + # @raise NotImplementedError always. + def raise_not_implemented(method_name) + raise NotImplementedError, "Subclasses must override #{method_name}" + end + end + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/data_sources/transitions_data_timezone_info.rb ruby-tzinfo-2.0.4/lib/tzinfo/data_sources/transitions_data_timezone_info.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/data_sources/transitions_data_timezone_info.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/data_sources/transitions_data_timezone_info.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,214 @@ +# encoding: UTF-8 +# frozen_string_literal: true + +module TZInfo + module DataSources + # Represents a data time zone defined by a list of transitions that change + # the locally observed time. + class TransitionsDataTimezoneInfo < DataTimezoneInfo + # @return [Array] the transitions that define this + # time zone in order of ascending timestamp. + attr_reader :transitions + + # Initializes a new {TransitionsDataTimezoneInfo}. + # + # The passed in `identifier` instance will be frozen. A reference to the + # passed in `Array` will be retained. + # + # The `transitions` `Array` must be sorted in order of ascending + # timestamp. Each transition must have a + # {TimezoneTransition#timestamp_value timestamp_value} that is greater + # than the {TimezoneTransition#timestamp_value timestamp_value} of the + # prior transition. + # + # @param identifier [String] the identifier of the time zone. + # @param transitions [Array] an `Array` of + # transitions that each indicate when a change occurs in the locally + # observed time. + # @raise [ArgumentError] if `identifier` is `nil`. + # @raise [ArgumentError] if `transitions` is `nil`. + # @raise [ArgumentError] if `transitions` is an empty `Array`. + def initialize(identifier, transitions) + super(identifier) + raise ArgumentError, 'transitions must be specified' unless transitions + raise ArgumentError, 'transitions must not be an empty Array' if transitions.empty? + @transitions = transitions.freeze + end + + # (see DataTimezoneInfo#period_for) + def period_for(timestamp) + raise ArgumentError, 'timestamp must be specified' unless timestamp + raise ArgumentError, 'timestamp must have a specified utc_offset' unless timestamp.utc_offset + + timestamp_value = timestamp.value + + index = find_minimum_transition {|t| t.timestamp_value >= timestamp_value } + + if index + transition = @transitions[index] + + if transition.timestamp_value == timestamp_value + # timestamp occurs within the second of the found transition, so is + # the transition that starts the period. + start_transition = transition + end_transition = @transitions[index + 1] + else + # timestamp occurs before the second of the found transition, so is + # the transition that ends the period. + start_transition = index == 0 ? nil : @transitions[index - 1] + end_transition = transition + end + else + start_transition = @transitions.last + end_transition = nil + end + + TransitionsTimezonePeriod.new(start_transition, end_transition) + end + + # (see DataTimezoneInfo#periods_for_local) + def periods_for_local(local_timestamp) + raise ArgumentError, 'local_timestamp must be specified' unless local_timestamp + raise ArgumentError, 'local_timestamp must have an unspecified utc_offset' if local_timestamp.utc_offset + + local_timestamp_value = local_timestamp.value + latest_possible_utc_value = local_timestamp_value + 86400 + earliest_possible_utc_value = local_timestamp_value - 86400 + + # Find the index of the first transition that occurs after a latest + # possible UTC representation of the local timestamp and then search + # backwards until an earliest possible UTC representation. + + index = find_minimum_transition {|t| t.timestamp_value >= latest_possible_utc_value } + + # No transitions after latest_possible_utc_value, set to max index + 1 + # to search backwards including the period after the last transition + index = @transitions.length unless index + + result = [] + + index.downto(0) do |i| + start_transition = i > 0 ? @transitions[i - 1] : nil + end_transition = @transitions[i] + offset = start_transition ? start_transition.offset : end_transition.previous_offset + utc_timestamp_value = local_timestamp_value - offset.observed_utc_offset + + # It is not necessary to compare the sub-seconds because a timestamp + # is in the period if is >= the start transition (sub-seconds would + # make == become >) and if it is < the end transition (which + # sub-seconds cannot affect). + if (!start_transition || utc_timestamp_value >= start_transition.timestamp_value) && (!end_transition || utc_timestamp_value < end_transition.timestamp_value) + result << TransitionsTimezonePeriod.new(start_transition, end_transition) + elsif end_transition && end_transition.timestamp_value < earliest_possible_utc_value + break + end + end + + result.reverse! + end + + # (see DataTimezoneInfo#transitions_up_to) + def transitions_up_to(to_timestamp, from_timestamp = nil) + raise ArgumentError, 'to_timestamp must be specified' unless to_timestamp + raise ArgumentError, 'to_timestamp must have a specified utc_offset' unless to_timestamp.utc_offset + + if from_timestamp + raise ArgumentError, 'from_timestamp must have a specified utc_offset' unless from_timestamp.utc_offset + raise ArgumentError, 'to_timestamp must be greater than from_timestamp' if to_timestamp <= from_timestamp + end + + if from_timestamp + from_index = find_minimum_transition {|t| transition_on_or_after_timestamp?(t, from_timestamp) } + return [] unless from_index + else + from_index = 0 + end + + to_index = find_minimum_transition {|t| transition_on_or_after_timestamp?(t, to_timestamp) } + + if to_index + return [] if to_index < 1 + to_index -= 1 + else + to_index = -1 + end + + @transitions[from_index..to_index] + end + + private + + # Array#bsearch_index was added in Ruby 2.3.0. Use bsearch_index to find + # transitions if it is available, otherwise use a Ruby implementation. + if [].respond_to?(:bsearch_index) + # Performs a binary search on {transitions} to find the index of the + # earliest transition satisfying a condition. + # + # @yield [transition] the caller will be yielded to to test the search + # condition. + # @yieldparam transition [TimezoneTransition] a {TimezoneTransition} + # instance from {transitions}. + # @yieldreturn [Boolean] `true` for the earliest transition that + # satisfies the condition and return `true` for all subsequent + # transitions. In all other cases, the result of the block must be + # `false`. + # @return [Integer] the index of the earliest transition safisfying + # the condition or `nil` if there are no such transitions. + # + # :nocov_no_array_bsearch_index: + def find_minimum_transition(&block) + @transitions.bsearch_index(&block) + end + # :nocov_no_array_bsearch_index: + else + # Performs a binary search on {transitions} to find the index of the + # earliest transition satisfying a condition. + # + # @yield [transition] the caller will be yielded to to test the search + # condition. + # @yieldparam transition [TimezoneTransition] a {TimezoneTransition} + # instance from {transitions}. + # @yieldreturn [Boolean] `true` for the earliest transition that + # satisfies the condition and return `true` for all subsequent + # transitions. In all other cases, the result of the block must be + # `false`. + # @return [Integer] the index of the earliest transition safisfying + # the condition or `nil` if there are no such transitions. + # + # :nocov_array_bsearch_index: + def find_minimum_transition + # A Ruby implementation of the find-minimum mode of Array#bsearch_index. + low = 0 + high = @transitions.length + satisfied = false + + while low < high do + mid = (low + high).div(2) + if yield @transitions[mid] + satisfied = true + high = mid + else + low = mid + 1 + end + end + + satisfied ? low : nil + end + # :nocov_array_bsearch_index: + end + + # Determines if a transition occurs at or after a given {Timestamp}, + # taking the {Timestamp#sub_second sub_second} into consideration. + # + # @param transition [TimezoneTransition] the transition to compare. + # @param timestamp [Timestamp] the timestamp to compare. + # @return [Boolean] `true` if `transition` occurs at or after `timestamp`, + # otherwise `false`. + def transition_on_or_after_timestamp?(transition, timestamp) + transition_timestamp_value = transition.timestamp_value + timestamp_value = timestamp.value + transition_timestamp_value > timestamp_value || transition_timestamp_value == timestamp_value && timestamp.sub_second == 0 + end + end + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/data_sources/zoneinfo_data_source.rb ruby-tzinfo-2.0.4/lib/tzinfo/data_sources/zoneinfo_data_source.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/data_sources/zoneinfo_data_source.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/data_sources/zoneinfo_data_source.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,580 @@ +# encoding: UTF-8 +# frozen_string_literal: true + +module TZInfo + # Use send as a workaround for erroneous 'wrong number of arguments' errors + # with JRuby 9.0.5.0 when calling methods with Java implementations. See #114. + send(:using, UntaintExt) if TZInfo.const_defined?(:UntaintExt) + + module DataSources + # An {InvalidZoneinfoDirectory} exception is raised if {ZoneinfoDataSource} + # is initialized with a specific zoneinfo path that is not a valid zoneinfo + # directory. A valid zoneinfo directory is one that contains time zone + # files, a country code index file named iso3166.tab and a time zone index + # file named zone1970.tab or zone.tab. + class InvalidZoneinfoDirectory < StandardError + end + + # A {ZoneinfoDirectoryNotFound} exception is raised if no valid zoneinfo + # directory could be found when checking the paths listed in + # {ZoneinfoDataSource.search_path}. A valid zoneinfo directory is one that + # contains time zone files, a country code index file named iso3166.tab and + # a time zone index file named zone1970.tab or zone.tab. + class ZoneinfoDirectoryNotFound < StandardError + end + + # A DataSource implementation that loads data from a 'zoneinfo' directory + # containing compiled "TZif" version 3 (or earlier) files in addition to + # iso3166.tab and zone1970.tab or zone.tab index files. + # + # To have TZInfo load the system zoneinfo files, call + # {TZInfo::DataSource.set} as follows: + # + # TZInfo::DataSource.set(:zoneinfo) + # + # To load zoneinfo files from a particular directory, pass the directory to + # {TZInfo::DataSource.set}: + # + # TZInfo::DataSource.set(:zoneinfo, directory) + # + # To load zoneinfo files from a particular directory, but load the + # iso3166.tab index file from a separate location, pass the directory and + # path to the iso3166.tab file to {TZInfo::DataSource.set}: + # + # TZInfo::DataSource.set(:zoneinfo, directory, iso3166_path) + # + # Please note that versions of the 'zic' tool (used to build zoneinfo files) + # that were released prior to February 2006 created zoneinfo files that used + # 32-bit integers for transition timestamps. Later versions of zic produce + # zoneinfo files that use 64-bit integers. If you have 32-bit zoneinfo files + # on your system, then any queries falling outside of the range 1901-12-13 + # 20:45:52 to 2038-01-19 03:14:07 may be inaccurate. + # + # Most modern platforms include 64-bit zoneinfo files. However, Mac OS X (up + # to at least 10.8.4) still uses 32-bit zoneinfo files. + # + # To check whether your zoneinfo files contain 32-bit or 64-bit transition + # data, you can run the following code (substituting the identifier of the + # zone you want to test for `zone_identifier`): + # + # TZInfo::DataSource.set(:zoneinfo) + # dir = TZInfo::DataSource.get.zoneinfo_dir + # File.open(File.join(dir, zone_identifier), 'r') {|f| f.read(5) } + # + # If the last line returns `"TZif\\x00"`, then you have a 32-bit zoneinfo + # file. If it returns `"TZif2"` or `"TZif3"` then you have a 64-bit zoneinfo + # file. + # + # It is also worth noting that as of the 2017c release of the IANA Time Zone + # Database, 64-bit zoneinfo files only include future transitions up to + # 2038-01-19 03:14:07. Any queries falling after this time may be + # inaccurate. + class ZoneinfoDataSource < DataSource + # The default value of {ZoneinfoDataSource.search_path}. + DEFAULT_SEARCH_PATH = ['/usr/share/zoneinfo', '/usr/share/lib/zoneinfo', '/etc/zoneinfo'].freeze + private_constant :DEFAULT_SEARCH_PATH + + # The default value of {ZoneinfoDataSource.alternate_iso3166_tab_search_path}. + DEFAULT_ALTERNATE_ISO3166_TAB_SEARCH_PATH = ['/usr/share/misc/iso3166.tab', '/usr/share/misc/iso3166'].freeze + private_constant :DEFAULT_ALTERNATE_ISO3166_TAB_SEARCH_PATH + + # Paths to be checked to find the system zoneinfo directory. + # + # @private + @@search_path = DEFAULT_SEARCH_PATH.dup + + # Paths to possible alternate iso3166.tab files (used to locate the + # system-wide iso3166.tab files on FreeBSD and OpenBSD). + # + # @private + @@alternate_iso3166_tab_search_path = DEFAULT_ALTERNATE_ISO3166_TAB_SEARCH_PATH.dup + + class << self + # An `Array` of directories that will be checked to find the system + # zoneinfo directory. + # + # Directories are checked in the order they appear in the `Array`. + # + # The default value is `['/usr/share/zoneinfo', + # '/usr/share/lib/zoneinfo', '/etc/zoneinfo']`. + # + # @return [Array] an `Array` of directories to check in order to + # find the system zoneinfo directory. + def search_path + @@search_path + end + + # Sets the directories to be checked when locating the system zoneinfo + # directory. + # + # Can be set to an `Array` of directories or a `String` containing + # directories separated with `File::PATH_SEPARATOR`. + # + # Directories are checked in the order they appear in the `Array` or + # `String`. + # + # Set to `nil` to revert to the default paths. + # + # @param search_path [Object] either `nil` or a list of directories to + # check as either an `Array` of `String` or a `File::PATH_SEPARATOR` + # separated `String`. + def search_path=(search_path) + @@search_path = process_search_path(search_path, DEFAULT_SEARCH_PATH) + end + + # An `Array` of paths that will be checked to find an alternate + # iso3166.tab file if one was not included in the zoneinfo directory + # (for example, on FreeBSD and OpenBSD systems). + # + # Paths are checked in the order they appear in the `Array`. + # + # The default value is `['/usr/share/misc/iso3166.tab', + # '/usr/share/misc/iso3166']`. + # + # @return [Array] an `Array` of paths to check in order to + # locate an iso3166.tab file. + def alternate_iso3166_tab_search_path + @@alternate_iso3166_tab_search_path + end + + # Sets the paths to check to locate an alternate iso3166.tab file if one + # was not included in the zoneinfo directory. + # + # Can be set to an `Array` of paths or a `String` containing paths + # separated with `File::PATH_SEPARATOR`. + # + # Paths are checked in the order they appear in the array. + # + # Set to `nil` to revert to the default paths. + # + # @param alternate_iso3166_tab_search_path [Object] either `nil` or a + # list of paths to check as either an `Array` of `String` or a + # `File::PATH_SEPARATOR` separated `String`. + def alternate_iso3166_tab_search_path=(alternate_iso3166_tab_search_path) + @@alternate_iso3166_tab_search_path = process_search_path(alternate_iso3166_tab_search_path, DEFAULT_ALTERNATE_ISO3166_TAB_SEARCH_PATH) + end + + private + + # Processes a path for use as the {search_path} or + # {alternate_iso3166_tab_search_path}. + # + # @param path [Object] either `nil` or a list of paths to check as + # either an `Array` of `String` or a `File::PATH_SEPARATOR` separated + # `String`. + # @param default [Array] the default value. + # @return [Array] the processed path. + def process_search_path(path, default) + if path + if path.kind_of?(String) + path.split(File::PATH_SEPARATOR) + else + path.collect(&:to_s) + end + else + default.dup + end + end + end + + # @return [String] the zoneinfo directory being used. + attr_reader :zoneinfo_dir + + # (see DataSource#country_codes) + attr_reader :country_codes + + # Initializes a new {ZoneinfoDataSource}. + # + # If `zoneinfo_dir` is specified, it will be checked and used as the + # source of zoneinfo files. + # + # The directory must contain a file named iso3166.tab and a file named + # either zone1970.tab or zone.tab. These may either be included in the + # root of the directory or in a 'tab' sub-directory and named country.tab + # and zone_sun.tab respectively (as is the case on Solaris). + # + # Additionally, the path to iso3166.tab can be overridden using the + # `alternate_iso3166_tab_path` parameter. + # + # If `zoneinfo_dir` is not specified or `nil`, the paths referenced in + # {search_path} are searched in order to find a valid zoneinfo directory + # (one that contains zone1970.tab or zone.tab and iso3166.tab files as + # above). + # + # The paths referenced in {alternate_iso3166_tab_search_path} are also + # searched to find an iso3166.tab file if one of the searched zoneinfo + # directories doesn't contain an iso3166.tab file. + # + # @param zoneinfo_dir [String] an optional path to a directory to use as + # the source of zoneinfo files. + # @param alternate_iso3166_tab_path [String] an optional path to the + # iso3166.tab file. + # @raise [InvalidZoneinfoDirectory] if the iso3166.tab and zone1970.tab or + # zone.tab files cannot be found using the `zoneinfo_dir` and + # `alternate_iso3166_tab_path` parameters. + # @raise [ZoneinfoDirectoryNotFound] if no valid directory can be found + # by searching. + def initialize(zoneinfo_dir = nil, alternate_iso3166_tab_path = nil) + super() + + if zoneinfo_dir + iso3166_tab_path, zone_tab_path = validate_zoneinfo_dir(zoneinfo_dir, alternate_iso3166_tab_path) + + unless iso3166_tab_path && zone_tab_path + raise InvalidZoneinfoDirectory, "#{zoneinfo_dir} is not a directory or doesn't contain a iso3166.tab file and a zone1970.tab or zone.tab file." + end + + @zoneinfo_dir = zoneinfo_dir + else + @zoneinfo_dir, iso3166_tab_path, zone_tab_path = find_zoneinfo_dir + + unless @zoneinfo_dir && iso3166_tab_path && zone_tab_path + raise ZoneinfoDirectoryNotFound, "None of the paths included in #{self.class.name}.search_path are valid zoneinfo directories." + end + end + + @zoneinfo_dir = File.expand_path(@zoneinfo_dir).freeze + @timezone_identifiers = load_timezone_identifiers.freeze + @countries = load_countries(iso3166_tab_path, zone_tab_path).freeze + @country_codes = @countries.keys.sort!.freeze + + string_deduper = ConcurrentStringDeduper.new + posix_tz_parser = PosixTimeZoneParser.new(string_deduper) + @zoneinfo_reader = ZoneinfoReader.new(posix_tz_parser, string_deduper) + end + + # Returns a frozen `Array` of all the available time zone identifiers. The + # identifiers are sorted according to `String#<=>`. + # + # @return [Array] a frozen `Array` of all the available time zone + # identifiers. + def data_timezone_identifiers + @timezone_identifiers + end + + # Returns an empty `Array`. There is no information about linked/aliased + # time zones in the zoneinfo files. When using {ZoneinfoDataSource}, every + # time zone will be returned as a {DataTimezone}. + # + # @return [Array] an empty `Array`. + def linked_timezone_identifiers + [].freeze + end + + # (see DataSource#to_s) + def to_s + "Zoneinfo DataSource: #{@zoneinfo_dir}" + end + + # (see DataSource#inspect) + def inspect + "#<#{self.class}: #{@zoneinfo_dir}>" + end + + protected + + # Returns a {TimezoneInfo} instance for the given time zone identifier. + # The result will either be a {ConstantOffsetDataTimezoneInfo} or a + # {TransitionsDataTimezoneInfo}. + # + # @param identifier [String] A time zone identifier. + # @return [TimezoneInfo] a {TimezoneInfo} instance for the given time zone + # identifier. + # @raise [InvalidTimezoneIdentifier] if the time zone is not found, the + # identifier is invalid, the zoneinfo file cannot be opened or the + # zoneinfo file is not valid. + def load_timezone_info(identifier) + valid_identifier = validate_timezone_identifier(identifier) + path = File.join(@zoneinfo_dir, valid_identifier) + + zoneinfo = begin + @zoneinfo_reader.read(path) + rescue Errno::EACCES, InvalidZoneinfoFile => e + raise InvalidTimezoneIdentifier, "#{e.message.encode(Encoding::UTF_8)} (loading #{valid_identifier})" + rescue Errno::EISDIR, Errno::ENAMETOOLONG, Errno::ENOENT, Errno::ENOTDIR + raise InvalidTimezoneIdentifier, "Invalid identifier: #{valid_identifier}" + end + + if zoneinfo.kind_of?(TimezoneOffset) + ConstantOffsetDataTimezoneInfo.new(valid_identifier, zoneinfo) + else + TransitionsDataTimezoneInfo.new(valid_identifier, zoneinfo) + end + end + + # (see DataSource#load_country_info) + def load_country_info(code) + lookup_country_info(@countries, code) + end + + private + + # Validates a zoneinfo directory and returns the paths to the iso3166.tab + # and zone1970.tab or zone.tab files if valid. If the directory is not + # valid, returns `nil`. + # + # The path to the iso3166.tab file may be overridden by passing in a path. + # This is treated as either absolute or relative to the current working + # directory. + # + # @param path [String] the path to a possible zoneinfo directory. + # @param iso3166_tab_path [String] an optional path to an external + # iso3166.tab file. + # @return [Array] an `Array` containing the iso3166.tab and + # zone.tab paths if the directory is valid, otherwise `nil`. + def validate_zoneinfo_dir(path, iso3166_tab_path = nil) + if File.directory?(path) + if iso3166_tab_path + return nil unless File.file?(iso3166_tab_path) + else + iso3166_tab_path = resolve_tab_path(path, ['iso3166.tab'], 'country.tab') + return nil unless iso3166_tab_path + end + + zone_tab_path = resolve_tab_path(path, ['zone1970.tab', 'zone.tab'], 'zone_sun.tab') + return nil unless zone_tab_path + + [iso3166_tab_path, zone_tab_path] + else + nil + end + end + + # Attempts to resolve the path to a tab file given its standard names and + # tab sub-directory name (as used on Solaris). + # + # @param zoneinfo_path [String] the path to a zoneinfo directory. + # @param standard_names [Array] the standard names for the tab + # file. + # @param tab_name [String] the alternate name for the tab file to check in + # the tab sub-directory. + # @return [String] the path to the tab file. + def resolve_tab_path(zoneinfo_path, standard_names, tab_name) + standard_names.each do |standard_name| + path = File.join(zoneinfo_path, standard_name) + return path if File.file?(path) + end + + path = File.join(zoneinfo_path, 'tab', tab_name) + return path if File.file?(path) + + nil + end + + # Finds a zoneinfo directory using {search_path} and + # {alternate_iso3166_tab_search_path}. + # + # @return [Array] an `Array` containing the iso3166.tab and + # zone.tab paths if a zoneinfo directory was found, otherwise `nil`. + def find_zoneinfo_dir + alternate_iso3166_tab_path = self.class.alternate_iso3166_tab_search_path.detect do |path| + File.file?(path) + end + + self.class.search_path.each do |path| + # Try without the alternate_iso3166_tab_path first. + iso3166_tab_path, zone_tab_path = validate_zoneinfo_dir(path) + return path, iso3166_tab_path, zone_tab_path if iso3166_tab_path && zone_tab_path + + if alternate_iso3166_tab_path + iso3166_tab_path, zone_tab_path = validate_zoneinfo_dir(path, alternate_iso3166_tab_path) + return path, iso3166_tab_path, zone_tab_path if iso3166_tab_path && zone_tab_path + end + end + + # Not found. + nil + end + + # Scans @zoneinfo_dir and returns an `Array` of available time zone + # identifiers. The result is sorted according to `String#<=>`. + # + # @return [Array] an `Array` containing all the time zone + # identifiers found. + def load_timezone_identifiers + index = [] + + # Ignoring particular files: + # +VERSION is included on Mac OS X. + # leapseconds is a list of leap seconds. + # localtime is the current local timezone (may be a link). + # posix, posixrules and right are directories containing other versions of the zoneinfo files. + # src is a directory containing the tzdata source included on Solaris. + # timeconfig is a symlink included on Slackware. + + enum_timezones([], ['+VERSION', 'leapseconds', 'localtime', 'posix', 'posixrules', 'right', 'src', 'timeconfig']) do |identifier| + index << identifier.join('/').freeze + end + + index.sort! + end + + # Recursively enumerate a directory of time zones. + # + # @param dir [Array] the directory to enumerate as an `Array` of + # path components. + # @param exclude [Array] file names to exclude when scanning + # `dir`. + # @yield [path] the path of each time zone file found is passed to + # the block. + # @yieldparam path [Array] the path of a time zone file as an + # `Array` of path components. + def enum_timezones(dir, exclude = [], &block) + Dir.foreach(File.join(@zoneinfo_dir, *dir)) do |entry| + begin + entry.encode!(Encoding::UTF_8) + rescue EncodingError + next + end + + unless entry =~ /\./ || exclude.include?(entry) + entry.untaint + path = dir + [entry] + full_path = File.join(@zoneinfo_dir, *path) + + if File.directory?(full_path) + enum_timezones(path, [], &block) + elsif File.file?(full_path) + yield path + end + end + end + end + + # Uses the iso3166.tab and zone1970.tab or zone.tab files to return a Hash + # mapping country codes to CountryInfo instances. + # + # @param iso3166_tab_path [String] the path to the iso3166.tab file. + # @param zone_tab_path [String] the path to the zone.tab file. + # @return [Hash] a mapping from ISO 3166-1 alpha-2 + # country codes to {CountryInfo} instances. + def load_countries(iso3166_tab_path, zone_tab_path) + + # Handle standard 3 to 4 column zone.tab files as well as the 4 to 5 + # column format used by Solaris. + # + # On Solaris, an extra column before the comment gives an optional + # linked/alternate timezone identifier (or '-' if not set). + # + # Additionally, there is a section at the end of the file for timezones + # covering regions. These are given lower-case "country" codes. The timezone + # identifier column refers to a continent instead of an identifier. These + # lines will be ignored by TZInfo. + # + # Since the last column is optional in both formats, testing for the + # Solaris format is done in two passes. The first pass identifies if there + # are any lines using 5 columns. + + + # The first column is allowed to be a comma separated list of country + # codes, as used in zone1970.tab (introduced in tzdata 2014f). + # + # The first country code in the comma-separated list is the country that + # contains the city the zone identifier is based on. The first country + # code on each line is considered to be primary with the others + # secondary. + # + # The zones for each country are ordered primary first, then secondary. + # Within the primary and secondary groups, the zones are ordered by their + # order in the file. + + file_is_5_column = false + zone_tab = [] + + file = File.read(zone_tab_path, external_encoding: Encoding::UTF_8, internal_encoding: Encoding::UTF_8) + file.each_line do |line| + line.chomp! + + if line =~ /\A([A-Z]{2}(?:,[A-Z]{2})*)\t(?:([+\-])(\d{2})(\d{2})([+\-])(\d{3})(\d{2})|([+\-])(\d{2})(\d{2})(\d{2})([+\-])(\d{3})(\d{2})(\d{2}))\t([^\t]+)(?:\t([^\t]+))?(?:\t([^\t]+))?\z/ + codes = $1 + + if $2 + latitude = dms_to_rational($2, $3, $4) + longitude = dms_to_rational($5, $6, $7) + else + latitude = dms_to_rational($8, $9, $10, $11) + longitude = dms_to_rational($12, $13, $14, $15) + end + + zone_identifier = $16 + column4 = $17 + column5 = $18 + + file_is_5_column = true if column5 + + zone_tab << [codes.split(','.freeze), zone_identifier, latitude, longitude, column4, column5] + end + end + + string_deduper = StringDeduper.new + primary_zones = {} + secondary_zones = {} + + zone_tab.each do |codes, zone_identifier, latitude, longitude, column4, column5| + description = file_is_5_column ? column5 : column4 + description = string_deduper.dedupe(description) if description + + # Lookup the identifier in the timezone index, so that the same + # String instance can be used (saving memory). + begin + zone_identifier = validate_timezone_identifier(zone_identifier) + rescue InvalidTimezoneIdentifier + # zone_identifier is not valid, dedupe and allow anyway. + zone_identifier = string_deduper.dedupe(zone_identifier) + end + + country_timezone = CountryTimezone.new(zone_identifier, latitude, longitude, description) + + # codes will always have at least one element + + (primary_zones[codes.first.freeze] ||= []) << country_timezone + + codes[1..-1].each do |code| + (secondary_zones[code.freeze] ||= []) << country_timezone + end + end + + countries = {} + + file = File.read(iso3166_tab_path, external_encoding: Encoding::UTF_8, internal_encoding: Encoding::UTF_8) + file.each_line do |line| + line.chomp! + + # Handle both the two column alpha-2 and name format used in the tz + # database as well as the 4 column alpha-2, alpha-3, numeric-3 and + # name format used by FreeBSD and OpenBSD. + + if line =~ /\A([A-Z]{2})(?:\t[A-Z]{3}\t[0-9]{3})?\t(.+)\z/ + code = $1 + name = $2 + zones = (primary_zones[code] || []) + (secondary_zones[code] || []) + + countries[code] = CountryInfo.new(code, name, zones) + end + end + + countries + end + + # Converts degrees, minutes and seconds to a Rational. + # + # @param sign [String] `'-'` or `'+'`. + # @param degrees [String] the number of degrees. + # @param minutes [String] the number of minutes. + # @param seconds [String] the number of seconds (optional). + # @return [Rational] the result of converting from degrees, minutes and + # seconds to a `Rational`. + def dms_to_rational(sign, degrees, minutes, seconds = nil) + degrees = degrees.to_i + minutes = minutes.to_i + sign = sign == '-'.freeze ? -1 : 1 + + if seconds + Rational(sign * (degrees * 3600 + minutes * 60 + seconds.to_i), 3600) + else + Rational(sign * (degrees * 60 + minutes), 60) + end + end + end + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/data_sources/zoneinfo_reader.rb ruby-tzinfo-2.0.4/lib/tzinfo/data_sources/zoneinfo_reader.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/data_sources/zoneinfo_reader.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/data_sources/zoneinfo_reader.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,486 @@ +# encoding: UTF-8 +# frozen_string_literal: true + +module TZInfo + # Use send as a workaround for erroneous 'wrong number of arguments' errors + # with JRuby 9.0.5.0 when calling methods with Java implementations. See #114. + send(:using, UntaintExt) if TZInfo.const_defined?(:UntaintExt) + + module DataSources + # An {InvalidZoneinfoFile} exception is raised if an attempt is made to load + # an invalid zoneinfo file. + class InvalidZoneinfoFile < StandardError + end + + # Reads compiled zoneinfo TZif (\0, 2 or 3) files. + class ZoneinfoReader #:nodoc: + # The year to generate transitions up to. + # + # @private + GENERATE_UP_TO = Time.now.utc.year + 100 + private_constant :GENERATE_UP_TO + + # Initializes a new {ZoneinfoReader}. + # + # @param posix_tz_parser [PosixTimeZoneParser] a {PosixTimeZoneParser} + # instance to use to parse POSIX-style TZ strings. + # @param string_deduper [StringDeduper] a {StringDeduper} instance to use + # to dedupe abbreviations. + def initialize(posix_tz_parser, string_deduper) + @posix_tz_parser = posix_tz_parser + @string_deduper = string_deduper + end + + # Reads a zoneinfo structure from the given path. Returns either a + # {TimezoneOffset} that is constantly observed or an `Array` + # {TimezoneTransition}s. + # + # @param file_path [String] the path of a zoneinfo file. + # @return [Object] either a {TimezoneOffset} or an `Array` of + # {TimezoneTransition}s. + # @raise [SecurityError] if safe mode is enabled and `file_path` is + # tainted. + # @raise [InvalidZoneinfoFile] if `file_path`` does not refer to a valid + # zoneinfo file. + def read(file_path) + File.open(file_path, 'rb') { |file| parse(file) } + end + + private + + # Translates an unsigned 32-bit integer (as returned by unpack) to signed + # 32-bit. + # + # @param long [Integer] an unsigned 32-bit integer. + # @return [Integer] {long} translated to signed 32-bit. + def make_signed_int32(long) + long >= 0x80000000 ? long - 0x100000000 : long + end + + # Translates a pair of unsigned 32-bit integers (as returned by unpack, + # most significant first) to a signed 64-bit integer. + # + # @param high [Integer] the most significant 32-bits. + # @param low [Integer] the least significant 32-bits. + # @return [Integer] {high} and {low} combined and translated to signed + # 64-bit. + def make_signed_int64(high, low) + unsigned = (high << 32) | low + unsigned >= 0x8000000000000000 ? unsigned - 0x10000000000000000 : unsigned + end + + # Reads the given number of bytes from the given file and checks that the + # correct number of bytes could be read. + # + # @param file [IO] the file to read from. + # @param bytes [Integer] the number of bytes to read. + # @return [String] the bytes that were read. + # @raise [InvalidZoneinfoFile] if the number of bytes available didn't + # match the number requested. + def check_read(file, bytes) + result = file.read(bytes) + + unless result && result.length == bytes + raise InvalidZoneinfoFile, "Expected #{bytes} bytes reading '#{file.path}', but got #{result ? result.length : 0} bytes" + end + + result + end + + # Zoneinfo files don't include the offset from standard time (std_offset) + # for DST periods. Derive the base offset (base_utc_offset) where DST is + # observed from either the previous or next non-DST period. + # + # @param transitions [Array] an `Array` of transition hashes. + # @param offsets [Array] an `Array` of offset hashes. + # @return [Integer] the index of the offset to be used prior to the first + # transition. + def derive_offsets(transitions, offsets) + # The first non-DST offset (if there is one) is the offset observed + # before the first transition. Fall back to the first DST offset if + # there are no non-DST offsets. + first_non_dst_offset_index = offsets.index {|o| !o[:is_dst] } + first_offset_index = first_non_dst_offset_index || 0 + return first_offset_index if transitions.empty? + + # Determine the base_utc_offset of the next non-dst offset at each transition. + base_utc_offset_from_next = nil + + transitions.reverse_each do |transition| + offset = offsets[transition[:offset]] + if offset[:is_dst] + transition[:base_utc_offset_from_next] = base_utc_offset_from_next if base_utc_offset_from_next + else + base_utc_offset_from_next = offset[:observed_utc_offset] + end + end + + base_utc_offset_from_previous = first_non_dst_offset_index ? offsets[first_non_dst_offset_index][:observed_utc_offset] : nil + defined_offsets = {} + + transitions.each do |transition| + offset_index = transition[:offset] + offset = offsets[offset_index] + observed_utc_offset = offset[:observed_utc_offset] + + if offset[:is_dst] + base_utc_offset_from_next = transition[:base_utc_offset_from_next] + + difference_to_previous = (observed_utc_offset - (base_utc_offset_from_previous || observed_utc_offset)).abs + difference_to_next = (observed_utc_offset - (base_utc_offset_from_next || observed_utc_offset)).abs + + base_utc_offset = if difference_to_previous == 3600 + base_utc_offset_from_previous + elsif difference_to_next == 3600 + base_utc_offset_from_next + elsif difference_to_previous > 0 && difference_to_next > 0 + difference_to_previous < difference_to_next ? base_utc_offset_from_previous : base_utc_offset_from_next + elsif difference_to_previous > 0 + base_utc_offset_from_previous + elsif difference_to_next > 0 + base_utc_offset_from_next + else + # No difference, assume a 1 hour offset from standard time. + observed_utc_offset - 3600 + end + + if !offset[:base_utc_offset] + offset[:base_utc_offset] = base_utc_offset + defined_offsets[offset] = offset_index + elsif offset[:base_utc_offset] != base_utc_offset + # An earlier transition has already derived a different + # base_utc_offset. Define a new offset or reuse an existing identically + # defined offset. + new_offset = offset.dup + new_offset[:base_utc_offset] = base_utc_offset + + offset_index = defined_offsets[new_offset] + + unless offset_index + offsets << new_offset + offset_index = offsets.length - 1 + defined_offsets[new_offset] = offset_index + end + + transition[:offset] = offset_index + end + else + base_utc_offset_from_previous = observed_utc_offset + end + end + + first_offset_index + end + + # Determines if the offset from a transition matches the offset from a + # rule. This is a looser match than equality, not requiring that the + # base_utc_offset and std_offset both match (which have to be derived for + # transitions, but are known for rules. + # + # @param offset [TimezoneOffset] an offset from a transition. + # @param rule_offset [TimezoneOffset] an offset from a rule. + # @return [Boolean] whether the offsets match. + def offset_matches_rule?(offset, rule_offset) + offset.observed_utc_offset == rule_offset.observed_utc_offset && + offset.dst? == rule_offset.dst? && + offset.abbreviation == rule_offset.abbreviation + end + + # Apply the rules from the TZ string when there were no defined + # transitions. Checks for a matching offset. Returns the rules-based + # constant offset or generates transitions from 1970 until 100 years into + # the future (at the time of loading zoneinfo_reader.rb). + # + # @param file [IO] the file being processed. + # @param first_offset [TimezoneOffset] the first offset included in the + # file that would normally apply without the rules. + # @param rules [Object] a {TimezoneOffset} specifying a constant offset or + # {AnnualRules} instance specfying transitions. + # @return [Object] either a {TimezoneOffset} or an `Array` of + # {TimezoneTransition}s. + # @raise [InvalidZoneinfoFile] if the first offset does not match the + # rules. + def apply_rules_without_transitions(file, first_offset, rules) + if rules.kind_of?(TimezoneOffset) + unless offset_matches_rule?(first_offset, rules) + raise InvalidZoneinfoFile, "Constant offset POSIX-style TZ string does not match constant offset in file '#{file.path}'." + end + rules + else + transitions = 1970.upto(GENERATE_UP_TO).flat_map {|y| rules.transitions(y) } + first_transition = transitions[0] + + unless offset_matches_rule?(first_offset, first_transition.previous_offset) + # Not transitioning from the designated first offset. + + if offset_matches_rule?(first_offset, first_transition.offset) + # Skip an unnecessary transition to the first offset. + transitions.shift + else + # The initial offset doesn't match the ongoing rules. Replace the + # previous offset of the first transition. + transitions[0] = TimezoneTransition.new(first_transition.offset, first_offset, first_transition.timestamp_value) + end + end + + transitions + end + end + + # Finds an offset that is equivalent to the one specified in the given + # `Array`. Matching is performed with {TimezoneOffset#==}. + # + # @param offsets [Array] an `Array` to search. + # @param offset [TimezoneOffset] the offset to search for. + # @return [TimezoneOffset] the matching offset from `offsets` or `nil` + # if not found. + def find_existing_offset(offsets, offset) + offsets.find {|o| o == offset } + end + + # Returns a new AnnualRules instance with standard and daylight savings + # offsets replaced with equivalents from an array. This reduces the memory + # requirement for loaded time zones by reusing offsets for rule-generated + # transitions. + # + # @param offsets [Array] an `Array` to search for + # equivalent offsets. + # @param annual_rules [AnnualRules] the {AnnualRules} instance to check. + # @return [AnnualRules] either a new {AnnualRules} instance with either + # the {AnnualRules#std_offset std_offset} or {AnnualRules#dst_offset + # dst_offset} replaced, or the original instance if no equivalent for + # either {AnnualRules#std_offset std_offset} or {AnnualRules#dst_offset + # dst_offset} could be found. + def replace_with_existing_offsets(offsets, annual_rules) + existing_std_offset = find_existing_offset(offsets, annual_rules.std_offset) + existing_dst_offset = find_existing_offset(offsets, annual_rules.dst_offset) + if existing_std_offset || existing_dst_offset + AnnualRules.new(existing_std_offset || annual_rules.std_offset, existing_dst_offset || annual_rules.dst_offset, + annual_rules.dst_start_rule, annual_rules.dst_end_rule) + else + annual_rules + end + end + + # Validates the offset indicated to be observed by the rules before the + # first generated transition against the offset of the last defined + # transition. + # + # Fix the last defined transition if it differ on just base/std offsets + # (which are derived). Raise an error if the observed UTC offset or + # abbreviations differ. + # + # @param file [IO] the file being processed. + # @param last_defined [TimezoneTransition] the last defined transition in + # the file. + # @param first_rule_offset [TimezoneOffset] the offset the rules indicate + # is observed prior to the first rules generated transition. + # @return [TimezoneTransition] the last defined transition (either the + # original instance or a replacement). + # @raise [InvalidZoneinfoFile] if the offset of {last_defined} and + # {first_rule_offset} do not match. + def validate_and_fix_last_defined_transition_offset(file, last_defined, first_rule_offset) + offset_of_last_defined = last_defined.offset + + if offset_of_last_defined == first_rule_offset + last_defined + else + if offset_matches_rule?(offset_of_last_defined, first_rule_offset) + # The same overall offset, but differing in the base or std + # offset (which are derived). Correct by using the rule. + TimezoneTransition.new(first_rule_offset, last_defined.previous_offset, last_defined.timestamp_value) + else + raise InvalidZoneinfoFile, "The first offset indicated by the POSIX-style TZ string did not match the final defined offset in file '#{file.path}'." + end + end + end + + # Apply the rules from the TZ string when there were defined + # transitions. Checks for a matching offset with the last transition. + # Redefines the last transition if required and if the rules don't + # specific a constant offset, generates transitions until 100 years into + # the future (at the time of loading zoneinfo_reader.rb). + # + # @param file [IO] the file being processed. + # @param transitions [Array] the defined transitions. + # @param offsets [Array] the offsets used by the defined + # transitions. + # @param rules [Object] a {TimezoneOffset} specifying a constant offset or + # {AnnualRules} instance specfying transitions. + # @raise [InvalidZoneinfoFile] if the first offset does not match the + # rules. + # @raise [InvalidZoneinfoFile] if the previous offset of the first + # generated transition does not match the offset of the last defined + # transition. + def apply_rules_with_transitions(file, transitions, offsets, rules) + last_defined = transitions[-1] + + if rules.kind_of?(TimezoneOffset) + transitions[-1] = validate_and_fix_last_defined_transition_offset(file, last_defined, rules) + else + last_year = last_defined.local_end_at.to_time.year + + if last_year <= GENERATE_UP_TO + rules = replace_with_existing_offsets(offsets, rules) + + generated = rules.transitions(last_year).find_all do |t| + t.timestamp_value > last_defined.timestamp_value && !offset_matches_rule?(last_defined.offset, t.offset) + end + + generated += (last_year + 1).upto(GENERATE_UP_TO).flat_map {|y| rules.transitions(y) } + + unless generated.empty? + transitions[-1] = validate_and_fix_last_defined_transition_offset(file, last_defined, generated[0].previous_offset) + transitions.concat(generated) + end + end + end + end + + # Parses a zoneinfo file and returns either a {TimezoneOffset} that is + # constantly observed or an `Array` of {TimezoneTransition}s. + # + # @param file [IO] the file to be read. + # @return [Object] either a {TimezoneOffset} or an `Array` of + # {TimezoneTransition}s. + # @raise [InvalidZoneinfoFile] if the file is not a valid zoneinfo file. + def parse(file) + magic, version, ttisutccnt, ttisstdcnt, leapcnt, timecnt, typecnt, charcnt = + check_read(file, 44).unpack('a4 a x15 NNNNNN') + + if magic != 'TZif' + raise InvalidZoneinfoFile, "The file '#{file.path}' does not start with the expected header." + end + + if version == '2' || version == '3' + # Skip the first 32-bit section and read the header of the second 64-bit section + file.seek(timecnt * 5 + typecnt * 6 + charcnt + leapcnt * 8 + ttisstdcnt + ttisutccnt, IO::SEEK_CUR) + + prev_version = version + + magic, version, ttisutccnt, ttisstdcnt, leapcnt, timecnt, typecnt, charcnt = + check_read(file, 44).unpack('a4 a x15 NNNNNN') + + unless magic == 'TZif' && (version == prev_version) + raise InvalidZoneinfoFile, "The file '#{file.path}' contains an invalid 64-bit section header." + end + + using_64bit = true + elsif version != '3' && version != '2' && version != "\0" + raise InvalidZoneinfoFile, "The file '#{file.path}' contains a version of the zoneinfo format that is not currently supported." + else + using_64bit = false + end + + unless leapcnt == 0 + raise InvalidZoneinfoFile, "The file '#{file.path}' contains leap second data. TZInfo requires zoneinfo files that omit leap seconds." + end + + transitions = if using_64bit + timecnt.times.map do |i| + high, low = check_read(file, 8).unpack('NN'.freeze) + transition_time = make_signed_int64(high, low) + {at: transition_time} + end + else + timecnt.times.map do |i| + transition_time = make_signed_int32(check_read(file, 4).unpack('N'.freeze)[0]) + {at: transition_time} + end + end + + check_read(file, timecnt).unpack('C*'.freeze).each_with_index do |localtime_type, i| + raise InvalidZoneinfoFile, "Invalid offset referenced by transition in file '#{file.path}'." if localtime_type >= typecnt + transitions[i][:offset] = localtime_type + end + + offsets = typecnt.times.map do |i| + gmtoff, isdst, abbrind = check_read(file, 6).unpack('NCC'.freeze) + gmtoff = make_signed_int32(gmtoff) + isdst = isdst == 1 + {observed_utc_offset: gmtoff, is_dst: isdst, abbr_index: abbrind} + end + + abbrev = check_read(file, charcnt) + + if using_64bit + # Skip to the POSIX-style TZ string. + file.seek(ttisstdcnt + ttisutccnt, IO::SEEK_CUR) # + leapcnt * 8, but leapcnt is checked above and guaranteed to be 0. + tz_string_start = check_read(file, 1) + raise InvalidZoneinfoFile, "Expected newline starting POSIX-style TZ string in file '#{file.path}'." unless tz_string_start == "\n" + tz_string = file.readline("\n").force_encoding(Encoding::UTF_8) + raise InvalidZoneinfoFile, "Expected newline ending POSIX-style TZ string in file '#{file.path}'." unless tz_string.chomp!("\n") + + begin + rules = @posix_tz_parser.parse(tz_string) + rescue InvalidPosixTimeZone => e + raise InvalidZoneinfoFile, "Failed to parse POSIX-style TZ string in file '#{file.path}': #{e}" + end + else + rules = nil + end + + # Derive the offsets from standard time (std_offset). + first_offset_index = derive_offsets(transitions, offsets) + + offsets = offsets.map do |o| + observed_utc_offset = o[:observed_utc_offset] + base_utc_offset = o[:base_utc_offset] + + if base_utc_offset + # DST offset with base_utc_offset derived by derive_offsets. + std_offset = observed_utc_offset - base_utc_offset + elsif o[:is_dst] + # DST offset unreferenced by a transition (offset in use before the + # first transition). No derived base UTC offset, so assume 1 hour + # DST. + base_utc_offset = observed_utc_offset - 3600 + std_offset = 3600 + else + # Non-DST offset. + base_utc_offset = observed_utc_offset + std_offset = 0 + end + + abbrev_start = o[:abbr_index] + raise InvalidZoneinfoFile, "Abbreviation index is out of range in file '#{file.path}'." unless abbrev_start < abbrev.length + + abbrev_end = abbrev.index("\0", abbrev_start) + raise InvalidZoneinfoFile, "Missing abbreviation null terminator in file '#{file.path}'." unless abbrev_end + + abbr = @string_deduper.dedupe(abbrev[abbrev_start...abbrev_end].force_encoding(Encoding::UTF_8).untaint) + + TimezoneOffset.new(base_utc_offset, std_offset, abbr) + end + + first_offset = offsets[first_offset_index] + + + if transitions.empty? + if rules + apply_rules_without_transitions(file, first_offset, rules) + else + first_offset + end + else + previous_offset = first_offset + previous_at = nil + + transitions = transitions.map do |t| + offset = offsets[t[:offset]] + at = t[:at] + raise InvalidZoneinfoFile, "Transition at #{at} is not later than the previous transition at #{previous_at} in file '#{file.path}'." if previous_at && previous_at >= at + tt = TimezoneTransition.new(offset, previous_offset, at) + previous_offset = offset + previous_at = at + tt + end + + apply_rules_with_transitions(file, transitions, offsets, rules) if rules + transitions + end + end + end + private_constant :ZoneinfoReader + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/data_sources.rb ruby-tzinfo-2.0.4/lib/tzinfo/data_sources.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/data_sources.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/data_sources.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,8 @@ +# encoding: UTF-8 + +module TZInfo + # {DataSource} implementations and classes used by {DataSource} + # implementations. + module DataSources + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/data_timezone_info.rb ruby-tzinfo-2.0.4/lib/tzinfo/data_timezone_info.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/data_timezone_info.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/data_timezone_info.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,55 +0,0 @@ -module TZInfo - # Represents a defined timezone containing transition data. - class DataTimezoneInfo < TimezoneInfo - - # Returns the TimezonePeriod for the given UTC time. - def period_for_utc(utc) - raise_not_implemented('period_for_utc') - end - - # Returns the set of TimezonePeriods for the given local time as an array. - # Results returned are ordered by increasing UTC start date. - # Returns an empty array if no periods are found for the given time. - def periods_for_local(local) - raise_not_implemented('periods_for_local') - end - - # Returns an Array of TimezoneTransition instances representing the times - # where the UTC offset of the timezone changes. - # - # Transitions are returned up to a given date and time up to a given date - # and time, specified in UTC (utc_to). - # - # A from date and time may also be supplied using the utc_from parameter - # (also specified in UTC). If utc_from is not nil, only transitions from - # that date and time onwards will be returned. - # - # Comparisons with utc_to are exclusive. Comparisons with utc_from are - # inclusive. If a transition falls precisely on utc_to, it will be excluded. - # If a transition falls on utc_from, it will be included. - # - # Transitions returned are ordered by when they occur, from earliest to - # latest. - # - # utc_to and utc_from can be specified using either DateTime, Time or - # integer timestamps (Time.to_i). - # - # If utc_from is specified and utc_to is not greater than utc_from, then - # transitions_up_to raises an ArgumentError exception. - def transitions_up_to(utc_to, utc_from = nil) - raise_not_implemented('transitions_up_to') - end - - # Constructs a Timezone instance for the timezone represented by this - # DataTimezoneInfo. - def create_timezone - DataTimezone.new(self) - end - - private - - def raise_not_implemented(method_name) - raise NotImplementedError, "Subclasses must override #{method_name}" - end - end -end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/data_timezone.rb ruby-tzinfo-2.0.4/lib/tzinfo/data_timezone.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/data_timezone.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/data_timezone.rb 2020-12-30 06:49:15.000000000 +0000 @@ -1,56 +1,42 @@ +# encoding: UTF-8 +# frozen_string_literal: true + module TZInfo + # Represents time zones that are defined by rules that set out when + # transitions occur. + class DataTimezone < InfoTimezone + # (see Timezone#period_for) + def period_for(time) + raise ArgumentError, 'time must be specified' unless time + timestamp = Timestamp.for(time) + raise ArgumentError, 'time must have a specified utc_offset' unless timestamp.utc_offset + info.period_for(timestamp) + end - # A Timezone based on a DataTimezoneInfo. - # - # @private - class DataTimezone < InfoTimezone #:nodoc: - - # Returns the TimezonePeriod for the given UTC time. utc can either be - # a DateTime, Time or integer timestamp (Time.to_i). Any timezone - # information in utc is ignored (it is treated as a UTC time). - # - # If no TimezonePeriod could be found, PeriodNotFound is raised. - def period_for_utc(utc) - info.period_for_utc(utc) + # (see Timezone#periods_for_local) + def periods_for_local(local_time) + raise ArgumentError, 'local_time must be specified' unless local_time + info.periods_for_local(Timestamp.for(local_time, :ignore)) end - - # Returns the set of TimezonePeriod instances that are valid for the given - # local time as an array. If you just want a single period, use - # period_for_local instead and specify how abiguities should be resolved. - # Raises PeriodNotFound if no periods are found for the given time. - def periods_for_local(local) - info.periods_for_local(local) + + # (see Timezone#transitions_up_to) + def transitions_up_to(to, from = nil) + raise ArgumentError, 'to must be specified' unless to + to_timestamp = Timestamp.for(to) + from_timestamp = from && Timestamp.for(from) + + begin + info.transitions_up_to(to_timestamp, from_timestamp) + rescue ArgumentError => e + raise ArgumentError, e.message.gsub('_timestamp', '') + end end - - # Returns an Array of TimezoneTransition instances representing the times - # where the UTC offset of the timezone changes. - # - # Transitions are returned up to a given date and time up to a given date - # and time, specified in UTC (utc_to). - # - # A from date and time may also be supplied using the utc_from parameter - # (also specified in UTC). If utc_from is not nil, only transitions from - # that date and time onwards will be returned. - # - # Comparisons with utc_to are exclusive. Comparisons with utc_from are - # inclusive. If a transition falls precisely on utc_to, it will be excluded. - # If a transition falls on utc_from, it will be included. - # - # Transitions returned are ordered by when they occur, from earliest to - # latest. - # - # utc_to and utc_from can be specified using either DateTime, Time or - # integer timestamps (Time.to_i). + + # Returns the canonical {Timezone} instance for this {DataTimezone}. # - # If utc_from is specified and utc_to is not greater than utc_from, then - # transitions_up_to raises an ArgumentError exception. - def transitions_up_to(utc_to, utc_from = nil) - info.transitions_up_to(utc_to, utc_from) - end - - # Returns the canonical zone for this Timezone. + # For a {DataTimezone}, this is always `self`. # - # For a DataTimezone, this is always self. + # @return [Timezone] `self`. def canonical_zone self end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/datetime_with_offset.rb ruby-tzinfo-2.0.4/lib/tzinfo/datetime_with_offset.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/datetime_with_offset.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/datetime_with_offset.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,153 @@ +# encoding: UTF-8 +# frozen_string_literal: true + +require 'date' + +module TZInfo + # A subclass of `DateTime` used to represent local times. {DateTimeWithOffset} + # holds a reference to the related {TimezoneOffset} and overrides various + # methods to return results appropriate for the {TimezoneOffset}. Certain + # operations will clear the associated {TimezoneOffset} (if the + # {TimezoneOffset} would not necessarily be valid for the result). Once the + # {TimezoneOffset} has been cleared, {DateTimeWithOffset} behaves identically + # to `DateTime`. + # + # Arithmetic performed on {DateTimeWithOffset} instances is _not_ time + # zone-aware. Regardless of whether transitions in the time zone are crossed, + # results of arithmetic operations will always maintain the same offset from + # UTC (`offset`). The associated {TimezoneOffset} will aways be cleared. + class DateTimeWithOffset < DateTime + include WithOffset + + # @return [TimezoneOffset] the {TimezoneOffset} associated with this + # instance. + attr_reader :timezone_offset + + # Sets the associated {TimezoneOffset}. + # + # @param timezone_offset [TimezoneOffset] a {TimezoneOffset} valid at the + # time and for the offset of this {DateTimeWithOffset}. + # @return [DateTimeWithOffset] `self`. + # @raise [ArgumentError] if `timezone_offset` is `nil`. + # @raise [ArgumentError] if `timezone_offset.observed_utc_offset` does not + # equal `self.offset * 86400`. + def set_timezone_offset(timezone_offset) + raise ArgumentError, 'timezone_offset must be specified' unless timezone_offset + raise ArgumentError, 'timezone_offset.observed_utc_offset does not match self.utc_offset' if offset * 86400 != timezone_offset.observed_utc_offset + @timezone_offset = timezone_offset + self + end + + # An overridden version of `DateTime#to_time` that, if there is an + # associated {TimezoneOffset}, returns a {DateTimeWithOffset} with that + # offset. + # + # @return [Time] if there is an associated {TimezoneOffset}, a + # {TimeWithOffset} representation of this {DateTimeWithOffset}, otherwise + # a `Time` representation. + def to_time + if_timezone_offset(super) do |o,t| + # Ruby 2.4.0 changed the behaviour of to_time so that it preserves the + # offset instead of converting to the system local timezone. + # + # When self has an associated TimezonePeriod, this implementation will + # preserve the offset on all versions of Ruby. + TimeWithOffset.at(t.to_i, t.subsec * 1_000_000).set_timezone_offset(o) + end + end + + # An overridden version of `DateTime#downto` that clears the associated + # {TimezoneOffset} of the returned or yielded instances. + def downto(min) + if block_given? + super {|dt| yield dt.clear_timezone_offset } + else + enum = super + enum.each {|dt| dt.clear_timezone_offset } + enum + end + end + + # An overridden version of `DateTime#england` that preserves the associated + # {TimezoneOffset}. + # + # @return [DateTime] + def england + # super doesn't call #new_start on MRI, so each method has to be + # individually overridden. + if_timezone_offset(super) {|o,dt| dt.set_timezone_offset(o) } + end + + # An overridden version of `DateTime#gregorian` that preserves the + # associated {TimezoneOffset}. + # + # @return [DateTime] + def gregorian + # super doesn't call #new_start on MRI, so each method has to be + # individually overridden. + if_timezone_offset(super) {|o,dt| dt.set_timezone_offset(o) } + end + + # An overridden version of `DateTime#italy` that preserves the associated + # {TimezoneOffset}. + # + # @return [DateTime] + def italy + # super doesn't call #new_start on MRI, so each method has to be + # individually overridden. + if_timezone_offset(super) {|o,dt| dt.set_timezone_offset(o) } + end + + # An overridden version of `DateTime#julian` that preserves the associated + # {TimezoneOffset}. + # + # @return [DateTime] + def julian + # super doesn't call #new_start on MRI, so each method has to be + # individually overridden. + if_timezone_offset(super) {|o,dt| dt.set_timezone_offset(o) } + end + + # An overridden version of `DateTime#new_start` that preserves the + # associated {TimezoneOffset}. + # + # @return [DateTime] + def new_start(start = Date::ITALY) + if_timezone_offset(super) {|o,dt| dt.set_timezone_offset(o) } + end + + # An overridden version of `DateTime#step` that clears the associated + # {TimezoneOffset} of the returned or yielded instances. + def step(limit, step = 1) + if block_given? + super {|dt| yield dt.clear_timezone_offset } + else + enum = super + enum.each {|dt| dt.clear_timezone_offset } + enum + end + end + + # An overridden version of `DateTime#upto` that clears the associated + # {TimezoneOffset} of the returned or yielded instances. + def upto(max) + if block_given? + super {|dt| yield dt.clear_timezone_offset } + else + enum = super + enum.each {|dt| dt.clear_timezone_offset } + enum + end + end + + protected + + # Clears the associated {TimezoneOffset}. + # + # @return [DateTimeWithOffset] `self`. + def clear_timezone_offset + @timezone_offset = nil + self + end + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/format1/country_definer.rb ruby-tzinfo-2.0.4/lib/tzinfo/format1/country_definer.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/format1/country_definer.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/format1/country_definer.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,17 @@ +# encoding: UTF-8 + +module TZInfo + module Format1 + # Instances of {Format1::CountryDefiner} are yielded to the format 1 version + # of `TZInfo::Data::Indexes::Countries` by {CountryIndexDefinition} to allow + # the zones of a country to be specified. + # + # @private + class CountryDefiner < Format2::CountryDefiner #:nodoc: + # Initializes a new {CountryDefiner}. + def initialize(identifier_deduper, description_deduper) + super(nil, identifier_deduper, description_deduper) + end + end + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/format1/country_index_definition.rb ruby-tzinfo-2.0.4/lib/tzinfo/format1/country_index_definition.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/format1/country_index_definition.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/format1/country_index_definition.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,64 @@ +# encoding: UTF-8 + +module TZInfo + module Format1 + # The format 1 TZInfo::Data country index file includes + # {Format1::CountryIndexDefinition}, which provides a + # {CountryIndexDefinition::ClassMethods#country country} method used to + # define each country in the index. + # + # @private + module CountryIndexDefinition #:nodoc: + # Adds class methods to the includee and initializes class instance + # variables. + # + # @param base [Module] the includee. + def self.append_features(base) + super + base.extend(ClassMethods) + base.instance_eval { @countries = {} } + end + + # Class methods for inclusion. + # + # @private + module ClassMethods #:nodoc: + # @return [Hash] a frozen `Hash` + # of all the countries that have been defined in the index keyed by + # their codes. + def countries + @description_deduper = nil + @countries.freeze + end + + private + + # Defines a country with an ISO 3166-1 alpha-2 country code and name. + # + # @param code [String] the ISO 3166-1 alpha-2 country code. + # @param name [String] the name of the country. + # @yield [definer] (optional) to obtain the time zones for the country. + # @yieldparam definer [CountryDefiner] a {CountryDefiner} instance. + def country(code, name) + @description_deduper ||= StringDeduper.new + + zones = if block_given? + definer = CountryDefiner.new(StringDeduper.global, @description_deduper) + yield definer + definer.timezones + else + [] + end + + @countries[code.freeze] = DataSources::CountryInfo.new(code, name, zones) + end + end + end + end + + # Alias used by TZInfo::Data format1 releases. + # + # @private + CountryIndexDefinition = Format1::CountryIndexDefinition #:nodoc: + private_constant :CountryIndexDefinition +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/format1/timezone_definer.rb ruby-tzinfo-2.0.4/lib/tzinfo/format1/timezone_definer.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/format1/timezone_definer.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/format1/timezone_definer.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,64 @@ +# encoding: UTF-8 +# frozen_string_literal: true + +module TZInfo + module Format1 + # Instances of {Format1::TimezoneDefiner} are yielded to TZInfo::Data + # format 1 modules by {TimezoneDefinition} to allow the offsets and + # transitions of the time zone to be specified. + # + # @private + class TimezoneDefiner < Format2::TimezoneDefiner #:nodoc: + undef_method :subsequent_rules + + # Defines an offset. + # + # @param id [Symbol] an arbitrary value used identify the offset in + # subsequent calls to transition. It must be unique. + # @param utc_offset [Integer] the base offset from UTC of the zone in + # seconds. This does not include daylight savings time. + # @param std_offset [Integer] the daylight savings offset from the base + # offset in seconds. Typically either 0 or 3600. + # @param abbreviation [Symbol] an abbreviation for the offset, for + # example, `:EST` or `:EDT`. + # @raise [ArgumentError] if another offset has already been defined with + # the given id. + def offset(id, utc_offset, std_offset, abbreviation) + super(id, utc_offset, std_offset, abbreviation.to_s) + end + + # Defines a transition to a given offset. + # + # Transitions must be defined in increasing time order. + # + # @param year [Integer] the UTC year in which the transition occurs. Used + # in earlier versions of TZInfo, but now ignored. + # @param month [Integer] the UTC month in which the transition occurs. + # Used in earlier versions of TZInfo, but now ignored. + # @param offset_id [Symbol] references the id of a previously defined + # offset (see #offset). + # @param timestamp_value [Integer] the time the transition occurs as an + # Integer number of seconds since 1970-01-01 00:00:00 UTC ignoring leap + # seconds (i.e. each day is treated as if it were 86,400 seconds long). + # @param datetime_numerator [Integer] the time of the transition as the + # numerator of the `Rational` returned by `DateTime#ajd`. Used in + # earlier versions of TZInfo, but now ignored. + # @param datetime_denominator [Integer] the time of the transition as the + # denominator of the `Rational` returned by `DateTime#ajd`. Used in + # earlier versions of TZInfo, but now ignored. + # @raise [ArgumentError] if `offset_id` does not reference a defined + # offset. + # @raise [ArgumentError] if `timestamp_value` is not greater than the + # `timestamp_value` of the previously defined transition. + # @raise [ArgumentError] if `datetime_numerator` is specified, but + # `datetime_denominator` is not. In older versions of TZInfo, it was + # possible to define a transition with the `DateTime` numerator as the + # 4th parameter and the denominator as the 5th parameter. This style of + # definition is not used in released versions of TZInfo::Data. + def transition(year, month, offset_id, timestamp_value, datetime_numerator = nil, datetime_denominator = nil) + raise ArgumentError, 'DateTime-only transitions are not supported' if datetime_numerator && !datetime_denominator + super(offset_id, timestamp_value) + end + end + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/format1/timezone_definition.rb ruby-tzinfo-2.0.4/lib/tzinfo/format1/timezone_definition.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/format1/timezone_definition.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/format1/timezone_definition.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,39 @@ +# encoding: UTF-8 + +module TZInfo + module Format1 + # {Format1::TimezoneDefinition} is included into format 1 time zone + # definition modules and provides the methods for defining time zones. + # + # @private + module TimezoneDefinition #:nodoc: + # Adds class methods to the includee. + # + # @param base [Module] the includee. + def self.append_features(base) + super + base.extend(Format2::TimezoneDefinition::ClassMethods) + base.extend(ClassMethods) + end + + # Class methods for inclusion. + # + # @private + module ClassMethods #:nodoc: + private + + # @return the class to be instantiated and yielded by + # {Format2::TimezoneDefinition::ClassMethods#timezone}. + def timezone_definer_class + TimezoneDefiner + end + end + end + end + + # Alias used by TZInfo::Data format1 releases. + # + # @private + TimezoneDefinition = Format1::TimezoneDefinition #:nodoc: + private_constant :TimezoneDefinition +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/format1/timezone_index_definition.rb ruby-tzinfo-2.0.4/lib/tzinfo/format1/timezone_index_definition.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/format1/timezone_index_definition.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/format1/timezone_index_definition.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,77 @@ +# encoding: UTF-8 + +module TZInfo + module Format1 + # The format 1 TZInfo::Data time zone index file includes + # {Format1::TimezoneIndexDefinition}, which provides methods used to define + # time zones in the index. + # + # @private + module TimezoneIndexDefinition #:nodoc: + # Adds class methods to the includee and initializes class instance + # variables. + # + # @param base [Module] the includee. + def self.append_features(base) + super + base.extend(ClassMethods) + base.instance_eval do + @timezones = [] + @data_timezones = [] + @linked_timezones = [] + end + end + + # Class methods for inclusion. + # + # @private + module ClassMethods #:nodoc: + # @return [Array] a frozen `Array` containing the identifiers of + # all data time zones. Identifiers are sorted according to + # `String#<=>`. + def data_timezones + unless @data_timezones.frozen? + @data_timezones = @data_timezones.sort.freeze + end + @data_timezones + end + + # @return [Array] a frozen `Array` containing the identifiers of + # all linked time zones. Identifiers are sorted according to + # `String#<=>`. + def linked_timezones + unless @linked_timezones.frozen? + @linked_timezones = @linked_timezones.sort.freeze + end + @linked_timezones + end + + private + + # Adds a data time zone to the index. + # + # @param identifier [String] the time zone identifier. + def timezone(identifier) + identifier = StringDeduper.global.dedupe(identifier) + @timezones << identifier + @data_timezones << identifier + end + + # Adds a linked time zone to the index. + # + # @param identifier [String] the time zone identifier. + def linked_timezone(identifier) + identifier = StringDeduper.global.dedupe(identifier) + @timezones << identifier + @linked_timezones << identifier + end + end + end + end + + # Alias used by TZInfo::Data format 1 releases. + # + # @private + TimezoneIndexDefinition = Format1::TimezoneIndexDefinition #:nodoc: + private_constant :TimezoneIndexDefinition +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/format1.rb ruby-tzinfo-2.0.4/lib/tzinfo/format1.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/format1.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/format1.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,10 @@ +# encoding: UTF-8 + +module TZInfo + # Modules and classes used by the format 1 version of TZInfo::Data. + # + # @private + module Format1 #:nodoc: + end + private_constant :Format1 +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/format2/country_definer.rb ruby-tzinfo-2.0.4/lib/tzinfo/format2/country_definer.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/format2/country_definer.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/format2/country_definer.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,68 @@ +# encoding: UTF-8 +# frozen_string_literal: true + +module TZInfo + module Format2 + # Instances of {Format2::CountryDefiner} are yielded to the format 2 version + # of `TZInfo::Data::Indexes::Countries` by {CountryIndexDefiner} to allow + # the zones of a country to be specified. + # + # @private + class CountryDefiner #:nodoc: + # @return [Array] the time zones observed in the country. + attr_reader :timezones + + # Initializes a new {CountryDefiner}. + # + # @param shared_timezones [Hash] a `Hash` + # containing time zones shared by more than one country, keyed by a + # unique reference. + # @param identifier_deduper [StringDeduper] a {StringDeduper} instance to + # use when deduping time zone identifiers. + # @param description_deduper [StringDeduper] a {StringDeduper} instance to + # use when deduping time zone descriptions. + def initialize(shared_timezones, identifier_deduper, description_deduper) + @shared_timezones = shared_timezones + @identifier_deduper = identifier_deduper + @description_deduper = description_deduper + @timezones = [] + end + + # @overload timezone(reference) + # Defines a time zone of a country as a reference to a pre-defined + # shared time zone. + # @param reference [Symbol] a reference for a pre-defined shared time + # zone. + # @overload timezone(identifier, latitude_numerator, latitude_denominator, longitude_numerator, longitude_denominator, description) + # Defines a (non-shared) time zone of a country. The latitude and + # longitude are given as the numerator and denominator of a `Rational`. + # @param identifier [String] the time zone identifier. + # @param latitude_numerator [Integer] the numerator of the latitude. + # @param latitude_denominator [Integer] the denominator of the latitude. + # @param longitude_numerator [Integer] the numerator of the longitude. + # @param longitude_denominator [Integer] the denominator of the + # longitude. + # @param description [String] an optional description for the time zone. + def timezone(identifier_or_reference, latitude_numerator = nil, + latitude_denominator = nil, longitude_numerator = nil, + longitude_denominator = nil, description = nil) + if latitude_numerator + unless latitude_denominator && longitude_numerator && longitude_denominator + raise ArgumentError, 'Either just a reference should be supplied, or the identifier, latitude and longitude must all be specified' + end + + # Dedupe non-frozen literals from format 1 on all Ruby versions and + # format 2 on Ruby < 2.3 (without frozen_string_literal support). + + @timezones << CountryTimezone.new(@identifier_deduper.dedupe(identifier_or_reference), + Rational(latitude_numerator, latitude_denominator), + Rational(longitude_numerator, longitude_denominator), description && @description_deduper.dedupe(description)) + else + shared_timezone = @shared_timezones[identifier_or_reference] + raise ArgumentError, "Unknown shared timezone: #{identifier_or_reference}" unless shared_timezone + @timezones << shared_timezone + end + end + end + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/format2/country_index_definer.rb ruby-tzinfo-2.0.4/lib/tzinfo/format2/country_index_definer.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/format2/country_index_definer.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/format2/country_index_definer.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,68 @@ +# encoding: UTF-8 + +module TZInfo + module Format2 + # Instances of {Format2::CountryIndexDefiner} are yielded to the format 2 + # version of `TZInfo::Data::Indexes::Countries` by {CountryIndexDefinition} + # to allow countries and their time zones to be specified. + # + # @private + class CountryIndexDefiner #:nodoc: + # @return [Hash] a `Hash` of all the countries that + # have been defined in the index keyed by their codes. + attr_reader :countries + + # Initializes a new {CountryIndexDefiner}. + # + # @param identifier_deduper [StringDeduper] a {StringDeduper} instance to + # use when deduping time zone identifiers. + # @param description_deduper [StringDeduper] a {StringDeduper} instance to + # use when deduping time zone descriptions. + def initialize(identifier_deduper, description_deduper) + @identifier_deduper = identifier_deduper + @description_deduper = description_deduper + @shared_timezones = {} + @countries = {} + end + + # Defines a time zone shared by many countries with an reference for + # subsequent use in country definitions. The latitude and longitude are + # given as the numerator and denominator of a `Rational`. + # + # @param reference [Symbol] a unique reference for the time zone. + # @param identifier [String] the time zone identifier. + # @param latitude_numerator [Integer] the numerator of the latitude. + # @param latitude_denominator [Integer] the denominator of the latitude. + # @param longitude_numerator [Integer] the numerator of the longitude. + # @param longitude_denominator [Integer] the denominator of the longitude. + # @param description [String] an optional description for the time zone. + def timezone(reference, identifier, latitude_numerator, latitude_denominator, + longitude_numerator, longitude_denominator, description = nil) + # Dedupe non-frozen literals from format 1 on all Ruby versions and + # format 2 on Ruby < 2.3 (without frozen_string_literal support). + @shared_timezones[reference] = CountryTimezone.new(@identifier_deduper.dedupe(identifier), + Rational(latitude_numerator, latitude_denominator), + Rational(longitude_numerator, longitude_denominator), description && @description_deduper.dedupe(description)) + end + + # Defines a country. + # + # @param code [String] The ISO 3166-1 alpha-2 code of the country. + # @param name [String] Then name of the country. + # @yield [definer] yields (optional) to obtain the time zones for the + # country. + # @yieldparam definer [CountryDefiner] a {CountryDefiner} + # instance that should be used to specify the time zones of the country. + def country(code, name) + timezones = if block_given? + definer = CountryDefiner.new(@shared_timezones, @identifier_deduper, @description_deduper) + yield definer + definer.timezones + else + [] + end + @countries[code.freeze] = DataSources::CountryInfo.new(code, name, timezones) + end + end + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/format2/country_index_definition.rb ruby-tzinfo-2.0.4/lib/tzinfo/format2/country_index_definition.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/format2/country_index_definition.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/format2/country_index_definition.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,46 @@ +# encoding: UTF-8 + +module TZInfo + module Format2 + # The format 2 country index file includes + # {Format2::CountryIndexDefinition}, which provides a + # {CountryIndexDefinition::ClassMethods#country_index country_index} method + # used to define the country index. + # + # @private + module CountryIndexDefinition #:nodoc: + # Adds class methods to the includee and initializes class instance + # variables. + # + # @param base [Module] the includee. + def self.append_features(base) + super + base.extend(ClassMethods) + base.instance_eval { @countries = {}.freeze } + end + + # Class methods for inclusion. + # + # @private + module ClassMethods #:nodoc: + # @return [Hash] a frozen `Hash` + # of all the countries that have been defined in the index keyed by + # their codes. + attr_reader :countries + + private + + # Defines the index. + # + # @yield [definer] yields to allow the index to be defined. + # @yieldparam definer [CountryIndexDefiner] a {CountryIndexDefiner} + # instance that should be used to define the index. + def country_index + definer = CountryIndexDefiner.new(StringDeduper.global, StringDeduper.new) + yield definer + @countries = definer.countries.freeze + end + end + end + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/format2/timezone_definer.rb ruby-tzinfo-2.0.4/lib/tzinfo/format2/timezone_definer.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/format2/timezone_definer.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/format2/timezone_definer.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,94 @@ +# encoding: UTF-8 +# frozen_string_literal: true + +module TZInfo + module Format2 + # Instances of {TimezoneDefiner} are yielded to TZInfo::Data modules by + # {TimezoneDefinition} to allow the offsets and transitions of the time zone + # to be specified. + # + # @private + class TimezoneDefiner #:nodoc: + # @return [Array] the defined transitions of the time + # zone. + attr_reader :transitions + + # Initializes a new TimezoneDefiner. + # + # @param string_deduper [StringDeduper] a {StringDeduper} instance to use + # when deduping abbreviations. + def initialize(string_deduper) + @string_deduper = string_deduper + @offsets = {} + @transitions = [] + end + + # Returns the first offset to be defined or `nil` if no offsets have been + # defined. The first offset is observed before the time of the first + # transition. + # + # @return [TimezoneOffset] the first offset to be defined or `nil` if no + # offsets have been defined. + def first_offset + first = @offsets.first + first && first.last + end + + # Defines an offset. + # + # @param id [Symbol] an arbitrary value used identify the offset in + # subsequent calls to transition. It must be unique. + # @param base_utc_offset [Integer] the base offset from UTC of the zone in + # seconds. This does not include daylight savings time. + # @param std_offset [Integer] the daylight savings offset from the base + # offset in seconds. Typically either 0 or 3600. + # @param abbreviation [String] an abbreviation for the offset, for + # example, EST or EDT. + # @raise [ArgumentError] if another offset has already been defined with + # the given id. + def offset(id, base_utc_offset, std_offset, abbreviation) + raise ArgumentError, 'An offset has already been defined with the given id' if @offsets.has_key?(id) + + # Dedupe non-frozen literals from format 1 on all Ruby versions and + # format 2 on Ruby < 2.3 (without frozen_string_literal support). + abbreviation = @string_deduper.dedupe(abbreviation) + + offset = TimezoneOffset.new(base_utc_offset, std_offset, abbreviation) + @offsets[id] = offset + @previous_offset ||= offset + end + + # Defines a transition to a given offset. + # + # Transitions must be defined in increasing time order. + # + # @param offset_id [Symbol] references the id of a previously defined + # offset. + # @param timestamp_value [Integer] the time the transition occurs as a + # number of seconds since 1970-01-01 00:00:00 UTC ignoring leap seconds + # (i.e. each day is treated as if it were 86,400 seconds long). + # @raise [ArgumentError] if `offset_id` does not reference a defined + # offset. + # @raise [ArgumentError] if `timestamp_value` is not greater than the + # `timestamp_value` of the previously defined transition. + def transition(offset_id, timestamp_value) + offset = @offsets[offset_id] + raise ArgumentError, 'offset_id has not been defined' unless offset + raise ArgumentError, 'timestamp is not greater than the timestamp of the previously defined transition' if !@transitions.empty? && @transitions.last.timestamp_value >= timestamp_value + @transitions << TimezoneTransition.new(offset, @previous_offset, timestamp_value) + @previous_offset = offset + end + + # Defines the rules that will be used for handling instants after the last + # transition. + # + # This method is currently just a placeholder for forward compatibility + # that accepts and ignores any arguments passed. + # + # Support for subsequent rules will be added in a future version of TZInfo + # and the rules will be included in format 2 releases of TZInfo::Data. + def subsequent_rules(*args) + end + end + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/format2/timezone_definition.rb ruby-tzinfo-2.0.4/lib/tzinfo/format2/timezone_definition.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/format2/timezone_definition.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/format2/timezone_definition.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,73 @@ +# encoding: UTF-8 + +module TZInfo + module Format2 + # {Format2::TimezoneDefinition} is included into format 2 time zone + # definition modules and provides methods for defining time zones. + # + # @private + module TimezoneDefinition #:nodoc: + # Adds class methods to the includee. + # + # @param base [Module] the includee. + def self.append_features(base) + super + base.extend(ClassMethods) + end + + # Class methods for inclusion. + # + # @private + module ClassMethods #:nodoc: + # @return [TimezoneInfo] the last time zone to be defined. + def get + @timezone + end + + private + + # @return [Class] the class to be instantiated and yielded by + # {#timezone}. + def timezone_definer_class + TimezoneDefiner + end + + # Defines a data time zone. + # + # @param identifier [String] the identifier of the time zone. + # @yield [definer] yields to the caller to define the time zone. + # @yieldparam definer [Object] an instance of the class returned by + # {#timezone_definer_class}, typically {TimezoneDefiner}. + def timezone(identifier) + # Dedupe non-frozen literals from format 1 on all Ruby versions and + # format 2 on Ruby < 2.3 (without frozen_string_literal support). + string_deduper = StringDeduper.global + identifier = string_deduper.dedupe(identifier) + + definer = timezone_definer_class.new(string_deduper) + yield definer + transitions = definer.transitions + + @timezone = if transitions.empty? + DataSources::ConstantOffsetDataTimezoneInfo.new(identifier, definer.first_offset) + else + DataSources::TransitionsDataTimezoneInfo.new(identifier, transitions) + end + end + + # Defines a linked time zone. + # + # @param identifier [String] the identifier of the time zone being + # defined. + # @param link_to_identifier [String] the identifier the new time zone + # links to (is an alias for). + def linked_timezone(identifier, link_to_identifier) + # Dedupe non-frozen literals from format 1 on all Ruby versions and + # format 2 on Ruby < 2.3 (without frozen_string_literal support). + string_deduper = StringDeduper.global + @timezone = DataSources::LinkedTimezoneInfo.new(string_deduper.dedupe(identifier), string_deduper.dedupe(link_to_identifier)) + end + end + end + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/format2/timezone_index_definer.rb ruby-tzinfo-2.0.4/lib/tzinfo/format2/timezone_index_definer.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/format2/timezone_index_definer.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/format2/timezone_index_definer.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,45 @@ +# encoding: UTF-8 + +module TZInfo + module Format2 + # Instances of {TimezoneIndexDefiner} are yielded by + # {TimezoneIndexDefinition} to allow the time zone index to be defined. + # + # @private + class TimezoneIndexDefiner #:nodoc: + # @return [Array] the identifiers of all data time zones. + attr_reader :data_timezones + + # @return [Array] the identifiers of all linked time zones. + attr_reader :linked_timezones + + # Initializes a new TimezoneDefiner. + # + # @param string_deduper [StringDeduper] a {StringDeduper} instance to use + # when deduping identifiers. + def initialize(string_deduper) + @string_deduper = string_deduper + @data_timezones = [] + @linked_timezones = [] + end + + # Adds a data time zone to the index. + # + # @param identifier [String] the time zone identifier. + def data_timezone(identifier) + # Dedupe non-frozen literals from format 1 on all Ruby versions and + # format 2 on Ruby < 2.3 (without frozen_string_literal support). + @data_timezones << @string_deduper.dedupe(identifier) + end + + # Adds a linked time zone to the index. + # + # @param identifier [String] the time zone identifier. + def linked_timezone(identifier) + # Dedupe non-frozen literals from format 1 on all Ruby versions and + # format 2 on Ruby < 2.3 (without frozen_string_literal support). + @linked_timezones << @string_deduper.dedupe(identifier) + end + end + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/format2/timezone_index_definition.rb ruby-tzinfo-2.0.4/lib/tzinfo/format2/timezone_index_definition.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/format2/timezone_index_definition.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/format2/timezone_index_definition.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,55 @@ +# encoding: UTF-8 + +module TZInfo + module Format2 + # The format 2 time zone index file includes {TimezoneIndexDefinition}, + # which provides the {TimezoneIndexDefinition::ClassMethods#timezone_index + # timezone_index} method used to define the index. + # + # @private + module TimezoneIndexDefinition #:nodoc: + # Adds class methods to the includee and initializes class instance + # variables. + # + # @param base [Module] the includee. + def self.append_features(base) + super + base.extend(ClassMethods) + base.instance_eval do + empty = [].freeze + @timezones = empty + @data_timezones = empty + @linked_timezones = empty + end + end + + # Class methods for inclusion. + # + # @private + module ClassMethods #:nodoc: + # @return [Array] a frozen `Array` containing the identifiers of + # all data time zones. Identifiers are sorted according to + # `String#<=>`. + attr_reader :data_timezones + + # @return [Array] a frozen `Array` containing the identifiers of + # all linked time zones. Identifiers are sorted according to + # `String#<=>`. + attr_reader :linked_timezones + + # Defines the index. + # + # @yield [definer] yields to the caller to allow the index to be + # defined. + # @yieldparam definer [TimezoneIndexDefiner] a {TimezoneIndexDefiner} + # instance that should be used to define the index. + def timezone_index + definer = TimezoneIndexDefiner.new(StringDeduper.global) + yield definer + @data_timezones = definer.data_timezones.sort!.freeze + @linked_timezones = definer.linked_timezones.sort!.freeze + end + end + end + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/format2.rb ruby-tzinfo-2.0.4/lib/tzinfo/format2.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/format2.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/format2.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,10 @@ +# encoding: UTF-8 + +module TZInfo + # Modules and classes used by the format 2 version of TZInfo::Data. + # + # @private + module Format2 #:nodoc: + end + private_constant :Format2 +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/info_timezone.rb ruby-tzinfo-2.0.4/lib/tzinfo/info_timezone.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/info_timezone.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/info_timezone.rb 2020-12-30 06:49:15.000000000 +0000 @@ -1,30 +1,35 @@ +# encoding: UTF-8 + module TZInfo - # A Timezone based on a TimezoneInfo. + # A {Timezone} based on a {DataSources::TimezoneInfo}. # - # @private - class InfoTimezone < Timezone #:nodoc: - - # Constructs a new InfoTimezone with a TimezoneInfo instance. - def self.new(info) - tz = super() - tz.send(:setup, info) - tz + # @abstract + class InfoTimezone < Timezone + # Initializes a new {InfoTimezone}. + # + # {InfoTimezone} instances should not normally be created directly. Use + # the {Timezone.get} method to obtain {Timezone} instances. + # + # @param info [DataSources::TimezoneInfo] a {DataSources::TimezoneInfo} + # instance supplied by a {DataSource} that will be used as the source of + # data for this {InfoTimezone}. + def initialize(info) + super() + @info = info end - - # The identifier of the timezone, e.g. "Europe/Paris". + + # (see Timezone#identifier) def identifier @info.identifier end - + protected - # The TimezoneInfo for this Timezone. - def info - @info - end - - def setup(info) - @info = info - end - end + + # @return [DataSources::TimezoneInfo] the {DataSources::TimezoneInfo} this + # {InfoTimezone} is based on. + def info + @info + end + end end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/linked_timezone_info.rb ruby-tzinfo-2.0.4/lib/tzinfo/linked_timezone_info.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/linked_timezone_info.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/linked_timezone_info.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -module TZInfo - # Represents a timezone that is defined as a link or alias to another zone. - class LinkedTimezoneInfo < TimezoneInfo - - # The zone that provides the data (that this zone is an alias for). - attr_reader :link_to_identifier - - # Constructs a new LinkedTimezoneInfo with an identifier and the identifier - # of the zone linked to. - def initialize(identifier, link_to_identifier) - super(identifier) - @link_to_identifier = link_to_identifier - end - - # Returns internal object state as a programmer-readable string. - def inspect - "#<#{self.class}: #@identifier,#@link_to_identifier>" - end - - # Constructs a Timezone instance for the timezone represented by this - # DataTimezoneInfo. - def create_timezone - LinkedTimezone.new(self) - end - end -end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/linked_timezone.rb ruby-tzinfo-2.0.4/lib/tzinfo/linked_timezone.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/linked_timezone.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/linked_timezone.rb 2020-12-30 06:49:15.000000000 +0000 @@ -1,63 +1,44 @@ +# encoding: UTF-8 + module TZInfo + # Represents time zones that are defined as a link to or alias for another + # time zone. + class LinkedTimezone < InfoTimezone + # Initializes a new {LinkedTimezone}. + # + # {LinkedTimezone} instances should not normally be created directly. Use + # the {Timezone.get} method to obtain {Timezone} instances. + # + # @param info [DataSources::LinkedTimezoneInfo] a + # {DataSources::LinkedTimezoneInfo} instance supplied by a {DataSource} + # that will be used as the source of data for this {LinkedTimezone}. + def initialize(info) + super + @linked_timezone = Timezone.get(info.link_to_identifier) + end - # A Timezone based on a LinkedTimezoneInfo. - # - # @private - class LinkedTimezone < InfoTimezone #:nodoc: - # Returns the TimezonePeriod for the given UTC time. utc can either be - # a DateTime, Time or integer timestamp (Time.to_i). Any timezone - # information in utc is ignored (it is treated as a UTC time). - # - # If no TimezonePeriod could be found, PeriodNotFound is raised. - def period_for_utc(utc) - @linked_timezone.period_for_utc(utc) + # (see Timezone#period_for) + def period_for(time) + @linked_timezone.period_for(time) end - - # Returns the set of TimezonePeriod instances that are valid for the given - # local time as an array. If you just want a single period, use - # period_for_local instead and specify how abiguities should be resolved. - # Raises PeriodNotFound if no periods are found for the given time. - def periods_for_local(local) - @linked_timezone.periods_for_local(local) + + # (see Timezone#periods_for_local) + def periods_for_local(local_time) + @linked_timezone.periods_for_local(local_time) end - - # Returns an Array of TimezoneTransition instances representing the times - # where the UTC offset of the timezone changes. - # - # Transitions are returned up to a given date and time up to a given date - # and time, specified in UTC (utc_to). - # - # A from date and time may also be supplied using the utc_from parameter - # (also specified in UTC). If utc_from is not nil, only transitions from - # that date and time onwards will be returned. - # - # Comparisons with utc_to are exclusive. Comparisons with utc_from are - # inclusive. If a transition falls precisely on utc_to, it will be excluded. - # If a transition falls on utc_from, it will be included. - # - # Transitions returned are ordered by when they occur, from earliest to - # latest. - # - # utc_to and utc_from can be specified using either DateTime, Time or - # integer timestamps (Time.to_i). - # - # If utc_from is specified and utc_to is not greater than utc_from, then - # transitions_up_to raises an ArgumentError exception. - def transitions_up_to(utc_to, utc_from = nil) - @linked_timezone.transitions_up_to(utc_to, utc_from) + + # (see Timezone#transitions_up_to) + def transitions_up_to(to, from = nil) + @linked_timezone.transitions_up_to(to, from) end - - # Returns the canonical zone for this Timezone. + + # Returns the canonical {Timezone} instance for this {LinkedTimezone}. + # + # For a {LinkedTimezone}, this is the canonical zone of the link target. # - # For a LinkedTimezone, this is the canonical zone of the link target. + # @return [Timezone] the canonical {Timezone} instance for this {Timezone}. def canonical_zone @linked_timezone.canonical_zone end - - protected - def setup(info) - super(info) - @linked_timezone = Timezone.get(info.link_to_identifier) - end end end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/offset_rationals.rb ruby-tzinfo-2.0.4/lib/tzinfo/offset_rationals.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/offset_rationals.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/offset_rationals.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,77 +0,0 @@ -require 'rational' unless defined?(Rational) - -module TZInfo - - # Provides a method for getting Rationals for a timezone offset in seconds. - # Pre-reduced rationals are returned for all the half-hour intervals between - # -14 and +14 hours to avoid having to call gcd at runtime. - # - # @private - module OffsetRationals #:nodoc: - @@rational_cache = { - -50400 => RubyCoreSupport.rational_new!(-7,12), - -48600 => RubyCoreSupport.rational_new!(-9,16), - -46800 => RubyCoreSupport.rational_new!(-13,24), - -45000 => RubyCoreSupport.rational_new!(-25,48), - -43200 => RubyCoreSupport.rational_new!(-1,2), - -41400 => RubyCoreSupport.rational_new!(-23,48), - -39600 => RubyCoreSupport.rational_new!(-11,24), - -37800 => RubyCoreSupport.rational_new!(-7,16), - -36000 => RubyCoreSupport.rational_new!(-5,12), - -34200 => RubyCoreSupport.rational_new!(-19,48), - -32400 => RubyCoreSupport.rational_new!(-3,8), - -30600 => RubyCoreSupport.rational_new!(-17,48), - -28800 => RubyCoreSupport.rational_new!(-1,3), - -27000 => RubyCoreSupport.rational_new!(-5,16), - -25200 => RubyCoreSupport.rational_new!(-7,24), - -23400 => RubyCoreSupport.rational_new!(-13,48), - -21600 => RubyCoreSupport.rational_new!(-1,4), - -19800 => RubyCoreSupport.rational_new!(-11,48), - -18000 => RubyCoreSupport.rational_new!(-5,24), - -16200 => RubyCoreSupport.rational_new!(-3,16), - -14400 => RubyCoreSupport.rational_new!(-1,6), - -12600 => RubyCoreSupport.rational_new!(-7,48), - -10800 => RubyCoreSupport.rational_new!(-1,8), - -9000 => RubyCoreSupport.rational_new!(-5,48), - -7200 => RubyCoreSupport.rational_new!(-1,12), - -5400 => RubyCoreSupport.rational_new!(-1,16), - -3600 => RubyCoreSupport.rational_new!(-1,24), - -1800 => RubyCoreSupport.rational_new!(-1,48), - 0 => RubyCoreSupport.rational_new!(0,1), - 1800 => RubyCoreSupport.rational_new!(1,48), - 3600 => RubyCoreSupport.rational_new!(1,24), - 5400 => RubyCoreSupport.rational_new!(1,16), - 7200 => RubyCoreSupport.rational_new!(1,12), - 9000 => RubyCoreSupport.rational_new!(5,48), - 10800 => RubyCoreSupport.rational_new!(1,8), - 12600 => RubyCoreSupport.rational_new!(7,48), - 14400 => RubyCoreSupport.rational_new!(1,6), - 16200 => RubyCoreSupport.rational_new!(3,16), - 18000 => RubyCoreSupport.rational_new!(5,24), - 19800 => RubyCoreSupport.rational_new!(11,48), - 21600 => RubyCoreSupport.rational_new!(1,4), - 23400 => RubyCoreSupport.rational_new!(13,48), - 25200 => RubyCoreSupport.rational_new!(7,24), - 27000 => RubyCoreSupport.rational_new!(5,16), - 28800 => RubyCoreSupport.rational_new!(1,3), - 30600 => RubyCoreSupport.rational_new!(17,48), - 32400 => RubyCoreSupport.rational_new!(3,8), - 34200 => RubyCoreSupport.rational_new!(19,48), - 36000 => RubyCoreSupport.rational_new!(5,12), - 37800 => RubyCoreSupport.rational_new!(7,16), - 39600 => RubyCoreSupport.rational_new!(11,24), - 41400 => RubyCoreSupport.rational_new!(23,48), - 43200 => RubyCoreSupport.rational_new!(1,2), - 45000 => RubyCoreSupport.rational_new!(25,48), - 46800 => RubyCoreSupport.rational_new!(13,24), - 48600 => RubyCoreSupport.rational_new!(9,16), - 50400 => RubyCoreSupport.rational_new!(7,12)}.freeze - - # Returns a Rational expressing the fraction of a day that offset in - # seconds represents (i.e. equivalent to Rational(offset, 86400)). - def rational_for_offset(offset) - @@rational_cache[offset] || Rational(offset, 86400) - end - module_function :rational_for_offset - end -end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/offset_timezone_period.rb ruby-tzinfo-2.0.4/lib/tzinfo/offset_timezone_period.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/offset_timezone_period.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/offset_timezone_period.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,42 @@ +# encoding: UTF-8 + +module TZInfo + # Represents the infinite period of time in a time zone that constantly + # observes the same offset from UTC (has an unbounded start and end). + class OffsetTimezonePeriod < TimezonePeriod + # Initializes an {OffsetTimezonePeriod}. + # + # @param offset [TimezoneOffset] the offset that is constantly observed. + # @raise [ArgumentError] if `offset` is `nil`. + def initialize(offset) + super + end + + # @return [TimezoneTransition] the transition that defines the start of this + # {TimezonePeriod}, always `nil` for {OffsetTimezonePeriod}. + def start_transition + nil + end + + # @return [TimezoneTransition] the transition that defines the end of this + # {TimezonePeriod}, always `nil` for {OffsetTimezonePeriod}. + def end_transition + nil + end + + # Determines if this {OffsetTimezonePeriod} is equal to another instance. + # + # @param p [Object] the instance to test for equality. + # @return [Boolean] `true` if `p` is a {OffsetTimezonePeriod} with the same + # {offset}, otherwise `false`. + def ==(p) + p.kind_of?(OffsetTimezonePeriod) && offset == p.offset + end + alias eql? == + + # @return [Integer] a hash based on {offset}. + def hash + offset.hash + end + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/ruby_core_support.rb ruby-tzinfo-2.0.4/lib/tzinfo/ruby_core_support.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/ruby_core_support.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/ruby_core_support.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,176 +0,0 @@ -require 'date' -require 'rational' unless defined?(Rational) - -module TZInfo - - # Methods to support different versions of Ruby. - # - # @private - module RubyCoreSupport #:nodoc: - - # Use Rational.new! for performance reasons in Ruby 1.8. - # This has been removed from 1.9, but Rational performs better. - if Rational.respond_to? :new! - def self.rational_new!(numerator, denominator = 1) - Rational.new!(numerator, denominator) - end - else - def self.rational_new!(numerator, denominator = 1) - Rational(numerator, denominator) - end - end - - # Ruby 1.8.6 introduced new! and deprecated new0. - # Ruby 1.9.0 removed new0. - # Ruby trunk revision 31668 removed the new! method. - # Still support new0 for better performance on older versions of Ruby (new0 indicates - # that the rational has already been reduced to its lowest terms). - # Fallback to jd with conversion from ajd if new! and new0 are unavailable. - if DateTime.respond_to? :new! - def self.datetime_new!(ajd = 0, of = 0, sg = Date::ITALY) - DateTime.new!(ajd, of, sg) - end - elsif DateTime.respond_to? :new0 - def self.datetime_new!(ajd = 0, of = 0, sg = Date::ITALY) - DateTime.new0(ajd, of, sg) - end - else - HALF_DAYS_IN_DAY = rational_new!(1, 2) - - def self.datetime_new!(ajd = 0, of = 0, sg = Date::ITALY) - # Convert from an Astronomical Julian Day number to a civil Julian Day number. - jd = ajd + of + HALF_DAYS_IN_DAY - - # Ruby trunk revision 31862 changed the behaviour of DateTime.jd so that it will no - # longer accept a fractional civil Julian Day number if further arguments are specified. - # Calculate the hours, minutes and seconds to pass to jd. - - jd_i = jd.to_i - jd_i -= 1 if jd < 0 - hours = (jd - jd_i) * 24 - hours_i = hours.to_i - minutes = (hours - hours_i) * 60 - minutes_i = minutes.to_i - seconds = (minutes - minutes_i) * 60 - - DateTime.jd(jd_i, hours_i, minutes_i, seconds, of, sg) - end - end - - # DateTime in Ruby 1.8.6 doesn't consider times within the 60th second to be - # valid. When attempting to specify such a DateTime, subtract the fractional - # part and then add it back later - if Date.respond_to?(:valid_time?) && !Date.valid_time?(0, 0, rational_new!(59001, 1000)) # 0:0:59.001 - def self.datetime_new(y=-4712, m=1, d=1, h=0, min=0, s=0, of=0, sg=Date::ITALY) - if !s.kind_of?(Integer) && s > 59 - dt = DateTime.new(y, m, d, h, min, 59, of, sg) - dt + (s - 59) / 86400 - else - DateTime.new(y, m, d, h, min, s, of, sg) - end - end - else - def self.datetime_new(y=-4712, m=1, d=1, h=0, min=0, s=0, of=0, sg=Date::ITALY) - DateTime.new(y, m, d, h, min, s, of, sg) - end - end - - # Returns true if Time on the runtime platform supports Times defined - # by negative 32-bit timestamps, otherwise false. - begin - Time.at(-1) - Time.at(-2147483648) - - def self.time_supports_negative - true - end - rescue ArgumentError - def self.time_supports_negative - false - end - end - - # Returns true if Time on the runtime platform supports Times defined by - # 64-bit timestamps, otherwise false. - begin - Time.at(-2147483649) - Time.at(2147483648) - - def self.time_supports_64bit - true - end - rescue RangeError - def self.time_supports_64bit - false - end - end - - # Return the result of Time#nsec if it exists, otherwise return the - # result of Time#usec * 1000. - if Time.method_defined?(:nsec) - def self.time_nsec(time) - time.nsec - end - else - def self.time_nsec(time) - time.usec * 1000 - end - end - - # Call String#force_encoding if this version of Ruby has encoding support - # otherwise treat as a no-op. - if String.method_defined?(:force_encoding) - def self.force_encoding(str, encoding) - str.force_encoding(encoding) - end - else - def self.force_encoding(str, encoding) - str - end - end - - - # Wrapper for File.open that supports passing hash options for specifying - # encodings on Ruby 1.9+. The options are ignored on earlier versions of - # Ruby. - if RUBY_VERSION =~ /\A1\.[0-8]\./ - def self.open_file(file_name, mode, opts, &block) - File.open(file_name, mode, &block) - end - elsif RUBY_VERSION =~ /\A1\.9\./ - def self.open_file(file_name, mode, opts, &block) - File.open(file_name, mode, opts, &block) - end - else - # Evaluate method as a string because **opts isn't valid syntax prior to - # Ruby 2.0. - eval(<<-EOF - def self.open_file(file_name, mode, opts, &block) - File.open(file_name, mode, **opts, &block) - end - EOF - ) - end - - - # Object#untaint is a deprecated no-op in Ruby >= 2.7 and will be removed in - # 3.0. Add a refinement to either silence the warning, or supply the method - # if needed. - old_verbose = $VERBOSE - $VERBOSE = false - begin - o = Object.new - if [:taint, :untaint, :tainted?].none? {|m| o.respond_to?(m) } || !o.taint.tainted? - module UntaintExt - refine Object do - def untaint - self - end - end - end - end - ensure - $VERBOSE = old_verbose - end - end -end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/ruby_country_info.rb ruby-tzinfo-2.0.4/lib/tzinfo/ruby_country_info.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/ruby_country_info.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/ruby_country_info.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,74 +0,0 @@ -module TZInfo - # Represents information about a country returned by RubyDataSource. - # - # @private - class RubyCountryInfo < CountryInfo #:nodoc: - # Constructs a new CountryInfo with an ISO 3166 country code, name and - # block. The block will be evaluated to obtain the timezones for the - # country when the zones are first needed. - def initialize(code, name, &block) - super(code, name) - @block = block - @zones = nil - @zone_identifiers = nil - end - - # Returns a frozen array of all the zone identifiers for the country. These - # are in the order they were added using the timezone method. - def zone_identifiers - # Thread-safety: It is possible that the value of @zone_identifiers may be - # calculated multiple times in concurrently executing threads. It is not - # worth the overhead of locking to ensure that @zone_identifiers is only - # calculated once. - - unless @zone_identifiers - result = zones.collect {|zone| zone.identifier}.freeze - return result if frozen? - @zone_identifiers = result - end - - @zone_identifiers - end - - # Returns a frozen array of all the timezones for the for the country as - # CountryTimezone instances. These are in the order they were added using - # the timezone method. - def zones - # Thread-safety: It is possible that the value of @zones may be - # calculated multiple times in concurrently executing threads. It is not - # worth the overhead of locking to ensure that @zones is only - # calculated once. - - unless @zones - zones = Zones.new - @block.call(zones) if @block - result = zones.list.freeze - return result if frozen? - @block = nil - @zones = result - end - - @zones - end - - # An instance of the Zones class is passed to the block used to define - # timezones. - # - # @private - class Zones #:nodoc: - attr_reader :list - - def initialize - @list = [] - end - - # Called by the index data to define a timezone for the country. - def timezone(identifier, latitude_numerator, latitude_denominator, - longitude_numerator, longitude_denominator, description = nil) - @list << CountryTimezone.new!(identifier, latitude_numerator, - latitude_denominator, longitude_numerator, longitude_denominator, - description) - end - end - end -end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/ruby_data_source.rb ruby-tzinfo-2.0.4/lib/tzinfo/ruby_data_source.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/ruby_data_source.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/ruby_data_source.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,138 +0,0 @@ -module TZInfo - using RubyCoreSupport::UntaintExt if RubyCoreSupport.const_defined?(:UntaintExt) - - # A DataSource that loads data from the set of Ruby modules included in the - # TZInfo::Data library (tzinfo-data gem). - # - # To have TZInfo use this DataSource, call TZInfo::DataSource.set as follows: - # - # TZInfo::DataSource.set(:ruby) - class RubyDataSource < DataSource - # Whether the timezone index has been loaded yet. - @@timezone_index_loaded = false - - # Whether the country index has been loaded yet. - @@country_index_loaded = false - - # Initializes a new RubyDataSource instance. - def initialize - tzinfo_data = File.join('tzinfo', 'data') - begin - require(tzinfo_data) - - data_file = File.join('', 'tzinfo', 'data.rb') - path = $".reverse_each.detect {|p| p.end_with?(data_file) } - if path - @base_path = File.join(File.dirname(path), 'data').untaint - else - @base_path = tzinfo_data - end - rescue LoadError - @base_path = tzinfo_data - end - end - - # Returns a TimezoneInfo instance for a given identifier. - # Raises InvalidTimezoneIdentifier if the timezone is not found or the - # identifier is invalid. - def load_timezone_info(identifier) - raise InvalidTimezoneIdentifier, 'Invalid identifier' if identifier !~ /^[A-Za-z0-9\+\-_]+(\/[A-Za-z0-9\+\-_]+)*$/ - - identifier = identifier.gsub(/-/, '__m__').gsub(/\+/, '__p__') - - # Untaint identifier after it has been reassigned to a new string. We - # don't want to modify the original identifier. identifier may also be - # frozen and therefore cannot be untainted. - identifier.untaint - - identifier = identifier.split('/') - begin - require_definition(identifier) - - m = Data::Definitions - identifier.each {|part| - m = m.const_get(part) - } - - m.get - rescue LoadError, NameError => e - raise InvalidTimezoneIdentifier, e.message - end - end - - # Returns an array of all the available timezone identifiers. - def timezone_identifiers - load_timezone_index - Data::Indexes::Timezones.timezones - end - - # Returns an array of all the available timezone identifiers for - # data timezones (i.e. those that actually contain definitions). - def data_timezone_identifiers - load_timezone_index - Data::Indexes::Timezones.data_timezones - end - - # Returns an array of all the available timezone identifiers that - # are links to other timezones. - def linked_timezone_identifiers - load_timezone_index - Data::Indexes::Timezones.linked_timezones - end - - # Returns a CountryInfo instance for the given ISO 3166-1 alpha-2 - # country code. Raises InvalidCountryCode if the country could not be found - # or the code is invalid. - def load_country_info(code) - load_country_index - info = Data::Indexes::Countries.countries[code] - raise InvalidCountryCode, 'Invalid country code' unless info - info - end - - # Returns an array of all the available ISO 3166-1 alpha-2 - # country codes. - def country_codes - load_country_index - Data::Indexes::Countries.countries.keys.freeze - end - - # Returns the name of this DataSource. - def to_s - "Ruby DataSource" - end - - private - - # Requires a zone definition by its identifier (split on /). - def require_definition(identifier) - require_data(*(['definitions'] + identifier)) - end - - # Requires an index by its name. - def require_index(name) - require_data(*['indexes', name]) - end - - # Requires a file from tzinfo/data. - def require_data(*file) - require(File.join(@base_path, *file)) - end - - # Loads in the index of timezones if it hasn't already been loaded. - def load_timezone_index - unless @@timezone_index_loaded - require_index('timezones') - @@timezone_index_loaded = true - end - end - - # Loads in the index of countries if it hasn't already been loaded. - def load_country_index - unless @@country_index_loaded - require_index('countries') - @@country_index_loaded = true - end - end - end -end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/string_deduper.rb ruby-tzinfo-2.0.4/lib/tzinfo/string_deduper.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/string_deduper.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/string_deduper.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,118 @@ +# encoding: UTF-8 +# frozen_string_literal: true + +require 'concurrent' + +module TZInfo + # Maintains a pool of `String` instances. The {#dedupe} method will return + # either a pooled copy of a given `String` or add the instance to the pool. + # + # @private + class StringDeduper #:nodoc: + class << self + # @return [StringDeduper] a globally available singleton instance of + # {StringDeduper}. This instance is safe for use in concurrently + # executing threads. + attr_reader :global + end + + # Initializes a new {StringDeduper}. + def initialize + @strings = create_hash do |h, k| + v = k.dup.freeze + h[v] = v + end + end + + # @param string [String] the string to deduplicate. + # @return [bool] `string` if it is frozen, otherwise a frozen, possibly + # pre-existing copy of `string`. + def dedupe(string) + return string if string.frozen? + @strings[string] + end + + protected + + # Creates a `Hash` to store pooled `String` instances. + # + # @param block [Proc] Default value block to be passed to `Hash.new`. + # @return [Hash] a `Hash` to store pooled `String` instances. + def create_hash(&block) + Hash.new(&block) + end + end + private_constant :StringDeduper + + # A thread-safe version of {StringDeduper}. + # + # @private + class ConcurrentStringDeduper < StringDeduper #:nodoc: + protected + + def create_hash(&block) + Concurrent::Map.new(&block) + end + end + private_constant :ConcurrentStringDeduper + + + string_unary_minus_does_dedupe = if '0'.respond_to?(:-@) + # :nocov_no_string_-@: + s1 = -('0'.dup) + s2 = -('0'.dup) + s1.object_id == s2.object_id + # :nocov_no_string_-@: + else + # :nocov_string_-@: + false + # :nocov_string_-@: + end + + if string_unary_minus_does_dedupe + # :nocov_no_deduping_string_unary_minus: + + # An implementation of {StringDeduper} using the `String#-@` method where + # that method performs deduplication (Ruby 2.5 and later). + # + # Note that this is slightly different to the plain {StringDeduper} + # implementation. In this implementation, frozen literal strings are already + # in the pool and are candidates for being returned, even when passed + # another equal frozen non-literal string. {StringDeduper} will always + # return frozen strings. + # + # There are also differences in encoding handling. This implementation will + # treat strings with different encodings as different strings. + # {StringDeduper} will treat strings with the compatible encodings as the + # same string. + # + # @private + class UnaryMinusGlobalStringDeduper #:nodoc: + # @param string [String] the string to deduplicate. + # @return [bool] `string` if it is frozen, otherwise a frozen, possibly + # pre-existing copy of `string`. + def dedupe(string) + # String#-@ on Ruby 2.6 will dedupe a frozen non-literal String. Ruby + # 2.5 will just return frozen strings. + # + # The pooled implementation can't tell the difference between frozen + # literals and frozen non-literals, so must always return frozen String + # instances to avoid doing unncessary work when loading format 2 + # TZInfo::Data modules. + # + # For compatibility with the pooled implementation, just return frozen + # string instances (acting like Ruby 2.5). + return string if string.frozen? + -string + end + end + private_constant :UnaryMinusGlobalStringDeduper + + StringDeduper.instance_variable_set(:@global, UnaryMinusGlobalStringDeduper.new) + # :nocov_no_deduping_string_unary_minus: + else + # :nocov_deduping_string_unary_minus: + StringDeduper.instance_variable_set(:@global, ConcurrentStringDeduper.new) + # :nocov_deduping_string_unary_minus: + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/time_or_datetime.rb ruby-tzinfo-2.0.4/lib/tzinfo/time_or_datetime.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/time_or_datetime.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/time_or_datetime.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,340 +0,0 @@ -require 'date' -require 'rational' unless defined?(Rational) -require 'time' - -module TZInfo - # Used by TZInfo internally to represent either a Time, DateTime or - # an Integer timestamp (seconds since 1970-01-01 00:00:00). - class TimeOrDateTime - include Comparable - - # Constructs a new TimeOrDateTime. timeOrDateTime can be a Time, DateTime - # or Integer. If using a Time or DateTime, any time zone information - # is ignored. - # - # Integer timestamps must be within the range supported by Time on the - # platform being used. - def initialize(timeOrDateTime) - @time = nil - @datetime = nil - @timestamp = nil - - if timeOrDateTime.is_a?(Time) - @time = timeOrDateTime - - # Avoid using the slower Rational class unless necessary. - nsec = RubyCoreSupport.time_nsec(@time) - usec = nsec % 1000 == 0 ? nsec / 1000 : Rational(nsec, 1000) - - @time = Time.utc(@time.year, @time.mon, @time.mday, @time.hour, @time.min, @time.sec, usec) unless @time.utc? - @orig = @time - elsif timeOrDateTime.is_a?(DateTime) - @datetime = timeOrDateTime - @datetime = @datetime.new_offset(0) unless @datetime.offset == 0 - @orig = @datetime - else - @timestamp = timeOrDateTime.to_i - - if !RubyCoreSupport.time_supports_64bit && (@timestamp > 2147483647 || @timestamp < -2147483648 || (@timestamp < 0 && !RubyCoreSupport.time_supports_negative)) - raise RangeError, 'Timestamp is outside the supported range of Time on this platform' - end - - @orig = @timestamp - end - end - - # Returns the time as a Time. - # - # When converting from a DateTime, the result is truncated to microsecond - # precision. - def to_time - # Thread-safety: It is possible that the value of @time may be - # calculated multiple times in concurrently executing threads. It is not - # worth the overhead of locking to ensure that @time is only - # calculated once. - - unless @time - result = if @timestamp - Time.at(@timestamp).utc - else - Time.utc(year, mon, mday, hour, min, sec, usec) - end - - return result if frozen? - @time = result - end - - @time - end - - # Returns the time as a DateTime. - # - # When converting from a Time, the result is truncated to microsecond - # precision. - def to_datetime - # Thread-safety: It is possible that the value of @datetime may be - # calculated multiple times in concurrently executing threads. It is not - # worth the overhead of locking to ensure that @datetime is only - # calculated once. - - unless @datetime - # Avoid using Rational unless necessary. - u = usec - s = u == 0 ? sec : Rational(sec * 1000000 + u, 1000000) - result = RubyCoreSupport.datetime_new(year, mon, mday, hour, min, s) - return result if frozen? - @datetime = result - end - - @datetime - end - - # Returns the time as an integer timestamp. - def to_i - # Thread-safety: It is possible that the value of @timestamp may be - # calculated multiple times in concurrently executing threads. It is not - # worth the overhead of locking to ensure that @timestamp is only - # calculated once. - - unless @timestamp - result = to_time.to_i - return result if frozen? - @timestamp = result - end - - @timestamp - end - - # Returns the time as the original time passed to new. - def to_orig - @orig - end - - # Returns a string representation of the TimeOrDateTime. - def to_s - if @orig.is_a?(Time) - "Time: #{@orig.to_s}" - elsif @orig.is_a?(DateTime) - "DateTime: #{@orig.to_s}" - else - "Timestamp: #{@orig.to_s}" - end - end - - # Returns internal object state as a programmer-readable string. - def inspect - "#<#{self.class}: #{@orig.inspect}>" - end - - # Returns the year. - def year - if @time - @time.year - elsif @datetime - @datetime.year - else - to_time.year - end - end - - # Returns the month of the year (1..12). - def mon - if @time - @time.mon - elsif @datetime - @datetime.mon - else - to_time.mon - end - end - alias :month :mon - - # Returns the day of the month (1..n). - def mday - if @time - @time.mday - elsif @datetime - @datetime.mday - else - to_time.mday - end - end - alias :day :mday - - # Returns the hour of the day (0..23). - def hour - if @time - @time.hour - elsif @datetime - @datetime.hour - else - to_time.hour - end - end - - # Returns the minute of the hour (0..59). - def min - if @time - @time.min - elsif @datetime - @datetime.min - else - to_time.min - end - end - - # Returns the second of the minute (0..60). (60 for a leap second). - def sec - if @time - @time.sec - elsif @datetime - @datetime.sec - else - to_time.sec - end - end - - # Returns the number of microseconds for the time. - def usec - if @time - @time.usec - elsif @datetime - # Ruby 1.8 has sec_fraction (of which the documentation says - # 'I do NOT recommend you to use this method'). sec_fraction no longer - # exists in Ruby 1.9. - - # Calculate the sec_fraction from the day_fraction. - ((@datetime.day_fraction - OffsetRationals.rational_for_offset(@datetime.hour * 3600 + @datetime.min * 60 + @datetime.sec)) * 86400000000).to_i - else - 0 - end - end - - # Compares this TimeOrDateTime with another Time, DateTime, timestamp - # (Integer) or TimeOrDateTime. Returns -1, 0 or +1 depending - # whether the receiver is less than, equal to, or greater than - # timeOrDateTime. - # - # Returns nil if the passed in timeOrDateTime is not comparable with - # TimeOrDateTime instances. - # - # Comparisons involving a DateTime will be performed using DateTime#<=>. - # Comparisons that don't involve a DateTime, but include a Time will be - # performed with Time#<=>. Otherwise comparisons will be performed with - # Integer#<=>. - def <=>(timeOrDateTime) - return nil unless timeOrDateTime.is_a?(TimeOrDateTime) || - timeOrDateTime.is_a?(Time) || - timeOrDateTime.is_a?(DateTime) || - timeOrDateTime.respond_to?(:to_i) - - unless timeOrDateTime.is_a?(TimeOrDateTime) - timeOrDateTime = TimeOrDateTime.wrap(timeOrDateTime) - end - - orig = timeOrDateTime.to_orig - - if @orig.is_a?(DateTime) || orig.is_a?(DateTime) - # If either is a DateTime, assume it is there for a reason - # (i.e. for its larger range of acceptable values on 32-bit systems). - to_datetime <=> timeOrDateTime.to_datetime - elsif @orig.is_a?(Time) || orig.is_a?(Time) - to_time <=> timeOrDateTime.to_time - else - to_i <=> timeOrDateTime.to_i - end - end - - # Adds a number of seconds to the TimeOrDateTime. Returns a new - # TimeOrDateTime, preserving what the original constructed type was. - # If the original type is a Time and the resulting calculation goes out of - # range for Times, then an exception will be raised by the Time class. - def +(seconds) - if seconds == 0 - self - else - if @orig.is_a?(DateTime) - TimeOrDateTime.new(@orig + OffsetRationals.rational_for_offset(seconds)) - else - # + defined for Time and Integer - TimeOrDateTime.new(@orig + seconds) - end - end - end - - # Subtracts a number of seconds from the TimeOrDateTime. Returns a new - # TimeOrDateTime, preserving what the original constructed type was. - # If the original type is a Time and the resulting calculation goes out of - # range for Times, then an exception will be raised by the Time class. - def -(seconds) - self + (-seconds) - end - - # Similar to the + operator, but converts to a DateTime based TimeOrDateTime - # where the Time or Integer timestamp to go out of the allowed range for a - # Time, converts to a DateTime based TimeOrDateTime. - # - # Note that the range of Time varies based on the platform. - def add_with_convert(seconds) - if seconds == 0 - self - else - if @orig.is_a?(DateTime) - TimeOrDateTime.new(@orig + OffsetRationals.rational_for_offset(seconds)) - else - # A Time or timestamp. - result = to_i + seconds - - if ((result > 2147483647 || result < -2147483648) && !RubyCoreSupport.time_supports_64bit) || (result < 0 && !RubyCoreSupport.time_supports_negative) - result = TimeOrDateTime.new(to_datetime + OffsetRationals.rational_for_offset(seconds)) - else - result = TimeOrDateTime.new(@orig + seconds) - end - end - end - end - - # Returns true if todt represents the same time and was originally - # constructed with the same type (DateTime, Time or timestamp) as this - # TimeOrDateTime. - def eql?(todt) - todt.kind_of?(TimeOrDateTime) && to_orig.eql?(todt.to_orig) - end - - # Returns a hash of this TimeOrDateTime. - def hash - @orig.hash - end - - # If no block is given, returns a TimeOrDateTime wrapping the given - # timeOrDateTime. If a block is specified, a TimeOrDateTime is constructed - # and passed to the block. The result of the block must be a TimeOrDateTime. - # - # The result of the block will be converted to the type of the originally - # passed in timeOrDateTime and then returned as the result of wrap. - # - # timeOrDateTime can be a Time, DateTime, timestamp (Integer) or - # TimeOrDateTime. If a TimeOrDateTime is passed in, no new TimeOrDateTime - # will be constructed and the value passed to wrap will be used when - # calling the block. - def self.wrap(timeOrDateTime) - t = timeOrDateTime.is_a?(TimeOrDateTime) ? timeOrDateTime : TimeOrDateTime.new(timeOrDateTime) - - if block_given? - t = yield t - - if timeOrDateTime.is_a?(TimeOrDateTime) - t - elsif timeOrDateTime.is_a?(Time) - t.to_time - elsif timeOrDateTime.is_a?(DateTime) - t.to_datetime - else - t.to_i - end - else - t - end - end - end -end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/timestamp.rb ruby-tzinfo-2.0.4/lib/tzinfo/timestamp.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/timestamp.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/timestamp.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,548 @@ +# encoding: UTF-8 +# frozen_string_literal: true + +module TZInfo + # A time represented as an `Integer` number of seconds since 1970-01-01 + # 00:00:00 UTC (ignoring leap seconds), the fraction through the second + # (sub_second as a `Rational`) and an optional UTC offset. Like Ruby's `Time` + # class, {Timestamp} can distinguish between a local time with a zero offset + # and a time specified explicitly as UTC. + class Timestamp + include Comparable + + # The Unix epoch (1970-01-01 00:00:00 UTC) as a chronological Julian day + # number. + JD_EPOCH = 2440588 + private_constant :JD_EPOCH + + class << self + # Returns a new {Timestamp} representing the (Gregorian calendar) date and + # time specified by the supplied parameters. + # + # If `utc_offset` is `nil`, `:utc` or 0, the date and time parameters will + # be interpreted as representing a UTC date and time. Otherwise the date + # and time parameters will be interpreted as a local date and time with + # the given offset. + # + # @param year [Integer] the year. + # @param month [Integer] the month (1-12). + # @param day [Integer] the day of the month (1-31). + # @param hour [Integer] the hour (0-23). + # @param minute [Integer] the minute (0-59). + # @param second [Integer] the second (0-59). + # @param sub_second [Numeric] the fractional part of the second as either + # a `Rational` that is greater than or equal to 0 and less than 1, or + # the `Integer` 0. + # @param utc_offset [Object] either `nil` for a {Timestamp} without a + # specified offset, an offset from UTC specified as an `Integer` number + # of seconds or the `Symbol` `:utc`). + # @return [Timestamp] a new {Timestamp} representing the specified + # (Gregorian calendar) date and time. + # @raise [ArgumentError] if either of `year`, `month`, `day`, `hour`, + # `minute`, or `second` is not an `Integer`. + # @raise [ArgumentError] if `sub_second` is not a `Rational`, or the + # `Integer` 0. + # @raise [ArgumentError] if `utc_offset` is not `nil`, not an `Integer` + # and not the `Symbol` `:utc`. + # @raise [RangeError] if `month` is not between 1 and 12. + # @raise [RangeError] if `day` is not between 1 and 31. + # @raise [RangeError] if `hour` is not between 0 and 23. + # @raise [RangeError] if `minute` is not between 0 and 59. + # @raise [RangeError] if `second` is not between 0 and 59. + # @raise [RangeError] if `sub_second` is a `Rational` but that is less + # than 0 or greater than or equal to 1. + def create(year, month = 1, day = 1, hour = 0, minute = 0, second = 0, sub_second = 0, utc_offset = nil) + raise ArgumentError, 'year must be an Integer' unless year.kind_of?(Integer) + raise ArgumentError, 'month must be an Integer' unless month.kind_of?(Integer) + raise ArgumentError, 'day must be an Integer' unless day.kind_of?(Integer) + raise ArgumentError, 'hour must be an Integer' unless hour.kind_of?(Integer) + raise ArgumentError, 'minute must be an Integer' unless minute.kind_of?(Integer) + raise ArgumentError, 'second must be an Integer' unless second.kind_of?(Integer) + raise RangeError, 'month must be between 1 and 12' if month < 1 || month > 12 + raise RangeError, 'day must be between 1 and 31' if day < 1 || day > 31 + raise RangeError, 'hour must be between 0 and 23' if hour < 0 || hour > 23 + raise RangeError, 'minute must be between 0 and 59' if minute < 0 || minute > 59 + raise RangeError, 'second must be between 0 and 59' if second < 0 || second > 59 + + # Based on days_from_civil from https://howardhinnant.github.io/date_algorithms.html#days_from_civil + after_february = month > 2 + year -= 1 unless after_february + era = year / 400 + year_of_era = year - era * 400 + day_of_year = (153 * (month + (after_february ? -3 : 9)) + 2) / 5 + day - 1 + day_of_era = year_of_era * 365 + year_of_era / 4 - year_of_era / 100 + day_of_year + days_since_epoch = era * 146097 + day_of_era - 719468 + value = ((days_since_epoch * 24 + hour) * 60 + minute) * 60 + second + value -= utc_offset if utc_offset.kind_of?(Integer) + + new(value, sub_second, utc_offset) + end + + # When used without a block, returns a {Timestamp} representation of a + # given `Time`, `DateTime` or {Timestamp}. + # + # When called with a block, the {Timestamp} representation of `value` is + # passed to the block. The block must then return a {Timestamp}, which + # will be converted back to the type of the initial value. If the initial + # value was a {Timestamp}, the block result will just be returned. + # + # The UTC offset of `value` can either be preserved (the {Timestamp} + # representation will have the same UTC offset as `value`), ignored (the + # {Timestamp} representation will have no defined UTC offset), or treated + # as though it were UTC (the {Timestamp} representation will have a + # {utc_offset} of 0 and {utc?} will return `true`). + # + # @param value [Object] a `Time`, `DateTime` or {Timestamp}. + # @param offset [Symbol] either `:preserve` to preserve the offset of + # `value`, `:ignore` to ignore the offset of `value` and create a + # {Timestamp} with an unspecified offset, or `:treat_as_utc` to treat + # the offset of `value` as though it were UTC and create a UTC + # {Timestamp}. + # @yield [timestamp] if a block is provided, the {Timestamp} + # representation is passed to the block. + # @yieldparam timestamp [Timestamp] the {Timestamp} representation of + # `value`. + # @yieldreturn [Timestamp] a {Timestamp} to be converted back to the type + # of `value`. + # @return [Object] if called without a block, the {Timestamp} + # representation of `value`, otherwise the result of the block, + # converted back to the type of `value`. + def for(value, offset = :preserve) + raise ArgumentError, 'value must be specified' unless value + + case offset + when :ignore + ignore_offset = true + target_utc_offset = nil + when :treat_as_utc + ignore_offset = true + target_utc_offset = :utc + when :preserve + ignore_offset = false + target_utc_offset = nil + else + raise ArgumentError, 'offset must be :preserve, :ignore or :treat_as_utc' + end + + time_like = false + timestamp = case value + when Time + for_time(value, ignore_offset, target_utc_offset) + when DateTime + for_datetime(value, ignore_offset, target_utc_offset) + when Timestamp + for_timestamp(value, ignore_offset, target_utc_offset) + else + raise ArgumentError, "#{value.class} values are not supported" unless is_time_like?(value) + time_like = true + for_time_like(value, ignore_offset, target_utc_offset) + end + + if block_given? + result = yield timestamp + raise ArgumentError, 'block must return a Timestamp' unless result.kind_of?(Timestamp) + + case value + when Time + result.to_time + when DateTime + result.to_datetime + else # A Time-like value or a Timestamp + time_like ? result.to_time : result + end + else + timestamp + end + end + + # Creates a new UTC {Timestamp}. + # + # @param value [Integer] the number of seconds since 1970-01-01 00:00:00 + # UTC ignoring leap seconds. + # @param sub_second [Numeric] the fractional part of the second as either + # a `Rational` that is greater than or equal to 0 and less than 1, or + # the `Integer` 0. + # @raise [ArgumentError] if `value` is not an `Integer`. + # @raise [ArgumentError] if `sub_second` is not a `Rational`, or the + # `Integer` 0. + # @raise [RangeError] if `sub_second` is a `Rational` but that is less + # than 0 or greater than or equal to 1. + def utc(value, sub_second = 0) + new(value, sub_second, :utc) + end + + private + + # Constructs a new instance of `self` (i.e. {Timestamp} or a subclass of + # {Timestamp}) without validating the parameters. This method is used + # internally within {Timestamp} to avoid the overhead of checking + # parameters. + # + # @param value [Integer] the number of seconds since 1970-01-01 00:00:00 + # UTC ignoring leap seconds. + # @param sub_second [Numeric] the fractional part of the second as either + # a `Rational` that is greater than or equal to 0 and less than 1, or + # the `Integer` 0. + # @param utc_offset [Object] either `nil` for a {Timestamp} without a + # specified offset, an offset from UTC specified as an `Integer` number + # of seconds or the `Symbol` `:utc`). + # @return [Timestamp] a new instance of `self`. + def new!(value, sub_second = 0, utc_offset = nil) + result = allocate + result.send(:initialize!, value, sub_second, utc_offset) + result + end + + # Creates a {Timestamp} that represents a given `Time`, optionally + # ignoring the offset. + # + # @param time [Time] a `Time`. + # @param ignore_offset [Boolean] whether to ignore the offset of `time`. + # @param target_utc_offset [Object] if `ignore_offset` is `true`, the UTC + # offset of the result (`:utc`, `nil` or an `Integer`). + # @return [Timestamp] the {Timestamp} representation of `time`. + def for_time(time, ignore_offset, target_utc_offset) + value = time.to_i + sub_second = time.subsec + + if ignore_offset + utc_offset = target_utc_offset + value += time.utc_offset + elsif time.utc? + utc_offset = :utc + else + utc_offset = time.utc_offset + end + + new!(value, sub_second, utc_offset) + end + + # Creates a {Timestamp} that represents a given `DateTime`, optionally + # ignoring the offset. + # + # @param datetime [DateTime] a `DateTime`. + # @param ignore_offset [Boolean] whether to ignore the offset of + # `datetime`. + # @param target_utc_offset [Object] if `ignore_offset` is `true`, the UTC + # offset of the result (`:utc`, `nil` or an `Integer`). + # @return [Timestamp] the {Timestamp} representation of `datetime`. + def for_datetime(datetime, ignore_offset, target_utc_offset) + value = (datetime.jd - JD_EPOCH) * 86400 + datetime.sec + datetime.min * 60 + datetime.hour * 3600 + sub_second = datetime.sec_fraction + + if ignore_offset + utc_offset = target_utc_offset + else + utc_offset = (datetime.offset * 86400).to_i + value -= utc_offset + end + + new!(value, sub_second, utc_offset) + end + + # Returns a {Timestamp} that represents another {Timestamp}, optionally + # ignoring the offset. If the result would be identical to `value`, the + # same instance is returned. If the passed in value is an instance of a + # subclass of {Timestamp}, then a new {Timestamp} will always be returned. + # + # @param timestamp [Timestamp] a {Timestamp}. + # @param ignore_offset [Boolean] whether to ignore the offset of + # `timestamp`. + # @param target_utc_offset [Object] if `ignore_offset` is `true`, the UTC + # offset of the result (`:utc`, `nil` or an `Integer`). + # @return [Timestamp] a [Timestamp] representation of `timestamp`. + def for_timestamp(timestamp, ignore_offset, target_utc_offset) + if ignore_offset + if target_utc_offset + unless target_utc_offset == :utc && timestamp.utc? || timestamp.utc_offset == target_utc_offset + return new!(timestamp.value + (timestamp.utc_offset || 0), timestamp.sub_second, target_utc_offset) + end + elsif timestamp.utc_offset + return new!(timestamp.value + timestamp.utc_offset, timestamp.sub_second) + end + end + + unless timestamp.instance_of?(Timestamp) + # timestamp is identical in value, sub_second and utc_offset but is a + # subclass (i.e. TimestampWithOffset). Return a new Timestamp + # instance. + return new!(timestamp.value, timestamp.sub_second, timestamp.utc? ? :utc : timestamp.utc_offset) + end + + timestamp + end + + # Determines if an object is like a `Time` (for the purposes of converting + # to a {Timestamp} with {for}), responding to `to_i` and `subsec`. + # + # @param value [Object] an object to test. + # @return [Boolean] `true` if the object is `Time`-like, otherwise + # `false`. + def is_time_like?(value) + value.respond_to?(:to_i) && value.respond_to?(:subsec) + end + + # Creates a {Timestamp} that represents a given `Time`-like object, + # optionally ignoring the offset (if the `time_like` responds to + # `utc_offset`). + # + # @param time_like [Object] a `Time`-like object. + # @param ignore_offset [Boolean] whether to ignore the offset of `time`. + # @param target_utc_offset [Object] if `ignore_offset` is `true`, the UTC + # offset of the result (`:utc`, `nil` or an `Integer`). + # @return [Timestamp] the {Timestamp} representation of `time_like`. + def for_time_like(time_like, ignore_offset, target_utc_offset) + value = time_like.to_i + sub_second = time_like.subsec.to_r + + if ignore_offset + utc_offset = target_utc_offset + value += time_like.utc_offset.to_i if time_like.respond_to?(:utc_offset) + elsif time_like.respond_to?(:utc_offset) + utc_offset = time_like.utc_offset.to_i + else + utc_offset = 0 + end + + new(value, sub_second, utc_offset) + end + end + + # @return [Integer] the number of seconds since 1970-01-01 00:00:00 UTC + # ignoring leap seconds (i.e. each day is treated as if it were 86,400 + # seconds long). + attr_reader :value + + # @return [Numeric] the fraction of a second elapsed since timestamp as + # either a `Rational` or the `Integer` 0. Always greater than or equal to + # 0 and less than 1. + attr_reader :sub_second + + # @return [Integer] the offset from UTC in seconds or `nil` if the + # {Timestamp} doesn't have a specified offset. + attr_reader :utc_offset + + # Initializes a new {Timestamp}. + # + # @param value [Integer] the number of seconds since 1970-01-01 00:00:00 UTC + # ignoring leap seconds. + # @param sub_second [Numeric] the fractional part of the second as either a + # `Rational` that is greater than or equal to 0 and less than 1, or + # the `Integer` 0. + # @param utc_offset [Object] either `nil` for a {Timestamp} without a + # specified offset, an offset from UTC specified as an `Integer` number of + # seconds or the `Symbol` `:utc`). + # @raise [ArgumentError] if `value` is not an `Integer`. + # @raise [ArgumentError] if `sub_second` is not a `Rational`, or the + # `Integer` 0. + # @raise [RangeError] if `sub_second` is a `Rational` but that is less + # than 0 or greater than or equal to 1. + # @raise [ArgumentError] if `utc_offset` is not `nil`, not an `Integer` and + # not the `Symbol` `:utc`. + def initialize(value, sub_second = 0, utc_offset = nil) + raise ArgumentError, 'value must be an Integer' unless value.kind_of?(Integer) + raise ArgumentError, 'sub_second must be a Rational or the Integer 0' unless (sub_second.kind_of?(Integer) && sub_second == 0) || sub_second.kind_of?(Rational) + raise RangeError, 'sub_second must be >= 0 and < 1' if sub_second < 0 || sub_second >= 1 + raise ArgumentError, 'utc_offset must be an Integer, :utc or nil' if utc_offset && utc_offset != :utc && !utc_offset.kind_of?(Integer) + initialize!(value, sub_second, utc_offset) + end + + # @return [Boolean] `true` if this {Timestamp} represents UTC, `false` if + # the {Timestamp} wasn't specified as UTC or `nil` if the {Timestamp} has + # no specified offset. + def utc? + @utc + end + + # Adds a number of seconds to the {Timestamp} value, setting the UTC offset + # of the result. + # + # @param seconds [Integer] the number of seconds to be added. + # @param utc_offset [Object] either `nil` for a {Timestamp} without a + # specified offset, an offset from UTC specified as an `Integer` number of + # seconds or the `Symbol` `:utc`). + # @return [Timestamp] the result of adding `seconds` to the + # {Timestamp} value as a new {Timestamp} instance with the chosen + # `utc_offset`. + # @raise [ArgumentError] if `seconds` is not an `Integer`. + # @raise [ArgumentError] if `utc_offset` is not `nil`, not an `Integer` and + # not the `Symbol` `:utc`. + def add_and_set_utc_offset(seconds, utc_offset) + raise ArgumentError, 'seconds must be an Integer' unless seconds.kind_of?(Integer) + raise ArgumentError, 'utc_offset must be an Integer, :utc or nil' if utc_offset && utc_offset != :utc && !utc_offset.kind_of?(Integer) + return self if seconds == 0 && utc_offset == (@utc ? :utc : @utc_offset) + Timestamp.send(:new!, @value + seconds, @sub_second, utc_offset) + end + + # @return [Timestamp] a UTC {Timestamp} equivalent to this instance. Returns + # `self` if {#utc? self.utc?} is `true`. + def utc + return self if @utc + Timestamp.send(:new!, @value, @sub_second, :utc) + end + + # Converts this {Timestamp} to a `Time`. + # + # @return [Time] a `Time` representation of this {Timestamp}. If the UTC + # offset of this {Timestamp} is not specified, a UTC `Time` will be + # returned. + def to_time + time = new_time + + if @utc_offset && !@utc + time.localtime(@utc_offset) + else + time.utc + end + end + + # Converts this {Timestamp} to a `DateTime`. + # + # @return [DateTime] a DateTime representation of this {Timestamp}. If the + # UTC offset of this {Timestamp} is not specified, a UTC `DateTime` will + # be returned. + def to_datetime + new_datetime + end + + # Converts this {Timestamp} to an `Integer` number of seconds since + # 1970-01-01 00:00:00 UTC (ignoring leap seconds). + # + # @return [Integer] an Integer representation of this {Timestamp} (the + # number of seconds since 1970-01-01 00:00:00 UTC ignoring leap seconds). + def to_i + value + end + + # Formats this {Timestamp} according to the directives in the given format + # string. + # + # @param format [String] the format string. Please refer to `Time#strftime` + # for a list of supported format directives. + # @return [String] the formatted {Timestamp}. + # @raise [ArgumentError] if `format` is not specified. + def strftime(format) + raise ArgumentError, 'format must be specified' unless format + to_time.strftime(format) + end + + # @return [String] a `String` representation of this {Timestamp}. + def to_s + return value_and_sub_second_to_s unless @utc_offset + return "#{value_and_sub_second_to_s} UTC" if @utc + + sign = @utc_offset >= 0 ? '+' : '-' + min, sec = @utc_offset.abs.divmod(60) + hour, min = min.divmod(60) + + "#{value_and_sub_second_to_s(@utc_offset)} #{sign}#{'%02d' % hour}:#{'%02d' % min}#{sec > 0 ? ':%02d' % sec : nil}#{@utc_offset != 0 ? " (#{value_and_sub_second_to_s} UTC)" : nil}" + end + + # Compares this {Timestamp} with another. + # + # {Timestamp} instances without a defined UTC offset are not comparable with + # {Timestamp} instances that have a defined UTC offset. + # + # @param t [Timestamp] the {Timestamp} to compare this instance with. + # @return [Integer] -1, 0 or 1 depending if this instance is earlier, equal + # or later than `t` respectively. Returns `nil` when comparing a + # {Timestamp} that does not have a defined UTC offset with a {Timestamp} + # that does have a defined UTC offset. Returns `nil` if `t` is not a + # {Timestamp}. + def <=>(t) + return nil unless t.kind_of?(Timestamp) + return nil if utc_offset && !t.utc_offset + return nil if !utc_offset && t.utc_offset + + result = value <=> t.value + result = sub_second <=> t.sub_second if result == 0 + result + end + + alias eql? == + + # @return [Integer] a hash based on the value, sub-second and whether there + # is a defined UTC offset. + def hash + [@value, @sub_second, !!@utc_offset].hash + end + + # @return [String] the internal object state as a programmer-readable + # `String`. + def inspect + "#<#{self.class}: @value=#{@value}, @sub_second=#{@sub_second}, @utc_offset=#{@utc_offset.inspect}, @utc=#{@utc.inspect}>" + end + + protected + + # Creates a new instance of a `Time` or `Time`-like class matching the + # {value} and {sub_second} of this {Timestamp}, but not setting the offset. + # + # @param klass [Class] the class to instantiate. + # + # @private + def new_time(klass = Time) + klass.at(@value, @sub_second * 1_000_000) + end + + # Constructs a new instance of a `DateTime` or `DateTime`-like class with + # the same {value}, {sub_second} and {utc_offset} as this {Timestamp}. + # + # @param klass [Class] the class to instantiate. + # + # @private + def new_datetime(klass = DateTime) + datetime = klass.jd(JD_EPOCH + ((@value.to_r + @sub_second) / 86400)) + @utc_offset && @utc_offset != 0 ? datetime.new_offset(Rational(@utc_offset, 86400)) : datetime + end + + private + + # Converts the value and sub-seconds to a `String`, adding on the given + # offset. + # + # @param offset [Integer] the offset to add to the value. + # @return [String] the value and sub-seconds. + def value_and_sub_second_to_s(offset = 0) + "#{@value + offset}#{sub_second_to_s}" + end + + # Converts the {sub_second} value to a `String` suitable for appending to + # the `String` representation of a {Timestamp}. + # + # @return [String] a `String` representation of {sub_second}. + def sub_second_to_s + if @sub_second == 0 + '' + else + " #{@sub_second.numerator}/#{@sub_second.denominator}" + end + end + + # Initializes a new {Timestamp} without validating the parameters. This + # method is used internally within {Timestamp} to avoid the overhead of + # checking parameters. + # + # @param value [Integer] the number of seconds since 1970-01-01 00:00:00 UTC + # ignoring leap seconds. + # @param sub_second [Numeric] the fractional part of the second as either a + # `Rational` that is greater than or equal to 0 and less than 1, or the + # `Integer` 0. + # @param utc_offset [Object] either `nil` for a {Timestamp} without a + # specified offset, an offset from UTC specified as an `Integer` number of + # seconds or the `Symbol` `:utc`). + def initialize!(value, sub_second = 0, utc_offset = nil) + @value = value + + # Convert Rational(0,1) to 0. + @sub_second = sub_second == 0 ? 0 : sub_second + + if utc_offset + @utc = utc_offset == :utc + @utc_offset = @utc ? 0 : utc_offset + else + @utc = @utc_offset = nil + end + end + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/timestamp_with_offset.rb ruby-tzinfo-2.0.4/lib/tzinfo/timestamp_with_offset.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/timestamp_with_offset.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/timestamp_with_offset.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,85 @@ +# encoding: UTF-8 +# frozen_string_literal: true + +module TZInfo + # A subclass of {Timestamp} used to represent local times. + # {TimestampWithOffset} holds a reference to the related {TimezoneOffset} and + # overrides various methods to return results appropriate for the + # {TimezoneOffset}. Certain operations will clear the associated + # {TimezoneOffset} (if the {TimezoneOffset} would not necessarily be valid for + # the result). Once the {TimezoneOffset} has been cleared, + # {TimestampWithOffset} behaves identically to {Timestamp}. + class TimestampWithOffset < Timestamp + include WithOffset + + # @return [TimezoneOffset] the {TimezoneOffset} associated with this + # instance. + attr_reader :timezone_offset + + # Creates a new {TimestampWithOffset} from a given {Timestamp} and + # {TimezoneOffset}. + # + # @param timestamp [Timestamp] a {Timestamp}. + # @param timezone_offset [TimezoneOffset] a {TimezoneOffset} valid at the + # time of `timestamp`. + # @return [TimestampWithOffset] a {TimestampWithOffset} that has the same + # {value value} and {sub_second sub_second} as the `timestamp` parameter, + # a {utc_offset utc_offset} equal to the + # {TimezoneOffset#observed_utc_offset observed_utc_offset} of the + # `timezone_offset` parameter and {timezone_offset timezone_offset} set to + # the `timezone_offset` parameter. + # @raise [ArgumentError] if `timestamp` or `timezone_offset` is `nil`. + def self.set_timezone_offset(timestamp, timezone_offset) + raise ArgumentError, 'timestamp must be specified' unless timestamp + raise ArgumentError, 'timezone_offset must be specified' unless timezone_offset + new!(timestamp.value, timestamp.sub_second, timezone_offset.observed_utc_offset).set_timezone_offset(timezone_offset) + end + + # Sets the associated {TimezoneOffset} of this {TimestampWithOffset}. + # + # @param timezone_offset [TimezoneOffset] a {TimezoneOffset} valid at the time + # and for the offset of this {TimestampWithOffset}. + # @return [TimestampWithOffset] `self`. + # @raise [ArgumentError] if `timezone_offset` is `nil`. + # @raise [ArgumentError] if {utc? self.utc?} is `true`. + # @raise [ArgumentError] if `timezone_offset.observed_utc_offset` does not equal + # `self.utc_offset`. + def set_timezone_offset(timezone_offset) + raise ArgumentError, 'timezone_offset must be specified' unless timezone_offset + raise ArgumentError, 'timezone_offset.observed_utc_offset does not match self.utc_offset' if utc? || utc_offset != timezone_offset.observed_utc_offset + @timezone_offset = timezone_offset + self + end + + # An overridden version of {Timestamp#to_time} that, if there is an + # associated {TimezoneOffset}, returns a {TimeWithOffset} with that offset. + # + # @return [Time] if there is an associated {TimezoneOffset}, a + # {TimeWithOffset} representation of this {TimestampWithOffset}, otherwise + # a `Time` representation. + def to_time + to = timezone_offset + if to + new_time(TimeWithOffset).set_timezone_offset(to) + else + super + end + end + + # An overridden version of {Timestamp#to_datetime}, if there is an + # associated {TimezoneOffset}, returns a {DateTimeWithOffset} with that + # offset. + # + # @return [DateTime] if there is an associated {TimezoneOffset}, a + # {DateTimeWithOffset} representation of this {TimestampWithOffset}, + # otherwise a `DateTime` representation. + def to_datetime + to = timezone_offset + if to + new_datetime(DateTimeWithOffset).set_timezone_offset(to) + else + super + end + end + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/time_with_offset.rb ruby-tzinfo-2.0.4/lib/tzinfo/time_with_offset.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/time_with_offset.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/time_with_offset.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,154 @@ +# encoding: UTF-8 +# frozen_string_literal: true + +module TZInfo + # A subclass of `Time` used to represent local times. {TimeWithOffset} holds a + # reference to the related {TimezoneOffset} and overrides various methods to + # return results appropriate for the {TimezoneOffset}. Certain operations will + # clear the associated {TimezoneOffset} (if the {TimezoneOffset} would not + # necessarily be valid for the result). Once the {TimezoneOffset} has been + # cleared, {TimeWithOffset} behaves identically to `Time`. + # + # Arithmetic performed on {TimeWithOffset} instances is _not_ time zone-aware. + # Regardless of whether transitions in the time zone are crossed, results of + # arithmetic operations will always maintain the same offset from UTC + # (`utc_offset`). The associated {TimezoneOffset} will aways be cleared. + class TimeWithOffset < Time + include WithOffset + + # @return [TimezoneOffset] the {TimezoneOffset} associated with this + # instance. + attr_reader :timezone_offset + + # Marks this {TimeWithOffset} as a local time with the UTC offset of a given + # {TimezoneOffset} and sets the associated {TimezoneOffset}. + # + # @param timezone_offset [TimezoneOffset] the {TimezoneOffset} to use to set + # the offset of this {TimeWithOffset}. + # @return [TimeWithOffset] `self`. + # @raise [ArgumentError] if `timezone_offset` is `nil`. + def set_timezone_offset(timezone_offset) + raise ArgumentError, 'timezone_offset must be specified' unless timezone_offset + localtime(timezone_offset.observed_utc_offset) + @timezone_offset = timezone_offset + self + end + + # An overridden version of `Time#dst?` that, if there is an associated + # {TimezoneOffset}, returns the result of calling {TimezoneOffset#dst? dst?} + # on that offset. + # + # @return [Boolean] `true` if daylight savings time is being observed, + # otherwise `false`. + def dst? + to = timezone_offset + to ? to.dst? : super + end + alias isdst dst? + + # An overridden version of `Time#getlocal` that clears the associated + # {TimezoneOffset} if the base implementation of `getlocal` returns a + # {TimeWithOffset}. + # + # @return [Time] a representation of the {TimeWithOffset} using either the + # local time zone or the given offset. + def getlocal(*args) + # JRuby < 9.3 returns a Time in all cases. + # JRuby >= 9.3 returns a Time when called with no arguments and a + # TimeWithOffset with a timezone_offset assigned when called with an + # offset argument. + result = super + result.clear_timezone_offset if result.kind_of?(TimeWithOffset) + result + end + + # An overridden version of `Time#gmtime` that clears the associated + # {TimezoneOffset}. + # + # @return [TimeWithOffset] `self`. + def gmtime + super + @timezone_offset = nil + self + end + + # An overridden version of `Time#localtime` that clears the associated + # {TimezoneOffset}. + # + # @return [TimeWithOffset] `self`. + def localtime(*args) + super + @timezone_offset = nil + self + end + + # An overridden version of `Time#round` that, if there is an associated + # {TimezoneOffset}, returns a {TimeWithOffset} preserving that offset. + # + # @return [Time] the rounded time. + def round(ndigits = 0) + if_timezone_offset(super) {|o,t| self.class.at(t.to_i, t.subsec * 1_000_000).set_timezone_offset(o) } + end + + # An overridden version of `Time#to_a`. The `isdst` (index 8) and `zone` + # (index 9) elements of the array are set according to the associated + # {TimezoneOffset}. + # + # @return [Array] an `Array` representation of the {TimeWithOffset}. + def to_a + if_timezone_offset(super) do |o,a| + a[8] = o.dst? + a[9] = o.abbreviation + a + end + end + + # An overridden version of `Time#utc` that clears the associated + # {TimezoneOffset}. + # + # @return [TimeWithOffset] `self`. + def utc + super + @timezone_offset = nil + self + end + + # An overridden version of `Time#zone` that, if there is an associated + # {TimezoneOffset}, returns the {TimezoneOffset#abbreviation abbreviation} + # of that offset. + # + # @return [String] the {TimezoneOffset#abbreviation abbreviation} of the + # associated {TimezoneOffset}, or the result from `Time#zone` if there is + # no such offset. + def zone + to = timezone_offset + to ? to.abbreviation : super + end + + # An overridden version of `Time#to_datetime` that, if there is an + # associated {TimezoneOffset}, returns a {DateTimeWithOffset} with that + # offset. + # + # @return [DateTime] if there is an associated {TimezoneOffset}, a + # {DateTimeWithOffset} representation of this {TimeWithOffset}, otherwise + # a `Time` representation. + def to_datetime + if_timezone_offset(super) do |o,dt| + offset = dt.offset + result = DateTimeWithOffset.jd(dt.jd + dt.day_fraction - offset) + result = result.new_offset(offset) unless offset == 0 + result.set_timezone_offset(o) + end + end + + protected + + # Clears the associated {TimezoneOffset}. + # + # @return [TimeWithOffset] `self`. + def clear_timezone_offset + @timezone_offset = nil + self + end + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/timezone_definition.rb ruby-tzinfo-2.0.4/lib/tzinfo/timezone_definition.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/timezone_definition.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/timezone_definition.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -module TZInfo - - # TimezoneDefinition is included into Timezone definition modules. - # TimezoneDefinition provides the methods for defining timezones. - # - # @private - module TimezoneDefinition #:nodoc: - # Add class methods to the includee. - def self.append_features(base) - super - base.extend(ClassMethods) - end - - # Class methods for inclusion. - # - # @private - module ClassMethods #:nodoc: - # Returns and yields a TransitionDataTimezoneInfo object to define a - # timezone. - def timezone(identifier) - yield @timezone = TransitionDataTimezoneInfo.new(identifier) - end - - # Defines a linked timezone. - def linked_timezone(identifier, link_to_identifier) - @timezone = LinkedTimezoneInfo.new(identifier, link_to_identifier) - end - - # Returns the last TimezoneInfo to be defined with timezone or - # linked_timezone. - def get - @timezone - end - end - end -end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/timezone_index_definition.rb ruby-tzinfo-2.0.4/lib/tzinfo/timezone_index_definition.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/timezone_index_definition.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/timezone_index_definition.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -module TZInfo - # The timezone index file includes TimezoneIndexDefinition which provides - # methods used to define timezones in the index. - # - # @private - module TimezoneIndexDefinition #:nodoc: - # Add class methods to the includee and initialize class instance variables. - def self.append_features(base) - super - base.extend(ClassMethods) - base.instance_eval do - @timezones = [] - @data_timezones = [] - @linked_timezones = [] - end - end - - # Class methods for inclusion. - # - # @private - module ClassMethods #:nodoc: - # Defines a timezone based on data. - def timezone(identifier) - @timezones << identifier - @data_timezones << identifier - end - - # Defines a timezone which is a link to another timezone. - def linked_timezone(identifier) - @timezones << identifier - @linked_timezones << identifier - end - - # Returns a frozen array containing the identifiers of all the timezones. - # Identifiers appear in the order they were defined in the index. - def timezones - @timezones.freeze - end - - # Returns a frozen array containing the identifiers of all data timezones. - # Identifiers appear in the order they were defined in the index. - def data_timezones - @data_timezones.freeze - end - - # Returns a frozen array containing the identifiers of all linked - # timezones. Identifiers appear in the order they were defined in - # the index. - def linked_timezones - @linked_timezones.freeze - end - end - end -end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/timezone_info.rb ruby-tzinfo-2.0.4/lib/tzinfo/timezone_info.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/timezone_info.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/timezone_info.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -module TZInfo - # Represents a timezone defined by a data source. - class TimezoneInfo - - # The timezone identifier. - attr_reader :identifier - - # Constructs a new TimezoneInfo with an identifier. - def initialize(identifier) - @identifier = identifier - end - - # Returns internal object state as a programmer-readable string. - def inspect - "#<#{self.class}: #@identifier>" - end - - # Constructs a Timezone instance for the timezone represented by this - # TimezoneInfo. - def create_timezone - raise_not_implemented('create_timezone') - end - - private - - def raise_not_implemented(method_name) - raise NotImplementedError, "Subclasses must override #{method_name}" - end - end -end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/timezone_offset.rb ruby-tzinfo-2.0.4/lib/tzinfo/timezone_offset.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/timezone_offset.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/timezone_offset.rb 2020-12-30 06:49:15.000000000 +0000 @@ -1,101 +1,111 @@ +# encoding: UTF-8 +# frozen_string_literal: true + module TZInfo - # Represents an offset defined in a Timezone data file. + # Represents an offset from UTC observed by a time zone. class TimezoneOffset - # The base offset of the timezone from UTC in seconds. This does not include - # any adjustment made for daylight savings time and will typically remain - # constant throughout the year. + # Returns the base offset from UTC in seconds (`observed_utc_offset - + # std_offset`). This does not include any adjustment made for daylight + # savings time and will typically remain constant throughout the year. # # To obtain the currently observed offset from UTC, including the effect of - # daylight savings time, use utc_total_offset instead. + # daylight savings time, use {observed_utc_offset} instead. # - # Note that zoneinfo files only include the value of utc_total_offset and a - # DST flag. When using ZoneinfoDataSource, the utc_offset will be derived - # from changes to the UTC total offset and the DST flag. As a consequence, - # utc_total_offset will always be correct, but utc_offset may be inaccurate. - # - # If you require utc_offset to be accurate, install the tzinfo-data gem and - # set RubyDataSource as the DataSource. - attr_reader :utc_offset - - # The offset from the time zone's standard time in seconds. Zero - # when daylight savings time is not in effect. Non-zero (usually 3600 = 1 - # hour) if daylight savings is being observed. - # - # Note that zoneinfo files only include the value of utc_total_offset and - # a DST flag. When using DataSources::ZoneinfoDataSource, the std_offset - # will be derived from changes to the UTC total offset and the DST flag. As - # a consequence, utc_total_offset will always be correct, but std_offset - # may be inaccurate. + # If you require accurate {base_utc_offset} values, you should install the + # tzinfo-data gem and set {DataSources::RubyDataSource} as the {DataSource}. + # When using {DataSources::ZoneinfoDataSource}, the value of + # {base_utc_offset} has to be derived from changes to the observed UTC + # offset and DST status since it is not included in zoneinfo files. + # + # @return [Integer] the base offset from UTC in seconds. + attr_reader :base_utc_offset + alias utc_offset base_utc_offset + + # Returns the offset from the time zone's standard time in seconds + # (`observed_utc_offset - base_utc_offset`). Zero when daylight savings time + # is not in effect. Non-zero (usually 3600 = 1 hour) if daylight savings is + # being observed. + # + # If you require accurate {std_offset} values, you should install the + # tzinfo-data gem and set {DataSources::RubyDataSource} as the {DataSource}. + # When using {DataSources::ZoneinfoDataSource}, the value of {std_offset} + # has to be derived from changes to the observed UTC offset and DST status + # since it is not included in zoneinfo files. # - # If you require std_offset to be accurate, install the tzinfo-data gem - # and set RubyDataSource as the DataSource. + # @return [Integer] the offset from the time zone's standard time in + # seconds. attr_reader :std_offset - - # The total offset of this observance from UTC in seconds - # (utc_offset + std_offset). - attr_reader :utc_total_offset - - # The abbreviation that identifies this observance, e.g. "GMT" - # (Greenwich Mean Time) or "BST" (British Summer Time) for "Europe/London". The returned identifier is a - # symbol. + + # Returns the observed offset from UTC in seconds (`base_utc_offset + + # std_offset`). This includes adjustments made for daylight savings time. + # + # @return [Integer] the observed offset from UTC in seconds. + attr_reader :observed_utc_offset + alias utc_total_offset observed_utc_offset + + # The abbreviation that identifies this offset. For example GMT + # (Greenwich Mean Time) or BST (British Summer Time) for Europe/London. + # + # @return [String] the abbreviation that identifies this offset. attr_reader :abbreviation - - # Constructs a new TimezoneOffset. utc_offset and std_offset are specified - # in seconds. - def initialize(utc_offset, std_offset, abbreviation) - @utc_offset = utc_offset - @std_offset = std_offset - @abbreviation = abbreviation - - @utc_total_offset = @utc_offset + @std_offset - end - - # True if std_offset is non-zero. + alias abbr abbreviation + + # Initializes a new {TimezoneOffset}. + # + # {TimezoneOffset} instances should not normally be constructed manually. + # + # The passed in `abbreviation` instance will be frozen. + # + # @param base_utc_offset [Integer] the base offset from UTC in seconds. + # @param std_offset [Integer] the offset from standard time in seconds. + # @param abbreviation [String] the abbreviation identifying the offset. + def initialize(base_utc_offset, std_offset, abbreviation) + @base_utc_offset = base_utc_offset + @std_offset = std_offset + @abbreviation = abbreviation.freeze + + @observed_utc_offset = @base_utc_offset + @std_offset + end + + # Determines if daylight savings is in effect (i.e. if {std_offset} is + # non-zero). + # + # @return [Boolean] `true` if {std_offset} is non-zero, otherwise `false`. def dst? @std_offset != 0 end - - # Converts a UTC Time, DateTime or integer timestamp to local time, based on - # the offset of this period. - # - # Deprecation warning: this method will be removed in TZInfo version 2.0.0. - def to_local(utc) - TimeOrDateTime.wrap(utc) {|wrapped| - wrapped + @utc_total_offset - } - end - - # Converts a local Time, DateTime or integer timestamp to UTC, based on the - # offset of this period. - # - # Deprecation warning: this method will be removed in TZInfo version 2.0.0. - def to_utc(local) - TimeOrDateTime.wrap(local) {|wrapped| - wrapped - @utc_total_offset - } - end - - # Returns true if and only if toi has the same utc_offset, std_offset - # and abbreviation as this TimezoneOffset. + + # Determines if this {TimezoneOffset} is equal to another instance. + # + # @param toi [Object] the instance to test for equality. + # @return [Boolean] `true` if `toi` is a {TimezoneOffset} with the same + # {utc_offset}, {std_offset} and {abbreviation} as this {TimezoneOffset}, + # otherwise `false`. def ==(toi) toi.kind_of?(TimezoneOffset) && - utc_offset == toi.utc_offset && std_offset == toi.std_offset && abbreviation == toi.abbreviation + base_utc_offset == toi.base_utc_offset && std_offset == toi.std_offset && abbreviation == toi.abbreviation end - - # Returns true if and only if toi has the same utc_offset, std_offset - # and abbreviation as this TimezoneOffset. + + # Determines if this {TimezoneOffset} is equal to another instance. + # + # @param toi [Object] the instance to test for equality. + # @return [Boolean] `true` if `toi` is a {TimezoneOffset} with the same + # {utc_offset}, {std_offset} and {abbreviation} as this {TimezoneOffset}, + # otherwise `false`. def eql?(toi) self == toi end - - # Returns a hash of this TimezoneOffset. + + # @return [Integer] a hash based on {utc_offset}, {std_offset} and + # {abbreviation}. def hash - utc_offset.hash ^ std_offset.hash ^ abbreviation.hash + [@base_utc_offset, @std_offset, @abbreviation].hash end - - # Returns internal object state as a programmer-readable string. + + # @return [String] the internal object state as a programmer-readable + # `String`. def inspect - "#<#{self.class}: #@utc_offset,#@std_offset,#@abbreviation>" + "#<#{self.class}: @base_utc_offset=#{@base_utc_offset}, @std_offset=#{@std_offset}, @abbreviation=#{@abbreviation}>" end end end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/timezone_period.rb ruby-tzinfo-2.0.4/lib/tzinfo/timezone_period.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/timezone_period.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/timezone_period.rb 2020-12-30 06:49:15.000000000 +0000 @@ -1,245 +1,179 @@ +# encoding: UTF-8 +# frozen_string_literal: true + module TZInfo - # A period of time in a timezone where the same offset from UTC applies. + # {TimezonePeriod} represents a period of time for a time zone where the same + # offset from UTC applies. It provides access to the observed offset, time + # zone abbreviation, start time and end time. # - # All the methods that take times accept instances of Time or DateTime as well - # as Integer timestamps. + # The period of time can be unbounded at the start, end, or both the start + # and end. + # + # @abstract Time zone period data will returned as an instance of one of the + # subclasses of {TimezonePeriod}. class TimezonePeriod - # The TimezoneTransition that defines the start of this TimezonePeriod - # (may be nil if unbounded). - attr_reader :start_transition - - # The TimezoneTransition that defines the end of this TimezonePeriod - # (may be nil if unbounded). - attr_reader :end_transition - - # The TimezoneOffset for this period. + # @return [TimezoneOffset] the offset that applies in the period of time. attr_reader :offset - - # Initializes a new TimezonePeriod. + + # Initializes a {TimezonePeriod}. # - # TimezonePeriod instances should not normally be constructed manually. - def initialize(start_transition, end_transition, offset = nil) - @start_transition = start_transition - @end_transition = end_transition - - if offset - raise ArgumentError, 'Offset specified with transitions' if @start_transition || @end_transition - @offset = offset - else - if @start_transition - @offset = @start_transition.offset - elsif @end_transition - @offset = @end_transition.previous_offset - else - raise ArgumentError, 'No offset specified and no transitions to determine it from' - end - end - - @utc_total_offset_rational = nil - end - - # The base offset of the timezone from UTC in seconds. This does not include - # any adjustment made for daylight savings time and will typically remain - # constant throughout the year. + # @param offset [TimezoneOffset] the offset that is observed for the period + # of time. + # @raise [ArgumentError] if `offset` is `nil`. + def initialize(offset) + raise ArgumentError, 'offset must be specified' unless offset + @offset = offset + end + + # @return [TimezoneTransition] the transition that defines the start of this + # {TimezonePeriod} (`nil` if the start is unbounded). + def start_transition + raise_not_implemented(:start_transition) + end + + # @return [TimezoneTransition] the transition that defines the end of this + # {TimezonePeriod} (`nil` if the end is unbounded). + def end_transition + raise_not_implemented(:end_transition) + end + + # Returns the base offset from UTC in seconds (`observed_utc_offset - + # std_offset`). This does not include any adjustment made for daylight + # savings time and will typically remain constant throughout the year. # # To obtain the currently observed offset from UTC, including the effect of - # daylight savings time, use utc_total_offset instead. + # daylight savings time, use {observed_utc_offset} instead. # - # Note that zoneinfo files only include the value of utc_total_offset and a - # DST flag. When using ZoneinfoDataSource, the utc_offset will be derived - # from changes to the UTC total offset and the DST flag. As a consequence, - # utc_total_offset will always be correct, but utc_offset may be inaccurate. - # - # If you require utc_offset to be accurate, install the tzinfo-data gem and - # set RubyDataSource as the DataSource. - def utc_offset - @offset.utc_offset - end - - # The offset from the time zone's standard time in seconds. Zero - # when daylight savings time is not in effect. Non-zero (usually 3600 = 1 - # hour) if daylight savings is being observed. - # - # Note that zoneinfo files only include the value of utc_total_offset and - # a DST flag. When using DataSources::ZoneinfoDataSource, the std_offset - # will be derived from changes to the UTC total offset and the DST flag. As - # a consequence, utc_total_offset will always be correct, but std_offset - # may be inaccurate. + # If you require accurate {base_utc_offset} values, you should install the + # tzinfo-data gem and set {DataSources::RubyDataSource} as the {DataSource}. + # When using {DataSources::ZoneinfoDataSource}, the value of + # {base_utc_offset} has to be derived from changes to the observed UTC + # offset and DST status since it is not included in zoneinfo files. + # + # @return [Integer] the base offset from UTC in seconds. + def base_utc_offset + @offset.base_utc_offset + end + alias utc_offset base_utc_offset + + # Returns the offset from the time zone's standard time in seconds + # (`observed_utc_offset - base_utc_offset`). Zero when daylight savings time + # is not in effect. Non-zero (usually 3600 = 1 hour) if daylight savings is + # being observed. + # + # If you require accurate {std_offset} values, you should install the + # tzinfo-data gem and set {DataSources::RubyDataSource} as the {DataSource}. + # When using {DataSources::ZoneinfoDataSource}, the value of {std_offset} + # has to be derived from changes to the observed UTC offset and DST status + # since it is not included in zoneinfo files. # - # If you require std_offset to be accurate, install the tzinfo-data gem - # and set RubyDataSource as the DataSource. + # @return [Integer] the offset from the time zone's standard time in + # seconds. def std_offset @offset.std_offset end - - # The identifier of this period, e.g. "GMT" (Greenwich Mean Time) or "BST" - # (British Summer Time) for "Europe/London". The returned identifier is a - # symbol. + + # The abbreviation that identifies this offset. For example GMT + # (Greenwich Mean Time) or BST (British Summer Time) for Europe/London. + # + # @return [String] the abbreviation that identifies this offset. def abbreviation @offset.abbreviation end - alias :zone_identifier :abbreviation - - # Total offset from UTC (seconds). Equal to utc_offset + std_offset. - def utc_total_offset - @offset.utc_total_offset - end - - # Total offset from UTC (days). Result is a Rational. - def utc_total_offset_rational - # Thread-safety: It is possible that the value of - # @utc_total_offset_rational may be calculated multiple times in - # concurrently executing threads. It is not worth the overhead of locking - # to ensure that @zone_identifiers is only calculated once. - - unless @utc_total_offset_rational - result = OffsetRationals.rational_for_offset(utc_total_offset) - return result if frozen? - @utc_total_offset_rational = result - end - @utc_total_offset_rational - end - - # The start time of the period in UTC as a DateTime. May be nil if unbounded. - def utc_start - @start_transition ? @start_transition.at.to_datetime : nil - end - - # The start time of the period in UTC as a Time. May be nil if unbounded. - def utc_start_time - @start_transition ? @start_transition.at.to_time : nil - end - - # The end time of the period in UTC as a DateTime. May be nil if unbounded. - def utc_end - @end_transition ? @end_transition.at.to_datetime : nil - end - - # The end time of the period in UTC as a Time. May be nil if unbounded. - def utc_end_time - @end_transition ? @end_transition.at.to_time : nil - end - - # The start time of the period in local time as a DateTime. May be nil if - # unbounded. - def local_start - @start_transition ? @start_transition.local_start_at.to_datetime : nil - end - - # The start time of the period in local time as a Time. May be nil if - # unbounded. - def local_start_time - @start_transition ? @start_transition.local_start_at.to_time : nil - end - - # The end time of the period in local time as a DateTime. May be nil if - # unbounded. - def local_end - @end_transition ? @end_transition.local_end_at.to_datetime : nil - end - - # The end time of the period in local time as a Time. May be nil if - # unbounded. - def local_end_time - @end_transition ? @end_transition.local_end_at.to_time : nil - end - - # true if daylight savings is in effect for this period; otherwise false. + alias abbr abbreviation + alias zone_identifier abbreviation + + # Returns the observed offset from UTC in seconds (`base_utc_offset + + # std_offset`). This includes adjustments made for daylight savings time. + # + # @return [Integer] the observed offset from UTC in seconds. + def observed_utc_offset + @offset.observed_utc_offset + end + alias utc_total_offset observed_utc_offset + + # Determines if daylight savings is in effect (i.e. if {std_offset} is + # non-zero). + # + # @return [Boolean] `true` if {std_offset} is non-zero, otherwise `false`. def dst? @offset.dst? end - - # true if this period is valid for the given UTC DateTime; otherwise false. - # - # Deprecation warning: this method will be removed in TZInfo version 2.0.0. - def valid_for_utc?(utc) - utc_after_start?(utc) && utc_before_end?(utc) - end - - # true if the given UTC DateTime is after the start of the period - # (inclusive); otherwise false. - # - # Deprecation warning: this method will be removed in TZInfo version 2.0.0. - def utc_after_start?(utc) - !@start_transition || @start_transition.at <= utc - end - - # true if the given UTC DateTime is before the end of the period - # (exclusive); otherwise false. - # - # Deprecation warning: this method will be removed in TZInfo version 2.0.0. - def utc_before_end?(utc) - !@end_transition || @end_transition.at > utc - end - - # true if this period is valid for the given local DateTime; otherwise - # false. - # - # Deprecation warning: this method will be removed in TZInfo version 2.0.0. - def valid_for_local?(local) - local_after_start?(local) && local_before_end?(local) - end - - # true if the given local DateTime is after the start of the period - # (inclusive); otherwise false. - # - # Deprecation warning: this method will be removed in TZInfo version 2.0.0. - def local_after_start?(local) - !@start_transition || @start_transition.local_start_at <= local - end - - # true if the given local DateTime is before the end of the period - # (exclusive); otherwise false. - # - # Deprecation warning: this method will be removed in TZInfo version 2.0.0. - def local_before_end?(local) - !@end_transition || @end_transition.local_end_at > local - end - - # Converts a UTC DateTime to local time based on the offset of this period. - # - # Deprecation warning: this method will be removed in TZInfo version 2.0.0. - def to_local(utc) - @offset.to_local(utc) - end - - # Converts a local DateTime to UTC based on the offset of this period. - # - # Deprecation warning: this method will be removed in TZInfo version 2.0.0. - def to_utc(local) - @offset.to_utc(local) - end - - # Returns true if this TimezonePeriod is equal to p. This compares the - # start_transition, end_transition and offset using ==. - def ==(p) - p.kind_of?(TimezonePeriod) && - start_transition == p.start_transition && - end_transition == p.end_transition && - offset == p.offset - end - - # Returns true if this TimezonePeriods is equal to p. This compares the - # start_transition, end_transition and offset using eql? - def eql?(p) - p.kind_of?(TimezonePeriod) && - start_transition.eql?(p.start_transition) && - end_transition.eql?(p.end_transition) && - offset.eql?(p.offset) - end - - # Returns a hash of this TimezonePeriod. - def hash - result = @start_transition.hash ^ @end_transition.hash - result ^= @offset.hash unless @start_transition || @end_transition - result - end - - # Returns internal object state as a programmer-readable string. - def inspect - result = "#<#{self.class}: #{@start_transition.inspect},#{@end_transition.inspect}" - result << ",#{@offset.inspect}>" unless @start_transition || @end_transition - result + '>' + + # Returns the UTC start time of the period or `nil` if the start of the + # period is unbounded. + # + # The result is returned as a {Timestamp}. To obtain the start time as a + # `Time` or `DateTime`, call either {Timestamp#to_time to_time} or + # {Timestamp#to_datetime to_datetime} on the result. + # + # @return [Timestamp] the UTC start time of the period or `nil` if the start + # of the period is unbounded. + def starts_at + timestamp(start_transition) + end + + # Returns the UTC end time of the period or `nil` if the end of the period + # is unbounded. + # + # The result is returned as a {Timestamp}. To obtain the end time as a + # `Time` or `DateTime`, call either {Timestamp#to_time to_time} or + # {Timestamp#to_datetime to_datetime} on the result. + # + # @return [Timestamp] the UTC end time of the period or `nil` if the end of + # the period is unbounded. + def ends_at + timestamp(end_transition) + end + + # Returns the local start time of the period or `nil` if the start of the + # period is unbounded. + # + # The result is returned as a {TimestampWithOffset}. To obtain the start + # time as a `Time` or `DateTime`, call either {TimestampWithOffset#to_time + # to_time} or {TimestampWithOffset#to_datetime to_datetime} on the result. + # + # @return [TimestampWithOffset] the local start time of the period or `nil` + # if the start of the period is unbounded. + def local_starts_at + timestamp_with_offset(start_transition) + end + + # Returns the local end time of the period or `nil` if the end of the period + # is unbounded. + # + # The result is returned as a {TimestampWithOffset}. To obtain the end time + # as a `Time` or `DateTime`, call either {TimestampWithOffset#to_time + # to_time} or {TimestampWithOffset#to_datetime to_datetime} on the result. + # + # @return [TimestampWithOffset] the local end time of the period or `nil` if + # the end of the period is unbounded. + def local_ends_at + timestamp_with_offset(end_transition) + end + + private + + # Raises a {NotImplementedError} to indicate that subclasses should override + # a method. + # + # @raise [NotImplementedError] always. + def raise_not_implemented(method_name) + raise NotImplementedError, "Subclasses must override #{method_name}" + end + + # @param transition [TimezoneTransition] a transition or `nil`. + # @return [Timestamp] the {Timestamp} representing when a transition occurs, + # or `nil` if `transition` is `nil`. + def timestamp(transition) + transition ? transition.at : nil + end + + # @param transition [TimezoneTransition] a transition or `nil`. + # @return [TimestampWithOffset] a {Timestamp} representing when a transition + # occurs with offset set to {#offset}, or `nil` if `transition` is `nil`. + def timestamp_with_offset(transition) + transition ? TimestampWithOffset.set_timezone_offset(transition.at, offset) : nil end end end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/timezone_proxy.rb ruby-tzinfo-2.0.4/lib/tzinfo/timezone_proxy.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/timezone_proxy.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/timezone_proxy.rb 2020-12-30 06:49:15.000000000 +0000 @@ -1,105 +1,96 @@ +# encoding: UTF-8 + module TZInfo - # A proxy class representing a timezone with a given identifier. TimezoneProxy - # inherits from Timezone and can be treated like any Timezone loaded with - # Timezone.get. + # A proxy class standing in for a {Timezone} with a given identifier. + # {TimezoneProxy} inherits from {Timezone} and can be treated identically to + # {Timezone} instances loaded with {Timezone.get}. + # + # {TimezoneProxy} instances are used to avoid the performance overhead of + # loading time zone data into memory, for example, by {Timezone.all}. # - # The first time an attempt is made to access the data for the timezone, the - # real Timezone is loaded. If the proxy's identifier was not valid, then an - # exception will be raised at this point. + # The first time an attempt is made to access the data for the time zone, the + # real {Timezone} will be loaded is loaded. If the proxy's identifier was not + # valid, then an exception will be raised at this point. class TimezoneProxy < Timezone - # Construct a new TimezoneProxy for the given identifier. The identifier - # is not checked when constructing the proxy. It will be validated on the - # when the real Timezone is loaded. - def self.new(identifier) - # Need to override new to undo the behaviour introduced in Timezone#new. - tzp = super() - tzp.send(:setup, identifier) - tzp + # Initializes a new {TimezoneProxy}. + # + # The `identifier` parameter is not checked when initializing the proxy. It + # will be validated when the real {Timezone} instance is loaded. + # + # @param identifier [String] an IANA Time Zone Database time zone + # identifier. + def initialize(identifier) + super() + @identifier = identifier + @real_timezone = nil end - - # The identifier of the timezone, e.g. "Europe/Paris". + + # (see Timezone#identifier) def identifier @real_timezone ? @real_timezone.identifier : @identifier end - - # Returns the TimezonePeriod for the given UTC time. utc can either be - # a DateTime, Time or integer timestamp (Time.to_i). Any timezone - # information in utc is ignored (it is treated as a UTC time). - def period_for_utc(utc) - real_timezone.period_for_utc(utc) - end - - # Returns the set of TimezonePeriod instances that are valid for the given - # local time as an array. If you just want a single period, use - # period_for_local instead and specify how abiguities should be resolved. - # Returns an empty array if no periods are found for the given time. - def periods_for_local(local) - real_timezone.periods_for_local(local) - end - - # Returns an Array of TimezoneTransition instances representing the times - # where the UTC offset of the timezone changes. - # - # Transitions are returned up to a given date and time up to a given date - # and time (to). - # - # A from date and time may also be supplied using the from parameter. If - # from is not nil, only transitions from that date and time onwards will be - # returned. - # - # Comparisons with to are exclusive. Comparisons with from are inclusive. - # If a transition falls precisely on to, it will be excluded. If a - # transition falls on from, it will be included. - # - # Transitions returned are ordered by when they occur, from earliest to - # latest. - # - # to and from can be specified using either a Time, DateTime, Time or - # Timestamp. - # - # If from is specified and to is not greater than from, then an - # ArgumentError exception is raised. - # - # ArgumentError is raised if to is nil or of either to or from are - # Timestamps with unspecified offsets. + + # (see Timezone#period_for) + def period_for(time) + real_timezone.period_for_utc(time) + end + + # (see Timezone#periods_for_local) + def periods_for_local(local_time) + real_timezone.periods_for_local(local_time) + end + + # (see Timezone#transitions_up_to) def transitions_up_to(to, from = nil) real_timezone.transitions_up_to(to, from) end - # Returns the canonical zone for this Timezone. + # (see Timezone#canonical_zone) def canonical_zone real_timezone.canonical_zone end - - # Dumps this TimezoneProxy for marshalling. + + # Returns a serialized representation of this {TimezoneProxy}. This method + # is called when using `Marshal.dump` with an instance of {TimezoneProxy}. + # + # @param limit [Integer] the maximum depth to dump - ignored. @return + # [String] a serialized representation of this {TimezoneProxy}. + # @return [String] a serialized representation of this {TimezoneProxy}. def _dump(limit) identifier end - - # Loads a marshalled TimezoneProxy. + + # Loads a {TimezoneProxy} from the serialized representation returned by + # {_dump}. This is method is called when using `Marshal.load` or + # `Marshal.restore` to restore a serialized {Timezone}. + # + # @param data [String] a serialized representation of a {TimezoneProxy}. + # @return [TimezoneProxy] the result of converting `data` back into a + # {TimezoneProxy}. def self._load(data) TimezoneProxy.new(data) end - + private - def setup(identifier) - @identifier = identifier - @real_timezone = nil - end - - def real_timezone - # Thread-safety: It is possible that the value of @real_timezone may be - # calculated multiple times in concurrently executing threads. It is not - # worth the overhead of locking to ensure that @real_timezone is only - # calculated once. - unless @real_timezone - result = Timezone.get(@identifier) - return result if frozen? - @real_timezone = result - end - - @real_timezone - end - end + + # Returns the real {Timezone} instance being proxied. + # + # The real {Timezone} is loaded using {Timezone.get} on the first access. + # + # @return [Timezone] the real {Timezone} instance being proxied. + def real_timezone + # Thread-safety: It is possible that the value of @real_timezone may be + # calculated multiple times in concurrently executing threads. It is not + # worth the overhead of locking to ensure that @real_timezone is only + # calculated once. + unless @real_timezone + result = Timezone.get(@identifier) + return result if frozen? + @real_timezone = result + end + + @real_timezone + end + end end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/timezone.rb ruby-tzinfo-2.0.4/lib/tzinfo/timezone.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/timezone.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/timezone.rb 2020-12-30 06:49:15.000000000 +0000 @@ -1,252 +1,300 @@ -require 'date' +# encoding: UTF-8 +# frozen_string_literal: true + require 'set' -require 'thread_safe' module TZInfo - # AmbiguousTime is raised to indicates that a specified time in a local - # timezone has more than one possible equivalent UTC time. This happens when - # transitioning from daylight savings time to standard time where the clocks - # are rolled back. + # {AmbiguousTime} is raised to indicate that a specified local time has more + # than one possible equivalent UTC time. Such ambiguities arise when the + # clocks are set back in a time zone, most commonly during the repeated hour + # when transitioning from daylight savings time to standard time. # - # AmbiguousTime is raised by period_for_local and local_to_utc when using an - # ambiguous time and not specifying any means to resolve the ambiguity. + # {AmbiguousTime} is raised by {Timezone#local_datetime}, + # {Timezone#local_time}, {Timezone#local_timestamp}, {Timezone#local_to_utc} + # and {Timezone#period_for_local} when using an ambiguous time and not + # specifying how to resolve the ambiguity. class AmbiguousTime < StandardError end - - # PeriodNotFound is raised to indicate that no TimezonePeriod matching a given - # time could be found. + + # {PeriodNotFound} is raised to indicate that no {TimezonePeriod} matching a + # given time could be found. class PeriodNotFound < StandardError end - - # Raised by Timezone#get if the identifier given is not valid. + + # {InvalidTimezoneIdentifier} is raised by {Timezone.get} if the identifier + # given is not valid. class InvalidTimezoneIdentifier < StandardError end - - # Raised if an attempt is made to use a timezone created with - # Timezone.new(nil). + + # {UnknownTimezone} is raised when calling methods on an instance of + # {Timezone} that was created directly. To obtain {Timezone} instances the + # {Timezone.get} method should be used instead. class UnknownTimezone < StandardError end - - # Timezone is the base class of all timezones. It provides a factory method, - # 'get', to access timezones by identifier. Once a specific Timezone has been - # retrieved, DateTimes, Times and timestamps can be converted between the UTC - # and the local time for the zone. For example: - # - # tz = TZInfo::Timezone.get('America/New_York') - # puts tz.utc_to_local(DateTime.new(2005,8,29,15,35,0)).to_s - # puts tz.local_to_utc(Time.utc(2005,8,29,11,35,0)).to_s - # puts tz.utc_to_local(1125315300).to_s - # - # Each time conversion method returns an object of the same type it was - # passed. - # - # The Timezone class is thread-safe. It is safe to use class and instance - # methods of Timezone in concurrently executing threads. Instances of Timezone - # can be shared across thread boundaries. + + # The {Timezone} class represents a time zone. It provides a factory method, + # {get}, to retrieve {Timezone} instances by their identifier. + # + # The {Timezone#to_local} method can be used to convert `Time` and `DateTime` + # instances to the local time for the zone. For example: + # + # tz = TZInfo::Timezone.get('America/New_York') + # local_time = tz.to_local(Time.utc(2005,8,29,15,35,0)) + # local_datetime = tz.to_local(DateTime.new(2005,8,29,15,35,0)) + # + # Local `Time` and `DateTime` instances returned by `Timezone` have the + # correct local offset. + # + # The {Timezone#local_to_utc} method can by used to convert local `Time` and + # `DateTime` instances to UTC. {Timezone#local_to_utc} ignores the UTC offset + # of the supplied value and treats if it is a local time for the zone. For + # example: + # + # tz = TZInfo::Timezone.get('America/New_York') + # utc_time = tz.local_to_utc(Time.new(2005,8,29,11,35,0)) + # utc_datetime = tz.local_to_utc(DateTime.new(2005,8,29,11,35,0)) + # + # Each time zone is treated as sequence of periods of time ({TimezonePeriod}) + # that observe the same offset ({TimezoneOffset}). Transitions + # ({TimezoneTransition}) denote the end of one period and the start of the + # next. The {Timezone} class has methods that allow the periods, offsets and + # transitions of a time zone to be interrogated. + # + # All methods that take `Time` objects as parameters can be used with + # arbitrary `Time`-like objects that respond to both `to_i` and `subsec` and + # optionally `utc_offset`. + # + # The {Timezone} class is thread-safe. It is safe to use class and instance + # methods of {Timezone} in concurrently executing threads. Instances of + # {Timezone} can be shared across thread boundaries. + # + # The IANA Time Zone Database maintainers recommend that time zone identifiers + # are not made visible to end-users (see [Names of + # timezones](https://data.iana.org/time-zones/theory.html#naming)). The + # {Country} class can be used to obtain lists of time zones by country, + # including user-friendly descriptions and approximate locations. + # + # @abstract The {get} method returns an instance of either {DataTimezone} or + # {LinkedTimezone}. The {get_proxy} method and other methods returning + # collections of time zones return instances of {TimezoneProxy}. class Timezone include Comparable - - # Cache of loaded zones by identifier to avoid using require if a zone - # has already been loaded. - # - # @!visibility private - @@loaded_zones = nil - - # Default value of the dst parameter of the local_to_utc and - # period_for_local methods. + + # The default value of the dst parameter of the {local_datetime}, + # {local_time}, {local_timestamp}, {local_to_utc} and {period_for_local} + # methods. # # @!visibility private @@default_dst = nil - - # Sets the default value of the optional dst parameter of the - # local_to_utc and period_for_local methods. Can be set to nil, true or - # false. - # - # The value of default_dst defaults to nil if unset. - def self.default_dst=(value) - @@default_dst = value.nil? ? nil : !!value - end - - # Gets the default value of the optional dst parameter of the - # local_to_utc and period_for_local methods. Can be set to nil, true or - # false. - def self.default_dst - @@default_dst - end - - # Returns a timezone by its identifier (e.g. "Europe/London", - # "America/Chicago" or "UTC"). - # - # Raises InvalidTimezoneIdentifier if the timezone couldn't be found. - def self.get(identifier) - instance = @@loaded_zones[identifier] - - unless instance - # Thread-safety: It is possible that multiple equivalent Timezone - # instances could be created here in concurrently executing threads. - # The consequences of this are that the data may be loaded more than - # once (depending on the data source) and memoized calculations could - # be discarded. The performance benefit of ensuring that only a single - # instance is created is unlikely to be worth the overhead of only - # allowing one Timezone to be loaded at a time. - info = data_source.load_timezone_info(identifier) - instance = info.create_timezone - @@loaded_zones[instance.identifier] = instance - end - - instance - end - - # Returns a proxy for the Timezone with the given identifier. The proxy - # will cause the real timezone to be loaded when an attempt is made to - # find a period or convert a time. get_proxy will not validate the - # identifier. If an invalid identifier is specified, no exception will be - # raised until the proxy is used. - def self.get_proxy(identifier) - TimezoneProxy.new(identifier) - end - - # If identifier is nil calls super(), otherwise calls get. An identfier - # should always be passed in when called externally. - def self.new(identifier = nil) - if identifier - get(identifier) - else - super() + + class << self + # Sets the default value of the optional `dst` parameter of the + # {local_datetime}, {local_time}, {local_timestamp}, {local_to_utc} and + # {period_for_local} methods. Can be set to `nil`, `true` or `false`. + # + # @param value [Boolean] `nil`, `true` or `false`. + def default_dst=(value) + @@default_dst = value.nil? ? nil : !!value + end + + # Returns the default value of the optional `dst` parameter of the + # {local_time}, {local_datetime} and {local_timestamp}, {local_to_utc} + # and {period_for_local} methods (`nil`, `true` or `false`). + # + # {default_dst} defaults to `nil` unless changed with {default_dst=}. + # + # @return [Boolean] the default value of the optional `dst` parameter of + # the {local_time}, {local_datetime} and {local_timestamp}, + # {local_to_utc} and {period_for_local} methods (`nil`, `true` or + # `false`). + def default_dst + @@default_dst + end + + # Returns a time zone by its IANA Time Zone Database identifier (e.g. + # `"Europe/London"` or `"America/Chicago"`). Call {all_identifiers} for a + # list of all the valid identifiers. + # + # The {get} method will return a subclass of {Timezone}, either a + # {DataTimezone} (for a time zone defined by rules that set out when + # transitions occur) or a {LinkedTimezone} (for a time zone that is just a + # link to or alias for a another time zone). + # + # @param identifier [String] an IANA Time Zone Database time zone + # identifier. + # @return [Timezone] the {Timezone} with the given `identifier`. + # @raise [InvalidTimezoneIdentifier] if the `identifier` is not valid. + def get(identifier) + data_source.get_timezone_info(identifier).create_timezone + end + + # Returns a proxy for the time zone with the given identifier. This allows + # loading of the time zone data to be deferred until it is first needed. + # + # The identifier will not be validated. If an invalid identifier is + # specified, no exception will be raised until the proxy is used. + # + # @param identifier [String] an IANA Time Zone Database time zone + # identifier. + # @return [TimezoneProxy] a proxy for the time zone with the given + # `identifier`. + def get_proxy(identifier) + TimezoneProxy.new(identifier) + end + + # Returns an `Array` of all the available time zones. + # + # {TimezoneProxy} instances are returned to avoid the overhead of loading + # time zone data until it is first needed. + # + # @return [Array] all available time zones. + def all + get_proxies(all_identifiers) + end + + # @return [Array] an `Array` containing the identifiers of all the + # available time zones. + def all_identifiers + data_source.timezone_identifiers + end + + # Returns an `Array` of all the available time zones that are + # defined by offsets and transitions. + # + # {TimezoneProxy} instances are returned to avoid the overhead of loading + # time zone data until it is first needed. + # + # @return [Array] an `Array` of all the available time zones + # that are defined by offsets and transitions. + def all_data_zones + get_proxies(all_data_zone_identifiers) + end + + # @return [Array] an `Array` of the identifiers of all available + # time zones that are defined by offsets and transitions. + def all_data_zone_identifiers + data_source.data_timezone_identifiers + end + + # Returns an `Array` of all the available time zones that are + # defined as links to / aliases for other time zones. + # + # {TimezoneProxy} instances are returned to avoid the overhead of loading + # time zone data until it is first needed. + # + # @return [Array] an `Array` of all the available time zones + # that are defined as links to / aliases for other time zones. + def all_linked_zones + get_proxies(all_linked_zone_identifiers) + end + + # @return [Array] an `Array` of the identifiers of all available + # time zones that are defined as links to / aliases for other time zones. + def all_linked_zone_identifiers + data_source.linked_timezone_identifiers + end + + # Returns an `Array` of all the time zones that are observed by at least + # one {Country}. This is not the complete set of time zones as some are + # not country specific (e.g. `'Etc/GMT'`). + # + # {TimezoneProxy} instances are returned to avoid the overhead of loading + # time zone data until it is first needed. + # + # @return [Array] an `Array` of all the time zones that are + # observed by at least one {Country}. + def all_country_zones + Country.all.map(&:zones).flatten.uniq + end + + # Returns an `Array` of the identifiers of all the time zones that are + # observed by at least one {Country}. This is not the complete set of time + # zone identifiers as some are not country specific (e.g. `'Etc/GMT'`). + # + # {TimezoneProxy} instances are returned to avoid the overhead of loading + # time zone data until it is first needed. + # + # @return [Array] an `Array` of the identifiers of all the time + # zones that are observed by at least one {Country}. + def all_country_zone_identifiers + Country.all.map(&:zone_identifiers).flatten.uniq + end + + private + + # @param [Enumerable] identifiers an `Enumerable` of time zone + # identifiers. + # @return [Array] an `Array` of {TimezoneProxy} + # instances corresponding to the given identifiers. + def get_proxies(identifiers) + identifiers.collect {|identifier| get_proxy(identifier)} + end + + # @return [DataSource] the current DataSource. + def data_source + DataSource.get end end - - # Returns an array containing all the available Timezones. - # - # Returns TimezoneProxy objects to avoid the overhead of loading Timezone - # definitions until a conversion is actually required. - def self.all - get_proxies(all_identifiers) - end - - # Returns an array containing the identifiers of all the available - # Timezones. - def self.all_identifiers - data_source.timezone_identifiers - end - - # Returns an array containing all the available Timezones that are based - # on data (are not links to other Timezones). - # - # Returns TimezoneProxy objects to avoid the overhead of loading Timezone - # definitions until a conversion is actually required. - def self.all_data_zones - get_proxies(all_data_zone_identifiers) - end - - # Returns an array containing the identifiers of all the available - # Timezones that are based on data (are not links to other Timezones).. - def self.all_data_zone_identifiers - data_source.data_timezone_identifiers - end - - # Returns an array containing all the available Timezones that are links - # to other Timezones. - # - # Returns TimezoneProxy objects to avoid the overhead of loading Timezone - # definitions until a conversion is actually required. - def self.all_linked_zones - get_proxies(all_linked_zone_identifiers) - end - - # Returns an array containing the identifiers of all the available - # Timezones that are links to other Timezones. - def self.all_linked_zone_identifiers - data_source.linked_timezone_identifiers - end - - # Returns all the Timezones defined for all Countries. This is not the - # complete set of Timezones as some are not country specific (e.g. - # 'Etc/GMT'). - # - # Returns TimezoneProxy objects to avoid the overhead of loading Timezone - # definitions until a conversion is actually required. - def self.all_country_zones - Country.all_codes.inject([]) do |zones,country| - zones += Country.get(country).zones - end.uniq - end - - # Returns all the zone identifiers defined for all Countries. This is not the - # complete set of zone identifiers as some are not country specific (e.g. - # 'Etc/GMT'). You can obtain a Timezone instance for a given identifier - # with the get method. - def self.all_country_zone_identifiers - Country.all_codes.inject([]) do |zones,country| - zones += Country.get(country).zone_identifiers - end.uniq - end - - # Returns all US Timezone instances. A shortcut for - # TZInfo::Country.get('US').zones. - # - # Returns TimezoneProxy objects to avoid the overhead of loading Timezone - # definitions until a conversion is actually required. - def self.us_zones - Country.get('US').zones - end - - # Returns all US zone identifiers. A shortcut for - # TZInfo::Country.get('US').zone_identifiers. - def self.us_zone_identifiers - Country.get('US').zone_identifiers - end - - # The identifier of the timezone, e.g. "Europe/Paris". + + # @return [String] the identifier of the time zone, for example, + # `"Europe/Paris"`. def identifier raise_unknown_timezone end - - # An alias for identifier. + + # @return [String] the identifier of the time zone, for example, + # `"Europe/Paris"`. def name # Don't use alias, as identifier gets overridden. identifier end - - # Returns a friendlier version of the identifier. + + # @return [String] {identifier}, modified to make it more readable. def to_s friendly_identifier end - - # Returns internal object state as a programmer-readable string. + + # @return [String] the internal object state as a programmer-readable + # `String`. def inspect "#<#{self.class}: #{identifier}>" end - - # Returns a friendlier version of the identifier. Set skip_first_part to - # omit the first part of the identifier (typically a region name) where - # there is more than one part. + + # Returns {identifier}, modified to make it more readable. Set + # `skip_first_part` to omit the first part of the identifier (typically a + # region name) where there is more than one part. # # For example: # - # Timezone.get('Europe/Paris').friendly_identifier(false) #=> "Europe - Paris" - # Timezone.get('Europe/Paris').friendly_identifier(true) #=> "Paris" - # Timezone.get('America/Indiana/Knox').friendly_identifier(false) #=> "America - Knox, Indiana" - # Timezone.get('America/Indiana/Knox').friendly_identifier(true) #=> "Knox, Indiana" + # TZInfo::Timezone.get('Europe/Paris').friendly_identifier(false) #=> "Europe - Paris" + # TZInfo::Timezone.get('Europe/Paris').friendly_identifier(true) #=> "Paris" + # TZInfo::Timezone.get('America/Indiana/Knox').friendly_identifier(false) #=> "America - Knox, Indiana" + # TZInfo::Timezone.get('America/Indiana/Knox').friendly_identifier(true) #=> "Knox, Indiana" + # + # @param skip_first_part [Boolean] whether the first part of the identifier + # (typically a region name) should be omitted. + # @return [String] the modified identifier. def friendly_identifier(skip_first_part = false) - parts = identifier.split('/') + id = identifier + id = id.encode(Encoding::UTF_8) unless id.encoding.ascii_compatible? + parts = id.split('/') if parts.empty? # shouldn't happen identifier - elsif parts.length == 1 + elsif parts.length == 1 parts[0] else prefix = skip_first_part ? nil : "#{parts[0]} - " parts = parts.drop(1).map do |part| part.gsub!(/_/, ' ') - + if part.index(/[a-z]/) # Missing a space if a lower case followed by an upper case and the # name isn't McXxxx. part.gsub!(/([^M][a-z])([A-Z])/, '\1 \2') part.gsub!(/([M][a-bd-z])([A-Z])/, '\1 \2') - + # Missing an apostrophe if two consecutive upper case characters. part.gsub!(/([A-Z])([A-Z])/, '\1\'\2') end @@ -257,417 +305,856 @@ "#{prefix}#{parts.reverse.join(', ')}" end end - - # Returns the TimezonePeriod for the given UTC time. utc can either be - # a DateTime, Time or integer timestamp (Time.to_i). Any timezone - # information in utc is ignored (it is treated as a UTC time). - def period_for_utc(utc) + + # Returns the {TimezonePeriod} that is valid at a given time. + # + # Unlike {period_for_local} and {period_for_utc}, the UTC offset of the + # `time` parameter is taken into consideration. + # + # @param time [Object] a `Time`, `DateTime` or {Timestamp}. + # @return [TimezonePeriod] the {TimezonePeriod} that is valid at `time`. + # @raise [ArgumentError] if `time` is `nil`. + # @raise [ArgumentError] if `time` is a {Timestamp} with an unspecified + # offset. + def period_for(time) raise_unknown_timezone end - - # Returns the set of TimezonePeriod instances that are valid for the given - # local time as an array. If you just want a single period, use - # period_for_local instead and specify how ambiguities should be resolved. - # Returns an empty array if no periods are found for the given time. - def periods_for_local(local) + + # Returns the set of {TimezonePeriod}s that are valid for the given + # local time as an `Array`. + # + # The UTC offset of the `local_time` parameter is ignored (it is treated as + # a time in the time zone represented by `self`). + # + # This will typically return an `Array` containing a single + # {TimezonePeriod}. More than one {TimezonePeriod} will be returned when the + # local time is ambiguous (for example, when daylight savings time ends). An + # empty `Array` will be returned when the local time is not valid (for + # example, when daylight savings time begins). + # + # To obtain just a single {TimezonePeriod} in all cases, use + # {period_for_local} instead and specify how ambiguities should be resolved. + # + # @param local_time [Object] a `Time`, `DateTime` or {Timestamp}. + # @return [Array] the set of {TimezonePeriod}s that are + # valid at `local_time`. + # @raise [ArgumentError] if `local_time` is `nil`. + def periods_for_local(local_time) raise_unknown_timezone end - - # Returns an Array of TimezoneTransition instances representing the times - # where the UTC offset of the timezone changes. - # - # Transitions are returned up to a given date and time up to a given date - # and time, specified in UTC (utc_to). - # - # A from date and time may also be supplied using the utc_from parameter - # (also specified in UTC). If utc_from is not nil, only transitions from - # that date and time onwards will be returned. - # - # Comparisons with utc_to are exclusive. Comparisons with utc_from are - # inclusive. If a transition falls precisely on utc_to, it will be excluded. - # If a transition falls on utc_from, it will be included. - # - # Transitions returned are ordered by when they occur, from earliest to - # latest. - # - # utc_to and utc_from can be specified using either DateTime, Time or - # integer timestamps (Time.to_i). - # - # If utc_from is specified and utc_to is not greater than utc_from, then - # transitions_up_to raises an ArgumentError exception. - def transitions_up_to(utc_to, utc_from = nil) + + # Returns an `Array` of {TimezoneTransition} instances representing the + # times where the UTC offset of the timezone changes. + # + # Transitions are returned up to a given time (`to`). + # + # A from time may also be supplied using the `from` parameter. If from is + # not `nil`, only transitions from that time onwards will be returned. + # + # Comparisons with `to` are exclusive. Comparisons with `from` are + # inclusive. If a transition falls precisely on `to`, it will be excluded. + # If a transition falls on `from`, it will be included. + # + # @param to [Object] a `Time`, `DateTime` or {Timestamp} specifying the + # latest (exclusive) transition to return. + # @param from [Object] an optional `Time`, `DateTime` or {Timestamp} + # specifying the earliest (inclusive) transition to return. + # @return [Array] the transitions that are earlier than + # `to` and, if specified, at or later than `from`. Transitions are ordered + # by when they occur, from earliest to latest. + # @raise [ArgumentError] if `from` is specified and `to` is not greater than + # `from`. + # @raise [ArgumentError] is raised if `to` is `nil`. + # @raise [ArgumentError] if either `to` or `from` is a {Timestamp} with an + # unspecified offset. + def transitions_up_to(to, from = nil) raise_unknown_timezone end - - # Returns the canonical Timezone instance for this Timezone. + + # Returns the canonical {Timezone} instance for this {Timezone}. # - # The IANA Time Zone database contains two types of definition: Zones and - # Links. Zones are defined by rules that set out when transitions occur. - # Links are just references to fully defined Zone, creating an alias for + # The IANA Time Zone database contains two types of definition: Zones and + # Links. Zones are defined by rules that set out when transitions occur. + # Links are just references to fully defined Zone, creating an alias for # that Zone. # - # Links are commonly used where a time zone has been renamed in a - # release of the Time Zone database. For example, the Zone US/Eastern was - # renamed as America/New_York. A US/Eastern Link was added in its place, - # linking to (and creating an alias for) for America/New_York. + # Links are commonly used where a time zone has been renamed in a release of + # the Time Zone database. For example, the US/Eastern Zone was renamed as + # America/New_York. A US/Eastern Link was added in its place, linking to + # (and creating an alias for) America/New_York. # - # Links are also used for time zones that are currently identical to a full - # Zone, but that are administered seperately. For example, Europe/Vatican is + # Links are also used for time zones that are currently identical to a full + # Zone, but that are administered separately. For example, Europe/Vatican is # a Link to (and alias for) Europe/Rome. # - # For a full Zone, canonical_zone returns self. + # For a full Zone (implemented by {DataTimezone}), {canonical_zone} returns + # self. # - # For a Link, canonical_zone returns a Timezone instance representing the - # full Zone that the link targets. + # For a Link (implemented by {LinkedTimezone}), {canonical_zone} returns a + # {Timezone} instance representing the full Zone that the link targets. # # TZInfo can be used with different data sources (see the documentation for - # TZInfo::DataSource). Please note that some DataSource implementations may - # not support distinguishing between full Zones and Links and will treat all - # time zones as full Zones. In this case, the canonical_zone will always - # return self. - # - # There are two built-in DataSource implementations. RubyDataSource (which - # will be used if the tzinfo-data gem is available) supports Link zones. - # ZoneinfoDataSource returns Link zones as if they were full Zones. If the - # canonical_zone or canonical_identifier methods are required, the - # tzinfo-data gem should be installed. + # {TZInfo::DataSource}). Some DataSource implementations may not support + # distinguishing between full Zones and Links and will treat all time zones + # as full Zones. In this case, {canonical_zone} will always return `self`. + # + # There are two built-in DataSource implementations. + # {DataSources::RubyDataSource} (which will be used if the tzinfo-data gem + # is available) supports Link zones. {DataSources::ZoneinfoDataSource} + # returns Link zones as if they were full Zones. If the {canonical_zone} or + # {canonical_identifier} methods are needed, the tzinfo-data gem should be + # installed. # - # The TZInfo::DataSource.get method can be used to check which DataSource + # The {TZInfo::DataSource.get} method can be used to check which DataSource # implementation is being used. + # + # @return [Timezone] the canonical {Timezone} instance for this {Timezone}. def canonical_zone raise_unknown_timezone end - - # Returns the TimezonePeriod for the given local time. local can either be - # a DateTime, Time or integer timestamp (Time.to_i). Any timezone - # information in local is ignored (it is treated as a time in the current - # timezone). - # - # Warning: There are local times that have no equivalent UTC times (e.g. - # in the transition from standard time to daylight savings time). There are - # also local times that have more than one UTC equivalent (e.g. in the - # transition from daylight savings time to standard time). - # - # In the first case (no equivalent UTC time), a PeriodNotFound exception - # will be raised. + + # Returns the {TimezonePeriod} that is valid at a given time. # - # In the second case (more than one equivalent UTC time), an AmbiguousTime - # exception will be raised unless the optional dst parameter or block - # handles the ambiguity. + # The UTC offset of the `utc_time` parameter is ignored (it is treated as a + # UTC time). Use the {period_for} method instead if the UTC offset of the + # time needs to be taken into consideration. + # + # @param utc_time [Object] a `Time`, `DateTime` or {Timestamp}. + # @return [TimezonePeriod] the {TimezonePeriod} that is valid at `utc_time`. + # @raise [ArgumentError] if `utc_time` is `nil`. + def period_for_utc(utc_time) + raise ArgumentError, 'utc_time must be specified' unless utc_time + period_for(Timestamp.for(utc_time, :treat_as_utc)) + end + + # Returns the {TimezonePeriod} that is valid at the given local time. # - # If the ambiguity is due to a transition from daylight savings time to - # standard time, the dst parameter can be used to select whether the - # daylight savings time or local time is used. For example, + # The UTC offset of the `local_time` parameter is ignored (it is treated as + # a time in the time zone represented by `self`). Use the {period_for} + # method instead if the the UTC offset of the time needs to be taken into + # consideration. + # + # _Warning:_ There are local times that have no equivalent UTC times (for + # example, during the transition from standard time to daylight savings + # time). There are also local times that have more than one UTC equivalent + # (for example, during the transition from daylight savings time to standard + # time). # - # Timezone.get('America/New_York').period_for_local(DateTime.new(2004,10,31,1,30,0)) + # In the first case (no equivalent UTC time), a {PeriodNotFound} exception + # will be raised. # - # would raise an AmbiguousTime exception. + # In the second case (more than one equivalent UTC time), an {AmbiguousTime} + # exception will be raised unless the optional `dst` parameter or block + # handles the ambiguity. # - # Specifying dst=true would the daylight savings period from April to - # October 2004. Specifying dst=false would return the standard period - # from October 2004 to April 2005. - # - # If the dst parameter does not resolve the ambiguity, and a block is - # specified, it is called. The block must take a single parameter - an - # array of the periods that need to be resolved. The block can select and - # return a single period or return nil or an empty array - # to cause an AmbiguousTime exception to be raised. - # - # The default value of the dst parameter can be specified by setting - # Timezone.default_dst. If default_dst is not set, or is set to nil, then - # an AmbiguousTime exception will be raised in ambiguous situations unless - # a block is given to resolve the ambiguity. - def period_for_local(local, dst = Timezone.default_dst) - results = periods_for_local(local) - + # If the ambiguity is due to a transition from daylight savings time to + # standard time, the `dst` parameter can be used to select whether the + # daylight savings time or local time is used. For example, the following + # code would raise an {AmbiguousTime} exception: + # + # tz = TZInfo::Timezone.get('America/New_York') + # tz.period_for_local(Time.new(2004,10,31,1,30,0)) + # + # Specifying `dst = true` would select the daylight savings period from + # April to October 2004. Specifying `dst = false` would return the + # standard time period from October 2004 to April 2005. + # + # The `dst` parameter will not be able to resolve an ambiguity resulting + # from the clocks being set back without changing from daylight savings time + # to standard time. In this case, if a block is specified, it will be called + # to resolve the ambiguity. The block must take a single parameter - an + # `Array` of {TimezonePeriod}s that need to be resolved. The block can + # select and return a single {TimezonePeriod} or return `nil` or an empty + # `Array` to cause an {AmbiguousTime} exception to be raised. + # + # The default value of the `dst` parameter can be specified using + # {Timezone.default_dst=}. + # + # @param local_time [Object] a `Time`, `DateTime` or {Timestamp}. + # @param dst [Boolean] whether to resolve ambiguous local times by always + # selecting the period observing daylight savings time (`true`), always + # selecting the period observing standard time (`false`), or leaving the + # ambiguity unresolved (`nil`). + # @yield [periods] if the `dst` parameter did not resolve an ambiguity, an + # optional block is yielded to. + # @yieldparam periods [Array] an `Array` containing all + # the {TimezonePeriod}s that still match `local_time` after applying the + # `dst` parameter. + # @yieldreturn [Object] to resolve the ambiguity: a chosen {TimezonePeriod} + # or an `Array` containing a chosen {TimezonePeriod}; to leave the + # ambiguity unresolved: an empty `Array`, an `Array` containing more than + # one {TimezonePeriod}, or `nil`. + # @return [TimezonePeriod] the {TimezonePeriod} that is valid at + # `local_time`. + # @raise [ArgumentError] if `local_time` is `nil`. + # @raise [PeriodNotFound] if `local_time` is not valid for the time zone + # (there is no equivalent UTC time). + # @raise [AmbiguousTime] if `local_time` was ambiguous for the time zone and + # the `dst` parameter or block did not resolve the ambiguity. + def period_for_local(local_time, dst = Timezone.default_dst) + raise ArgumentError, 'local_time must be specified' unless local_time + local_time = Timestamp.for(local_time, :ignore) + results = periods_for_local(local_time) + if results.empty? - raise PeriodNotFound + raise PeriodNotFound, "#{local_time.strftime('%Y-%m-%d %H:%M:%S')} is an invalid local time." elsif results.size < 2 results.first else # ambiguous result try to resolve - + if !dst.nil? matches = results.find_all {|period| period.dst? == dst} - results = matches if !matches.empty? + results = matches if !matches.empty? end - + if results.size < 2 results.first else # still ambiguous, try the block - + if block_given? results = yield results end - + if results.is_a?(TimezonePeriod) results elsif results && results.size == 1 results.first - else - raise AmbiguousTime, "#{local} is an ambiguous local time." + else + raise AmbiguousTime, "#{local_time.strftime('%Y-%m-%d %H:%M:%S')} is an ambiguous local time." end end - end + end end - - # Converts a time in UTC to the local timezone. utc can either be - # a DateTime, Time or timestamp (Time.to_i). The returned time has the same - # type as utc. Any timezone information in utc is ignored (it is treated as - # a UTC time). - def utc_to_local(utc) - TimeOrDateTime.wrap(utc) {|wrapped| - period_for_utc(wrapped).to_local(wrapped) - } - end - - # Converts a time in the local timezone to UTC. local can either be - # a DateTime, Time or timestamp (Time.to_i). The returned time has the same - # type as local. Any timezone information in local is ignored (it is treated - # as a local time). - # - # Warning: There are local times that have no equivalent UTC times (e.g. - # in the transition from standard time to daylight savings time). There are - # also local times that have more than one UTC equivalent (e.g. in the - # transition from daylight savings time to standard time). + + # Converts a time to the local time for the time zone. # - # In the first case (no equivalent UTC time), a PeriodNotFound exception - # will be raised. + # The result will be of type {TimeWithOffset} (if passed a `Time`), + # {DateTimeWithOffset} (if passed a `DateTime`) or {TimestampWithOffset} (if + # passed a {Timestamp}). {TimeWithOffset}, {DateTimeWithOffset} and + # {TimestampWithOffset} are subclasses of `Time`, `DateTime` and {Timestamp} + # that provide additional information about the local result. + # + # Unlike {utc_to_local}, {to_local} takes the UTC offset of the given time + # into consideration. + # + # @param time [Object] a `Time`, `DateTime` or {Timestamp}. + # @return [Object] the local equivalent of `time` as a {TimeWithOffset}, + # {DateTimeWithOffset} or {TimestampWithOffset}. + # @raise [ArgumentError] if `time` is `nil`. + # @raise [ArgumentError] if `time` is a {Timestamp} that does not have a + # specified UTC offset. + def to_local(time) + raise ArgumentError, 'time must be specified' unless time + + Timestamp.for(time) do |ts| + TimestampWithOffset.set_timezone_offset(ts, period_for(ts).offset) + end + end + + # Converts a time in UTC to the local time for the time zone. # - # In the second case (more than one equivalent UTC time), an AmbiguousTime - # exception will be raised unless the optional dst parameter or block - # handles the ambiguity. + # The result will be of type {TimeWithOffset} (if passed a `Time`), + # {DateTimeWithOffset} (if passed a `DateTime`) or {TimestampWithOffset} (if + # passed a {Timestamp}). {TimeWithOffset}, {DateTimeWithOffset} and + # {TimestampWithOffset} are subclasses of `Time`, `DateTime` and {Timestamp} + # that provide additional information about the local result. + # + # The UTC offset of the `utc_time` parameter is ignored (it is treated as a + # UTC time). Use the {to_local} method instead if the the UTC offset of the + # time needs to be taken into consideration. + # + # @param utc_time [Object] a `Time`, `DateTime` or {Timestamp}. + # @return [Object] the local equivalent of `utc_time` as a {TimeWithOffset}, + # {DateTimeWithOffset} or {TimestampWithOffset}. + # @raise [ArgumentError] if `utc_time` is `nil`. + def utc_to_local(utc_time) + raise ArgumentError, 'utc_time must be specified' unless utc_time + + Timestamp.for(utc_time, :treat_as_utc) do |ts| + to_local(ts) + end + end + + # Converts a local time for the time zone to UTC. # - # If the ambiguity is due to a transition from daylight savings time to - # standard time, the dst parameter can be used to select whether the - # daylight savings time or local time is used. For example, + # The result will either be a `Time`, `DateTime` or {Timestamp} according to + # the type of the `local_time` parameter. + # + # The UTC offset of the `local_time` parameter is ignored (it is treated as + # a time in the time zone represented by `self`). + # + # _Warning:_ There are local times that have no equivalent UTC times (for + # example, during the transition from standard time to daylight savings + # time). There are also local times that have more than one UTC equivalent + # (for example, during the transition from daylight savings time to standard + # time). # - # Timezone.get('America/New_York').local_to_utc(DateTime.new(2004,10,31,1,30,0)) + # In the first case (no equivalent UTC time), a {PeriodNotFound} exception + # will be raised. # - # would raise an AmbiguousTime exception. + # In the second case (more than one equivalent UTC time), an {AmbiguousTime} + # exception will be raised unless the optional `dst` parameter or block + # handles the ambiguity. # - # Specifying dst=true would return 2004-10-31 5:30:00. Specifying dst=false - # would return 2004-10-31 6:30:00. - # - # If the dst parameter does not resolve the ambiguity, and a block is - # specified, it is called. The block must take a single parameter - an - # array of the periods that need to be resolved. The block can return a - # single period to use to convert the time or return nil or an empty array - # to cause an AmbiguousTime exception to be raised. - # - # The default value of the dst parameter can be specified by setting - # Timezone.default_dst. If default_dst is not set, or is set to nil, then - # an AmbiguousTime exception will be raised in ambiguous situations unless - # a block is given to resolve the ambiguity. - def local_to_utc(local, dst = Timezone.default_dst) - TimeOrDateTime.wrap(local) {|wrapped| - if block_given? - period = period_for_local(wrapped, dst) {|periods| yield periods } + # If the ambiguity is due to a transition from daylight savings time to + # standard time, the `dst` parameter can be used to select whether the + # daylight savings time or local time is used. For example, the following + # code would raise an {AmbiguousTime} exception: + # + # tz = TZInfo::Timezone.get('America/New_York') + # tz.period_for_local(Time.new(2004,10,31,1,30,0)) + # + # Specifying `dst = true` would select the daylight savings period from + # April to October 2004. Specifying `dst = false` would return the + # standard time period from October 2004 to April 2005. + # + # The `dst` parameter will not be able to resolve an ambiguity resulting + # from the clocks being set back without changing from daylight savings time + # to standard time. In this case, if a block is specified, it will be called + # to resolve the ambiguity. The block must take a single parameter - an + # `Array` of {TimezonePeriod}s that need to be resolved. The block can + # select and return a single {TimezonePeriod} or return `nil` or an empty + # `Array` to cause an {AmbiguousTime} exception to be raised. + # + # The default value of the `dst` parameter can be specified using + # {Timezone.default_dst=}. + # + # @param local_time [Object] a `Time`, `DateTime` or {Timestamp}. + # @param dst [Boolean] whether to resolve ambiguous local times by always + # selecting the period observing daylight savings time (`true`), always + # selecting the period observing standard time (`false`), or leaving the + # ambiguity unresolved (`nil`). + # @yield [periods] if the `dst` parameter did not resolve an ambiguity, an + # optional block is yielded to. + # @yieldparam periods [Array] an `Array` containing all + # the {TimezonePeriod}s that still match `local_time` after applying the + # `dst` parameter. + # @yieldreturn [Object] to resolve the ambiguity: a chosen {TimezonePeriod} + # or an `Array` containing a chosen {TimezonePeriod}; to leave the + # ambiguity unresolved: an empty `Array`, an `Array` containing more than + # one {TimezonePeriod}, or `nil`. + # @return [Object] the UTC equivalent of `local_time` as a `Time`, + # `DateTime` or {Timestamp}. + # @raise [ArgumentError] if `local_time` is `nil`. + # @raise [PeriodNotFound] if `local_time` is not valid for the time zone + # (there is no equivalent UTC time). + # @raise [AmbiguousTime] if `local_time` was ambiguous for the time zone and + # the `dst` parameter or block did not resolve the ambiguity. + def local_to_utc(local_time, dst = Timezone.default_dst) + raise ArgumentError, 'local_time must be specified' unless local_time + + Timestamp.for(local_time, :ignore) do |ts| + period = if block_given? + period_for_local(ts, dst) {|periods| yield periods } else - period = period_for_local(wrapped, dst) + period_for_local(ts, dst) end - - period.to_utc(wrapped) - } - end - - # Returns information about offsets used by the Timezone up to a given - # date and time, specified using UTC (utc_to). The information is returned - # as an Array of TimezoneOffset instances. - # - # A from date and time may also be supplied using the utc_from parameter - # (also specified in UTC). If utc_from is not nil, only offsets used from - # that date and time forward will be returned. + + ts.add_and_set_utc_offset(-period.observed_utc_offset, :utc) + end + end + + # Creates a `Time` object based on the given (Gregorian calendar) date and + # time parameters. The parameters are interpreted as a local time in the + # time zone. The result has the appropriate `utc_offset`, `zone` and + # {TimeWithOffset#timezone_offset timezone_offset}. + # + # _Warning:_ There are time values that are not valid as local times in a + # time zone (for example, during the transition from standard time to + # daylight savings time). There are also time values that are ambiguous, + # occurring more than once with different offsets to UTC (for example, + # during the transition from daylight savings time to standard time). # - # Comparisons with utc_to are exclusive. Comparisons with utc_from are - # inclusive. + # In the first case (an invalid local time), a {PeriodNotFound} exception + # will be raised. # - # Offsets may be returned in any order. + # In the second case (more than one occurrence), an {AmbiguousTime} + # exception will be raised unless the optional `dst` parameter or block + # handles the ambiguity. # - # utc_to and utc_from can be specified using either DateTime, Time or - # integer timestamps (Time.to_i). + # If the ambiguity is due to a transition from daylight savings time to + # standard time, the `dst` parameter can be used to select whether the + # daylight savings time or local time is used. For example, the following + # code would raise an {AmbiguousTime} exception: + # + # tz = TZInfo::Timezone.get('America/New_York') + # tz.local_time(2004,10,31,1,30,0,0) + # + # Specifying `dst = true` would return a `Time` with a UTC offset of -4 + # hours and abbreviation EDT (Eastern Daylight Time). Specifying `dst = + # false` would return a `Time` with a UTC offset of -5 hours and + # abbreviation EST (Eastern Standard Time). + # + # The `dst` parameter will not be able to resolve an ambiguity resulting + # from the clocks being set back without changing from daylight savings time + # to standard time. In this case, if a block is specified, it will be called + # to resolve the ambiguity. The block must take a single parameter - an + # `Array` of {TimezonePeriod}s that need to be resolved. The block can + # select and return a single {TimezonePeriod} or return `nil` or an empty + # `Array` to cause an {AmbiguousTime} exception to be raised. + # + # The default value of the `dst` parameter can be specified using + # {Timezone.default_dst=}. + # + # @param year [Integer] the year. + # @param month [Integer] the month (1-12). + # @param day [Integer] the day of the month (1-31). + # @param hour [Integer] the hour (0-23). + # @param minute [Integer] the minute (0-59). + # @param second [Integer] the second (0-59). + # @param sub_second [Numeric] the fractional part of the second as either + # a `Rational` that is greater than or equal to 0 and less than 1, or + # the `Integer` 0. + # @param dst [Boolean] whether to resolve ambiguous local times by always + # selecting the period observing daylight savings time (`true`), always + # selecting the period observing standard time (`false`), or leaving the + # ambiguity unresolved (`nil`). + # @yield [periods] if the `dst` parameter did not resolve an ambiguity, an + # optional block is yielded to. + # @yieldparam periods [Array] an `Array` containing all + # the {TimezonePeriod}s that still match `local_time` after applying the + # `dst` parameter. + # @yieldreturn [Object] to resolve the ambiguity: a chosen {TimezonePeriod} + # or an `Array` containing a chosen {TimezonePeriod}; to leave the + # ambiguity unresolved: an empty `Array`, an `Array` containing more than + # one {TimezonePeriod}, or `nil`. + # @return [TimeWithOffset] a new `Time` object based on the given values, + # interpreted as a local time in the time zone. + # @raise [ArgumentError] if either of `year`, `month`, `day`, `hour`, + # `minute`, or `second` is not an `Integer`. + # @raise [ArgumentError] if `sub_second` is not a `Rational`, or the + # `Integer` 0. + # @raise [ArgumentError] if `utc_offset` is not `nil`, not an `Integer` + # and not the `Symbol` `:utc`. + # @raise [RangeError] if `month` is not between 1 and 12. + # @raise [RangeError] if `day` is not between 1 and 31. + # @raise [RangeError] if `hour` is not between 0 and 23. + # @raise [RangeError] if `minute` is not between 0 and 59. + # @raise [RangeError] if `second` is not between 0 and 59. + # @raise [RangeError] if `sub_second` is a `Rational` but that is less + # than 0 or greater than or equal to 1. + # @raise [PeriodNotFound] if the date and time parameters do not specify a + # valid local time in the time zone. + # @raise [AmbiguousTime] if the date and time parameters are ambiguous for + # the time zone and the `dst` parameter or block did not resolve the + # ambiguity. + def local_time(year, month = 1, day = 1, hour = 0, minute = 0, second = 0, sub_second = 0, dst = Timezone.default_dst, &block) + local_timestamp(year, month, day, hour, minute, second, sub_second, dst, &block).to_time + end + + # Creates a `DateTime` object based on the given (Gregorian calendar) date + # and time parameters. The parameters are interpreted as a local time in the + # time zone. The result has the appropriate `offset` and + # {DateTimeWithOffset#timezone_offset timezone_offset}. + # + # _Warning:_ There are time values that are not valid as local times in a + # time zone (for example, during the transition from standard time to + # daylight savings time). There are also time values that are ambiguous, + # occurring more than once with different offsets to UTC (for example, + # during the transition from daylight savings time to standard time). + # + # In the first case (an invalid local time), a {PeriodNotFound} exception + # will be raised. + # + # In the second case (more than one occurrence), an {AmbiguousTime} + # exception will be raised unless the optional `dst` parameter or block + # handles the ambiguity. + # + # If the ambiguity is due to a transition from daylight savings time to + # standard time, the `dst` parameter can be used to select whether the + # daylight savings time or local time is used. For example, the following + # code would raise an {AmbiguousTime} exception: + # + # tz = TZInfo::Timezone.get('America/New_York') + # tz.local_datetime(2004,10,31,1,30,0,0) + # + # Specifying `dst = true` would return a `Time` with a UTC offset of -4 + # hours and abbreviation EDT (Eastern Daylight Time). Specifying `dst = + # false` would return a `Time` with a UTC offset of -5 hours and + # abbreviation EST (Eastern Standard Time). + # + # The `dst` parameter will not be able to resolve an ambiguity resulting + # from the clocks being set back without changing from daylight savings time + # to standard time. In this case, if a block is specified, it will be called + # to resolve the ambiguity. The block must take a single parameter - an + # `Array` of {TimezonePeriod}s that need to be resolved. The block can + # select and return a single {TimezonePeriod} or return `nil` or an empty + # `Array` to cause an {AmbiguousTime} exception to be raised. + # + # The default value of the `dst` parameter can be specified using + # {Timezone.default_dst=}. + # + # @param year [Integer] the year. + # @param month [Integer] the month (1-12). + # @param day [Integer] the day of the month (1-31). + # @param hour [Integer] the hour (0-23). + # @param minute [Integer] the minute (0-59). + # @param second [Integer] the second (0-59). + # @param sub_second [Numeric] the fractional part of the second as either + # a `Rational` that is greater than or equal to 0 and less than 1, or + # the `Integer` 0. + # @param dst [Boolean] whether to resolve ambiguous local times by always + # selecting the period observing daylight savings time (`true`), always + # selecting the period observing standard time (`false`), or leaving the + # ambiguity unresolved (`nil`). + # @yield [periods] if the `dst` parameter did not resolve an ambiguity, an + # optional block is yielded to. + # @yieldparam periods [Array] an `Array` containing all + # the {TimezonePeriod}s that still match `local_time` after applying the + # `dst` parameter. + # @yieldreturn [Object] to resolve the ambiguity: a chosen {TimezonePeriod} + # or an `Array` containing a chosen {TimezonePeriod}; to leave the + # ambiguity unresolved: an empty `Array`, an `Array` containing more than + # one {TimezonePeriod}, or `nil`. + # @return [DateTimeWithOffset] a new `DateTime` object based on the given + # values, interpreted as a local time in the time zone. + # @raise [ArgumentError] if either of `year`, `month`, `day`, `hour`, + # `minute`, or `second` is not an `Integer`. + # @raise [ArgumentError] if `sub_second` is not a `Rational`, or the + # `Integer` 0. + # @raise [ArgumentError] if `utc_offset` is not `nil`, not an `Integer` + # and not the `Symbol` `:utc`. + # @raise [RangeError] if `month` is not between 1 and 12. + # @raise [RangeError] if `day` is not between 1 and 31. + # @raise [RangeError] if `hour` is not between 0 and 23. + # @raise [RangeError] if `minute` is not between 0 and 59. + # @raise [RangeError] if `second` is not between 0 and 59. + # @raise [RangeError] if `sub_second` is a `Rational` but that is less + # than 0 or greater than or equal to 1. + # @raise [PeriodNotFound] if the date and time parameters do not specify a + # valid local time in the time zone. + # @raise [AmbiguousTime] if the date and time parameters are ambiguous for + # the time zone and the `dst` parameter or block did not resolve the + # ambiguity. + def local_datetime(year, month = 1, day = 1, hour = 0, minute = 0, second = 0, sub_second = 0, dst = Timezone.default_dst, &block) + local_timestamp(year, month, day, hour, minute, second, sub_second, dst, &block).to_datetime + end + + # Creates a {Timestamp} object based on the given (Gregorian calendar) date + # and time parameters. The parameters are interpreted as a local time in the + # time zone. The result has the appropriate {Timestamp#utc_offset + # utc_offset} and {TimestampWithOffset#timezone_offset timezone_offset}. + # + # _Warning:_ There are time values that are not valid as local times in a + # time zone (for example, during the transition from standard time to + # daylight savings time). There are also time values that are ambiguous, + # occurring more than once with different offsets to UTC (for example, + # during the transition from daylight savings time to standard time). + # + # In the first case (an invalid local time), a {PeriodNotFound} exception + # will be raised. + # + # In the second case (more than one occurrence), an {AmbiguousTime} + # exception will be raised unless the optional `dst` parameter or block + # handles the ambiguity. # - # If utc_from is specified and utc_to is not greater than utc_from, then - # offsets_up_to raises an ArgumentError exception. - def offsets_up_to(utc_to, utc_from = nil) - utc_to = TimeOrDateTime.wrap(utc_to) - transitions = transitions_up_to(utc_to, utc_from) - + # If the ambiguity is due to a transition from daylight savings time to + # standard time, the `dst` parameter can be used to select whether the + # daylight savings time or local time is used. For example, the following + # code would raise an {AmbiguousTime} exception: + # + # tz = TZInfo::Timezone.get('America/New_York') + # tz.local_timestamp(2004,10,31,1,30,0,0) + # + # Specifying `dst = true` would return a `Time` with a UTC offset of -4 + # hours and abbreviation EDT (Eastern Daylight Time). Specifying `dst = + # false` would return a `Time` with a UTC offset of -5 hours and + # abbreviation EST (Eastern Standard Time). + # + # The `dst` parameter will not be able to resolve an ambiguity resulting + # from the clocks being set back without changing from daylight savings time + # to standard time. In this case, if a block is specified, it will be called + # to resolve the ambiguity. The block must take a single parameter - an + # `Array` of {TimezonePeriod}s that need to be resolved. The block can + # select and return a single {TimezonePeriod} or return `nil` or an empty + # `Array` to cause an {AmbiguousTime} exception to be raised. + # + # The default value of the `dst` parameter can be specified using + # {Timezone.default_dst=}. + # + # @param year [Integer] the year. + # @param month [Integer] the month (1-12). + # @param day [Integer] the day of the month (1-31). + # @param hour [Integer] the hour (0-23). + # @param minute [Integer] the minute (0-59). + # @param second [Integer] the second (0-59). + # @param sub_second [Numeric] the fractional part of the second as either + # a `Rational` that is greater than or equal to 0 and less than 1, or + # the `Integer` 0. + # @param dst [Boolean] whether to resolve ambiguous local times by always + # selecting the period observing daylight savings time (`true`), always + # selecting the period observing standard time (`false`), or leaving the + # ambiguity unresolved (`nil`). + # @yield [periods] if the `dst` parameter did not resolve an ambiguity, an + # optional block is yielded to. + # @yieldparam periods [Array] an `Array` containing all + # the {TimezonePeriod}s that still match `local_time` after applying the + # `dst` parameter. + # @yieldreturn [Object] to resolve the ambiguity: a chosen {TimezonePeriod} + # or an `Array` containing a chosen {TimezonePeriod}; to leave the + # ambiguity unresolved: an empty `Array`, an `Array` containing more than + # one {TimezonePeriod}, or `nil`. + # @return [TimestampWithOffset] a new {Timestamp} object based on the given + # values, interpreted as a local time in the time zone. + # @raise [ArgumentError] if either of `year`, `month`, `day`, `hour`, + # `minute`, or `second` is not an `Integer`. + # @raise [ArgumentError] if `sub_second` is not a `Rational`, or the + # `Integer` 0. + # @raise [ArgumentError] if `utc_offset` is not `nil`, not an `Integer` + # and not the `Symbol` `:utc`. + # @raise [RangeError] if `month` is not between 1 and 12. + # @raise [RangeError] if `day` is not between 1 and 31. + # @raise [RangeError] if `hour` is not between 0 and 23. + # @raise [RangeError] if `minute` is not between 0 and 59. + # @raise [RangeError] if `second` is not between 0 and 59. + # @raise [RangeError] if `sub_second` is a `Rational` but that is less + # than 0 or greater than or equal to 1. + # @raise [PeriodNotFound] if the date and time parameters do not specify a + # valid local time in the time zone. + # @raise [AmbiguousTime] if the date and time parameters are ambiguous for + # the time zone and the `dst` parameter or block did not resolve the + # ambiguity. + def local_timestamp(year, month = 1, day = 1, hour = 0, minute = 0, second = 0, sub_second = 0, dst = Timezone.default_dst, &block) + ts = Timestamp.create(year, month, day, hour, minute, second, sub_second) + timezone_offset = period_for_local(ts, dst, &block).offset + utc_offset = timezone_offset.observed_utc_offset + TimestampWithOffset.new(ts.value - utc_offset, sub_second, utc_offset).set_timezone_offset(timezone_offset) + end + + # Returns the unique offsets used by the time zone up to a given time (`to`) + # as an `Array` of {TimezoneOffset} instances. + # + # A from time may also be supplied using the `from` parameter. If from is + # not `nil`, only offsets used from that time onwards will be returned. + # + # Comparisons with `to` are exclusive. Comparisons with `from` are + # inclusive. + # + # @param to [Object] a `Time`, `DateTime` or {Timestamp} specifying the + # latest (exclusive) offset to return. + # @param from [Object] an optional `Time`, `DateTime` or {Timestamp} + # specifying the earliest (inclusive) offset to return. + # @return [Array] the offsets that are used earlier than + # `to` and, if specified, at or later than `from`. Offsets may be returned + # in any order. + # @raise [ArgumentError] if `from` is specified and `to` is not greater than + # `from`. + # @raise [ArgumentError] is raised if `to` is `nil`. + # @raise [ArgumentError] if either `to` or `from` is a {Timestamp} with an + # unspecified offset. + def offsets_up_to(to, from = nil) + raise ArgumentError, 'to must be specified' unless to + + to_timestamp = Timestamp.for(to) + from_timestamp = from && Timestamp.for(from) + transitions = transitions_up_to(to_timestamp, from_timestamp) + if transitions.empty? # No transitions in the range, find the period that covers it. - if utc_from + if from_timestamp # Use the from date as it is inclusive. - period = period_for_utc(utc_from) + period = period_for(from_timestamp) else - # utc_to is exclusive, so this can't be used with period_for_utc. - # However, any time earlier than utc_to can be used. - - # Subtract 1 hour (since this is one of the cached OffsetRationals). - # Use add_with_convert so that conversion to DateTime is performed if - # required. - period = period_for_utc(utc_to.add_with_convert(-3600)) + # to is exclusive, so this can't be used with period_for. However, any + # time earlier than to can be used. Subtract 1 hour. + period = period_for(to_timestamp.add_and_set_utc_offset(-3600, :utc)) end - + [period.offset] else result = Set.new - - first = transitions.first - result << first.previous_offset unless utc_from && first.at == utc_from - + + first = transitions.first + result << first.previous_offset unless from_timestamp && first.at == from_timestamp + transitions.each do |t| result << t.offset end - + result.to_a end end - - # Returns the canonical identifier for this Timezone. + + # Returns the canonical identifier of this time zone. + # + # This is a shortcut for calling `canonical_zone.identifier`. Please refer + # to the {canonical_zone} documentation for further information. # - # This is a shortcut for calling canonical_zone.identifier. Please refer - # to the canonical_zone documentation for further information. + # @return [String] the canonical identifier of this time zone. def canonical_identifier canonical_zone.identifier end - - # Returns the current time in the timezone as a Time. + + # @return [TimeWithOffset] the current local time in the time zone. def now - utc_to_local(Time.now.utc) + to_local(Time.now) end - - # Returns the TimezonePeriod for the current time. + + # @return [TimezonePeriod] the current {TimezonePeriod} for the time zone. def current_period - period_for_utc(Time.now.utc) + period_for(Time.now) end - - # Returns the current Time and TimezonePeriod as an array. The first element - # is the time, the second element is the period. - def current_period_and_time - utc = Time.now.utc - period = period_for_utc(utc) - [period.to_local(utc), period] - end - - alias :current_time_and_period :current_period_and_time - - # Converts a time in UTC to local time and returns it as a string according - # to the given format. - # - # The formatting is identical to Time.strftime and DateTime.strftime, except - # %Z and %z are replaced with the timezone abbreviation (for example, EST or - # EDT) and offset for the specified Timezone and time. - # - # The offset can be formatted as follows: - # - # - %z - hour and minute (e.g. +0500) - # - %:z - hour and minute separated with a colon (e.g. +05:00) - # - %::z - hour minute and second separated with colons (e.g. +05:00:00) - # - %:::z - hour only (e.g. +05) - # - # Timezone#strftime currently handles the replacement of %z. From TZInfo - # version 2.0.0, %z will be passed to Time#strftime and DateTime#strftime - # instead. Some of the formatting options may cease to be available - # depending on the version of Ruby in use (for example, %:::z is only - # supported by Time#strftime from MRI version 2.0.0 onwards). - def strftime(format, utc = Time.now.utc) - utc = TimeOrDateTime.wrap(utc) - period = period_for_utc(utc) - local_wrapped = period.to_local(utc) - local = local_wrapped.to_orig - local = local_wrapped.to_time unless local.kind_of?(Time) || local.kind_of?(DateTime) - abbreviation = period.abbreviation.to_s.gsub(/%/, '%%') - - format = format.gsub(/%(%*)([sZ]|:*z)/) do - if $1.length.odd? - # Escaped literal percent or series of percents. Pass on to strftime. - "#$1%#$2" - elsif $2 == "s" - "#$1#{utc.to_i}" - elsif $2 == "Z" - "#$1#{abbreviation}" - else - m, s = period.utc_total_offset.divmod(60) - h, m = m.divmod(60) - case $2.length - when 1 - "#$1#{'%+03d%02d' % [h,m]}" - when 2 - "#$1#{'%+03d:%02d' % [h,m]}" - when 3 - "#$1#{'%+03d:%02d:%02d' % [h,m,s]}" - when 4 - "#$1#{'%+03d' % [h]}" - else # more than 3 colons - not a valid option - # Passing the invalid format string through to Time#strftime or - # DateTime#strtime would normally result in it being returned in the - # result. However, with Ruby 1.8.7 on Windows (as tested with Ruby - # 1.8.7-p374 from http://rubyinstaller.org/downloads/archives), this - # causes Time#strftime to always return an empty string (e.g. - # Time.now.strftime('a %::::z b') returns ''). - # - # Escape the percent to force it to be evaluated as a literal. - "#$1%%#$2" - end - end + + # Returns the current local time and {TimezonePeriod} for the time zone as + # an `Array`. The first element is the time as a {TimeWithOffset}. The + # second element is the period. + # + # @return [Array] an `Array` containing the current {TimeWithOffset} for the + # time zone as the first element and the current {TimezonePeriod} for the + # time zone as the second element. + def current_time_and_period + period = nil + + local_time = Timestamp.for(Time.now) do |ts| + period = period_for(ts) + TimestampWithOffset.set_timezone_offset(ts, period.offset) end - - local.strftime(format) + + [local_time, period] end - - # Compares two Timezones based on their identifier. Returns -1 if tz is less - # than self, 0 if tz is equal to self and +1 if tz is greater than self. + alias current_period_and_time current_time_and_period + + # Converts a time to local time for the time zone and returns a `String` + # representation of the local time according to the given format. # - # Returns nil if tz is not comparable with Timezone instances. + # `Timezone#strftime` first expands any occurrences of `%Z` in the format + # string to the time zone abbreviation for the local time (for example, EST + # or EDT). Depending on the type of `time` parameter, the result of the + # expansion is then passed to either `Time#strftime`, `DateTime#strftime` or + # `Timestamp#strftime` to handle any other format directives. + # + # This method is equivalent to the following: + # + # time_zone.to_local(time).strftime(format) + # + # @param format [String] the format string. + # @param time [Object] a `Time`, `DateTime` or `Timestamp`. + # @return [String] the formatted local time. + # @raise [ArgumentError] if `format` or `time` is `nil`. + # @raise [ArgumentError] if `time` is a {Timestamp} with an unspecified UTC + # offset. + def strftime(format, time = Time.now) + to_local(time).strftime(format) + end + + # @param time [Object] a `Time`, `DateTime` or `Timestamp`. + # @return [String] the abbreviation of this {Timezone} at the given time. + # @raise [ArgumentError] if `time` is `nil`. + # @raise [ArgumentError] if `time` is a {Timestamp} with an unspecified UTC + # offset. + def abbreviation(time = Time.now) + period_for(time).abbreviation + end + alias abbr abbreviation + + # @param time [Object] a `Time`, `DateTime` or `Timestamp`. + # @return [Boolean] whether daylight savings time is in effect at the given + # time. + # @raise [ArgumentError] if `time` is `nil`. + # @raise [ArgumentError] if `time` is a {Timestamp} with an unspecified UTC + # offset. + def dst?(time = Time.now) + period_for(time).dst? + end + + # Returns the base offset from UTC in seconds at the given time. This does + # not include any adjustment made for daylight savings time and will + # typically remain constant throughout the year. + # + # To obtain the observed offset from UTC, including the effect of daylight + # savings time, use {observed_utc_offset} instead. + # + # If you require accurate {base_utc_offset} values, you should install the + # tzinfo-data gem and set {DataSources::RubyDataSource} as the {DataSource}. + # When using {DataSources::ZoneinfoDataSource}, the value of + # {base_utc_offset} has to be derived from changes to the observed UTC + # offset and DST status since it is not included in zoneinfo files. + # + # @param time [Object] a `Time`, `DateTime` or `Timestamp`. + # @return [Integer] the base offset from UTC in seconds at the given time. + # @raise [ArgumentError] if `time` is `nil`. + # @raise [ArgumentError] if `time` is a {Timestamp} with an unspecified UTC + # offset. + def base_utc_offset(time = Time.now) + period_for(time).base_utc_offset + end + + # Returns the observed offset from UTC in seconds at the given time. This + # includes adjustments made for daylight savings time. + # + # @param time [Object] a `Time`, `DateTime` or `Timestamp`. + # @return [Integer] the observed offset from UTC in seconds at the given + # time. + # @raise [ArgumentError] if `time` is `nil`. + # @raise [ArgumentError] if `time` is a {Timestamp} with an unspecified UTC + # offset. + def observed_utc_offset(time = Time.now) + period_for(time).observed_utc_offset + end + alias utc_offset observed_utc_offset + + # Compares this {Timezone} with another based on the {identifier}. + # + # @param tz [Object] an `Object` to compare this {Timezone} with. + # @return [Integer] -1 if `tz` is less than `self`, 0 if `tz` is equal to + # `self` and +1 if `tz` is greater than `self`, or `nil` if `tz` is not an + # instance of {Timezone}. def <=>(tz) return nil unless tz.is_a?(Timezone) identifier <=> tz.identifier end - # Returns true if and only if the identifier of tz is equal to the - # identifier of this Timezone. + # @param tz [Object] an `Object` to compare this {Timezone} with. + # @return [Boolean] `true` if `tz` is an instance of {Timezone} and has the + # same {identifier} as `self`, otherwise `false`. def eql?(tz) self == tz end - - # Returns a hash of this Timezone. + + # @return [Integer] a hash based on the {identifier}. def hash identifier.hash end - - # Dumps this Timezone for marshalling. + + # Matches `regexp` against the {identifier} of this {Timezone}. + # + # @param regexp [Regexp] a `Regexp` to match against the {identifier} of + # this {Timezone}. + # @return [Integer] the position the match starts, or `nil` if there is no + # match. + def =~(regexp) + regexp =~ identifier + end + + # Returns a serialized representation of this {Timezone}. This method is + # called when using `Marshal.dump` with an instance of {Timezone}. + # + # @param limit [Integer] the maximum depth to dump - ignored. + # @return [String] a serialized representation of this {Timezone}. def _dump(limit) identifier end - - # Loads a marshalled Timezone. + + # Loads a {Timezone} from the serialized representation returned by {_dump}. + # This is method is called when using `Marshal.load` or `Marshal.restore` + # to restore a serialized {Timezone}. + # + # @param data [String] a serialized representation of a {Timezone}. + # @return [Timezone] the result of converting `data` back into a {Timezone}. def self._load(data) Timezone.get(data) end - + private - # Initializes @@loaded_zones. - def self.init_loaded_zones - @@loaded_zones = ThreadSafe::Cache.new - end - init_loaded_zones - - # Returns an array of proxies corresponding to the given array of - # identifiers. - def self.get_proxies(identifiers) - identifiers.collect {|identifier| get_proxy(identifier)} - end - - # Returns the current DataSource. - def self.data_source - DataSource.get - end - # Raises an UnknownTimezone exception. - def raise_unknown_timezone - raise UnknownTimezone, 'TZInfo::Timezone constructed directly' - end - end + # Raises an {UnknownTimezone} exception. + # + # @raise [UnknownTimezone] always. + def raise_unknown_timezone + raise UnknownTimezone, 'TZInfo::Timezone should not be constructed directly (use TZInfo::Timezone.get instead)' + end + end end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/timezone_transition_definition.rb ruby-tzinfo-2.0.4/lib/tzinfo/timezone_transition_definition.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/timezone_transition_definition.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/timezone_transition_definition.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,104 +0,0 @@ -module TZInfo - # A TimezoneTransition defined by as integer timestamp, as a rational to - # create a DateTime or as both. - # - # @private - class TimezoneTransitionDefinition < TimezoneTransition #:nodoc: - # The numerator of the DateTime if the transition time is defined as a - # DateTime, otherwise the transition time as a timestamp. - attr_reader :numerator_or_time - protected :numerator_or_time - - # Either the denominator of the DateTime if the transition time is defined - # as a DateTime, otherwise nil. - attr_reader :denominator - protected :denominator - - # Creates a new TimezoneTransitionDefinition with the given offset, - # previous_offset (both TimezoneOffset instances) and UTC time. - # - # The time can be specified as a timestamp, as a rational to create a - # DateTime, or as both. - # - # If both a timestamp and rational are given, then the rational will only - # be used if the timestamp falls outside of the range of Time on the - # platform being used at runtime. - # - # DateTimes are created from the rational as follows: - # - # RubyCoreSupport.datetime_new!(RubyCoreSupport.rational_new!(numerator, denominator), 0, Date::ITALY) - # - # For performance reasons, the numerator and denominator must be specified - # in their lowest form. - def initialize(offset, previous_offset, numerator_or_timestamp, denominator_or_numerator = nil, denominator = nil) - super(offset, previous_offset) - - if denominator - numerator = denominator_or_numerator - timestamp = numerator_or_timestamp - elsif denominator_or_numerator - numerator = numerator_or_timestamp - denominator = denominator_or_numerator - timestamp = nil - else - numerator = nil - denominator = nil - timestamp = numerator_or_timestamp - end - - # Determine whether to use the timestamp or the numerator and denominator. - if numerator && ( - !timestamp || - (timestamp < 0 && !RubyCoreSupport.time_supports_negative) || - ((timestamp < -2147483648 || timestamp > 2147483647) && !RubyCoreSupport.time_supports_64bit) - ) - - @numerator_or_time = numerator - @denominator = denominator - else - @numerator_or_time = timestamp - @denominator = nil - end - - @at = nil - end - - # A TimeOrDateTime instance representing the UTC time when this transition - # occurs. - def at - # Thread-safety: It is possible that the value of @at may be calculated - # multiple times in concurrently executing threads. It is not worth the - # overhead of locking to ensure that @at is only calculated once. - - unless @at - result = unless @denominator - TimeOrDateTime.new(@numerator_or_time) - else - r = RubyCoreSupport.rational_new!(@numerator_or_time, @denominator) - dt = RubyCoreSupport.datetime_new!(r, 0, Date::ITALY) - TimeOrDateTime.new(dt) - end - - return result if frozen? - @at = result - end - - @at - end - - # Returns true if this TimezoneTransitionDefinition is equal to the given - # TimezoneTransitionDefinition. Two TimezoneTransitionDefinition instances - # are considered to be equal by eql? if offset, previous_offset, - # numerator_or_time and denominator are all equal. - def eql?(tti) - tti.kind_of?(TimezoneTransitionDefinition) && - offset == tti.offset && previous_offset == tti.previous_offset && - numerator_or_time == tti.numerator_or_time && denominator == tti.denominator - end - - # Returns a hash of this TimezoneTransitionDefinition instance. - def hash - @offset.hash ^ @previous_offset.hash ^ @numerator_or_time.hash ^ @denominator.hash - end - end -end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/timezone_transition.rb ruby-tzinfo-2.0.4/lib/tzinfo/timezone_transition.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/timezone_transition.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/timezone_transition.rb 2020-12-30 06:49:15.000000000 +0000 @@ -1,130 +1,98 @@ +# encoding: UTF-8 +# frozen_string_literal: true + module TZInfo - # Represents a transition from one timezone offset to another at a particular - # date and time. + # Represents a transition from one observed UTC offset ({TimezoneOffset} to + # another for a time zone. class TimezoneTransition - # The offset this transition changes to (a TimezoneOffset instance). + # @return [TimezoneOffset] the offset this transition changes to. attr_reader :offset - - # The offset this transition changes from (a TimezoneOffset instance). + + # @return [TimezoneOffset] the offset this transition changes from. attr_reader :previous_offset - - # Initializes a new TimezoneTransition. + + # When this transition occurs as an `Integer` number of seconds since + # 1970-01-01 00:00:00 UTC ignoring leap seconds (i.e. each day is treated as + # if it were 86,400 seconds long). Equivalent to the result of calling the + # {Timestamp#value value} method on the {Timestamp} returned by {at}. # - # TimezoneTransition instances should not normally be constructed manually. - def initialize(offset, previous_offset) + # @return [Integer] when this transition occurs as a number of seconds since + # 1970-01-01 00:00:00 UTC ignoring leap seconds. + attr_reader :timestamp_value + + # Initializes a new {TimezoneTransition}. + # + # {TimezoneTransition} instances should not normally be constructed + # manually. + # + # @param offset [TimezoneOffset] the offset the transition changes to. + # @param previous_offset [TimezoneOffset] the offset the transition changes + # from. + # @param timestamp_value [Integer] when the transition occurs as a + # number of seconds since 1970-01-01 00:00:00 UTC ignoring leap seconds + # (i.e. each day is treated as if it were 86,400 seconds long). + def initialize(offset, previous_offset, timestamp_value) @offset = offset @previous_offset = previous_offset - @local_end_at = nil - @local_start_at = nil + @timestamp_value = timestamp_value end - - # A TimeOrDateTime instance representing the UTC time when this transition - # occurs. + + # Returns a {Timestamp} instance representing the UTC time when this + # transition occurs. + # + # To obtain the result as a `Time` or `DateTime`, call either + # {Timestamp#to_time to_time} or {Timestamp#to_datetime to_datetime} on the + # {Timestamp} instance that is returned. + # + # @return [Timestamp] the UTC time when this transition occurs. def at - raise_not_implemented('at') + Timestamp.utc(@timestamp_value) end - - # The UTC time when this transition occurs, returned as a DateTime instance. - def datetime - at.to_datetime - end - - # The UTC time when this transition occurs, returned as a Time instance. - def time - at.to_time - end - - # A TimeOrDateTime instance representing the local time when this transition - # causes the previous observance to end (calculated from at using - # previous_offset). + + # Returns a {TimestampWithOffset} instance representing the local time when + # this transition causes the previous observance to end (calculated from + # {at} using {previous_offset}). + # + # To obtain the result as a `Time` or `DateTime`, call either + # {TimestampWithOffset#to_time to_time} or {TimestampWithOffset#to_datetime + # to_datetime} on the {TimestampWithOffset} instance that is returned. + # + # @return [TimestampWithOffset] the local time when this transition causes + # the previous observance to end. def local_end_at - # Thread-safety: It is possible that the value of @local_end_at may be - # calculated multiple times in concurrently executing threads. It is not - # worth the overhead of locking to ensure that @local_end_at is only - # calculated once. - - unless @local_end_at - result = at.add_with_convert(@previous_offset.utc_total_offset) - return result if frozen? - @local_end_at = result - end - - @local_end_at - end - - # The local time when this transition causes the previous observance to end, - # returned as a DateTime instance. - def local_end - local_end_at.to_datetime - end - - # The local time when this transition causes the previous observance to end, - # returned as a Time instance. - def local_end_time - local_end_at.to_time - end - - # A TimeOrDateTime instance representing the local time when this transition - # causes the next observance to start (calculated from at using offset). + TimestampWithOffset.new(@timestamp_value, 0, @previous_offset.observed_utc_offset).set_timezone_offset(@previous_offset) + end + + # Returns a {TimestampWithOffset} instance representing the local time when + # this transition causes the next observance to start (calculated from {at} + # using {offset}). + # + # To obtain the result as a `Time` or `DateTime`, call either + # {TimestampWithOffset#to_time to_time} or {TimestampWithOffset#to_datetime + # to_datetime} on the {TimestampWithOffset} instance that is returned. + # + # @return [TimestampWithOffset] the local time when this transition causes + # the next observance to start. def local_start_at - # Thread-safety: It is possible that the value of @local_start_at may be - # calculated multiple times in concurrently executing threads. It is not - # worth the overhead of locking to ensure that @local_start_at is only - # calculated once. - - unless @local_start_at - result = at.add_with_convert(@offset.utc_total_offset) - return result if frozen? - @local_start_at = result - end - - @local_start_at - end - - # The local time when this transition causes the next observance to start, - # returned as a DateTime instance. - def local_start - local_start_at.to_datetime - end - - # The local time when this transition causes the next observance to start, - # returned as a Time instance. - def local_start_time - local_start_at.to_time - end - - # Returns true if this TimezoneTransition is equal to the given - # TimezoneTransition. Two TimezoneTransition instances are - # considered to be equal by == if offset, previous_offset and at are all - # equal. - def ==(tti) - tti.kind_of?(TimezoneTransition) && - offset == tti.offset && previous_offset == tti.previous_offset && at == tti.at + TimestampWithOffset.new(@timestamp_value, 0, @offset.observed_utc_offset).set_timezone_offset(@offset) end - - # Returns true if this TimezoneTransition is equal to the given - # TimezoneTransition. Two TimezoneTransition instances are - # considered to be equal by eql? if offset, previous_offset and at are all - # equal and the type used to define at in both instances is the same. - def eql?(tti) + + # Determines if this {TimezoneTransition} is equal to another instance. + # + # @param tti [Object] the instance to test for equality. + # @return [Boolean] `true` if `tti` is a {TimezoneTransition} with the same + # {offset}, {previous_offset} and {timestamp_value} as this + # {TimezoneTransition}, otherwise `false`. + def ==(tti) tti.kind_of?(TimezoneTransition) && - offset == tti.offset && previous_offset == tti.previous_offset && at.eql?(tti.at) - end - - # Returns a hash of this TimezoneTransition instance. - def hash - @offset.hash ^ @previous_offset.hash ^ at.hash + offset == tti.offset && previous_offset == tti.previous_offset && timestamp_value == tti.timestamp_value end - - # Returns internal object state as a programmer-readable string. - def inspect - "#<#{self.class}: #{at.inspect},#{@offset.inspect}>" - end - - private + alias eql? == - def raise_not_implemented(method_name) - raise NotImplementedError, "Subclasses must override #{method_name}" + # @return [Integer] a hash based on {offset}, {previous_offset} and + # {timestamp_value}. + def hash + [@offset, @previous_offset, @timestamp_value].hash end end end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/transition_data_timezone_info.rb ruby-tzinfo-2.0.4/lib/tzinfo/transition_data_timezone_info.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/transition_data_timezone_info.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/transition_data_timezone_info.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,274 +0,0 @@ -module TZInfo - # Raised if no offsets have been defined when calling period_for_utc or - # periods_for_local. Indicates an error in the timezone data. - class NoOffsetsDefined < StandardError - end - - # Represents a data timezone defined by a set of offsets and a set - # of transitions. - # - # @private - class TransitionDataTimezoneInfo < DataTimezoneInfo #:nodoc: - - # Constructs a new TransitionDataTimezoneInfo with its identifier. - def initialize(identifier) - super(identifier) - @offsets = {} - @transitions = [] - @previous_offset = nil - @transitions_index = nil - end - - # Defines a offset. The id uniquely identifies this offset within the - # timezone. utc_offset and std_offset define the offset in seconds of - # standard time from UTC and daylight savings from standard time - # respectively. abbreviation describes the timezone offset (e.g. GMT, BST, - # EST or EDT). - # - # The first offset to be defined is treated as the offset that applies - # until the first transition. This will usually be in Local Mean Time (LMT). - # - # ArgumentError will be raised if the id is already defined. - def offset(id, utc_offset, std_offset, abbreviation) - raise ArgumentError, 'Offset already defined' if @offsets.has_key?(id) - - offset = TimezoneOffset.new(utc_offset, std_offset, abbreviation) - @offsets[id] = offset - @previous_offset = offset unless @previous_offset - end - - # Defines a transition. Transitions must be defined in chronological order. - # ArgumentError will be raised if a transition is added out of order. - # offset_id refers to an id defined with offset. ArgumentError will be - # raised if the offset_id cannot be found. numerator_or_time and - # denomiator specify the time the transition occurs as. See - # TimezoneTransition for more detail about specifying times. - def transition(year, month, offset_id, numerator_or_timestamp, denominator_or_numerator = nil, denominator = nil) - offset = @offsets[offset_id] - raise ArgumentError, 'Offset not found' unless offset - - if @transitions_index - if year < @last_year || (year == @last_year && month < @last_month) - raise ArgumentError, 'Transitions must be increasing date order' - end - - # Record the position of the first transition with this index. - index = transition_index(year, month) - @transitions_index[index] ||= @transitions.length - - # Fill in any gaps - (index - 1).downto(0) do |i| - break if @transitions_index[i] - @transitions_index[i] = @transitions.length - end - else - @transitions_index = [@transitions.length] - @start_year = year - @start_month = month - end - - @transitions << TimezoneTransitionDefinition.new(offset, @previous_offset, - numerator_or_timestamp, denominator_or_numerator, denominator) - @last_year = year - @last_month = month - @previous_offset = offset - end - - # Returns the TimezonePeriod for the given UTC time. - # Raises NoOffsetsDefined if no offsets have been defined. - def period_for_utc(utc) - unless @transitions.empty? - utc = TimeOrDateTime.wrap(utc) - index = transition_index(utc.year, utc.mon) - - start_transition = nil - start = transition_before_end(index) - if start - start.downto(0) do |i| - if @transitions[i].at <= utc - start_transition = @transitions[i] - break - end - end - end - - end_transition = nil - start = transition_after_start(index) - if start - start.upto(@transitions.length - 1) do |i| - if @transitions[i].at > utc - end_transition = @transitions[i] - break - end - end - end - - if start_transition || end_transition - TimezonePeriod.new(start_transition, end_transition) - else - # Won't happen since there are transitions. Must always find one - # transition that is either >= or < the specified time. - raise 'No transitions found in search' - end - else - raise NoOffsetsDefined, 'No offsets have been defined' unless @previous_offset - TimezonePeriod.new(nil, nil, @previous_offset) - end - end - - # Returns the set of TimezonePeriods for the given local time as an array. - # Results returned are ordered by increasing UTC start date. - # Returns an empty array if no periods are found for the given time. - # Raises NoOffsetsDefined if no offsets have been defined. - def periods_for_local(local) - unless @transitions.empty? - local = TimeOrDateTime.wrap(local) - index = transition_index(local.year, local.mon) - - result = [] - - start_index = transition_after_start(index - 1) - if start_index && @transitions[start_index].local_end_at > local - if start_index > 0 - if @transitions[start_index - 1].local_start_at <= local - result << TimezonePeriod.new(@transitions[start_index - 1], @transitions[start_index]) - end - else - result << TimezonePeriod.new(nil, @transitions[start_index]) - end - end - - end_index = transition_before_end(index + 1) - - if end_index - start_index = end_index unless start_index - - start_index.upto(transition_before_end(index + 1)) do |i| - if @transitions[i].local_start_at <= local - if i + 1 < @transitions.length - if @transitions[i + 1].local_end_at > local - result << TimezonePeriod.new(@transitions[i], @transitions[i + 1]) - end - else - result << TimezonePeriod.new(@transitions[i], nil) - end - end - end - end - - result - else - raise NoOffsetsDefined, 'No offsets have been defined' unless @previous_offset - [TimezonePeriod.new(nil, nil, @previous_offset)] - end - end - - # Returns an Array of TimezoneTransition instances representing the times - # where the UTC offset of the timezone changes. - # - # Transitions are returned up to a given date and time up to a given date - # and time, specified in UTC (utc_to). - # - # A from date and time may also be supplied using the utc_from parameter - # (also specified in UTC). If utc_from is not nil, only transitions from - # that date and time onwards will be returned. - # - # Comparisons with utc_to are exclusive. Comparisons with utc_from are - # inclusive. If a transition falls precisely on utc_to, it will be excluded. - # If a transition falls on utc_from, it will be included. - # - # Transitions returned are ordered by when they occur, from earliest to - # latest. - # - # utc_to and utc_from can be specified using either DateTime, Time or - # integer timestamps (Time.to_i). - # - # If utc_from is specified and utc_to is not greater than utc_from, then - # transitions_up_to raises an ArgumentError exception. - def transitions_up_to(utc_to, utc_from = nil) - utc_to = TimeOrDateTime.wrap(utc_to) - utc_from = utc_from ? TimeOrDateTime.wrap(utc_from) : nil - - if utc_from && utc_to <= utc_from - raise ArgumentError, 'utc_to must be greater than utc_from' - end - - unless @transitions.empty? - if utc_from - from = transition_after_start(transition_index(utc_from.year, utc_from.mon)) - - if from - while from < @transitions.length && @transitions[from].at < utc_from - from += 1 - end - - if from >= @transitions.length - return [] - end - else - # utc_from is later than last transition. - return [] - end - else - from = 0 - end - - to = transition_before_end(transition_index(utc_to.year, utc_to.mon)) - - if to - while to >= 0 && @transitions[to].at >= utc_to - to -= 1 - end - - if to < 0 - return [] - end - else - # utc_to is earlier than first transition. - return [] - end - - @transitions[from..to] - else - [] - end - end - - private - # Returns the index into the @transitions_index array for a given year - # and month. - def transition_index(year, month) - index = (year - @start_year) * 2 - index += 1 if month > 6 - index -= 1 if @start_month > 6 - index - end - - # Returns the index into @transitions of the first transition that occurs - # on or after the start of the given index into @transitions_index. - # Returns nil if there are no such transitions. - def transition_after_start(index) - if index >= @transitions_index.length - nil - else - index = 0 if index < 0 - @transitions_index[index] - end - end - - # Returns the index into @transitions of the first transition that occurs - # before the end of the given index into @transitions_index. - # Returns nil if there are no such transitions. - def transition_before_end(index) - index = index + 1 - - if index <= 0 - nil - elsif index >= @transitions_index.length - @transitions.length - 1 - else - @transitions_index[index] - 1 - end - end - end -end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/transition_rule.rb ruby-tzinfo-2.0.4/lib/tzinfo/transition_rule.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/transition_rule.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/transition_rule.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,455 @@ +# encoding: UTF-8 +# frozen_string_literal: true + +module TZInfo + # Base class for rules definining the transition between standard and daylight + # savings time. + # + # @abstract + # @private + class TransitionRule #:nodoc: + # Returns the number of seconds after midnight local time on the day + # identified by the rule at which the transition occurs. Can be negative to + # denote a time on the prior day. Can be greater than or equal to 86,400 to + # denote a time of the following day. + # + # @return [Integer] the time in seconds after midnight local time at which + # the transition occurs. + attr_reader :transition_at + + # Initializes a new {TransitionRule}. + # + # @param transition_at [Integer] the time in seconds after midnight local + # time at which the transition occurs. + # @raise [ArgumentError] if `transition_at` is not an `Integer`. + def initialize(transition_at) + raise ArgumentError, 'Invalid transition_at' unless transition_at.kind_of?(Integer) + @transition_at = transition_at + end + + # Calculates the time of the transition from a given offset on a given year. + # + # @param offset [TimezoneOffset] the current offset at the time the rule + # will transition. + # @param year [Integer] the year in which the transition occurs (local + # time). + # @return [TimestampWithOffset] the time at which the transition occurs. + def at(offset, year) + day = get_day(offset, year) + TimestampWithOffset.set_timezone_offset(Timestamp.for(day + @transition_at), offset) + end + + # Determines if this {TransitionRule} is equal to another instance. + # + # @param r [Object] the instance to test for equality. + # @return [Boolean] `true` if `r` is a {TransitionRule} with the same + # {transition_at} as this {TransitionRule}, otherwise `false`. + def ==(r) + r.kind_of?(TransitionRule) && @transition_at == r.transition_at + end + alias eql? == + + # @return [Integer] a hash based on {hash_args} (defaulting to + # {transition_at}). + def hash + hash_args.hash + end + + protected + + # @return [Array] an `Array` of parameters that will influence the output of + # {hash}. + def hash_args + [@transition_at] + end + end + private_constant :TransitionRule + + # A base class for transition rules that activate based on an integer day of + # the year. + # + # @abstract + # @private + class DayOfYearTransitionRule < TransitionRule #:nodoc: + # Initializes a new {DayOfYearTransitionRule}. + # + # @param day [Integer] the day of the year on which the transition occurs. + # The precise meaning is defined by subclasses. + # @param transition_at [Integer] the time in seconds after midnight local + # time at which the transition occurs. + # @raise [ArgumentError] if `transition_at` is not an `Integer`. + # @raise [ArgumentError] if `day` is not an `Integer`. + def initialize(day, transition_at) + super(transition_at) + raise ArgumentError, 'Invalid day' unless day.kind_of?(Integer) + @seconds = day * 86400 + end + + # Determines if this {DayOfYearTransitionRule} is equal to another instance. + # + # @param r [Object] the instance to test for equality. + # @return [Boolean] `true` if `r` is a {DayOfYearTransitionRule} with the + # same {transition_at} and day as this {DayOfYearTransitionRule}, + # otherwise `false`. + def ==(r) + super(r) && r.kind_of?(DayOfYearTransitionRule) && @seconds == r.seconds + end + alias eql? == + + protected + + # @return [Integer] the day multipled by the number of seconds in a day. + attr_reader :seconds + + # (see TransitionRule#hash_args) + def hash_args + [@seconds] + super + end + end + private_constant :DayOfYearTransitionRule + + # Defines transitions that occur on the zero-based nth day of the year. + # + # Day 0 is 1 January. + # + # Leap days are counted. Day 59 will be 29 February on a leap year and 1 March + # on a non-leap year. Day 365 will be 31 December on a leap year and 1 January + # the following year on a non-leap year. + # + # @private + class AbsoluteDayOfYearTransitionRule < DayOfYearTransitionRule #:nodoc: + # Initializes a new {AbsoluteDayOfYearTransitionRule}. + # + # @param day [Integer] the zero-based day of the year on which the + # transition occurs (0 to 365 inclusive). + # @param transition_at [Integer] the time in seconds after midnight local + # time at which the transition occurs. + # @raise [ArgumentError] if `transition_at` is not an `Integer`. + # @raise [ArgumentError] if `day` is not an `Integer`. + # @raise [ArgumentError] if `day` is less than 0 or greater than 365. + def initialize(day, transition_at = 0) + super(day, transition_at) + raise ArgumentError, 'Invalid day' unless day >= 0 && day <= 365 + end + + # @return [Boolean] `true` if the day specified by this transition is the + # first in the year (a day number of 0), otherwise `false`. + def is_always_first_day_of_year? + seconds == 0 + end + + # @return [Boolean] `false`. + def is_always_last_day_of_year? + false + end + + # Determines if this {AbsoluteDayOfYearTransitionRule} is equal to another + # instance. + # + # @param r [Object] the instance to test for equality. + # @return [Boolean] `true` if `r` is a {AbsoluteDayOfYearTransitionRule} + # with the same {transition_at} and day as this + # {AbsoluteDayOfYearTransitionRule}, otherwise `false`. + def ==(r) + super(r) && r.kind_of?(AbsoluteDayOfYearTransitionRule) + end + alias eql? == + + protected + + # Returns a `Time` representing midnight local time on the day specified by + # the rule for the given offset and year. + # + # @param offset [TimezoneOffset] the current offset at the time of the + # transition. + # @param year [Integer] the year in which the transition occurs. + # @return [Time] midnight local time on the day specified by the rule for + # the given offset and year. + def get_day(offset, year) + Time.new(year, 1, 1, 0, 0, 0, offset.observed_utc_offset) + seconds + end + + # (see TransitionRule#hash_args) + def hash_args + [AbsoluteDayOfYearTransitionRule] + super + end + end + + # Defines transitions that occur on the one-based nth Julian day of the year. + # + # Leap days are not counted. Day 1 is 1 January. Day 60 is always 1 March. + # Day 365 is always 31 December. + # + # @private + class JulianDayOfYearTransitionRule < DayOfYearTransitionRule #:nodoc: + # The 60 days in seconds. + LEAP = 60 * 86400 + private_constant :LEAP + + # The length of a non-leap year in seconds. + YEAR = 365 * 86400 + private_constant :YEAR + + # Initializes a new {JulianDayOfYearTransitionRule}. + # + # @param day [Integer] the one-based Julian day of the year on which the + # transition occurs (1 to 365 inclusive). + # @param transition_at [Integer] the time in seconds after midnight local + # time at which the transition occurs. + # @raise [ArgumentError] if `transition_at` is not an `Integer`. + # @raise [ArgumentError] if `day` is not an `Integer`. + # @raise [ArgumentError] if `day` is less than 1 or greater than 365. + def initialize(day, transition_at = 0) + super(day, transition_at) + raise ArgumentError, 'Invalid day' unless day >= 1 && day <= 365 + end + + # @return [Boolean] `true` if the day specified by this transition is the + # first in the year (a day number of 1), otherwise `false`. + def is_always_first_day_of_year? + seconds == 86400 + end + + # @return [Boolean] `true` if the day specified by this transition is the + # last in the year (a day number of 365), otherwise `false`. + def is_always_last_day_of_year? + seconds == YEAR + end + + # Determines if this {JulianDayOfYearTransitionRule} is equal to another + # instance. + # + # @param r [Object] the instance to test for equality. + # @return [Boolean] `true` if `r` is a {JulianDayOfYearTransitionRule} with + # the same {transition_at} and day as this + # {JulianDayOfYearTransitionRule}, otherwise `false`. + def ==(r) + super(r) && r.kind_of?(JulianDayOfYearTransitionRule) + end + alias eql? == + + protected + + # Returns a `Time` representing midnight local time on the day specified by + # the rule for the given offset and year. + # + # @param offset [TimezoneOffset] the current offset at the time of the + # transition. + # @param year [Integer] the year in which the transition occurs. + # @return [Time] midnight local time on the day specified by the rule for + # the given offset and year. + def get_day(offset, year) + # Returns 1 March on non-leap years. + leap = Time.new(year, 2, 29, 0, 0, 0, offset.observed_utc_offset) + diff = seconds - LEAP + diff += 86400 if diff >= 0 && leap.mday == 29 + leap + diff + end + + # (see TransitionRule#hash_args) + def hash_args + [JulianDayOfYearTransitionRule] + super + end + end + private_constant :JulianDayOfYearTransitionRule + + # A base class for rules that transition on a particular day of week of a + # given week (subclasses specify which week of the month). + # + # @abstract + # @private + class DayOfWeekTransitionRule < TransitionRule #:nodoc: + # Initializes a new {DayOfWeekTransitionRule}. + # + # @param month [Integer] the month of the year when the transition occurs. + # @param day_of_week [Integer] the day of the week when the transition + # occurs. 0 is Sunday, 6 is Saturday. + # @param transition_at [Integer] the time in seconds after midnight local + # time at which the transition occurs. + # @raise [ArgumentError] if `transition_at` is not an `Integer`. + # @raise [ArgumentError] if `month` is not an `Integer`. + # @raise [ArgumentError] if `month` is less than 1 or greater than 12. + # @raise [ArgumentError] if `day_of_week` is not an `Integer`. + # @raise [ArgumentError] if `day_of_week` is less than 0 or greater than 6. + def initialize(month, day_of_week, transition_at) + super(transition_at) + raise ArgumentError, 'Invalid month' unless month.kind_of?(Integer) && month >= 1 && month <= 12 + raise ArgumentError, 'Invalid day_of_week' unless day_of_week.kind_of?(Integer) && day_of_week >= 0 && day_of_week <= 6 + @month = month + @day_of_week = day_of_week + end + + # @return [Boolean] `false`. + def is_always_first_day_of_year? + false + end + + # @return [Boolean] `false`. + def is_always_last_day_of_year? + false + end + + # Determines if this {DayOfWeekTransitionRule} is equal to another + # instance. + # + # @param r [Object] the instance to test for equality. + # @return [Boolean] `true` if `r` is a {DayOfWeekTransitionRule} with the + # same {transition_at}, month and day of week as this + # {DayOfWeekTransitionRule}, otherwise `false`. + def ==(r) + super(r) && r.kind_of?(DayOfWeekTransitionRule) && @month == r.month && @day_of_week == r.day_of_week + end + alias eql? == + + protected + + # @return [Integer] the month of the year (1 to 12). + attr_reader :month + + # @return [Integer] the day of the week (0 to 6 for Sunday to Monday). + attr_reader :day_of_week + + # (see TransitionRule#hash_args) + def hash_args + [@month, @day_of_week] + super + end + end + private_constant :DayOfWeekTransitionRule + + # A rule that transitions on the nth occurrence of a particular day of week + # of a calendar month. + # + # @private + class DayOfMonthTransitionRule < DayOfWeekTransitionRule #:nodoc: + # Initializes a new {DayOfMonthTransitionRule}. + # + # @param month [Integer] the month of the year when the transition occurs. + # @param week [Integer] the week of the month when the transition occurs (1 + # to 4). + # @param day_of_week [Integer] the day of the week when the transition + # occurs. 0 is Sunday, 6 is Saturday. + # @param transition_at [Integer] the time in seconds after midnight local + # time at which the transition occurs. + # @raise [ArgumentError] if `transition_at` is not an `Integer`. + # @raise [ArgumentError] if `month` is not an `Integer`. + # @raise [ArgumentError] if `month` is less than 1 or greater than 12. + # @raise [ArgumentError] if `week` is not an `Integer`. + # @raise [ArgumentError] if `week` is less than 1 or greater than 4. + # @raise [ArgumentError] if `day_of_week` is not an `Integer`. + # @raise [ArgumentError] if `day_of_week` is less than 0 or greater than 6. + def initialize(month, week, day_of_week, transition_at = 0) + super(month, day_of_week, transition_at) + raise ArgumentError, 'Invalid week' unless week.kind_of?(Integer) && week >= 1 && week <= 4 + @offset_start = (week - 1) * 7 + 1 + end + + # Determines if this {DayOfMonthTransitionRule} is equal to another + # instance. + # + # @param r [Object] the instance to test for equality. + # @return [Boolean] `true` if `r` is a {DayOfMonthTransitionRule} with the + # same {transition_at}, month, week and day of week as this + # {DayOfMonthTransitionRule}, otherwise `false`. + def ==(r) + super(r) && r.kind_of?(DayOfMonthTransitionRule) && @offset_start == r.offset_start + end + alias eql? == + + protected + + # @return [Integer] the day the week starts on for a month starting on a + # Sunday. + attr_reader :offset_start + + # Returns a `Time` representing midnight local time on the day specified by + # the rule for the given offset and year. + # + # @param offset [TimezoneOffset] the current offset at the time of the + # transition. + # @param year [Integer] the year in which the transition occurs. + # @return [Time] midnight local time on the day specified by the rule for + # the given offset and year. + def get_day(offset, year) + candidate = Time.new(year, month, @offset_start, 0, 0, 0, offset.observed_utc_offset) + diff = day_of_week - candidate.wday + + if diff < 0 + candidate + (7 + diff) * 86400 + elsif diff > 0 + candidate + diff * 86400 + else + candidate + end + end + + # (see TransitionRule#hash_args) + def hash_args + [@offset_start] + super + end + end + private_constant :DayOfMonthTransitionRule + + # A rule that transitions on the last occurrence of a particular day of week + # of a calendar month. + # + # @private + class LastDayOfMonthTransitionRule < DayOfWeekTransitionRule #:nodoc: + # Initializes a new {LastDayOfMonthTransitionRule}. + # + # @param month [Integer] the month of the year when the transition occurs. + # @param day_of_week [Integer] the day of the week when the transition + # occurs. 0 is Sunday, 6 is Saturday. + # @param transition_at [Integer] the time in seconds after midnight local + # time at which the transition occurs. + # @raise [ArgumentError] if `transition_at` is not an `Integer`. + # @raise [ArgumentError] if `month` is not an `Integer`. + # @raise [ArgumentError] if `month` is less than 1 or greater than 12. + # @raise [ArgumentError] if `day_of_week` is not an `Integer`. + # @raise [ArgumentError] if `day_of_week` is less than 0 or greater than 6. + def initialize(month, day_of_week, transition_at = 0) + super(month, day_of_week, transition_at) + end + + # Determines if this {LastDayOfMonthTransitionRule} is equal to another + # instance. + # + # @param r [Object] the instance to test for equality. + # @return [Boolean] `true` if `r` is a {LastDayOfMonthTransitionRule} with + # the same {transition_at}, month and day of week as this + # {LastDayOfMonthTransitionRule}, otherwise `false`. + def ==(r) + super(r) && r.kind_of?(LastDayOfMonthTransitionRule) + end + alias eql? == + + protected + + # Returns a `Time` representing midnight local time on the day specified by + # the rule for the given offset and year. + # + # @param offset [TimezoneOffset] the current offset at the time of the + # transition. + # @param year [Integer] the year in which the transition occurs. + # @return [Time] midnight local time on the day specified by the rule for + # the given offset and year. + def get_day(offset, year) + next_month = month + 1 + if next_month == 13 + year += 1 + next_month = 1 + end + + candidate = Time.new(year, next_month, 1, 0, 0, 0, offset.observed_utc_offset) - 86400 + diff = candidate.wday - day_of_week + + if diff < 0 + candidate - (diff + 7) * 86400 + elsif diff > 0 + candidate - diff * 86400 + else + candidate + end + end + end + private_constant :LastDayOfMonthTransitionRule +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/transitions_timezone_period.rb ruby-tzinfo-2.0.4/lib/tzinfo/transitions_timezone_period.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/transitions_timezone_period.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/transitions_timezone_period.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,63 @@ +# encoding: UTF-8 +# frozen_string_literal: true + +module TZInfo + # Represents a period of time in a time zone where the same offset from UTC + # applies. The period of time is bounded at at least one end, either having a + # start transition, end transition or both start and end transitions. + class TransitionsTimezonePeriod < TimezonePeriod + # @return [TimezoneTransition] the transition that defines the start of this + # {TimezonePeriod} (`nil` if the start is unbounded). + attr_reader :start_transition + + # @return [TimezoneTransition] the transition that defines the end of this + # {TimezonePeriod} (`nil` if the end is unbounded). + attr_reader :end_transition + + # Initializes a {TransitionsTimezonePeriod}. + # + # At least one of `start_transition` and `end_transition` must be specified. + # + # @param start_transition [TimezoneTransition] the transition that defines + # the start of the period, or `nil` if the start is unbounded. + # @param end_transition [TimezoneTransition] the transition that defines the + # end of the period, or `nil` if the end is unbounded. + # @raise [ArgumentError] if both `start_transition` and `end_transition` are + # `nil`. + def initialize(start_transition, end_transition) + if start_transition + super(start_transition.offset) + elsif end_transition + super(end_transition.previous_offset) + else + raise ArgumentError, 'At least one of start_transition and end_transition must be specified' + end + + @start_transition = start_transition + @end_transition = end_transition + end + + # Determines if this {TransitionsTimezonePeriod} is equal to another + # instance. + # + # @param p [Object] the instance to test for equality. + # @return [Boolean] `true` if `p` is a {TransitionsTimezonePeriod} with the + # same {offset}, {start_transition} and {end_transition}, otherwise + # `false`. + def ==(p) + p.kind_of?(TransitionsTimezonePeriod) && start_transition == p.start_transition && end_transition == p.end_transition + end + alias eql? == + + # @return [Integer] a hash based on {start_transition} and {end_transition}. + def hash + [@start_transition, @end_transition].hash + end + + # @return [String] the internal object state as a programmer-readable + # `String`. + def inspect + "#<#{self.class}: @start_transition=#{@start_transition.inspect}, @end_transition=#{@end_transition.inspect}>" + end + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/untaint_ext.rb ruby-tzinfo-2.0.4/lib/tzinfo/untaint_ext.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/untaint_ext.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/untaint_ext.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,18 @@ +# encoding: UTF-8 +# frozen_string_literal: true + +module TZInfo + # Object#untaint is deprecated in Ruby >= 2.7 and will be removed in 3.2. + # UntaintExt adds a refinement to make Object#untaint a no-op and avoid the + # warning. + # + # @private + module UntaintExt # :nodoc: + refine Object do + def untaint + self + end + end + end + private_constant :UntaintExt +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/version.rb ruby-tzinfo-2.0.4/lib/tzinfo/version.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/version.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/version.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,7 @@ +# encoding: UTF-8 +# frozen_string_literal: true + +module TZInfo + # The TZInfo version number. + VERSION = '2.0.4' +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/with_offset.rb ruby-tzinfo-2.0.4/lib/tzinfo/with_offset.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/with_offset.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/with_offset.rb 2020-12-30 06:49:15.000000000 +0000 @@ -0,0 +1,61 @@ +# encoding: UTF-8 +# frozen_string_literal: true + +module TZInfo + # The {WithOffset} module is included in {TimeWithOffset}, + # {DateTimeWithOffset} and {TimestampWithOffset}. It provides an override for + # the {strftime} method that handles expanding the `%Z` directive according to + # the {TimezoneOffset#abbreviation abbreviation} of the {TimezoneOffset} + # associated with a local time. + module WithOffset + # Overrides the `Time`, `DateTime` or {Timestamp} version of `strftime`, + # replacing `%Z` with the {TimezoneOffset#abbreviation abbreviation} of the + # associated {TimezoneOffset}. If there is no associated offset, `%Z` is + # expanded by the base class instead. + # + # All the format directives handled by the base class are supported. + # + # @param format [String] the format string. + # @return [String] the formatted time. + # @raise [ArgumentError] if `format` is `nil`. + def strftime(format) + raise ArgumentError, 'format must be specified' unless format + + if_timezone_offset do |o| + abbreviation = nil + + format = format.gsub(/%(%*)Z/) do + if $1.length.odd? + # Return %%Z so the real strftime treats it as a literal %Z too. + "#$1%Z" + else + "#$1#{abbreviation ||= o.abbreviation.gsub(/%/, '%%')}" + end + end + end + + super + end + + protected + + # Performs a calculation if there is an associated {TimezoneOffset}. + # + # @param result [Object] a result value that can be manipulated by the block + # if there is an associated {TimezoneOffset}. + # @yield [period, result] if there is an associated {TimezoneOffset}, the + # block is yielded to in order to calculate the method result. + # @yieldparam period [TimezoneOffset] the associated {TimezoneOffset}. + # @yieldparam result [Object] the `result` parameter. + # @yieldreturn [Object] the result of the calculation performed if there is + # an associated {TimezoneOffset}. + # @return [Object] the result of the block if there is an associated + # {TimezoneOffset}, otherwise the `result` parameter. + # + # @private + def if_timezone_offset(result = nil) #:nodoc: + to = timezone_offset + to ? yield(to, result) : result + end + end +end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/zoneinfo_country_info.rb ruby-tzinfo-2.0.4/lib/tzinfo/zoneinfo_country_info.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/zoneinfo_country_info.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/zoneinfo_country_info.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -module TZInfo - # Represents information about a country returned by ZoneinfoDataSource. - # - # @private - class ZoneinfoCountryInfo < CountryInfo #:nodoc: - # Constructs a new CountryInfo with an ISO 3166 country code, name and - # an array of CountryTimezones. - def initialize(code, name, zones) - super(code, name) - @zones = zones.dup.freeze - @zone_identifiers = nil - end - - # Returns a frozen array of all the zone identifiers for the country ordered - # geographically, most populous first. - def zone_identifiers - # Thread-safety: It is possible that the value of @zone_identifiers may be - # calculated multiple times in concurrently executing threads. It is not - # worth the overhead of locking to ensure that @zone_identifiers is only - # calculated once. - - unless @zone_identifiers - result = zones.collect {|zone| zone.identifier}.freeze - return result if frozen? - @zone_identifiers = result - end - - @zone_identifiers - end - - # Returns a frozen array of all the timezones for the for the country - # ordered geographically, most populous first. - def zones - @zones - end - end -end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/zoneinfo_data_source.rb ruby-tzinfo-2.0.4/lib/tzinfo/zoneinfo_data_source.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/zoneinfo_data_source.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/zoneinfo_data_source.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,496 +0,0 @@ -module TZInfo - # Use send as a workaround for an issue on JRuby 9.2.9.0 where using the - # refinement causes calls to RubyCoreSupport.file_open to fail to pass the - # block parameter. - # - # https://travis-ci.org/tzinfo/tzinfo/jobs/628812051#L1931 - # https://github.com/jruby/jruby/issues/6009 - send(:using, TZInfo::RubyCoreSupport::UntaintExt) if TZInfo::RubyCoreSupport.const_defined?(:UntaintExt) - - # An InvalidZoneinfoDirectory exception is raised if the DataSource is - # set to a specific zoneinfo path, which is not a valid zoneinfo directory - # (i.e. a directory containing index files named iso3166.tab and zone.tab - # as well as other timezone files). - class InvalidZoneinfoDirectory < StandardError - end - - # A ZoneinfoDirectoryNotFound exception is raised if no valid zoneinfo - # directory could be found when checking the paths listed in - # ZoneinfoDataSource.search_path. A valid zoneinfo directory is one that - # contains timezone files, a country code index file named iso3166.tab and a - # timezone index file named zone1970.tab or zone.tab. - class ZoneinfoDirectoryNotFound < StandardError - end - - # A DataSource that loads data from a 'zoneinfo' directory containing - # compiled "TZif" version 3 (or earlier) files in addition to iso3166.tab and - # zone1970.tab or zone.tab index files. - # - # To have TZInfo load the system zoneinfo files, call TZInfo::DataSource.set - # as follows: - # - # TZInfo::DataSource.set(:zoneinfo) - # - # To load zoneinfo files from a particular directory, pass the directory to - # TZInfo::DataSource.set: - # - # TZInfo::DataSource.set(:zoneinfo, directory) - # - # Note that the platform used at runtime may limit the range of available - # transition data that can be loaded from zoneinfo files. There are two - # factors to consider: - # - # First of all, the zoneinfo support in TZInfo makes use of Ruby's Time class. - # On 32-bit builds of Ruby 1.8, the Time class only supports 32-bit - # timestamps. This means that only Times between 1901-12-13 20:45:52 and - # 2038-01-19 03:14:07 can be represented. Furthermore, certain platforms only - # allow for positive 32-bit timestamps (notably Windows), making the earliest - # representable time 1970-01-01 00:00:00. - # - # 64-bit builds of Ruby 1.8 and all builds of Ruby 1.9 support 64-bit - # timestamps. This means that there is no practical restriction on the range - # of the Time class on these platforms. - # - # TZInfo will only load transitions that fall within the supported range of - # the Time class. Any queries performed on times outside of this range may - # give inaccurate results. - # - # The second factor concerns the zoneinfo files. Versions of the 'zic' tool - # (used to build zoneinfo files) that were released prior to February 2006 - # created zoneinfo files that used 32-bit integers for transition timestamps. - # Later versions of zic produce zoneinfo files that use 64-bit integers. If - # you have 32-bit zoneinfo files on your system, then any queries falling - # outside of the range 1901-12-13 20:45:52 to 2038-01-19 03:14:07 may be - # inaccurate. - # - # Most modern platforms include 64-bit zoneinfo files. However, Mac OS X (up - # to at least 10.8.4) still uses 32-bit zoneinfo files. - # - # To check whether your zoneinfo files contain 32-bit or 64-bit transition - # data, you can run the following code (substituting the identifier of the - # zone you want to test for zone_identifier): - # - # TZInfo::DataSource.set(:zoneinfo) - # dir = TZInfo::DataSource.get.zoneinfo_dir - # File.open(File.join(dir, zone_identifier), 'r') {|f| f.read(5) } - # - # If the last line returns "TZif\\x00", then you have a 32-bit zoneinfo file. - # If it returns "TZif2" or "TZif3" then you have a 64-bit zoneinfo file. - # - # If you require support for 64-bit transitions, but are restricted to 32-bit - # zoneinfo support, then you may want to consider using TZInfo::RubyDataSource - # instead. - class ZoneinfoDataSource < DataSource - # The default value of ZoneinfoDataSource.search_path. - DEFAULT_SEARCH_PATH = ['/usr/share/zoneinfo', '/usr/share/lib/zoneinfo', '/etc/zoneinfo'].freeze - - # The default value of ZoneinfoDataSource.alternate_iso3166_tab_search_path. - DEFAULT_ALTERNATE_ISO3166_TAB_SEARCH_PATH = ['/usr/share/misc/iso3166.tab', '/usr/share/misc/iso3166'].freeze - - # Paths to be checked to find the system zoneinfo directory. - @@search_path = DEFAULT_SEARCH_PATH.dup - - # Paths to possible alternate iso3166.tab files (used to locate the - # system-wide iso3166.tab files on FreeBSD and OpenBSD). - @@alternate_iso3166_tab_search_path = DEFAULT_ALTERNATE_ISO3166_TAB_SEARCH_PATH.dup - - # An Array of directories that will be checked to find the system zoneinfo - # directory. - # - # Directories are checked in the order they appear in the Array. - # - # The default value is ['/usr/share/zoneinfo', '/usr/share/lib/zoneinfo', '/etc/zoneinfo']. - def self.search_path - @@search_path - end - - # Sets the directories to be checked when locating the system zoneinfo - # directory. - # - # Can be set to an Array of directories or a String containing directories - # separated with File::PATH_SEPARATOR. - # - # Directories are checked in the order they appear in the Array or String. - # - # Set to nil to revert to the default paths. - def self.search_path=(search_path) - @@search_path = process_search_path(search_path, DEFAULT_SEARCH_PATH) - end - - # An Array of paths that will be checked to find an alternate iso3166.tab - # file if one was not included in the zoneinfo directory (for example, on - # FreeBSD and OpenBSD systems). - # - # Paths are checked in the order they appear in the array. - # - # The default value is ['/usr/share/misc/iso3166.tab', '/usr/share/misc/iso3166']. - def self.alternate_iso3166_tab_search_path - @@alternate_iso3166_tab_search_path - end - - # Sets the paths to check to locate an alternate iso3166.tab file if one was - # not included in the zoneinfo directory. - # - # Can be set to an Array of directories or a String containing directories - # separated with File::PATH_SEPARATOR. - # - # Paths are checked in the order they appear in the array. - # - # Set to nil to revert to the default paths. - def self.alternate_iso3166_tab_search_path=(alternate_iso3166_tab_search_path) - @@alternate_iso3166_tab_search_path = process_search_path(alternate_iso3166_tab_search_path, DEFAULT_ALTERNATE_ISO3166_TAB_SEARCH_PATH) - end - - # The zoneinfo directory being used. - attr_reader :zoneinfo_dir - - # Creates a new ZoneinfoDataSource. - # - # If zoneinfo_dir is specified, it will be checked and used as the source - # of zoneinfo files. - # - # The directory must contain a file named iso3166.tab and a file named - # either zone1970.tab or zone.tab. These may either be included in the root - # of the directory or in a 'tab' sub-directory and named 'country.tab' and - # 'zone_sun.tab' respectively (as is the case on Solaris. - # - # Additionally, the path to iso3166.tab can be overridden using the - # alternate_iso3166_tab_path parameter. - # - # InvalidZoneinfoDirectory will be raised if the iso3166.tab and - # zone1970.tab or zone.tab files cannot be found using the zoneinfo_dir and - # alternate_iso3166_tab_path parameters. - # - # If zoneinfo_dir is not specified or nil, the paths referenced in - # search_path are searched in order to find a valid zoneinfo directory - # (one that contains zone1970.tab or zone.tab and iso3166.tab files as - # above). - # - # The paths referenced in alternate_iso3166_tab_search_path are also - # searched to find an iso3166.tab file if one of the searched zoneinfo - # directories doesn't contain an iso3166.tab file. - # - # If no valid directory can be found by searching, ZoneinfoDirectoryNotFound - # will be raised. - def initialize(zoneinfo_dir = nil, alternate_iso3166_tab_path = nil) - if zoneinfo_dir - iso3166_tab_path, zone_tab_path = validate_zoneinfo_dir(zoneinfo_dir, alternate_iso3166_tab_path) - - unless iso3166_tab_path && zone_tab_path - raise InvalidZoneinfoDirectory, "#{zoneinfo_dir} is not a directory or doesn't contain a iso3166.tab file and a zone1970.tab or zone.tab file." - end - - @zoneinfo_dir = zoneinfo_dir - else - @zoneinfo_dir, iso3166_tab_path, zone_tab_path = find_zoneinfo_dir - - unless @zoneinfo_dir && iso3166_tab_path && zone_tab_path - raise ZoneinfoDirectoryNotFound, "None of the paths included in TZInfo::ZoneinfoDataSource.search_path are valid zoneinfo directories." - end - end - - @zoneinfo_dir = File.expand_path(@zoneinfo_dir).freeze - @timezone_index = load_timezone_index.freeze - @country_index = load_country_index(iso3166_tab_path, zone_tab_path).freeze - end - - # Returns a TimezoneInfo instance for a given identifier. - # Raises InvalidTimezoneIdentifier if the timezone is not found or the - # identifier is invalid. - def load_timezone_info(identifier) - begin - if @timezone_index.include?(identifier) - path = File.join(@zoneinfo_dir, identifier) - - # Untaint path rather than identifier. We don't want to modify - # identifier. identifier may also be frozen and therefore cannot be - # untainted. - path.untaint - - begin - ZoneinfoTimezoneInfo.new(identifier, path) - rescue InvalidZoneinfoFile => e - raise InvalidTimezoneIdentifier, e.message - end - else - raise InvalidTimezoneIdentifier, 'Invalid identifier' - end - rescue Errno::ENOENT, Errno::ENAMETOOLONG, Errno::ENOTDIR - raise InvalidTimezoneIdentifier, 'Invalid identifier' - rescue Errno::EACCES => e - raise InvalidTimezoneIdentifier, e.message - end - end - - # Returns an array of all the available timezone identifiers. - def timezone_identifiers - @timezone_index - end - - # Returns an array of all the available timezone identifiers for - # data timezones (i.e. those that actually contain definitions). - # - # For ZoneinfoDataSource, this will always be identical to - # timezone_identifers. - def data_timezone_identifiers - @timezone_index - end - - # Returns an array of all the available timezone identifiers that - # are links to other timezones. - # - # For ZoneinfoDataSource, this will always be an empty array. - def linked_timezone_identifiers - [].freeze - end - - # Returns a CountryInfo instance for the given ISO 3166-1 alpha-2 - # country code. Raises InvalidCountryCode if the country could not be found - # or the code is invalid. - def load_country_info(code) - info = @country_index[code] - raise InvalidCountryCode, 'Invalid country code' unless info - info - end - - # Returns an array of all the available ISO 3166-1 alpha-2 - # country codes. - def country_codes - @country_index.keys.freeze - end - - # Returns the name and information about this DataSource. - def to_s - "Zoneinfo DataSource: #{@zoneinfo_dir}" - end - - # Returns internal object state as a programmer-readable string. - def inspect - "#<#{self.class}: #{@zoneinfo_dir}>" - end - - private - - # Processes a path for use as the search_path or - # alternate_iso3166_tab_search_path. - def self.process_search_path(path, default) - if path - if path.kind_of?(String) - path.split(File::PATH_SEPARATOR) - else - path.collect {|p| p.to_s} - end - else - default.dup - end - end - - # Validates a zoneinfo directory and returns the paths to the iso3166.tab - # and zone1970.tab or zone.tab files if valid. If the directory is not - # valid, returns nil. - # - # The path to the iso3166.tab file may be overriden by passing in a path. - # This is treated as either absolute or relative to the current working - # directory. - def validate_zoneinfo_dir(path, iso3166_tab_path = nil) - if File.directory?(path) - if iso3166_tab_path - return nil unless File.file?(iso3166_tab_path) - else - iso3166_tab_path = resolve_tab_path(path, ['iso3166.tab'], 'country.tab') - return nil unless iso3166_tab_path - end - - zone_tab_path = resolve_tab_path(path, ['zone1970.tab', 'zone.tab'], 'zone_sun.tab') - return nil unless zone_tab_path - - [iso3166_tab_path, zone_tab_path] - else - nil - end - end - - # Attempts to resolve the path to a tab file given its standard names and - # tab sub-directory name (as used on Solaris). - def resolve_tab_path(zoneinfo_path, standard_names, tab_name) - standard_names.each do |standard_name| - path = File.join(zoneinfo_path, standard_name) - return path if File.file?(path) - end - - path = File.join(zoneinfo_path, 'tab', tab_name) - return path if File.file?(path) - - nil - end - - # Finds a zoneinfo directory using search_path and - # alternate_iso3166_tab_search_path. Returns the paths to the directory, - # the iso3166.tab file and the zone.tab file or nil if not found. - def find_zoneinfo_dir - alternate_iso3166_tab_path = self.class.alternate_iso3166_tab_search_path.detect do |path| - File.file?(path) - end - - self.class.search_path.each do |path| - # Try without the alternate_iso3166_tab_path first. - iso3166_tab_path, zone_tab_path = validate_zoneinfo_dir(path) - return path, iso3166_tab_path, zone_tab_path if iso3166_tab_path && zone_tab_path - - if alternate_iso3166_tab_path - iso3166_tab_path, zone_tab_path = validate_zoneinfo_dir(path, alternate_iso3166_tab_path) - return path, iso3166_tab_path, zone_tab_path if iso3166_tab_path && zone_tab_path - end - end - - # Not found. - nil - end - - # Scans @zoneinfo_dir and returns an Array of available timezone - # identifiers. - def load_timezone_index - index = [] - - # Ignoring particular files: - # +VERSION is included on Mac OS X. - # leapseconds is a list of leap seconds. - # localtime is the current local timezone (may be a link). - # posix, posixrules and right are directories containing other versions of the zoneinfo files. - # src is a directory containing the tzdata source included on Solaris. - # timeconfig is a symlink included on Slackware. - - enum_timezones(nil, ['+VERSION', 'leapseconds', 'localtime', 'posix', 'posixrules', 'right', 'src', 'timeconfig']) do |identifier| - index << identifier - end - - index.sort - end - - # Recursively scans a directory of timezones, calling the passed in block - # for each identifier found. - def enum_timezones(dir, exclude = [], &block) - Dir.foreach(dir ? File.join(@zoneinfo_dir, dir) : @zoneinfo_dir) do |entry| - unless entry =~ /\./ || exclude.include?(entry) - entry.untaint - path = dir ? File.join(dir, entry) : entry - full_path = File.join(@zoneinfo_dir, path) - - if File.directory?(full_path) - enum_timezones(path, [], &block) - elsif File.file?(full_path) - yield path - end - end - end - end - - # Uses the iso3166.tab and zone1970.tab or zone.tab files to build an index - # of the available countries and their timezones. - def load_country_index(iso3166_tab_path, zone_tab_path) - - # Handle standard 3 to 4 column zone.tab files as well as the 4 to 5 - # column format used by Solaris. - # - # On Solaris, an extra column before the comment gives an optional - # linked/alternate timezone identifier (or '-' if not set). - # - # Additionally, there is a section at the end of the file for timezones - # covering regions. These are given lower-case "country" codes. The timezone - # identifier column refers to a continent instead of an identifier. These - # lines will be ignored by TZInfo. - # - # Since the last column is optional in both formats, testing for the - # Solaris format is done in two passes. The first pass identifies if there - # are any lines using 5 columns. - - - # The first column is allowed to be a comma separated list of country - # codes, as used in zone1970.tab (introduced in tzdata 2014f). - # - # The first country code in the comma-separated list is the country that - # contains the city the zone identifer is based on. The first country - # code on each line is considered to be primary with the others - # secondary. - # - # The zones for each country are ordered primary first, then secondary. - # Within the primary and secondary groups, the zones are ordered by their - # order in the file. - - file_is_5_column = false - zone_tab = [] - - RubyCoreSupport.open_file(zone_tab_path, 'r', :external_encoding => 'UTF-8', :internal_encoding => 'UTF-8') do |file| - file.each_line do |line| - line.chomp! - - if line =~ /\A([A-Z]{2}(?:,[A-Z]{2})*)\t(?:([+\-])(\d{2})(\d{2})([+\-])(\d{3})(\d{2})|([+\-])(\d{2})(\d{2})(\d{2})([+\-])(\d{3})(\d{2})(\d{2}))\t([^\t]+)(?:\t([^\t]+))?(?:\t([^\t]+))?\z/ - codes = $1 - - if $2 - latitude = dms_to_rational($2, $3, $4) - longitude = dms_to_rational($5, $6, $7) - else - latitude = dms_to_rational($8, $9, $10, $11) - longitude = dms_to_rational($12, $13, $14, $15) - end - - zone_identifier = $16 - column4 = $17 - column5 = $18 - - file_is_5_column = true if column5 - - zone_tab << [codes.split(','.freeze), zone_identifier, latitude, longitude, column4, column5] - end - end - end - - primary_zones = {} - secondary_zones = {} - - zone_tab.each do |codes, zone_identifier, latitude, longitude, column4, column5| - description = file_is_5_column ? column5 : column4 - country_timezone = CountryTimezone.new(zone_identifier, latitude, longitude, description) - - # codes will always have at least one element - - (primary_zones[codes.first] ||= []) << country_timezone - - codes[1..-1].each do |code| - (secondary_zones[code] ||= []) << country_timezone - end - end - - countries = {} - - RubyCoreSupport.open_file(iso3166_tab_path, 'r', :external_encoding => 'UTF-8', :internal_encoding => 'UTF-8') do |file| - file.each_line do |line| - line.chomp! - - # Handle both the two column alpha-2 and name format used in the tz - # database as well as the 4 column alpha-2, alpha-3, numeric-3 and - # name format used by FreeBSD and OpenBSD. - - if line =~ /\A([A-Z]{2})(?:\t[A-Z]{3}\t[0-9]{3})?\t(.+)\z/ - code = $1 - name = $2 - zones = (primary_zones[code] || []) + (secondary_zones[code] || []) - - countries[code] = ZoneinfoCountryInfo.new(code, name, zones) - end - end - end - - countries - end - - # Converts degrees, minutes and seconds to a Rational. - def dms_to_rational(sign, degrees, minutes, seconds = nil) - result = degrees.to_i + Rational(minutes.to_i, 60) - result += Rational(seconds.to_i, 3600) if seconds - result = -result if sign == '-'.freeze - result - end - end -end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo/zoneinfo_timezone_info.rb ruby-tzinfo-2.0.4/lib/tzinfo/zoneinfo_timezone_info.rb --- ruby-tzinfo-1.2.6/lib/tzinfo/zoneinfo_timezone_info.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo/zoneinfo_timezone_info.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,298 +0,0 @@ -module TZInfo - using RubyCoreSupport::UntaintExt if RubyCoreSupport.const_defined?(:UntaintExt) - - # An InvalidZoneinfoFile exception is raised if an attempt is made to load an - # invalid zoneinfo file. - class InvalidZoneinfoFile < StandardError - end - - # Represents a timezone defined by a compiled zoneinfo TZif (\0, 2 or 3) file. - # - # @private - class ZoneinfoTimezoneInfo < TransitionDataTimezoneInfo #:nodoc: - - # Minimum supported timestamp (inclusive). - # - # Time.utc(1700, 1, 1).to_i - MIN_TIMESTAMP = -8520336000 - - # Maximum supported timestamp (exclusive). - # - # Time.utc(2500, 1, 1).to_i - MAX_TIMESTAMP = 16725225600 - - # Constructs the new ZoneinfoTimezoneInfo with an identifier and path - # to the file. - def initialize(identifier, file_path) - super(identifier) - - File.open(file_path, 'rb') do |file| - parse(file) - end - end - - private - # Unpack will return unsigned 32-bit integers. Translate to - # signed 32-bit. - def make_signed_int32(long) - long >= 0x80000000 ? long - 0x100000000 : long - end - - # Unpack will return a 64-bit integer as two unsigned 32-bit integers - # (most significant first). Translate to signed 64-bit - def make_signed_int64(high, low) - unsigned = (high << 32) | low - unsigned >= 0x8000000000000000 ? unsigned - 0x10000000000000000 : unsigned - end - - # Read bytes from file and check that the correct number of bytes could - # be read. Raises InvalidZoneinfoFile if the number of bytes didn't match - # the number requested. - def check_read(file, bytes) - result = file.read(bytes) - - unless result && result.length == bytes - raise InvalidZoneinfoFile, "Expected #{bytes} bytes reading '#{file.path}', but got #{result ? result.length : 0} bytes" - end - - result - end - - # Zoneinfo files don't include the offset from standard time (std_offset) - # for DST periods. Derive the base offset (utc_offset) where DST is - # observed from either the previous or next non-DST period. - # - # Returns the index of the offset to be used prior to the first - # transition. - def derive_offsets(transitions, offsets) - # The first non-DST offset (if there is one) is the offset observed - # before the first transition. Fallback to the first DST offset if there - # are no non-DST offsets. - first_non_dst_offset_index = offsets.index {|o| !o[:is_dst] } - first_offset_index = first_non_dst_offset_index || 0 - return first_offset_index if transitions.empty? - - # Determine the utc_offset of the next non-dst offset at each transition. - utc_offset_from_next = nil - - transitions.reverse_each do |transition| - offset = offsets[transition[:offset]] - if offset[:is_dst] - transition[:utc_offset_from_next] = utc_offset_from_next if utc_offset_from_next - else - utc_offset_from_next = offset[:utc_total_offset] - end - end - - utc_offset_from_previous = first_non_dst_offset_index ? offsets[first_non_dst_offset_index][:utc_total_offset] : nil - defined_offsets = {} - - transitions.each do |transition| - offset_index = transition[:offset] - offset = offsets[offset_index] - utc_total_offset = offset[:utc_total_offset] - - if offset[:is_dst] - utc_offset_from_next = transition[:utc_offset_from_next] - - difference_to_previous = (utc_total_offset - (utc_offset_from_previous || utc_total_offset)).abs - difference_to_next = (utc_total_offset - (utc_offset_from_next || utc_total_offset)).abs - - utc_offset = if difference_to_previous == 3600 - utc_offset_from_previous - elsif difference_to_next == 3600 - utc_offset_from_next - elsif difference_to_previous > 0 && difference_to_next > 0 - difference_to_previous < difference_to_next ? utc_offset_from_previous : utc_offset_from_next - elsif difference_to_previous > 0 - utc_offset_from_previous - elsif difference_to_next > 0 - utc_offset_from_next - else - # No difference, assume a 1 hour offset from standard time. - utc_total_offset - 3600 - end - - if !offset[:utc_offset] - offset[:utc_offset] = utc_offset - defined_offsets[offset] = offset_index - elsif offset[:utc_offset] != utc_offset - # An earlier transition has already derived a different - # utc_offset. Define a new offset or reuse an existing identically - # defined offset. - new_offset = offset.dup - new_offset[:utc_offset] = utc_offset - - offset_index = defined_offsets[new_offset] - - unless offset_index - offsets << new_offset - offset_index = offsets.length - 1 - defined_offsets[new_offset] = offset_index - end - - transition[:offset] = offset_index - end - else - utc_offset_from_previous = utc_total_offset - end - end - - first_offset_index - end - - # Defines an offset for the timezone based on the given index and offset - # Hash. - def define_offset(index, offset) - utc_total_offset = offset[:utc_total_offset] - utc_offset = offset[:utc_offset] - - if utc_offset - # DST offset with base utc_offset derived by derive_offsets. - std_offset = utc_total_offset - utc_offset - elsif offset[:is_dst] - # DST offset unreferenced by a transition (offset in use before the - # first transition). No derived base UTC offset, so assume 1 hour - # DST. - utc_offset = utc_total_offset - 3600 - std_offset = 3600 - else - # Non-DST offset. - utc_offset = utc_total_offset - std_offset = 0 - end - - offset index, utc_offset, std_offset, offset[:abbr].untaint.to_sym - end - - # Parses a zoneinfo file and intializes the DataTimezoneInfo structures. - def parse(file) - magic, version, ttisgmtcnt, ttisstdcnt, leapcnt, timecnt, typecnt, charcnt = - check_read(file, 44).unpack('a4 a x15 NNNNNN') - - if magic != 'TZif' - raise InvalidZoneinfoFile, "The file '#{file.path}' does not start with the expected header." - end - - if (version == '2' || version == '3') && RubyCoreSupport.time_supports_64bit - # Skip the first 32-bit section and read the header of the second 64-bit section - file.seek(timecnt * 5 + typecnt * 6 + charcnt + leapcnt * 8 + ttisgmtcnt + ttisstdcnt, IO::SEEK_CUR) - - prev_version = version - - magic, version, ttisgmtcnt, ttisstdcnt, leapcnt, timecnt, typecnt, charcnt = - check_read(file, 44).unpack('a4 a x15 NNNNNN') - - unless magic == 'TZif' && (version == prev_version) - raise InvalidZoneinfoFile, "The file '#{file.path}' contains an invalid 64-bit section header." - end - - using_64bit = true - elsif version != '3' && version != '2' && version != "\0" - raise InvalidZoneinfoFile, "The file '#{file.path}' contains a version of the zoneinfo format that is not currently supported." - else - using_64bit = false - end - - unless leapcnt == 0 - raise InvalidZoneinfoFile, "The zoneinfo file '#{file.path}' contains leap second data. TZInfo requires zoneinfo files that omit leap seconds." - end - - transitions = [] - - if using_64bit - timecnt.times do |i| - high, low = check_read(file, 8).unpack('NN'.freeze) - transition_time = make_signed_int64(high, low) - transitions << {:at => transition_time} - end - else - timecnt.times do |i| - transition_time = make_signed_int32(check_read(file, 4).unpack('N'.freeze)[0]) - transitions << {:at => transition_time} - end - end - - timecnt.times do |i| - localtime_type = check_read(file, 1).unpack('C'.freeze)[0] - transitions[i][:offset] = localtime_type - end - - offsets = [] - - typecnt.times do |i| - gmtoff, isdst, abbrind = check_read(file, 6).unpack('NCC'.freeze) - gmtoff = make_signed_int32(gmtoff) - isdst = isdst == 1 - offset = {:utc_total_offset => gmtoff, :is_dst => isdst, :abbr_index => abbrind} - - unless isdst - offset[:utc_offset] = gmtoff - offset[:std_offset] = 0 - end - - offsets << offset - end - - abbrev = check_read(file, charcnt) - - offsets.each do |o| - abbrev_start = o[:abbr_index] - raise InvalidZoneinfoFile, "Abbreviation index is out of range in file '#{file.path}'" unless abbrev_start < abbrev.length - - abbrev_end = abbrev.index("\0", abbrev_start) - raise InvalidZoneinfoFile, "Missing abbreviation null terminator in file '#{file.path}'" unless abbrev_end - - o[:abbr] = RubyCoreSupport.force_encoding(abbrev[abbrev_start...abbrev_end], 'UTF-8') - end - - transitions.each do |t| - if t[:offset] < 0 || t[:offset] >= offsets.length - raise InvalidZoneinfoFile, "Invalid offset referenced by transition in file '#{file.path}'." - end - end - - # Derive the offsets from standard time (std_offset). - first_offset_index = derive_offsets(transitions, offsets) - - define_offset(first_offset_index, offsets[first_offset_index]) - - offsets.each_with_index do |o, i| - define_offset(i, o) unless i == first_offset_index - end - - if !using_64bit && !RubyCoreSupport.time_supports_negative - # Filter out transitions that are not supported by Time on this - # platform. - - # Move the last transition before the epoch up to the epoch. This - # allows for accurate conversions for all supported timestamps on the - # platform. - - before_epoch, after_epoch = transitions.partition {|t| t[:at] < 0} - - if before_epoch.length > 0 && after_epoch.length > 0 && after_epoch.first[:at] != 0 - last_before = before_epoch.last - last_before[:at] = 0 - transitions = [last_before] + after_epoch - else - transitions = after_epoch - end - end - - # Ignore transitions that occur outside of a defined window. The - # transition index cannot handle a large range of transition times. - # - # This is primarily intended to ignore the far in the past transition - # added in zic 2014c (at timestamp -2**63 in zic 2014c and at the - # approximate time of the big bang from zic 2014d). - transitions.each do |t| - at = t[:at] - if at >= MIN_TIMESTAMP && at < MAX_TIMESTAMP - time = Time.at(at).utc - transition time.year, time.mon, t[:offset], at - end - end - end - end -end diff -Nru ruby-tzinfo-1.2.6/lib/tzinfo.rb ruby-tzinfo-2.0.4/lib/tzinfo.rb --- ruby-tzinfo-1.2.6/lib/tzinfo.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/lib/tzinfo.rb 2020-12-30 06:49:15.000000000 +0000 @@ -1,40 +1,73 @@ -# Top level module for TZInfo. +# encoding: UTF-8 +# frozen_string_literal: true + +# The top level module for TZInfo. module TZInfo end -require 'tzinfo/ruby_core_support' -require 'tzinfo/offset_rationals' -require 'tzinfo/time_or_datetime' - -require 'tzinfo/timezone_definition' - -require 'tzinfo/timezone_offset' -require 'tzinfo/timezone_transition' -require 'tzinfo/timezone_transition_definition' - -require 'tzinfo/timezone_index_definition' - -require 'tzinfo/timezone_info' -require 'tzinfo/data_timezone_info' -require 'tzinfo/linked_timezone_info' -require 'tzinfo/transition_data_timezone_info' -require 'tzinfo/zoneinfo_timezone_info' - -require 'tzinfo/data_source' -require 'tzinfo/ruby_data_source' -require 'tzinfo/zoneinfo_data_source' - -require 'tzinfo/timezone_period' -require 'tzinfo/timezone' -require 'tzinfo/info_timezone' -require 'tzinfo/data_timezone' -require 'tzinfo/linked_timezone' -require 'tzinfo/timezone_proxy' - -require 'tzinfo/country_index_definition' -require 'tzinfo/country_info' -require 'tzinfo/ruby_country_info' -require 'tzinfo/zoneinfo_country_info' +# Object#untaint is a deprecated no-op in Ruby >= 2.7 and will be removed in +# 3.2. Add a refinement to either silence the warning, or supply the method if +# needed. +if !Object.new.respond_to?(:untaint) || RUBY_VERSION =~ /\A(\d+)\.(\d+)(?:\.|\z)/ && ($1 == '2' && $2.to_i >= 7 || $1.to_i >= 3) + require_relative 'tzinfo/untaint_ext' +end + +require_relative 'tzinfo/version' + +require_relative 'tzinfo/string_deduper' + +require_relative 'tzinfo/timestamp' -require 'tzinfo/country' -require 'tzinfo/country_timezone' +require_relative 'tzinfo/with_offset' +require_relative 'tzinfo/datetime_with_offset' +require_relative 'tzinfo/time_with_offset' +require_relative 'tzinfo/timestamp_with_offset' + +require_relative 'tzinfo/timezone_offset' +require_relative 'tzinfo/timezone_transition' +require_relative 'tzinfo/transition_rule' +require_relative 'tzinfo/annual_rules' + +require_relative 'tzinfo/data_sources' +require_relative 'tzinfo/data_sources/timezone_info' +require_relative 'tzinfo/data_sources/data_timezone_info' +require_relative 'tzinfo/data_sources/linked_timezone_info' +require_relative 'tzinfo/data_sources/constant_offset_data_timezone_info' +require_relative 'tzinfo/data_sources/transitions_data_timezone_info' + +require_relative 'tzinfo/data_sources/country_info' + +require_relative 'tzinfo/data_sources/posix_time_zone_parser' +require_relative 'tzinfo/data_sources/zoneinfo_reader' + +require_relative 'tzinfo/data_source' +require_relative 'tzinfo/data_sources/ruby_data_source' +require_relative 'tzinfo/data_sources/zoneinfo_data_source' + +require_relative 'tzinfo/timezone_period' +require_relative 'tzinfo/offset_timezone_period' +require_relative 'tzinfo/transitions_timezone_period' +require_relative 'tzinfo/timezone' +require_relative 'tzinfo/info_timezone' +require_relative 'tzinfo/data_timezone' +require_relative 'tzinfo/linked_timezone' +require_relative 'tzinfo/timezone_proxy' + +require_relative 'tzinfo/country' +require_relative 'tzinfo/country_timezone' + +require_relative 'tzinfo/format2' +require_relative 'tzinfo/format2/country_definer' +require_relative 'tzinfo/format2/country_index_definer' +require_relative 'tzinfo/format2/country_index_definition' +require_relative 'tzinfo/format2/timezone_definer' +require_relative 'tzinfo/format2/timezone_definition' +require_relative 'tzinfo/format2/timezone_index_definer' +require_relative 'tzinfo/format2/timezone_index_definition' + +require_relative 'tzinfo/format1' +require_relative 'tzinfo/format1/country_definer' +require_relative 'tzinfo/format1/country_index_definition' +require_relative 'tzinfo/format1/timezone_definer' +require_relative 'tzinfo/format1/timezone_definition' +require_relative 'tzinfo/format1/timezone_index_definition' diff -Nru ruby-tzinfo-1.2.6/LICENSE ruby-tzinfo-2.0.4/LICENSE --- ruby-tzinfo-1.2.6/LICENSE 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/LICENSE 2020-12-30 06:49:15.000000000 +0000 @@ -1,19 +1,19 @@ -Copyright (c) 2005-2019 Philip Ross +Copyright (c) 2005-2020 Philip Ross -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Binary files /tmp/tmp1__nrbj3/6KS5sjn70P/ruby-tzinfo-1.2.6/metadata.gz.sig and /tmp/tmp1__nrbj3/8QcohKxo2Z/ruby-tzinfo-2.0.4/metadata.gz.sig differ diff -Nru ruby-tzinfo-1.2.6/Rakefile ruby-tzinfo-2.0.4/Rakefile --- ruby-tzinfo-1.2.6/Rakefile 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/Rakefile 1970-01-01 00:00:00.000000000 +0000 @@ -1,107 +0,0 @@ -require 'rubygems' -require 'rubygems/package_task' -require 'fileutils' -require 'rake/testtask' - -# Ignore errors loading rdoc/task (the rdoc tasks will be excluded if -# rdoc is unavailable). -begin - require 'rdoc/task' -rescue LoadError, RuntimeError -end - -BASE_DIR = File.expand_path(File.dirname(__FILE__)) - -task :default => [:test] - -spec = eval(File.read('tzinfo.gemspec')) - -class TZInfoPackageTask < Gem::PackageTask - alias_method :orig_sh, :sh - private :orig_sh - - def sh(*cmd, &block) - if cmd[0] == '__tar_with_owner__' && cmd[1] =~ /\A-?[zjcvf]+\z/ - opts = cmd[1] - cmd = ['tar', 'c', '--owner', '0', '--group', '0', "#{opts.start_with?('-') ? '' : '-'}#{opts.gsub('c', '')}"] + cmd.drop(2) - elsif cmd.first =~ /\A__tar_with_owner__ -?([zjcvf]+)(.*)\z/ - opts = $1 - args = $2 - cmd[0] = "tar c --owner 0 --group 0 -#{opts.gsub('c', '')}#{args}" - end - - orig_sh(*cmd, &block) - end -end - -def add_signing_key(spec) - # Attempt to find the private key and add options to sign the gem if found. - private_key_path = File.expand_path(File.join(BASE_DIR, '..', 'key', 'gem-private_key.pem')) - - if File.exist?(private_key_path) - spec = spec.clone - spec.signing_key = private_key_path - spec.cert_chain = [File.join(BASE_DIR, 'gem-public_cert.pem')] - else - puts 'WARNING: Private key not found. Not signing gem file.' - end - - spec -end - -package_task = TZInfoPackageTask.new(add_signing_key(spec)) do |pkg| - pkg.need_zip = true - pkg.need_tar_gz = true - pkg.tar_command = '__tar_with_owner__' -end - -# Skip the rdoc task if RDoc::Task is unavailable -if defined?(RDoc) && defined?(RDoc::Task) - RDoc::Task.new do |rdoc| - rdoc.rdoc_dir = 'doc' - rdoc.options.concat spec.rdoc_options - rdoc.rdoc_files.include(spec.extra_rdoc_files) - rdoc.rdoc_files.include('lib') - end -end - -Rake::Task[package_task.package_dir_path].enhance do - recurse_chmod(package_task.package_dir_path) -end - -Rake::Task[:package].enhance do - FileUtils.rm_rf(package_task.package_dir_path) -end - -def recurse_chmod(dir) - File.chmod(0755, dir) - - Dir.entries(dir).each do |entry| - if entry != '.' && entry != '..' - path = File.join(dir, entry) - if File.directory?(path) - recurse_chmod(path) - else - File.chmod(0644, path) - end - end - end -end - -desc 'Run tests using RubyDataSource, then ZoneinfoDataSource' -task :test => [:test_ruby, :test_zoneinfo] do -end - -def setup_tests(test_task, type) - test_task.libs = [File.join(BASE_DIR, 'lib')] - test_task.pattern = File.join(BASE_DIR, 'test', "ts_all_#{type}.rb") - test_task.warning = true -end - -Rake::TestTask.new(:test_ruby) do |t| - setup_tests(t, :ruby) -end - -Rake::TestTask.new(:test_zoneinfo) do |t| - setup_tests(t, :zoneinfo) -end diff -Nru ruby-tzinfo-1.2.6/README.md ruby-tzinfo-2.0.4/README.md --- ruby-tzinfo-1.2.6/README.md 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/README.md 2020-12-30 06:49:15.000000000 +0000 @@ -1,152 +1,406 @@ -TZInfo - Ruby Timezone Library -============================== +# TZInfo - Ruby Time Zone Library -[![Gem Version](https://badge.fury.io/rb/tzinfo.svg)](http://badge.fury.io/rb/tzinfo) [![Build Status](https://travis-ci.org/tzinfo/tzinfo.svg?branch=master)](https://travis-ci.org/tzinfo/tzinfo) +[![RubyGems](https://img.shields.io/gem/v/tzinfo)](https://rubygems.org/gems/tzinfo) [![Travis CI Build](https://img.shields.io/travis/com/tzinfo/tzinfo?logo=travis)](https://travis-ci.com/github/tzinfo/tzinfo) [![AppVeyor Build](https://img.shields.io/appveyor/build/philr/tzinfo?logo=appveyor)](https://ci.appveyor.com/project/philr/tzinfo) -[TZInfo](http://tzinfo.github.io) provides daylight savings aware -transformations between times in different timezones. +[TZInfo](https://tzinfo.github.io) is a Ruby library that provides access to +time zone data and allows times to be converted using time zone rules. -Data Sources ------------- +## Data Sources -TZInfo requires a source of timezone data. There are two built-in options: +TZInfo requires a source of time zone data. There are two options: -1. The TZInfo::Data library (the tzinfo-data gem). TZInfo::Data contains a set - of Ruby modules that are generated from the [IANA Time Zone Database](http://www.iana.org/time-zones). -2. A zoneinfo directory. Most Unix-like systems include a zoneinfo directory - containing timezone definitions. These are also generated from the - [IANA Time Zone Database](http://www.iana.org/time-zones). +1. A zoneinfo directory containing timezone definition files. These files are + generated from the [IANA Time Zone Database](https://www.iana.org/time-zones) + using the `zic` utility. Most Unix-like systems include a zoneinfo directory. +2. The TZInfo::Data library (the tzinfo-data gem). TZInfo::Data contains a set + of Ruby modules that are also generated from the IANA Time Zone Database. -By default, TZInfo::Data will be used. If TZInfo::Data is not available (i.e. -if `require 'tzinfo/data'` fails), then TZInfo will search for a zoneinfo -directory instead (using the search path specified by +By default, TZInfo will attempt to use TZInfo::Data. If TZInfo::Data is not +available (i.e. if `require 'tzinfo/data'` fails), then TZInfo will search for a +zoneinfo directory instead (using the search path specified by `TZInfo::ZoneinfoDataSource::DEFAULT_SEARCH_PATH`). If no data source can be found, a `TZInfo::DataSourceNotFound` exception will be -raised when TZInfo is used. Further information is available -[in the wiki](http://tzinfo.github.io/datasourcenotfound) to help with -resolving `TZInfo::DataSourceNotFound` errors. +raised when TZInfo is used. Further information is available +[in the wiki](https://tzinfo.github.io/datasourcenotfound) to help resolve +`TZInfo::DataSourceNotFound` errors. -The default data source selection can be overridden using +The default data source selection can be overridden by calling `TZInfo::DataSource.set`. -Custom data sources can also be used. See `TZInfo::DataSource.set` for -further details. +Custom data sources can also be used. See the `TZInfo::DataSource.set` +documentation for further details. -Installation ------------- +## Installation -The TZInfo gem can be installed by running: - - gem install tzinfo +The TZInfo gem can be installed by running `gem install tzinfo` or by adding +to `gem 'tzinfo'` to your `Gemfile` and running `bundle install`. To use the Ruby modules as the data source, TZInfo::Data will also need to be -installed: +installed by running `gem install tzinfo-data` or by adding `gem 'tzinfo-data'` +to your `Gemfile`. + - gem install tzinfo-data - +## IANA Time Zone Database -Example Usage -------------- +The data returned and used by TZInfo is sourced from the +[IANA Time Zone Database](http://www.iana.org/time-zones). The +[Theory and pragmatics of the tz code and data](https://data.iana.org/time-zones/theory.html) +document gives details of how the data is organized and managed. + + +## Example Usage + +To use TZInfo, it must first be required with: + +```ruby +require 'tzinfo' +``` + +The `TZInfo::Timezone` class provides access to time zone data and methods for +converting times. + +The `all_identifiers` method returns a list of valid time zone identifiers: + +```ruby +identifiers = TZInfo::Timezone.all_identifiers +# => ["Africa/Adibdjan", "Africa/Accra", ..., "Zulu"] +``` + +A `TZInfo::Timezone` instance representing an individual time zone can be +obtained with `TZInfo::Timezone.get`: + +```ruby +tz = TZInfo::Timezone.get('America/New_York') +# => # +``` + +A time can be converted to the local time of the time zone with `to_local`: + +```ruby +tz.to_local(Time.utc(2018, 2, 1, 12, 30, 0)) +# => 2018-02-01 07:30:00 -0500 +tz.to_local(Time.utc(2018, 7, 1, 12, 30, 0)) +# => 2018-07-01 08:30:00 -0400 +tz.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 constructed +with `local_time`: + +```ruby +tz.local_time(2018, 2, 1, 7, 30, 0) +# => 2018-02-01 07:30:00 -0500 +tz.local_time(2018, 7, 1, 8, 30, 0) +# => 2018-07-01 08:30:00 -0400 +``` + +Local times can be converted to UTC by using `local_time` and calling `utc` on +the result: + +```ruby +tz.local_time(2018, 2, 1, 7, 30, 0).utc +# => 2018-02-01 12:30:00 UTC +tz.local_time(2018, 7, 1, 8, 30, 0).utc +# => 2018-07-01 12:30:00 UTC +``` + +The `local_to_utc` method can also be used to convert a time object to UTC. The +offset of the time is ignored - it is treated as if it were a local time for the +time zone: + +```ruby +tz.local_to_utc(Time.utc(2018, 2, 1, 7, 30, 0)) +# => 2018-02-01 12:30:00 UTC +tz.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: + +```ruby +local_time = tz.to_local(Time.utc(2018, 2, 1, 12, 30, 0)) +local_time.utc_offset # => -18000 +local_time.dst? # => false +local_time.zone # => "EST" + +local_time = tz.to_local(Time.utc(2018, 7, 1, 12, 30, 0)) +local_time.utc_offset # => -14400 +local_time.dst? # => true +local_time.zone # => "EDT" +``` + +Time zone information can be included when formatting times with `strftime` +using the `%z` and `%Z` directives: + +```ruby +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" +``` + +The `period_for` method can be used to obtain information about the observed +time zone information at a particular time as a `TZInfo::TimezonePeriod` object: + +```ruby +period = tz.period_for(Time.utc(2018, 7, 1, 12, 30, 0)) +period.base_utc_offset # => -18000 +period.std_offset # => 3600 +period.observed_utc_offset # => -14400 +period.abbreviation # => "EDT" +period.dst? # => true +period.local_starts_at.to_time # => 2018-03-11 03:00:00 -0400 +period.local_ends_at.to_time # => 2018-11-04 02:00:00 -0400 +``` + +A list of transitions between periods where different rules are observed can be +obtained with the `transitions_up_to` method. The result is returned as an +`Array` of `TZInfo::TimezoneTransition` objects: + +```ruby +transitions = tz.transitions_up_to(Time.utc(2019, 1, 1), Time.utc(2017, 1, 1)) +transitions.map do |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 the +`offsets_up_to` method. The result is returned as an `Array` of +`TZInfo::TimezoneOffset` objects: + +```ruby +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"]] +``` + +All `TZInfo::Timezone` methods that accept a time as a parameter can be used +with either instances of `Time`, `DateTime` or `TZInfo::Timestamp`. Arbitrary +`Time`-like objects that respond to both `to_i` and `subsec` and optionally +`utc_offset` will be treated as if they are instances of `Time`. + +`TZInfo::Timezone` methods that both accept and return times will return an +object with a type matching that of the parameter (actually a +`TZInfo::TimeWithOffset`, `TZInfo::DateTimeWithOffset` or +`TZInfo::TimestampWithOffset` subclass when returning a local time): + +```ruby +tz.to_local(Time.utc(2018, 7, 1, 12, 30, 0)) +# => 2018-07-01 08:30:00 -0400 +tz.to_local(DateTime.new(2018, 7, 1, 12, 30, 0)) +# => # +tz.to_local(TZInfo::Timestamp.create(2018, 7, 1, 12, 30, 0, 0, :utc)) +# => # +``` + +In addition to `local_time`, which returns `Time` instances, the +`local_datetime` and `local_timestamp` methods can be used to construct local +`DateTime` and `TZInfo::Timestamp` instances with the appropriate offset: + +```ruby +tz.local_time(2018, 2, 1, 7, 30, 0) +# => 2018-02-01 07:30:00 -0500 +tz.local_datetime(2018, 2, 1, 7, 30, 0) +# => # +tz.local_timestamp(2018, 2, 1, 7, 30, 0) +# => # +``` + +The `local_to_utc`, `local_time`, `local_datetime` and `local_timestamp` methods +may raise a `TZInfo::PeriodNotFound` or a `TZInfo::AmbiguousTime` exception. +`TZInfo::PeriodNotFound` signals that there is no equivalent UTC time (for +example, during the transition from standard time to daylight savings time when +the clocks are moved forward and an hour is skipped). `TZInfo::AmbiguousTime` +signals that there is more than one equivalent UTC time (for example, during the +transition from daylight savings time to standard time where the clocks are +moved back and an hour is repeated): + +```ruby +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: + +```ruby +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 the `dst` +parameter and/or specifying a block to choose one of the interpretations: + +```ruby +tz.local_time(2018, 11, 4, 1, 30, 0, 0, true) +# => 2018-11-04 01:30:00 -0400 +tz.local_time(2018, 11, 4, 1, 30, 0, 0, false) +# => 2018-11-04 01:30:00 -0500 + +tz.local_time(2018, 11, 4, 1, 30, 0, 0) {|p| p.first } +# => 2018-11-04 01:30:00 -0400 +tz.local_time(2018, 11, 4, 1, 30, 0, 0) {|p| p.last } +# => 2018-11-04 01:30:00 -0500 +``` + +The default value of the `dst` parameter can also be set globally: + +```ruby +TZInfo::Timezone.default_dst = true +tz.local_time(2018, 11, 4, 1, 30, 0, 0) +# => 2018-11-04 01:30:00 -0400 +TZInfo::Timezone.default_dst = false +tz.local_time(2018, 11, 4, 1, 30, 0, 0) +# => 2018-11-04 01:30:00 -0500 +``` + +TZInfo also provides information about +[ISO 3166-1](https://www.iso.org/iso-3166-country-codes.html) countries and +their associated time zones via the `TZInfo::Country` class. + +A list of valid ISO 3166-1 (alpha-2) country codes can be obtained by calling +`TZInfo::Country.all_codes`: + +```ruby +TZInfo::Country.all_codes +# => ["AD", "AE", ..., "ZW"] +``` + +A `TZInfo::Country` instance representing an individual time zone can be +obtained with `TZInfo::Country.get`: + +```ruby +c = TZInfo::Country.get('US') +# => # +c.name +# => "United States" +``` + +The `zone_identifiers` method returns a list of the time zone identifiers used +in a country: + +```ruby +c.zone_identifiers +# => ["America/New_York", "America/Detroit", ..., "Pacific/Honolulu"] +``` + +The `zone_info` method returns further information about the time zones used in +a country as an `Array` of `TZInfo::CountryTimezone` instances: + +```ruby +zi = c.zone_info.first +zi.identifier # => "America/New_York" +zi.latitude.to_f.round(5) # => 40.71417 +zi.longitude.to_f.round(5) # => -74.00639 +zi.description # => "Eastern (most areas)" +``` + +The `zones` method returns an `Array` of `TZInfo::Timezone` instances for a +country. A `TZInfo::Timezone` instance can be obtained from a +`TZInfo::CountryTimezone` using the `timezone` method: + +```ruby +zi.timezone.to_local(Time.utc(2018, 2, 1, 12, 30, 0)) +# => 2018-02-01 07:30:00 -0500 +``` -The following code will obtain the America/New_York timezone (as an instance -of `TZInfo::Timezone`) and convert a time in UTC to local New York time: - - require 'tzinfo' - - tz = TZInfo::Timezone.get('America/New_York') - local = tz.utc_to_local(Time.utc(2005,8,29,15,35,0)) - -Note that the local Time returned will have a UTC timezone (`local.zone` will -return `"UTC"`). This is because the Time class in older (but still supported by -TZInfo) versions of Ruby can only handle two timezones: UTC and the system local -timezone. - -To convert from a local time to UTC, the `local_to_utc` method can be used as -follows: - - utc = tz.local_to_utc(local) - -Note that the timezone information of the local Time object is ignored (TZInfo -will just read the date and time and treat them as if there were in the `tz` -timezone). The following two lines will return the same result regardless of -the system's local timezone: - - tz.local_to_utc(Time.local(2006,6,26,1,0,0)) - tz.local_to_utc(Time.utc(2006,6,26,1,0,0)) - -To obtain information about the rules in force at a particular UTC or local -time, the `TZInfo::Timezone.period_for_utc` and -`TZInfo::Timezone.period_for_local` methods can be used. Both of these methods -return `TZInfo::TimezonePeriod` objects. The following gets the identifier for -the period (in this case EDT). - - period = tz.period_for_utc(Time.utc(2005,8,29,15,35,0)) - id = period.zone_identifier - -The current local time in a `Timezone` can be obtained with the -`TZInfo::Timezone#now` method: - - now = tz.now - -All methods in TZInfo that operate on a time can be used with either `Time` or -`DateTime` instances or with Integer timestamps (i.e. as returned by -`Time#to_i`). The type of the values returned will match the type passed in. - -A list of all the available timezone identifiers can be obtained using the -`TZInfo::Timezone.all_identifiers` method. `TZInfo::Timezone.all` can be called -to get an `Array` of all the `TZInfo::Timezone` instances. - -Timezones can also be accessed by country (using an ISO 3166-1 alpha-2 country -code). The following code retrieves the `TZInfo::Country` instance representing -the USA (country code 'US') and then gets all the timezone identifiers used in -the USA. - - us = TZInfo::Country.get('US') - timezones = us.zone_identifiers - -The `TZInfo::Country#zone_info` method provides an additional description and -geographic location for each timezone in a country. - -A list of all the available country codes can be obtained using the -`TZInfo::Country.all_codes` method. `TZInfo::Country.all` can be called to get -an `Array` of all the `Country` instances. - -For further detail, please refer to the API documentation for the +For further detail, please refer to the API documentation for the `TZInfo::Timezone` and `TZInfo::Country` classes. -Thread-Safety -------------- +## Time Zone Selection + +The Time Zone Database maintainers recommend that time zone identifiers are not +made visible to end-users (see [Names of +timezones](https://data.iana.org/time-zones/theory.html#naming)). + +Instead of displaying a list of time zone identifiers, time zones can be +selected by the user's country. Call `TZInfo::Country.all` to obtain a list of +`TZInfo::Country` objects, each with a unique `code` and a `name` that can be +used for display purposes. + +Most countries have a single time zone. When choosing such a country, the time +zone can be inferred and selected automatically. + +```ruby +croatia = TZInfo::Country.get('HR') +# => # +croatia.zone_info.length +# => 1 +croatia.zone_info[0].identifier +# => "Europe/Belgrade" +``` + +Some countries have multiple time zones. The `zone_info` method can be used +to obtain a list of user-friendly descriptions of the available options: + +```ruby +australia = TZInfo::Country.get('AU') +# => # +australia.zone_info.length +# => 13 +australia.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 an +aid 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 territorial +claims. + + +## Compatibility + +TZInfo v2.0.0 requires a minimum of Ruby MRI 1.9.3 or JRuby 1.7 (in 1.9 mode or +later). + + +## Thread-Safety The `TZInfo::Country` and `TZInfo::Timezone` classes are thread-safe. It is safe -to use class and instance methods of `TZInfo::Country` and `TZInfo::Timezone` in -concurrently executing threads. Instances of both classes can be shared across +to use class and instance methods of `TZInfo::Country` and `TZInfo::Timezone` in +concurrently executing threads. Instances of both classes can be shared across thread boundaries. -Documentation -------------- +## Documentation -API documentation for TZInfo is available on [RubyDoc.info](http://rubydoc.info/gems/tzinfo/frames). +API documentation for TZInfo is available on +[RubyDoc.info](https://www.rubydoc.info/gems/tzinfo/). -License -------- +## License TZInfo is released under the MIT license, see LICENSE for details. -Source Code ------------ +## Source Code -Source code for TZInfo is available on [GitHub](https://github.com/tzinfo/tzinfo). +Source code for TZInfo is available on +[GitHub](https://github.com/tzinfo/tzinfo). -Issue Tracker -------------- +## Issue Tracker -Please post any bugs, issues, feature requests or questions to the +Please post any bugs, issues, feature requests or questions about TZInfo to the [GitHub issue tracker](https://github.com/tzinfo/tzinfo/issues). + +Issues with the underlying time zone data should be raised on the +[Time Zone Database Discussion mailing list](https://mm.icann.org/mailman/listinfo/tz). diff -Nru ruby-tzinfo-1.2.6/test/tc_country_index_definition.rb ruby-tzinfo-2.0.4/test/tc_country_index_definition.rb --- ruby-tzinfo-1.2.6/test/tc_country_index_definition.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_country_index_definition.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') - -include TZInfo - -class TCCountryIndexDefinition < Minitest::Test - - module CountriesTest1 - include CountryIndexDefinition - - country 'ZZ', 'Country One' do |c| - c.timezone 'Test/Zone/1', 3, 2, 41,20 - end - - country 'AA', 'Aland' do |c| - c.timezone 'Test/Zone/3', 71,30, 358, 15 - c.timezone 'Test/Zone/2', 41, 20, 211, 30 - end - - country 'TE', 'Three' - end - - module CountriesTest2 - include CountryIndexDefinition - - country 'CO', 'First Country' do |c| - end - end - - def test_module_1 - hash = CountriesTest1.countries - assert_equal(3, hash.length) - assert_equal(true, hash.frozen?) - - zz = hash['ZZ'] - aa = hash['AA'] - te = hash['TE'] - - assert_kind_of(RubyCountryInfo, zz) - assert_equal('ZZ', zz.code) - assert_equal('Country One', zz.name) - assert_equal(1, zz.zones.length) - assert_equal('Test/Zone/1', zz.zones[0].identifier) - - assert_kind_of(RubyCountryInfo, aa) - assert_equal('AA', aa.code) - assert_equal('Aland', aa.name) - assert_equal(2, aa.zones.length) - assert_equal('Test/Zone/3', aa.zones[0].identifier) - assert_equal('Test/Zone/2', aa.zones[1].identifier) - - assert_kind_of(RubyCountryInfo, te) - assert_equal('TE', te.code) - assert_equal('Three', te.name) - assert_equal(0, te.zones.length) - end - - def test_module_2 - hash = CountriesTest2.countries - assert_equal(1, hash.length) - assert_equal(true, hash.frozen?) - - co = hash['CO'] - - assert_kind_of(RubyCountryInfo, co) - assert_equal('CO', co.code) - assert_equal('First Country', co.name) - assert_equal(0, co.zones.length) - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_country_info.rb ruby-tzinfo-2.0.4/test/tc_country_info.rb --- ruby-tzinfo-1.2.6/test/tc_country_info.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_country_info.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') - -include TZInfo - -class TCCountryInfo < Minitest::Test - - def test_code - ci = CountryInfo.new('ZZ', 'Zzz') {|c| } - assert_equal('ZZ', ci.code) - end - - def test_name - ci = CountryInfo.new('ZZ', 'Zzz') {|c| } - assert_equal('Zzz', ci.name) - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_country.rb ruby-tzinfo-2.0.4/test/tc_country.rb --- ruby-tzinfo-1.2.6/test/tc_country.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_country.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,236 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') - -include TZInfo - -using TaintExt if Module.const_defined?(:TaintExt) - -class TCCountry < Minitest::Test - def setup - @orig_data_source = DataSource.get - Country.send :init_countries - end - - def teardown - DataSource.set(@orig_data_source) - end - - def test_get_valid - c = Country.get('GB') - - assert c - assert_equal('GB', c.code) - end - - def test_get_not_exist - assert_raises(InvalidCountryCode) { - Country.get('ZZ') - } - end - - def test_get_invalid - assert_raises(InvalidCountryCode) { - Country.get('../Countries/GB') - } - end - - def test_get_nil - assert_raises(InvalidCountryCode) { - Country.get(nil) - } - end - - def test_get_case - assert_raises(InvalidCountryCode) { - Country.get('gb') - } - end - - def test_get_tainted_loaded - Country.get('GB') - - safe_test(:unavailable => :skip) do - code = 'GB'.dup.taint - assert(code.tainted?) - country = Country.get(code) - assert_equal('GB', country.code) - assert(code.tainted?) - end - end - - def test_get_tainted_and_frozen_loaded - Country.get('GB') - - safe_test do - country = Country.get('GB'.dup.taint.freeze) - assert_equal('GB', country.code) - end - end - - def test_get_tainted_not_previously_loaded - safe_test(:unavailable => :skip) do - code = 'GB'.dup.taint - assert(code.tainted?) - country = Country.get(code) - assert_equal('GB', country.code) - assert(code.tainted?) - end - end - - def test_get_tainted_and_frozen_not_previously_loaded - safe_test do - country = Country.get('GB'.dup.taint.freeze) - assert_equal('GB', country.code) - end - end - - def test_new_nil - assert_raises(InvalidCountryCode) { - Country.new(nil) - } - end - - def test_new_arg - c = Country.new('GB') - assert_same(Country.get('GB'), c) - end - - def test_new_arg_not_exist - assert_raises(InvalidCountryCode) { - Country.new('ZZ') - } - end - - def test_all_codes - all_codes = Country.all_codes - assert_kind_of(Array, all_codes) - end - - def test_all - all = Country.all - assert_equal(Country.all_codes, all.collect {|c| c.code}) - end - - def test_code - assert_equal('US', Country.get('US').code) - end - - def test_name - assert_kind_of(String, Country.get('US').name) - end - - def test_to_s - assert_equal(Country.get('US').name, Country.get('US').to_s) - assert_equal(Country.get('GB').name, Country.get('GB').to_s) - end - - def test_zone_identifiers - zone_names = Country.get('US').zone_names - assert_kind_of(Array, zone_names) - assert_equal(true, zone_names.frozen?) - end - - def test_zone_names - assert_equal(Country.get('US').zone_identifiers, Country.get('US').zone_names) - end - - def test_zones - zones = Country.get('US').zones - assert_kind_of(Array, zones) - assert_equal(Country.get('US').zone_identifiers, zones.collect {|z| z.identifier}) - - zones.each {|z| assert_kind_of(TimezoneProxy, z)} - end - - def test_zone_info - zones = Country.get('US').zone_info - assert_kind_of(Array, zones) - assert_equal(true, zones.frozen?) - - assert_equal(Country.get('US').zone_identifiers, zones.collect {|z| z.identifier}) - assert_equal(Country.get('US').zone_identifiers, zones.collect {|z| z.timezone.identifier}) - - zones.each {|z| assert_kind_of(CountryTimezone, z)} - end - - def test_compare - assert_equal(0, Country.get('GB') <=> Country.get('GB')) - assert_equal(-1, Country.get('GB') <=> Country.get('US')) - assert_equal(1, Country.get('US') <=> Country.get('GB')) - assert_equal(-1, Country.get('FR') <=> Country.get('US')) - assert_equal(1, Country.get('US') <=> Country.get('FR')) - end - - def test_compare_non_comparable - assert_nil(Country.get('GB') <=> Object.new) - end - - def test_equality - assert_equal(true, Country.get('GB') == Country.get('GB')) - assert_equal(false, Country.get('GB') == Country.get('US')) - assert(!(Country.get('GB') == Object.new)) - end - - def test_eql - assert_equal(true, Country.get('GB').eql?(Country.get('GB'))) - assert_equal(false, Country.get('GB').eql?(Country.get('US'))) - assert(!Country.get('GB').eql?(Object.new)) - end - - def test_hash - assert_equal('GB'.hash, Country.get('GB').hash) - assert_equal('US'.hash, Country.get('US').hash) - end - - def test_marshal - c = Country.get('US') - - # Should get back the same instance because load calls Country.get. - assert_same(c, Marshal.load(Marshal.dump(c))) - end - - def test_reload - # If country gets reloaded for some reason, it needs to force a reload of - # the country index. - - assert_equal('US', Country.get('US').code) - - # Suppress redefined method warnings. - without_warnings do - load 'tzinfo/country.rb' - end - - assert_equal('US', Country.get('US').code) - end - - def test_get_missing_data_source - DataSource.set(DataSource.new) - - assert_raises(InvalidDataSource) do - Country.get('GB') - end - end - - def test_new_missing_data_source - DataSource.set(DataSource.new) - - assert_raises(InvalidDataSource) do - Country.new('GB') - end - end - - def test_all_codes_missing_data_source - DataSource.set(DataSource.new) - - assert_raises(InvalidDataSource) do - Country.all_codes - end - end - - def test_all_missing_data_source - DataSource.set(DataSource.new) - - assert_raises(InvalidDataSource) do - Country.all - end - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_country_timezone.rb ruby-tzinfo-2.0.4/test/tc_country_timezone.rb --- ruby-tzinfo-1.2.6/test/tc_country_timezone.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_country_timezone.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,173 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') - -include TZInfo - -class TCCountryTimezone < Minitest::Test - def test_identifier_new! - ct = CountryTimezone.new!('Europe/London', 2059, 40, -5, 16) - assert_equal('Europe/London', ct.identifier) - end - - def test_identifier_new - ct = CountryTimezone.new('Europe/London', Rational(2059, 40), Rational(-5, 16)) - assert_equal('Europe/London', ct.identifier) - end - - def test_latitude_new! - ct = CountryTimezone.new!('Europe/London', 2059, 40, -5, 16) - assert_equal(Rational(2059, 40), ct.latitude) - end - - def test_latitude_after_freeze_new! - ct = CountryTimezone.new!('Europe/London', 2059, 40, -5, 16) - ct.freeze - assert_equal(Rational(2059, 40), ct.latitude) - end - - def test_latitude_new - ct = CountryTimezone.new('Europe/London', Rational(2059, 40), Rational(-5, 16)) - assert_equal(Rational(2059, 40), ct.latitude) - end - - def test_longitude_new! - ct = CountryTimezone.new!('Europe/London', 2059, 40, -5, 16) - assert_equal(Rational(-5, 16), ct.longitude) - end - - def test_longitude_after_freeze_new! - ct = CountryTimezone.new!('Europe/London', 2059, 40, -5, 16) - ct.freeze - assert_equal(Rational(-5, 16), ct.longitude) - end - - def test_longitude_new - ct = CountryTimezone.new('Europe/London', Rational(2059, 40), Rational(-5, 16)) - assert_equal(Rational(-5, 16), ct.longitude) - end - - def test_description_omit_new! - ct = CountryTimezone.new!('Europe/London', 2059, 40, -5, 16) - assert_nil(ct.description) - end - - def test_description_omit_new - ct = CountryTimezone.new('Europe/London', Rational(2059, 40), Rational(-5, 16)) - assert_nil(ct.description) - end - - def test_description_nil_new! - ct = CountryTimezone.new!('Europe/London', 2059, 40, -5, 16, nil) - assert_nil(ct.description) - end - - def test_description_nil_new - ct = CountryTimezone.new('Europe/London', Rational(2059, 40), Rational(-5, 16), nil) - assert_nil(ct.description) - end - - def test_description_new! - ct = CountryTimezone.new!('America/New_York', 48857, 1200, -266423, 3600, 'Eastern Time') - assert_equal('Eastern Time', ct.description) - end - - def test_description_new - ct = CountryTimezone.new('America/New_York', Rational(48857, 1200), Rational(-266423, 3600), 'Eastern Time') - assert_equal('Eastern Time', ct.description) - end - - def test_timezone - ct = CountryTimezone.new('Europe/London', Rational(2059, 40), Rational(-5, 16)) - assert_kind_of(TimezoneProxy, ct.timezone) - assert_equal('Europe/London', ct.timezone.identifier) - end - - def test_description_or_friendly_idenfier_no_description - ct = CountryTimezone.new('Europe/London', Rational(2059, 40), Rational(-5, 16)) - assert_equal('London', ct.description_or_friendly_identifier) - end - - def test_description_or_friendly_idenfier_description - ct = CountryTimezone.new('America/New_York', Rational(48857, 1200), Rational(-266423, 3600), 'Eastern Time') - assert_equal('Eastern Time', ct.description_or_friendly_identifier) - end - - def test_equality_1 - ct1 = CountryTimezone.new!('Europe/London', 2059, 40, -5, 16) - ct2 = CountryTimezone.new!('Europe/London', 2059, 40, -5, 16) - ct3 = CountryTimezone.new('Europe/London', Rational(2059, 40), Rational(-5, 16)) - ct4 = CountryTimezone.new!('Europe/London', 2059, 40, -5, 16, 'Description') - ct5 = CountryTimezone.new!('Europe/LondonB', 2059, 40, -5, 16) - ct6 = CountryTimezone.new!('Europe/London', 2060, 40, -5, 16) - ct7 = CountryTimezone.new!('Europe/London', 2059, 40, -6, 16) - - assert_equal(true, ct1 == ct1) - assert_equal(true, ct1 == ct2) - assert_equal(true, ct1 == ct3) - assert_equal(false, ct1 == ct4) - assert_equal(false, ct1 == ct5) - assert_equal(false, ct1 == ct6) - assert_equal(false, ct1 == ct7) - end - - def test_equality_2 - ct1 = CountryTimezone.new!('America/New_York', 48857, 1200, -266423, 3600, 'Eastern Time') - ct2 = CountryTimezone.new!('America/New_York', 48857, 1200, -266423, 3600, 'Eastern Time2') - - assert_equal(true, ct1 == ct1) - assert_equal(false, ct1 == ct2) - end - - def test_equality_non_country_timezone - ct = CountryTimezone.new('Europe/London', Rational(2059, 40), Rational(-5, 16)) - - assert_equal(false, ct == Object.new) - end - - def test_eql_1 - ct1 = CountryTimezone.new!('Europe/London', 2059, 40, -5, 16) - ct2 = CountryTimezone.new!('Europe/London', 2059, 40, -5, 16) - ct3 = CountryTimezone.new('Europe/London', Rational(2059, 40), Rational(-5, 16)) - ct4 = CountryTimezone.new!('Europe/London', 2059, 40, -5, 16, 'Description') - ct5 = CountryTimezone.new!('Europe/LondonB', 2059, 40, -5, 16) - ct6 = CountryTimezone.new!('Europe/London', 2060, 40, -5, 16) - ct7 = CountryTimezone.new!('Europe/London', 2059, 40, -6, 16) - - assert_equal(true, ct1.eql?(ct1)) - assert_equal(true, ct1.eql?(ct2)) - assert_equal(true, ct1.eql?(ct3)) - assert_equal(false, ct1.eql?(ct4)) - assert_equal(false, ct1.eql?(ct5)) - assert_equal(false, ct1.eql?(ct6)) - assert_equal(false, ct1.eql?(ct7)) - end - - def test_eql_2 - ct1 = CountryTimezone.new!('America/New_York', 48857, 1200, -266423, 3600, 'Eastern Time') - ct2 = CountryTimezone.new!('America/New_York', 48857, 1200, -266423, 3600, 'Eastern Time2') - - assert_equal(true, ct1.eql?(ct1)) - assert_equal(false, ct1.eql?(ct2)) - end - - def test_eql_non_country_timezone - ct = CountryTimezone.new('Europe/London', Rational(2059, 40), Rational(-5, 16)) - - assert_equal(false, ct.eql?(Object.new)) - end - - def test_hash_new! - ct1 = CountryTimezone.new!('Europe/London', 2059, 40, -5, 16) - ct2 = CountryTimezone.new!('America/New_York', 48857, 1200, -266423, 3600, 'Eastern Time') - - assert_equal('Europe/London'.hash ^ 2059.hash ^ 40.hash ^ -5.hash ^ 16.hash ^ nil.hash, ct1.hash) - assert_equal('America/New_York'.hash ^ 48857.hash ^ 1200.hash ^ -266423.hash ^ 3600.hash ^ 'Eastern Time'.hash, ct2.hash) - end - - def test_hash_new - ct1 = CountryTimezone.new('Europe/London', Rational(2059, 40), Rational(-5, 16)) - ct2 = CountryTimezone.new('America/New_York', Rational(48857, 1200), Rational(-266423, 3600), 'Eastern Time') - - assert_equal('Europe/London'.hash ^ 2059.hash ^ 40.hash ^ -5.hash ^ 16.hash ^ nil.hash, ct1.hash) - assert_equal('America/New_York'.hash ^ 48857.hash ^ 1200.hash ^ -266423.hash ^ 3600.hash ^ 'Eastern Time'.hash, ct2.hash) - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_data_source.rb ruby-tzinfo-2.0.4/test/tc_data_source.rb --- ruby-tzinfo-1.2.6/test/tc_data_source.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_data_source.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,218 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') -require 'tmpdir' - -include TZInfo - -class TCDataSource < Minitest::Test - class InitDataSource < DataSource - end - - class DummyDataSource < DataSource - end - - def setup - @orig_data_source = DataSource.get - DataSource.set(InitDataSource.new) - @orig_search_path = ZoneinfoDataSource.search_path.clone - end - - def teardown - DataSource.set(@orig_data_source) - ZoneinfoDataSource.search_path = @orig_search_path - end - - def test_get - data_source = DataSource.get - assert_kind_of(InitDataSource, data_source) - end - - def test_get_default_ruby_only - code = <<-EOF - require 'tmpdir' - - begin - Dir.mktmpdir('tzinfo_test_dir') do |dir| - TZInfo::ZoneinfoDataSource.search_path = [dir] - - puts TZInfo::DataSource.get.class - end - rescue Exception => e - puts "Unexpected exception: \#{e}" - end - EOF - - assert_sub_process_returns(['TZInfo::RubyDataSource'], code, [TZINFO_TEST_DATA_DIR]) - end - - def test_get_default_zoneinfo_only - code = <<-EOF - require 'tmpdir' - - begin - Dir.mktmpdir('tzinfo_test_dir') do |dir| - TZInfo::ZoneinfoDataSource.search_path = [dir, '#{TZINFO_TEST_ZONEINFO_DIR}'] - - puts TZInfo::DataSource.get.class - puts TZInfo::DataSource.get.zoneinfo_dir - end - rescue Exception => e - puts "Unexpected exception: \#{e}" - end - EOF - - assert_sub_process_returns( - ['TZInfo::ZoneinfoDataSource', TZINFO_TEST_ZONEINFO_DIR], - code) - end - - def test_get_default_ruby_and_zoneinfo - code = <<-EOF - begin - TZInfo::ZoneinfoDataSource.search_path = ['#{TZINFO_TEST_ZONEINFO_DIR}'] - - puts TZInfo::DataSource.get.class - rescue Exception => e - puts "Unexpected exception: \#{e}" - end - EOF - - assert_sub_process_returns(['TZInfo::RubyDataSource'], code, [TZINFO_TEST_DATA_DIR]) - end - - def test_get_default_no_data - code = <<-EOF - require 'tmpdir' - - begin - Dir.mktmpdir('tzinfo_test_dir') do |dir| - TZInfo::ZoneinfoDataSource.search_path = [dir] - - begin - data_source = TZInfo::DataSource.get - puts "No exception raised, returned \#{data_source} instead" - rescue Exception => e - puts e.class - end - end - rescue Exception => e - puts "Unexpected exception: \#{e}" - end - EOF - - assert_sub_process_returns(['TZInfo::DataSourceNotFound'], code) - end - - def test_set_instance - DataSource.set(DummyDataSource.new) - data_source = DataSource.get - assert_kind_of(DummyDataSource, data_source) - end - - def test_set_standard_ruby - DataSource.set(:ruby) - data_source = DataSource.get - assert_kind_of(RubyDataSource, data_source) - end - - def test_set_standard_zoneinfo_search - Dir.mktmpdir('tzinfo_test_dir') do |dir| - FileUtils.touch(File.join(dir, 'iso3166.tab')) - FileUtils.touch(File.join(dir, 'zone.tab')) - - ZoneinfoDataSource.search_path = [dir] - - DataSource.set(:zoneinfo) - data_source = DataSource.get - assert_kind_of(ZoneinfoDataSource, data_source) - assert_equal(dir, data_source.zoneinfo_dir) - end - end - - def test_set_standard_zoneinfo_search_zone1970 - Dir.mktmpdir('tzinfo_test_dir') do |dir| - FileUtils.touch(File.join(dir, 'iso3166.tab')) - FileUtils.touch(File.join(dir, 'zone1970.tab')) - - ZoneinfoDataSource.search_path = [dir] - - DataSource.set(:zoneinfo) - data_source = DataSource.get - assert_kind_of(ZoneinfoDataSource, data_source) - assert_equal(dir, data_source.zoneinfo_dir) - end - end - - def test_set_standard_zoneinfo_explicit - Dir.mktmpdir('tzinfo_test_dir') do |dir| - FileUtils.touch(File.join(dir, 'iso3166.tab')) - FileUtils.touch(File.join(dir, 'zone.tab')) - - DataSource.set(:zoneinfo, dir) - data_source = DataSource.get - assert_kind_of(ZoneinfoDataSource, data_source) - assert_equal(dir, data_source.zoneinfo_dir) - end - end - - def test_set_standard_zoneinfo_explicit_zone1970 - Dir.mktmpdir('tzinfo_test_dir') do |dir| - FileUtils.touch(File.join(dir, 'iso3166.tab')) - FileUtils.touch(File.join(dir, 'zone.tab')) - - DataSource.set(:zoneinfo, dir) - data_source = DataSource.get - assert_kind_of(ZoneinfoDataSource, data_source) - assert_equal(dir, data_source.zoneinfo_dir) - end - end - - def test_set_standard_zoneinfo_explicit_alternate_iso3166 - Dir.mktmpdir('tzinfo_test_dir') do |dir| - zoneinfo_dir = File.join(dir, 'zoneinfo') - tab_dir = File.join(dir, 'tab') - - FileUtils.mkdir(zoneinfo_dir) - FileUtils.mkdir(tab_dir) - - FileUtils.touch(File.join(zoneinfo_dir, 'zone.tab')) - - iso3166_file = File.join(tab_dir, 'iso3166.tab') - FileUtils.touch(iso3166_file) - - DataSource.set(:zoneinfo, zoneinfo_dir, iso3166_file) - data_source = DataSource.get - assert_kind_of(ZoneinfoDataSource, data_source) - assert_equal(zoneinfo_dir, data_source.zoneinfo_dir) - end - end - - def test_set_standard_zoneinfo_search_not_found - Dir.mktmpdir('tzinfo_test_dir') do |dir| - ZoneinfoDataSource.search_path = [dir] - - assert_raises(ZoneinfoDirectoryNotFound) do - DataSource.set(:zoneinfo) - end - - assert_kind_of(InitDataSource, DataSource.get) - end - end - - def test_set_standard_zoneinfo_explicit_invalid - Dir.mktmpdir('tzinfo_test_dir') do |dir| - assert_raises(InvalidZoneinfoDirectory) do - DataSource.set(:zoneinfo, dir) - end - - assert_kind_of(InitDataSource, DataSource.get) - end - end - - def test_set_standard_zoneinfo_wrong_arg_count - assert_raises(ArgumentError) do - DataSource.set(:zoneinfo, 1, 2, 3) - end - - assert_kind_of(InitDataSource, DataSource.get) - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_data_timezone_info.rb ruby-tzinfo-2.0.4/test/tc_data_timezone_info.rb --- ruby-tzinfo-1.2.6/test/tc_data_timezone_info.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_data_timezone_info.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') - -include TZInfo - -class TCDataTimezoneInfo < Minitest::Test - - def test_identifier - ti = DataTimezoneInfo.new('Test/Zone') - assert_equal('Test/Zone', ti.identifier) - end - - def test_construct_timezone - ti = DataTimezoneInfo.new('Test/Zone') - tz = ti.create_timezone - assert_kind_of(DataTimezone, tz) - assert_equal('Test/Zone', tz.identifier) - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_data_timezone.rb ruby-tzinfo-2.0.4/test/tc_data_timezone.rb --- ruby-tzinfo-1.2.6/test/tc_data_timezone.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_data_timezone.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,99 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') - -include TZInfo - -class TCDataTimezone < Minitest::Test - - class TestTimezoneInfo < TimezoneInfo - attr_reader :utc - attr_reader :local - attr_reader :utc_to - attr_reader :utc_from - - def initialize(identifier, utc_period, local_periods, transitions_up_to) - super(identifier) - @utc_period = utc_period - @local_periods = local_periods || [] - @transitions_up_to = transitions_up_to - end - - def period_for_utc(utc) - @utc = utc - @utc_period - end - - def periods_for_local(local) - @local = local - @local_periods - end - - def transitions_up_to(utc_to, utc_from = nil) - @utc_to = utc_to - @utc_from = utc_from - @transitions_up_to - end - end - - def test_identifier - tz = DataTimezone.new(TestTimezoneInfo.new('Test/Zone', nil, [], [])) - assert_equal('Test/Zone', tz.identifier) - end - - def test_period_for_utc - # Don't need actual TimezonePeriods. DataTimezone isn't supposed to do - # anything with them apart from return them. - period = Object.new - tti = TestTimezoneInfo.new('Test/Zone', period, [], []) - tz = DataTimezone.new(tti) - - t = Time.utc(2006, 6, 27, 22, 50, 12) - assert_same(period, tz.period_for_utc(t)) - assert_same(t, tti.utc) - end - - def test_periods_for_local - # Don't need actual TimezonePeriods. DataTimezone isn't supposed to do - # anything with them apart from return them. - periods = [Object.new, Object.new] - tti = TestTimezoneInfo.new('Test/Zone', nil, periods, []) - tz = DataTimezone.new(tti) - - t = Time.utc(2006, 6, 27, 22, 50, 12) - assert_same(periods, tz.periods_for_local(t)) - assert_same(t, tti.local) - end - - def test_periods_for_local_not_found - periods = [] - tti = TestTimezoneInfo.new('Test/Zone', nil, periods, []) - tz = DataTimezone.new(tti) - - t = Time.utc(2006, 6, 27, 22, 50, 12) - assert_same(periods, tz.periods_for_local(t)) - assert_same(t, tti.local) - end - - def test_transitions_up_to - # Don't need actual TimezoneTransition instances. DataTimezone isn't - # supposed to do anything with them apart from return them. - transitions = [Object.new, Object.new] - tti = TestTimezoneInfo.new('Test/Zone', nil, nil, transitions) - tz = DataTimezone.new(tti) - - utc_to = Time.utc(2013, 1, 1, 0, 0, 0) - utc_from = Time.utc(2012, 1, 1, 0, 0, 0) - assert_same(transitions, tz.transitions_up_to(utc_to, utc_from)) - assert_same(utc_to, tti.utc_to) - assert_same(utc_from, tti.utc_from) - end - - def test_canonical_identifier - tz = DataTimezone.new(TestTimezoneInfo.new('Test/Zone', nil, [], [])) - assert_equal('Test/Zone', tz.canonical_identifier) - end - - def test_canonical_zone - tz = DataTimezone.new(TestTimezoneInfo.new('Test/Zone', nil, [], [])) - assert_same(tz, tz.canonical_zone) - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_info_timezone.rb ruby-tzinfo-2.0.4/test/tc_info_timezone.rb --- ruby-tzinfo-1.2.6/test/tc_info_timezone.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_info_timezone.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') - -include TZInfo - -class TCInfoTimezone < Minitest::Test - - class TestInfoTimezone < InfoTimezone - attr_reader :setup_info - - protected - def setup(info) - super(info) - @setup_info = info - end - end - - def test_identifier - tz = InfoTimezone.new(TimezoneInfo.new('Test/Identifier')) - assert_equal('Test/Identifier', tz.identifier) - end - - def test_info - i = TimezoneInfo.new('Test/Identifier') - tz = InfoTimezone.new(i) - assert_same(i, tz.send(:info)) - end - - def test_setup - i = TimezoneInfo.new('Test/Identifier') - tz = TestInfoTimezone.new(i) - assert_same(i, tz.setup_info) - end -end - diff -Nru ruby-tzinfo-1.2.6/test/tc_linked_timezone_info.rb ruby-tzinfo-2.0.4/test/tc_linked_timezone_info.rb --- ruby-tzinfo-1.2.6/test/tc_linked_timezone_info.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_linked_timezone_info.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') - -include TZInfo - -class TCLinkedTimezoneInfo < Minitest::Test - - def test_identifier - lti = LinkedTimezoneInfo.new('Test/Zone', 'Test/Linked') - assert_equal('Test/Zone', lti.identifier) - end - - def test_link_to_identifier - lti = LinkedTimezoneInfo.new('Test/Zone', 'Test/Linked') - assert_equal('Test/Linked', lti.link_to_identifier) - end - - def test_construct_timezone - lti = LinkedTimezoneInfo.new('Test/Zone', 'Europe/London') - tz = lti.create_timezone - assert_kind_of(LinkedTimezone, tz) - assert_equal('Test/Zone', tz.identifier) - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_linked_timezone.rb ruby-tzinfo-2.0.4/test/tc_linked_timezone.rb --- ruby-tzinfo-1.2.6/test/tc_linked_timezone.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_linked_timezone.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,155 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') - -include TZInfo - -class TCLinkedTimezone < Minitest::Test - - class TestTimezone < Timezone - attr_reader :utc_period - attr_reader :local_periods - attr_reader :up_to_transitions - attr_reader :utc - attr_reader :local - attr_reader :utc_to - attr_reader :utc_from - - def self.new(identifier, no_local_periods = false) - tz = super() - tz.send(:setup, identifier, no_local_periods) - tz - end - - def identifier - @identifier - end - - def period_for_utc(utc) - @utc = utc - @utc_period - end - - def periods_for_local(local) - @local = local - raise PeriodNotFound if @no_local_periods - @local_periods - end - - def transitions_up_to(utc_to, utc_from = nil) - @utc_to = utc_to - @utc_from = utc_from - @up_to_transitions - end - - def canonical_zone - self - end - - private - def setup(identifier, no_local_periods) - @identifier = identifier - @no_local_periods = no_local_periods - - # Don't have to be real TimezonePeriod or TimezoneTransition objects - # (nothing will use them). - @utc_period = Object.new - @local_periods = [Object.new, Object.new] - @up_to_transitions = [Object.new, Object.new] - end - end - - - def setup - # Redefine Timezone.get to return a fake timezone. - # Use without_warnings to suppress redefined get method warning. - without_warnings do - def Timezone.get(identifier) - raise InvalidTimezoneIdentifier, 'Invalid identifier' if identifier == 'Invalid/Identifier' - - @timezones ||= {} - @timezones[identifier] ||= - identifier == 'Test/Recursive/Linked' ? - LinkedTimezone.new(LinkedTimezoneInfo.new(identifier, 'Test/Recursive/Data')) : - TestTimezone.new(identifier, identifier == 'Test/No/Local') - end - end - end - - def teardown - # Re-require timezone to reset. - # Suppress redefined method warnings. - without_warnings do - load 'tzinfo/timezone.rb' - end - end - - def test_identifier - tz = LinkedTimezone.new(LinkedTimezoneInfo.new('Test/Zone', 'Test/Linked')) - assert_equal('Test/Zone', tz.identifier) - end - - def test_invalid_linked_identifier - assert_raises(InvalidTimezoneIdentifier) { LinkedTimezone.new(LinkedTimezoneInfo.new('Test/Zone', 'Invalid/Identifier')) } - end - - def test_period_for_utc - tz = LinkedTimezone.new(LinkedTimezoneInfo.new('Test/Zone', 'Test/Linked')) - linked_tz = Timezone.get('Test/Linked') - t = Time.utc(2006, 6, 27, 23, 12, 28) - assert_same(linked_tz.utc_period, tz.period_for_utc(t)) - assert_same(t, linked_tz.utc) - end - - def test_periods_for_local - tz = LinkedTimezone.new(LinkedTimezoneInfo.new('Test/Zone', 'Test/Linked')) - linked_tz = Timezone.get('Test/Linked') - t = Time.utc(2006, 6, 27, 23, 12, 28) - assert_same(linked_tz.local_periods, tz.periods_for_local(t)) - assert_same(t, linked_tz.local) - end - - def test_periods_for_local_not_found - tz = LinkedTimezone.new(LinkedTimezoneInfo.new('Test/Zone', 'Test/No/Local')) - linked_tz = Timezone.get('Test/No/Local') - t = Time.utc(2006, 6, 27, 23, 12, 28) - assert_raises(PeriodNotFound) { tz.periods_for_local(t) } - assert_same(t, linked_tz.local) - end - - def test_transitions_up_to - tz = LinkedTimezone.new(LinkedTimezoneInfo.new('Test/Zone', 'Test/Linked')) - linked_tz = Timezone.get('Test/Linked') - utc_to = Time.utc(2013, 1, 1, 0, 0, 0) - utc_from = Time.utc(2012, 1, 1, 0, 0, 0) - assert_same(linked_tz.up_to_transitions, tz.transitions_up_to(utc_to, utc_from)) - assert_same(utc_to, linked_tz.utc_to) - assert_same(utc_from, linked_tz.utc_from) - end - - def test_canonical_identifier - tz = LinkedTimezone.new(LinkedTimezoneInfo.new('Test/Zone', 'Test/Linked')) - assert_equal('Test/Linked', tz.canonical_identifier) - end - - def test_canonical_identifier_recursive - # Recursive links are not currently used in the Time Zone database, but - # will be supported by TZInfo. - - tz = LinkedTimezone.new(LinkedTimezoneInfo.new('Test/Zone', 'Test/Recursive/Linked')) - assert_equal('Test/Recursive/Data', tz.canonical_identifier) - end - - def test_canonical_zone - tz = LinkedTimezone.new(LinkedTimezoneInfo.new('Test/Zone', 'Test/Linked')) - linked_tz = Timezone.get('Test/Linked') - assert_same(linked_tz, tz.canonical_zone) - end - - def test_canonical_zone_recursive - # Recursive links are not currently used in the Time Zone database, but - # will be supported by TZInfo. - - tz = LinkedTimezone.new(LinkedTimezoneInfo.new('Test/Zone', 'Test/Recursive/Linked')) - linked_tz = Timezone.get('Test/Recursive/Data') - assert_same(linked_tz, tz.canonical_zone) - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_offset_rationals.rb ruby-tzinfo-2.0.4/test/tc_offset_rationals.rb --- ruby-tzinfo-1.2.6/test/tc_offset_rationals.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_offset_rationals.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') - -include TZInfo - -class TCOffsetRationals < Minitest::Test - def test_rational_for_offset - [0,1,2,3,4,-1,-2,-3,-4,30*60,-30*60,61*60,-61*60,14*60*60,-14*60*60,20*60*60,-20*60*60].each {|seconds| - assert_equal(Rational(seconds, 86400), OffsetRationals.rational_for_offset(seconds)) - } - end - - def test_rational_for_offset_constant - -28.upto(28) {|i| - seconds = i * 30 * 60 - - r1 = OffsetRationals.rational_for_offset(seconds) - r2 = OffsetRationals.rational_for_offset(seconds) - - assert_equal(Rational(seconds, 86400), r1) - assert_same(r1, r2) - } - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_ruby_core_support.rb ruby-tzinfo-2.0.4/test/tc_ruby_core_support.rb --- ruby-tzinfo-1.2.6/test/tc_ruby_core_support.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_ruby_core_support.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,168 +0,0 @@ -# encoding: UTF-8 - -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') - -include TZInfo - -class TCRubyCoreSupport < Minitest::Test - def test_rational_new! - assert_equal(Rational(3,4), RubyCoreSupport.rational_new!(3,4)) - end - - def test_datetime_new! - assert_equal(DateTime.new(2008,10,5,12,0,0, 0, Date::ITALY), RubyCoreSupport.datetime_new!(2454745,0,2299161)) - assert_equal(DateTime.new(2008,10,5,13,0,0, Rational(1, 24), Date::ITALY), RubyCoreSupport.datetime_new!(2454745,Rational(1, 24),2299161)) - - assert_equal(DateTime.new(2008,10,5,20,30,0, 0, Date::ITALY), RubyCoreSupport.datetime_new!(Rational(117827777, 48), 0, 2299161)) - assert_equal(DateTime.new(2008,10,5,21,30,0, Rational(1, 24), Date::ITALY), RubyCoreSupport.datetime_new!(Rational(117827777, 48), Rational(1, 24), 2299161)) - - assert_equal(DateTime.new(2008,10,6,6,26,21, 0, Date::ITALY), RubyCoreSupport.datetime_new!(Rational(70696678127,28800), 0, 2299161)) - assert_equal(DateTime.new(2008,10,6,7,26,21, Rational(1, 24), Date::ITALY), RubyCoreSupport.datetime_new!(Rational(70696678127, 28800), Rational(1, 24), 2299161)) - - assert_equal(DateTime.new(-4712,1,1,12,0,0, 0, Date::ITALY), RubyCoreSupport.datetime_new!(0, 0, 2299161)) - assert_equal(DateTime.new(-4712,1,1,13,0,0, Rational(1, 24), Date::ITALY), RubyCoreSupport.datetime_new!(0, Rational(1, 24), 2299161)) - - assert_equal(DateTime.new(-4713,12,31,23,58,59, 0, Date::ITALY), RubyCoreSupport.datetime_new!(Rational(-43261, 86400), 0, 2299161)) - assert_equal(DateTime.new(-4712,1,1,0,58,59, Rational(1, 24), Date::ITALY), RubyCoreSupport.datetime_new!(Rational(-43261, 86400), Rational(1, 24), 2299161)) - - assert_equal(DateTime.new(-4713,12,30,23,58,59, 0, Date::ITALY), RubyCoreSupport.datetime_new!(Rational(-129661, 86400), 0, 2299161)) - assert_equal(DateTime.new(-4713,12,31,0,58,59, Rational(1, 24), Date::ITALY), RubyCoreSupport.datetime_new!(Rational(-129661, 86400), Rational(1, 24), 2299161)) - end - - def test_datetime_new - assert_equal(DateTime.new(2012, 12, 31, 23, 59, 59, 0, Date::ITALY), RubyCoreSupport.datetime_new(2012, 12, 31, 23, 59, 59, 0, Date::ITALY)) - assert_equal(DateTime.new(2013, 2, 6, 23, 2, 36, Rational(1, 24), Date::ITALY), RubyCoreSupport.datetime_new(2013, 2, 6, 23, 2, 36, Rational(1,24), Date::ITALY)) - - assert_equal(DateTime.new(2012, 12, 31, 23, 59, 59, 0, Date::ITALY) + Rational(1, 86400000), RubyCoreSupport.datetime_new(2012, 12, 31, 23, 59, 59 + Rational(1, 1000), 0, Date::ITALY)) - assert_equal(DateTime.new(2001, 10, 12, 12, 22, 59, Rational(1, 24), Date::ITALY) + Rational(501, 86400000), RubyCoreSupport.datetime_new(2001, 10, 12, 12, 22, 59 + Rational(501, 1000), Rational(1, 24), Date::ITALY)) - end - - def test_time_supports_negative - if RubyCoreSupport.time_supports_negative - assert_equal(Time.utc(1969, 12, 31, 23, 59, 59), Time.at(-1).utc) - else - assert_raises(ArgumentError) do - Time.at(-1) - end - end - end - - def test_time_supports_64_bit - if RubyCoreSupport.time_supports_64bit - assert_equal(Time.utc(1901, 12, 13, 20, 45, 51), Time.at(-2147483649).utc) - assert_equal(Time.utc(2038, 1, 19, 3, 14, 8), Time.at(2147483648).utc) - else - assert_raises(RangeError) do - Time.at(-2147483649) - end - - assert_raises(RangeError) do - Time.at(2147483648) - end - end - end - - def test_time_nsec - t = Time.utc(2013, 2, 6, 21, 56, 23, 567890 + Rational(123,1000)) - - if t.respond_to?(:nsec) - assert_equal(567890123, RubyCoreSupport.time_nsec(t)) - else - assert_equal(567890000, RubyCoreSupport.time_nsec(t)) - end - end - - def test_force_encoding - s = [0xC2, 0xA9].pack('c2') - - if s.respond_to?(:force_encoding) - # Ruby 1.9+ - should call String#force_encoding - assert_equal('ASCII-8BIT', s.encoding.name) - assert_equal(2, s.bytesize) - result = RubyCoreSupport.force_encoding(s, 'UTF-8') - assert_same(s, result) - assert_equal('UTF-8', s.encoding.name) - assert_equal(2, s.bytesize) - assert_equal(1, s.length) - assert_equal('©', s) - else - # Ruby 1.8 - no-op - result = RubyCoreSupport.force_encoding(s, 'UTF-8') - assert_same(s, result) - assert_equal('©', s) - end - end - - begin - SUPPORTS_ENCODING = !!Encoding - rescue NameError - SUPPORTS_ENCODING = false - end - - def check_open_file_test_file_bytes(test_file) - if SUPPORTS_ENCODING - File.open(test_file, 'r') do |file| - file.binmode - data = file.read(2) - refute_nil(data) - assert_equal(2, data.length) - bytes = data.unpack('C2') - assert_equal(0xC2, bytes[0]) - assert_equal(0xA9, bytes[1]) - end - end - end - - def check_open_file_test_file_content(file) - content = file.gets - refute_nil(content) - content.chomp! - - if SUPPORTS_ENCODING - assert_equal('UTF-8', content.encoding.name) - assert_equal(1, content.length) - assert_equal(2, content.bytesize) - assert_equal('©', content) - else - assert_equal('x', content) - end - end - - def test_open_file - Dir.mktmpdir('tzinfo_test') do |dir| - test_file = File.join(dir, 'test.txt') - - file = RubyCoreSupport.open_file(test_file, 'w', :external_encoding => 'UTF-8') - begin - file.puts(SUPPORTS_ENCODING ? '©' : 'x') - ensure - file.close - end - - check_open_file_test_file_bytes(test_file) - - file = RubyCoreSupport.open_file(test_file, 'r', :external_encoding => 'UTF-8', :internal_encoding => 'UTF-8') - begin - check_open_file_test_file_content(file) - ensure - file.close - end - end - end - - def test_open_file_block - Dir.mktmpdir('tzinfo_test') do |dir| - test_file = File.join(dir, 'test.txt') - - RubyCoreSupport.open_file(test_file, 'w', :external_encoding => 'UTF-8') do |file| - file.puts(SUPPORTS_ENCODING ? '©' : 'x') - end - - check_open_file_test_file_bytes(test_file) - - RubyCoreSupport.open_file(test_file, 'r', :external_encoding => 'UTF-8', :internal_encoding => 'UTF-8') do |file| - check_open_file_test_file_content(file) - end - end - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_ruby_country_info.rb ruby-tzinfo-2.0.4/test/tc_ruby_country_info.rb --- ruby-tzinfo-1.2.6/test/tc_ruby_country_info.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_ruby_country_info.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,110 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') - -include TZInfo - -class TCRubyCountryInfo < Minitest::Test - - def test_code - ci = RubyCountryInfo.new('ZZ', 'Zzz') {|c| } - assert_equal('ZZ', ci.code) - end - - def test_name - ci = RubyCountryInfo.new('ZZ', 'Zzz') {|c| } - assert_equal('Zzz', ci.name) - end - - def test_zone_identifiers_empty - ci = RubyCountryInfo.new('ZZ', 'Zzz') {|c| } - assert(ci.zone_identifiers.empty?) - assert(ci.zone_identifiers.frozen?) - end - - def test_zone_identifiers_no_block - ci = RubyCountryInfo.new('ZZ', 'Zzz') - assert(ci.zone_identifiers.empty?) - assert(ci.zone_identifiers.frozen?) - end - - def test_zone_identifiers - ci = RubyCountryInfo.new('ZZ', 'Zzz') do |c| - c.timezone('ZZ/TimezoneB', 1, 2, 1, 2, 'Timezone B') - c.timezone('ZZ/TimezoneA', 1, 4, 1, 4, 'Timezone A') - c.timezone('ZZ/TimezoneC', -10, 3, -20, 7, 'C') - c.timezone('ZZ/TimezoneD', -10, 3, -20, 7) - end - - assert_equal(['ZZ/TimezoneB', 'ZZ/TimezoneA', 'ZZ/TimezoneC', 'ZZ/TimezoneD'], ci.zone_identifiers) - assert(ci.zone_identifiers.frozen?) - end - - def test_zone_identifiers_after_freeze - ci = RubyCountryInfo.new('ZZ', 'Zzz') do |c| - c.timezone('ZZ/TimezoneB', 1, 2, 1, 2, 'Timezone B') - c.timezone('ZZ/TimezoneA', 1, 4, 1, 4, 'Timezone A') - c.timezone('ZZ/TimezoneC', -10, 3, -20, 7, 'C') - c.timezone('ZZ/TimezoneD', -10, 3, -20, 7) - end - - ci.freeze - - assert_equal(['ZZ/TimezoneB', 'ZZ/TimezoneA', 'ZZ/TimezoneC', 'ZZ/TimezoneD'], ci.zone_identifiers) - end - - def test_zones_empty - ci = RubyCountryInfo.new('ZZ', 'Zzz') {|c| } - assert(ci.zones.empty?) - assert(ci.zones.frozen?) - end - - def test_zones_no_block - ci = RubyCountryInfo.new('ZZ', 'Zzz') - assert(ci.zones.empty?) - assert(ci.zones.frozen?) - end - - def test_zones - ci = RubyCountryInfo.new('ZZ', 'Zzz') do |c| - c.timezone('ZZ/TimezoneB', 1, 2, 1, 2, 'Timezone B') - c.timezone('ZZ/TimezoneA', 1, 4, 1, 4, 'Timezone A') - c.timezone('ZZ/TimezoneC', -10, 3, -20, 7, 'C') - c.timezone('ZZ/TimezoneD', -10, 3, -20, 7) - end - - assert_equal([CountryTimezone.new!('ZZ/TimezoneB', 1, 2, 1, 2, 'Timezone B'), - CountryTimezone.new!('ZZ/TimezoneA', 1, 4, 1, 4, 'Timezone A'), - CountryTimezone.new!('ZZ/TimezoneC', -10, 3, -20, 7, 'C'), - CountryTimezone.new!('ZZ/TimezoneD', -10, 3, -20, 7)], - ci.zones) - assert(ci.zones.frozen?) - end - - def test_zones_after_freeze - ci = RubyCountryInfo.new('ZZ', 'Zzz') do |c| - c.timezone('ZZ/TimezoneB', 1, 2, 1, 2, 'Timezone B') - c.timezone('ZZ/TimezoneA', 1, 4, 1, 4, 'Timezone A') - c.timezone('ZZ/TimezoneC', -10, 3, -20, 7, 'C') - c.timezone('ZZ/TimezoneD', -10, 3, -20, 7) - end - - ci.freeze - - assert_equal([CountryTimezone.new!('ZZ/TimezoneB', 1, 2, 1, 2, 'Timezone B'), - CountryTimezone.new!('ZZ/TimezoneA', 1, 4, 1, 4, 'Timezone A'), - CountryTimezone.new!('ZZ/TimezoneC', -10, 3, -20, 7, 'C'), - CountryTimezone.new!('ZZ/TimezoneD', -10, 3, -20, 7)], - ci.zones) - end - - def test_deferred_evaluate - block_called = false - - ci = RubyCountryInfo.new('ZZ', 'Zzz') do |c| - block_called = true - end - - assert_equal(false, block_called) - ci.zones - assert_equal(true, block_called) - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_ruby_data_source.rb ruby-tzinfo-2.0.4/test/tc_ruby_data_source.rb --- ruby-tzinfo-1.2.6/test/tc_ruby_data_source.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_ruby_data_source.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,165 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') - -include TZInfo - -using TaintExt if Module.const_defined?(:TaintExt) - -class TCRubyDataSource < Minitest::Test - def setup - @data_source = RubyDataSource.new - end - - def test_initialize_not_found - # A failure to load tzinfo/data in initialize will not cause an exception. - # Attempts to load data files will subsequently fail. - code = <<-EOF - begin - ds = TZInfo::RubyDataSource.new - puts 'Initialized' - ds.load_timezone_info('Europe/London') - rescue Exception => e - puts e.class - end - EOF - - assert_sub_process_returns(['Initialized', 'TZInfo::InvalidTimezoneIdentifier'], code) - end - - def test_load_timezone_info_data - info = @data_source.load_timezone_info('Europe/London') - assert_kind_of(DataTimezoneInfo, info) - assert_equal('Europe/London', info.identifier) - end - - def test_load_timezone_info_linked - info = @data_source.load_timezone_info('UTC') - assert_kind_of(LinkedTimezoneInfo, info) - assert_equal('UTC', info.identifier) - assert_equal('Etc/UTC', info.link_to_identifier) - end - - def test_load_timezone_info_does_not_exist - assert_raises(InvalidTimezoneIdentifier) do - @data_source.load_timezone_info('Nowhere/Special') - end - end - - def test_load_timezone_info_invalid - assert_raises(InvalidTimezoneIdentifier) do - @data_source.load_timezone_info('../Definitions/UTC') - end - end - - def test_load_timezone_info_nil - assert_raises(InvalidTimezoneIdentifier) do - @data_source.load_timezone_info(nil) - end - end - - def test_load_timezone_info_case - assert_raises(InvalidTimezoneIdentifier) do - @data_source.load_timezone_info('europe/london') - end - end - - def test_load_timezone_info_plus - info = @data_source.load_timezone_info('Etc/GMT+1') - assert_equal('Etc/GMT+1', info.identifier) - end - - def test_load_timezone_info_minus - info = @data_source.load_timezone_info('Etc/GMT-1') - assert_equal('Etc/GMT-1', info.identifier) - end - - def test_load_timezone_info_tainted - skip_if_has_bug_14060 - - safe_test(:unavailable => :skip) do - identifier = 'Europe/Amsterdam'.dup.taint - assert(identifier.tainted?) - info = @data_source.load_timezone_info(identifier) - assert_equal('Europe/Amsterdam', info.identifier) - assert(identifier.tainted?) - end - end - - def test_load_timezone_info_tainted_and_frozen - skip_if_has_bug_14060 - - safe_test do - info = @data_source.load_timezone_info('Europe/Amsterdam'.dup.taint.freeze) - assert_equal('Europe/Amsterdam', info.identifier) - end - end - - def test_timezone_identifiers - all = @data_source.timezone_identifiers - assert_equal(TZInfo::Data::Indexes::Timezones.timezones, all) - assert_equal(true, all.frozen?) - end - - def test_data_timezone_identifiers - all_data = @data_source.data_timezone_identifiers - assert_equal(TZInfo::Data::Indexes::Timezones.data_timezones, all_data) - assert_equal(true, all_data.frozen?) - end - - def test_linked_timezone_identifiers - all_linked = @data_source.linked_timezone_identifiers - assert_equal(TZInfo::Data::Indexes::Timezones.linked_timezones, all_linked) - assert_equal(true, all_linked.frozen?) - end - - def test_load_country_info - info = @data_source.load_country_info('GB') - assert_equal('GB', info.code) - end - - def test_load_country_info_not_exist - assert_raises(InvalidCountryCode) do - @data_source.load_country_info('ZZ') - end - end - - def test_load_country_info_invalid - assert_raises(InvalidCountryCode) do - @data_source.load_country_info('../Countries/GB') - end - end - - def test_load_country_info_nil - assert_raises(InvalidCountryCode) do - @data_source.load_country_info(nil) - end - end - - def test_load_country_info_case - assert_raises(InvalidCountryCode) do - @data_source.load_country_info('gb') - end - end - - def test_load_country_info_tainted - safe_test(:unavailable => :skip) do - code = 'NL'.dup.taint - assert(code.tainted?) - info = @data_source.load_country_info(code) - assert_equal('NL', info.code) - assert(code.tainted?) - end - end - - def test_load_country_info_tainted_and_frozen - safe_test do - info = @data_source.load_country_info('NL'.dup.taint.freeze) - assert_equal('NL', info.code) - end - end - - def test_country_codes - codes = @data_source.country_codes - assert_equal(TZInfo::Data::Indexes::Countries.countries.keys, codes) - assert_equal(true, codes.frozen?) - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_time_or_datetime.rb ruby-tzinfo-2.0.4/test/tc_time_or_datetime.rb --- ruby-tzinfo-1.2.6/test/tc_time_or_datetime.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_time_or_datetime.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,660 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') -require 'rational' unless defined?(Rational) - -include TZInfo - -class TCTimeOrDateTime < Minitest::Test - # Ruby 1.8.7 (built with GCC 8.3.0 on Ubuntu 19.04) fails to perform DateTime - # arithmetic operations correctly when sub-seconds are used. Detect this and - # disable the affected tests. - DATETIME_SUBSECOND_ARITHMETIC_IS_BROKEN = (DateTime.new(2019, 12, 22, 15, 0, Rational(1, 1000)) + Rational(1, 86400)).strftime('%Q') != '1577026801001' - puts "DateTime sub-second arithmetic is broken on this platform" if DATETIME_SUBSECOND_ARITHMETIC_IS_BROKEN - - def test_initialize_time - assert_nothing_raised do - TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 721000)) - end - end - - def test_initialize_time_local - tdt = TimeOrDateTime.new(Time.local(2006, 3, 24, 15, 32, 3)) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 3), tdt.to_time) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 3), tdt.to_orig) - assert(tdt.to_time.utc?) - assert(tdt.to_orig.utc?) - end - - def test_intialize_time_local_usec - tdt = TimeOrDateTime.new(Time.local(2006, 3, 24, 15, 32, 3, 721123)) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 3, 721123), tdt.to_time) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 3, 721123), tdt.to_orig) - assert(tdt.to_time.utc?) - assert(tdt.to_orig.utc?) - end - - if Time.utc(2013, 1, 1).respond_to?(:nsec) - def test_initialize_time_local_nsec - tdt = TimeOrDateTime.new(Time.local(2006, 3, 24, 15, 32, 3, 721123 + Rational(456,1000))) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 3, 721123 + Rational(456,1000)), tdt.to_time) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 3, 721123 + Rational(456,1000)), tdt.to_orig) - assert(tdt.to_time.utc?) - assert(tdt.to_orig.utc?) - end - end - - def test_initialize_time_utc_local - # Check that local Time instances on systems using UTC as the system - # time zone are still converted to UTC Time instances. - - # Note that this will only test will only work correctly on platforms where - # setting the TZ environment variable has an effect. If setting TZ has no - # effect, then this test will still pass. - - old_tz = ENV['TZ'] - begin - ENV['TZ'] = 'UTC' - tdt = TimeOrDateTime.new(Time.local(2014, 1, 11, 17, 18, 41)) - assert_equal(Time.utc(2014, 1, 11, 17, 18, 41), tdt.to_time) - assert_equal(Time.utc(2014, 1, 11, 17, 18, 41), tdt.to_orig) - assert(tdt.to_time.utc?) - assert(tdt.to_orig.utc?) - ensure - ENV['TZ'] = old_tz - end - end - - def test_initialize_datetime_offset - tdt = TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3).new_offset(Rational(5, 24))) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 3), tdt.to_datetime) - assert_equal(0, tdt.to_datetime.offset) - end - - def test_initialize_datetime - assert_nothing_raised do - TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) - end - end - - def test_initialize_timestamp - assert_nothing_raised do - TimeOrDateTime.new(1143214323) - end - end - - def test_initialize_timestamp_string - assert_nothing_raised do - TimeOrDateTime.new('1143214323') - end - end - - unless RubyCoreSupport.time_supports_64bit - # Only define this test for non-64bit platforms. Some 64-bit Rubies support - # greater than 64-bit, others support less than the full range. In either - # case, times at the far ends of the range are so far in the future or past - # that they are not going to turn up in timezone data. - def test_initialize_timestamp_supported_range - assert_equal((2 ** 31) - 1, TimeOrDateTime.new((2 ** 31) - 1).to_orig) - - assert_raises(RangeError) do - TimeOrDateTime.new(2 ** 31) - end - - if RubyCoreSupport.time_supports_negative - assert_equal(-(2 ** 31), TimeOrDateTime.new(-(2 ** 31)).to_orig) - - assert_raises(RangeError) do - TimeOrDateTime.new(-(2 ** 31) - 1) - end - else - assert_equal(0, TimeOrDateTime.new(0).to_orig) - - assert_raises(RangeError) do - TimeOrDateTime.new(-1) - end - end - end - end - - def test_to_time - assert_equal(Time.utc(2006, 3, 24, 15, 32, 3), - TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)).to_time) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 3, 721123), - TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 721123)).to_time) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 3), - TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)).to_time) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 3, 721123), - TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721123, 1000000))).to_time) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 3), - TimeOrDateTime.new(1143214323).to_time) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 3), - TimeOrDateTime.new('1143214323').to_time) - end - - def test_to_time_trunc_to_usec - assert_equal(Time.utc(2006, 3, 24, 15, 32, 3, 721123), - TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(7211239, 10000000))).to_time) - end - - def test_to_time_after_freeze - assert_equal(Time.utc(2006, 3, 24, 15, 32, 3), TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)).freeze.to_time) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 3), TimeOrDateTime.new(1143214323).freeze.to_time) - end - - def test_to_datetime - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 3), - TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)).to_datetime) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721123, 1000000)), - TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 721123)).to_datetime) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721123, 1000000)), - TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721123, 1000000))).to_datetime) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 3), - TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)).to_datetime) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 3), - TimeOrDateTime.new(1143214323).to_datetime) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 3), - TimeOrDateTime.new('1143214323').to_datetime) - end - - def test_to_datetime_ruby186_bug - # DateTime.new in Ruby 1.8.6 won't allow a time to be specified using - # fractions of a second that is within the 60th second of a minute. - - # TimeOrDateTime has a workaround for this issue. - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 59) + Rational(721123, 86400000000), - TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 59, 721123)).to_datetime) - end - - def test_to_datetime_trunc_to_usec - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721123, 1000000)), - TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 721123 + Rational(9, 10))).to_datetime) - end - - def test_to_datetime_after_freeze - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 3), TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)).freeze.to_datetime) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 3), TimeOrDateTime.new(1143214323).freeze.to_datetime) - end - - def test_to_i - assert_equal(1143214323, - TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)).to_i) - assert_equal(1143214323, - TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 721000)).to_i) - assert_equal(1143214323, - TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)).to_i) - assert_equal(1143214323, - TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721, 1000))).to_i) - assert_equal(1143214323, - TimeOrDateTime.new(1143214323).to_i) - assert_equal(1143214323, - TimeOrDateTime.new('1143214323').to_i) - end - - def test_to_i_after_freeze - assert_equal(1143214323, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)).freeze.to_i) - assert_equal(1143214323, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)).freeze.to_i) - end - - def test_to_orig - assert_equal(Time.utc(2006, 3, 24, 15, 32, 3), - TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)).to_orig) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 3, 721000), - TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 721000)).to_orig) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 3), - TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)).to_orig) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721, 1000)), - TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721, 1000))).to_orig) - assert_equal(1143214323, - TimeOrDateTime.new(1143214323).to_orig) - assert_equal(1143214323, - TimeOrDateTime.new('1143214323').to_orig) - end - - def test_to_s - assert_equal("Time: #{Time.utc(2006, 3, 24, 15, 32, 3).to_s}", - TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)).to_s) - assert_equal("DateTime: #{DateTime.new(2006, 3, 24, 15, 32, 3)}", - TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)).to_s) - assert_equal('Timestamp: 1143214323', - TimeOrDateTime.new(1143214323).to_s) - assert_equal('Timestamp: 1143214323', - TimeOrDateTime.new('1143214323').to_s) - end - - def test_year - assert_equal(2006, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)).year) - assert_equal(2006, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)).year) - assert_equal(2006, TimeOrDateTime.new(1143214323).year) - end - - def test_mon - assert_equal(3, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)).mon) - assert_equal(3, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)).mon) - assert_equal(3, TimeOrDateTime.new(1143214323).mon) - end - - def test_month - assert_equal(3, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)).month) - assert_equal(3, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)).month) - assert_equal(3, TimeOrDateTime.new(1143214323).month) - end - - def test_mday - assert_equal(24, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)).mday) - assert_equal(24, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)).mday) - assert_equal(24, TimeOrDateTime.new(1143214323).mday) - end - - def test_day - assert_equal(24, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)).day) - assert_equal(24, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)).day) - assert_equal(24, TimeOrDateTime.new(1143214323).day) - end - - def test_hour - assert_equal(15, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)).hour) - assert_equal(15, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)).hour) - assert_equal(15, TimeOrDateTime.new(1143214323).hour) - end - - def test_min - assert_equal(32, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)).min) - assert_equal(32, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)).min) - assert_equal(32, TimeOrDateTime.new(1143214323).min) - end - - def test_sec - assert_equal(3, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)).sec) - assert_equal(3, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)).sec) - assert_equal(3, TimeOrDateTime.new(1143214323).sec) - end - - def test_usec - assert_equal(0, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)).usec) - assert_equal(721123, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 721123)).usec) - assert_equal(0, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)).usec) - assert_equal(721123, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721123,1000000))).usec) - assert_equal(0, TimeOrDateTime.new(1143214323).usec) - end - - def test_usec_after_to_i - val = TimeOrDateTime.new(Time.utc(2013, 2, 4, 22, 10, 33, 598000)) - assert_equal(Time.utc(2013, 2, 4, 22, 10, 33).to_i, val.to_i) - assert_equal(598000, val.usec) - end - - def test_compare_timeordatetime_time - assert_equal(-1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 4))) - assert_equal(-1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(Time.utc(2007, 3, 24, 15, 32, 3))) - assert_equal(0, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3))) - assert_equal(1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 2))) - assert_equal(1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(Time.utc(2005, 3, 24, 15, 32, 3))) - assert_equal(-1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 4))) - assert_equal(-1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(Time.utc(2007, 3, 24, 15, 32, 3))) - assert_equal(0, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3))) - assert_equal(1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 2))) - assert_equal(1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(Time.utc(2005, 3, 24, 15, 32, 3))) - assert_equal(-1, TimeOrDateTime.new(DateTime.new(1960, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3))) - assert_equal(1, TimeOrDateTime.new(DateTime.new(2040, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3))) - assert_equal(-1, TimeOrDateTime.new(1143214323) <=> TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 4))) - assert_equal(-1, TimeOrDateTime.new(1143214323) <=> TimeOrDateTime.new(Time.utc(2007, 3, 24, 15, 32, 3))) - assert_equal(0, TimeOrDateTime.new(1143214323) <=> TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3))) - assert_equal(1, TimeOrDateTime.new(1143214323) <=> TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 2))) - assert_equal(1, TimeOrDateTime.new(1143214323) <=> TimeOrDateTime.new(Time.utc(2005, 3, 24, 15, 32, 3))) - - assert_equal(-1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 500000)) <=> TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 500001))) - assert_equal(0, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 500000)) <=> TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 500000))) - assert_equal(1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 500000)) <=> TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 499999))) - assert_equal(-1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(500000, 1000000))) <=> TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 500000 + DATETIME_RESOLUTION))) - assert_equal(0, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(500000, 1000000))) <=> TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 500000))) - assert_equal(1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(500000, 1000000))) <=> TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 500000 - DATETIME_RESOLUTION))) - end - - def test_compare_timeordatetime_datetime - assert_equal(-1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 4))) - assert_equal(-1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(DateTime.new(2040, 3, 24, 15, 32, 3))) - assert_equal(0, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3))) - assert_equal(1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 2))) - assert_equal(1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(DateTime.new(1960, 3, 24, 15, 32, 3))) - assert_equal(-1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 4))) - assert_equal(-1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(DateTime.new(2040, 3, 24, 15, 32, 3))) - assert_equal(0, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3))) - assert_equal(1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 2))) - assert_equal(1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(DateTime.new(1960, 3, 24, 15, 32, 3))) - assert_equal(-1, TimeOrDateTime.new(DateTime.new(1960, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3))) - assert_equal(1, TimeOrDateTime.new(DateTime.new(2040, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3))) - assert_equal(-1, TimeOrDateTime.new(1143214323) <=> TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 4))) - assert_equal(-1, TimeOrDateTime.new(1143214323) <=> TimeOrDateTime.new(DateTime.new(2040, 3, 24, 15, 32, 3))) - assert_equal(0, TimeOrDateTime.new(1143214323) <=> TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3))) - assert_equal(1, TimeOrDateTime.new(1143214323) <=> TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 2))) - assert_equal(1, TimeOrDateTime.new(1143214323) <=> TimeOrDateTime.new(DateTime.new(1960, 3, 24, 15, 32, 3))) - - assert_equal(-1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 500000)) <=> TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(500000 + DATETIME_RESOLUTION, 1000000)))) - assert_equal(0, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 500000)) <=> TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(500000, 1000000)))) - assert_equal(1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 500000)) <=> TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(500000 - DATETIME_RESOLUTION, 1000000)))) - assert_equal(-1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(500000, 1000000))) <=> TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(500000 + DATETIME_RESOLUTION, 1000000)))) - assert_equal(0, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(500000, 1000000))) <=> TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(500000, 1000000)))) - assert_equal(1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(500000, 1000000))) <=> TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(500000 - DATETIME_RESOLUTION, 1000000)))) - end - - def test_compare_timeordatetime_timestamp - assert_equal(-1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(1143214324)) - assert_equal(-1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(1174750323)) - assert_equal(0, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(1143214323)) - assert_equal(1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(1143214322)) - assert_equal(1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(1111678323)) - assert_equal(-1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(1143214324)) - assert_equal(-1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(1174750323)) - assert_equal(0, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(1143214323)) - assert_equal(1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(1143214322)) - assert_equal(1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(1111678323)) - assert_equal(-1, TimeOrDateTime.new(DateTime.new(1960, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(1143214323)) - assert_equal(1, TimeOrDateTime.new(DateTime.new(2040, 3, 24, 15, 32, 3)) <=> TimeOrDateTime.new(1143214323)) - assert_equal(-1, TimeOrDateTime.new(1143214323) <=> TimeOrDateTime.new(1143214324)) - assert_equal(-1, TimeOrDateTime.new(1143214323) <=> TimeOrDateTime.new(1174750323)) - assert_equal(0, TimeOrDateTime.new(1143214323) <=> TimeOrDateTime.new(1143214323)) - assert_equal(1, TimeOrDateTime.new(1143214323) <=> TimeOrDateTime.new(1143214322)) - assert_equal(1, TimeOrDateTime.new(1143214323) <=> TimeOrDateTime.new(1111678323)) - end - - def test_compare_time - assert_equal(-1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> Time.utc(2006, 3, 24, 15, 32, 4)) - assert_equal(-1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> Time.utc(2007, 3, 24, 15, 32, 3)) - assert_equal(0, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> Time.utc(2006, 3, 24, 15, 32, 3)) - assert_equal(1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> Time.utc(2006, 3, 24, 15, 32, 2)) - assert_equal(1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> Time.utc(2005, 3, 24, 15, 32, 3)) - assert_equal(-1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> Time.utc(2006, 3, 24, 15, 32, 4)) - assert_equal(-1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> Time.utc(2007, 3, 24, 15, 32, 3)) - assert_equal(0, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> Time.utc(2006, 3, 24, 15, 32, 3)) - assert_equal(1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> Time.utc(2006, 3, 24, 15, 32, 2)) - assert_equal(1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> Time.utc(2005, 3, 24, 15, 32, 3)) - assert_equal(-1, TimeOrDateTime.new(DateTime.new(1960, 3, 24, 15, 32, 3)) <=> Time.utc(2006, 3, 24, 15, 32, 3)) - assert_equal(1, TimeOrDateTime.new(DateTime.new(2040, 3, 24, 15, 32, 3)) <=> Time.utc(2006, 3, 24, 15, 32, 3)) - assert_equal(-1, TimeOrDateTime.new(1143214323) <=> Time.utc(2006, 3, 24, 15, 32, 4)) - assert_equal(-1, TimeOrDateTime.new(1143214323) <=> Time.utc(2007, 3, 24, 15, 32, 3)) - assert_equal(0, TimeOrDateTime.new(1143214323) <=> Time.utc(2006, 3, 24, 15, 32, 3)) - assert_equal(1, TimeOrDateTime.new(1143214323) <=> Time.utc(2006, 3, 24, 15, 32, 2)) - assert_equal(1, TimeOrDateTime.new(1143214323) <=> Time.utc(2005, 3, 24, 15, 32, 3)) - - assert_equal(-1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 500000)) <=> Time.utc(2006, 3, 24, 15, 32, 3, 500001)) - assert_equal(0, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 500000)) <=> Time.utc(2006, 3, 24, 15, 32, 3, 500000)) - assert_equal(1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 500000)) <=> Time.utc(2006, 3, 24, 15, 32, 3, 499999)) - assert_equal(-1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(500000, 1000000))) <=> Time.utc(2006, 3, 24, 15, 32, 3, 500000 + DATETIME_RESOLUTION)) - assert_equal(0, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(500000, 1000000))) <=> Time.utc(2006, 3, 24, 15, 32, 3, 500000)) - assert_equal(1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(500000, 1000000))) <=> Time.utc(2006, 3, 24, 15, 32, 3, 500000 - DATETIME_RESOLUTION)) - end - - def test_compare_datetime - assert_equal(-1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> DateTime.new(2006, 3, 24, 15, 32, 4)) - assert_equal(-1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> DateTime.new(2040, 3, 24, 15, 32, 3)) - assert_equal(0, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> DateTime.new(2006, 3, 24, 15, 32, 3)) - assert_equal(1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> DateTime.new(2006, 3, 24, 15, 32, 2)) - assert_equal(1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> DateTime.new(1960, 3, 24, 15, 32, 3)) - assert_equal(-1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> DateTime.new(2006, 3, 24, 15, 32, 4)) - assert_equal(-1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> DateTime.new(2040, 3, 24, 15, 32, 3)) - assert_equal(0, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> DateTime.new(2006, 3, 24, 15, 32, 3)) - assert_equal(1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> DateTime.new(2006, 3, 24, 15, 32, 2)) - assert_equal(1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> DateTime.new(1960, 3, 24, 15, 32, 3)) - assert_equal(-1, TimeOrDateTime.new(DateTime.new(1960, 3, 24, 15, 32, 3)) <=> DateTime.new(2006, 3, 24, 15, 32, 3)) - assert_equal(1, TimeOrDateTime.new(DateTime.new(2040, 3, 24, 15, 32, 3)) <=> DateTime.new(2006, 3, 24, 15, 32, 3)) - assert_equal(-1, TimeOrDateTime.new(1143214323) <=> DateTime.new(2006, 3, 24, 15, 32, 4)) - assert_equal(-1, TimeOrDateTime.new(1143214323) <=> DateTime.new(2040, 3, 24, 15, 32, 3)) - assert_equal(0, TimeOrDateTime.new(1143214323) <=> DateTime.new(2006, 3, 24, 15, 32, 3)) - assert_equal(1, TimeOrDateTime.new(1143214323) <=> DateTime.new(2006, 3, 24, 15, 32, 2)) - assert_equal(1, TimeOrDateTime.new(1143214323) <=> DateTime.new(1960, 3, 24, 15, 32, 3)) - - assert_equal(-1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 500000)) <=> DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(500000 + DATETIME_RESOLUTION, 1000000))) - assert_equal(0, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 500000)) <=> DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(500000, 1000000))) - assert_equal(1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 500000)) <=> DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(500000 - DATETIME_RESOLUTION, 1000000))) - assert_equal(-1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(500000, 1000000))) <=> DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(500000 + DATETIME_RESOLUTION, 1000000))) - assert_equal(0, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(500000, 1000000))) <=> DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(500000, 1000000))) - assert_equal(1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(500000, 1000000))) <=> DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(500000 - DATETIME_RESOLUTION, 1000000))) - end - - def test_compare_timestamp - assert_equal(-1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> 1143214324) - assert_equal(-1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> 1174750323) - assert_equal(0, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> 1143214323) - assert_equal(1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> 1143214322) - assert_equal(1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> 1111678323) - assert_equal(-1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> 1143214324) - assert_equal(-1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> 1174750323) - assert_equal(0, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> 1143214323) - assert_equal(1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> 1143214322) - assert_equal(1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> 1111678323) - assert_equal(-1, TimeOrDateTime.new(DateTime.new(1960, 3, 24, 15, 32, 3)) <=> 1143214323) - assert_equal(1, TimeOrDateTime.new(DateTime.new(2040, 3, 24, 15, 32, 3)) <=> 1143214323) - assert_equal(-1, TimeOrDateTime.new(1143214323) <=> 1143214324) - assert_equal(-1, TimeOrDateTime.new(1143214323) <=> 1174750323) - assert_equal(0, TimeOrDateTime.new(1143214323) <=> 1143214323) - assert_equal(1, TimeOrDateTime.new(1143214323) <=> 1143214322) - assert_equal(1, TimeOrDateTime.new(1143214323) <=> 1111678323) - end - - def test_compare_timestamp_str - assert_equal(-1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> '1143214324') - assert_equal(-1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> '1174750323') - assert_equal(0, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> '1143214323') - assert_equal(1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> '1143214322') - assert_equal(1, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> '1111678323') - assert_equal(-1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> '1143214324') - assert_equal(-1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> '1174750323') - assert_equal(0, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> '1143214323') - assert_equal(1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> '1143214322') - assert_equal(1, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> '1111678323') - assert_equal(-1, TimeOrDateTime.new(DateTime.new(1960, 3, 24, 15, 32, 3)) <=> '1143214323') - assert_equal(1, TimeOrDateTime.new(DateTime.new(2040, 3, 24, 15, 32, 3)) <=> '1143214323') - assert_equal(-1, TimeOrDateTime.new(1143214323) <=> '1143214324') - assert_equal(-1, TimeOrDateTime.new(1143214323) <=> '1174750323') - assert_equal(0, TimeOrDateTime.new(1143214323) <=> '1143214323') - assert_equal(1, TimeOrDateTime.new(1143214323) <=> '1143214322') - assert_equal(1, TimeOrDateTime.new(1143214323) <=> '1111678323') - end - - def test_compare_non_comparable - assert_nil(TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) <=> Object.new) - assert_nil(TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) <=> Object.new) - assert_nil(TimeOrDateTime.new(1143214323) <=> Object.new) - end - - def test_eql - assert_equal(true, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)).eql?(TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)))) - assert_equal(false, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)).eql?(TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)))) - assert_equal(false, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)).eql?(TimeOrDateTime.new(1143214323))) - assert_equal(false, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)).eql?(TimeOrDateTime.new('1143214323'))) - assert_equal(false, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)).eql?(TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 4)))) - assert_equal(false, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)).eql?(Object.new)) - - assert_equal(true, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 721000)).eql?(TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 721000)))) - assert_equal(false, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 721000)).eql?(TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721, 1000))))) - assert_equal(false, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 721000)).eql?(TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 722000)))) - assert_equal(false, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 721000)).eql?(Object.new)) - - assert_equal(false, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)).eql?(TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)))) - assert_equal(true, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)).eql?(TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)))) - assert_equal(false, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)).eql?(TimeOrDateTime.new(1143214323))) - assert_equal(false, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)).eql?(TimeOrDateTime.new('1143214323'))) - assert_equal(false, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)).eql?(TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 4)))) - assert_equal(false, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)).eql?(Object.new)) - - assert_equal(false, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721, 1000))).eql?(TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 721000)))) - assert_equal(true, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721, 1000))).eql?(TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721, 1000))))) - assert_equal(false, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721, 1000))).eql?(TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(722, 1000))))) - assert_equal(false, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721, 1000))).eql?(Object.new)) - - - assert_equal(false, TimeOrDateTime.new(1143214323).eql?(TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)))) - assert_equal(false, TimeOrDateTime.new(1143214323).eql?(TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)))) - assert_equal(true, TimeOrDateTime.new(1143214323).eql?(TimeOrDateTime.new(1143214323))) - assert_equal(true, TimeOrDateTime.new(1143214323).eql?(TimeOrDateTime.new('1143214323'))) - assert_equal(false, TimeOrDateTime.new(1143214323).eql?(TimeOrDateTime.new(1143214324))) - assert_equal(false, TimeOrDateTime.new(1143214323).eql?(Object.new)) - end - - def test_hash - assert_equal(Time.utc(2006, 3, 24, 15, 32, 3).hash, TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)).hash) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 3).hash, TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)).hash) - assert_equal(1143214323.hash, TimeOrDateTime.new(1143214323).hash) - assert_equal(1143214323.hash, TimeOrDateTime.new('1143214323').hash) - end - - def test_add - assert_equal(Time.utc(2006, 3, 24, 15, 32, 3), (TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) + 0).to_orig) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 3, 721000), (TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 721000)) + 0).to_orig) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 3), (TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) + 0).to_orig) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721, 1000)), (TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721, 1000))) + 0).to_orig) - assert_equal(1143214323, (TimeOrDateTime.new(1143214323) + 0).to_orig) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 4), (TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) + 1).to_orig) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 4, 721000), (TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 721000)) + 1).to_orig) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 4), (TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) + 1).to_orig) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 4 + Rational(721, 1000)), (TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721, 1000))) + 1).to_orig) unless DATETIME_SUBSECOND_ARITHMETIC_IS_BROKEN - assert_equal(1143214324, (TimeOrDateTime.new(1143214323) + 1).to_orig) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 2), (TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) + (-1)).to_orig) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 2, 721000), (TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 721000)) + (-1)).to_orig) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 2), (TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) + (-1)).to_orig) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 2 + Rational(721, 1000)), (TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721, 1000))) + (-1)).to_orig) unless DATETIME_SUBSECOND_ARITHMETIC_IS_BROKEN - assert_equal(1143214322, (TimeOrDateTime.new(1143214323) + (-1)).to_orig) - end - - def test_subtract - assert_equal(Time.utc(2006, 3, 24, 15, 32, 3), (TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) - 0).to_orig) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 3, 721000), (TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 721000)) - 0).to_orig) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 3), (TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) - 0).to_orig) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721, 1000)), (TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721, 1000))) - 0).to_orig) - assert_equal(1143214323, (TimeOrDateTime.new(1143214323) - 0).to_orig) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 2), (TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) - 1).to_orig) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 2, 721000), (TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 721000)) - 1).to_orig) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 2), (TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) - 1).to_orig) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 2 + Rational(721, 1000)), (TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721, 1000))) - 1).to_orig) unless DATETIME_SUBSECOND_ARITHMETIC_IS_BROKEN - assert_equal(1143214322, (TimeOrDateTime.new(1143214323) - 1).to_orig) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 4), (TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)) - (-1)).to_orig) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 4, 721000), (TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 721000)) - (-1)).to_orig) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 4), (TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)) - (-1)).to_orig) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 4 + Rational(721, 1000)), (TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721, 1000))) - (-1)).to_orig) unless DATETIME_SUBSECOND_ARITHMETIC_IS_BROKEN - assert_equal(1143214324, (TimeOrDateTime.new(1143214323) - (-1)).to_orig) - end - - def test_add_with_convert - assert_equal(Time.utc(2006, 3, 24, 15, 32, 3), TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)).add_with_convert(0).to_orig) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 3, 721000), TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 721000)).add_with_convert(0).to_orig) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 3), TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)).add_with_convert(0).to_orig) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721, 1000)), TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721, 1000))).add_with_convert(0).to_orig) - assert_equal(1143214323, TimeOrDateTime.new(1143214323).add_with_convert(0).to_orig) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 4), TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)).add_with_convert(1).to_orig) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 4, 721000), TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 721000)).add_with_convert(1).to_orig) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 4), TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)).add_with_convert(1).to_orig) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 4 + Rational(721, 1000)), TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721, 1000))).add_with_convert(1).to_orig) unless DATETIME_SUBSECOND_ARITHMETIC_IS_BROKEN - assert_equal(1143214324, TimeOrDateTime.new(1143214323).add_with_convert(1).to_orig) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 2), TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3)).add_with_convert(-1).to_orig) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 2, 721000), TimeOrDateTime.new(Time.utc(2006, 3, 24, 15, 32, 3, 721000)).add_with_convert(-1).to_orig) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 2), TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3)).add_with_convert(-1).to_orig) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 2 + Rational(721, 1000)), TimeOrDateTime.new(DateTime.new(2006, 3, 24, 15, 32, 3 + Rational(721, 1000))).add_with_convert(-1).to_orig) unless DATETIME_SUBSECOND_ARITHMETIC_IS_BROKEN - assert_equal(1143214322, TimeOrDateTime.new(1143214323).add_with_convert(-1).to_orig) - - if RubyCoreSupport.time_supports_negative - assert_equal(Time.utc(1969, 12, 31, 23, 59, 59), TimeOrDateTime.new(Time.utc(1970, 1, 1, 0, 0, 0)).add_with_convert(-1).to_orig) - assert_equal(-1, TimeOrDateTime.new(0).add_with_convert(-1).to_orig) - assert_equal(Time.utc(1969, 12, 31, 23, 59, 59, 892000), TimeOrDateTime.new(Time.utc(1970, 1, 1, 0, 0, 0, 892000)).add_with_convert(-1).to_orig) - - if RubyCoreSupport.time_supports_64bit - assert_equal(Time.utc(1901, 12, 13, 20, 45, 51), TimeOrDateTime.new(Time.utc(1901, 12, 13, 20, 45, 52)).add_with_convert(-1).to_orig) - assert_equal(-2147483649, TimeOrDateTime.new(-2147483648).add_with_convert(-1).to_orig) - assert_equal(Time.utc(1901, 12, 13, 20, 45, 51, 892000), TimeOrDateTime.new(Time.utc(1901, 12, 13, 20, 45, 52, 892000)).add_with_convert(-1).to_orig) - else - assert_equal(DateTime.new(1901, 12, 13, 20, 45, 51), TimeOrDateTime.new(Time.utc(1901, 12, 13, 20, 45, 52)).add_with_convert(-1).to_orig) - assert_equal(DateTime.new(1901, 12, 13, 20, 45, 51), TimeOrDateTime.new(-2147483648).add_with_convert(-1).to_orig) - assert_equal(DateTime.new(1901, 12, 13, 20, 45, 51 + Rational(892,1000)), TimeOrDateTime.new(Time.utc(1901, 12, 13, 20, 45, 52, 892000)).add_with_convert(-1).to_orig) - end - else - assert_equal(DateTime.new(1969, 12, 31, 23, 59, 59), TimeOrDateTime.new(Time.utc(1970, 1, 1, 0, 0, 0)).add_with_convert(-1).to_orig) - assert_equal(DateTime.new(1969, 12, 31, 23, 59, 59), TimeOrDateTime.new(0).add_with_convert(-1).to_orig) - assert_equal(RubyCoreSupport.datetime_new(1969, 12, 31, 23, 59, 59 + Rational(892,1000)), TimeOrDateTime.new(Time.utc(1970, 1, 1, 0, 0, 0, 892000)).add_with_convert(-1).to_orig) - end - - if RubyCoreSupport.time_supports_64bit - assert_equal(Time.utc(2038, 1, 19, 3, 14, 8), TimeOrDateTime.new(Time.utc(2038, 1, 19, 3, 14, 7)).add_with_convert(1).to_orig) - assert_equal(2147483648, TimeOrDateTime.new(2147483647).add_with_convert(1).to_orig) - assert_equal(Time.utc(2038, 1, 19, 3, 14, 8, 892000), TimeOrDateTime.new(Time.utc(2038, 1, 19, 3, 14, 7, 892000)).add_with_convert(1).to_orig) - else - assert_equal(DateTime.new(2038, 1, 19, 3, 14, 8), TimeOrDateTime.new(Time.utc(2038, 1, 19, 3, 14, 7)).add_with_convert(1).to_orig) - assert_equal(DateTime.new(2038, 1, 19, 3, 14, 8), TimeOrDateTime.new(2147483647).add_with_convert(1).to_orig) - assert_equal(DateTime.new(2038, 1, 19, 3, 14, 8 + Rational(892,1000)), TimeOrDateTime.new(Time.utc(2038, 1, 19, 3, 14, 7, 892000)).add_with_convert(1).to_orig) - - assert_equal(Time.utc(2038, 1, 19, 3, 14, 7, 892000), TimeOrDateTime.new(Time.utc(2038, 1, 19, 3, 14, 6, 892000)).add_with_convert(1).to_orig) - end - end - - def test_wrap_time - t = TimeOrDateTime.wrap(Time.utc(2006, 3, 24, 15, 32, 3)) - assert_instance_of(TimeOrDateTime, t) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 3), t.to_orig) - end - - def test_wrap_datetime - t = TimeOrDateTime.wrap(DateTime.new(2006, 3, 24, 15, 32, 3)) - assert_instance_of(TimeOrDateTime, t) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 3), t.to_orig) - end - - def test_wrap_timestamp - t = TimeOrDateTime.wrap(1143214323) - assert_instance_of(TimeOrDateTime, t) - assert_equal(1143214323, t.to_orig) - end - - def test_wrap_timestamp_str - t = TimeOrDateTime.wrap('1143214323') - assert_instance_of(TimeOrDateTime, t) - assert_equal(1143214323, t.to_orig) - end - - def test_wrap_timeordatetime - t = TimeOrDateTime.new(1143214323) - t2 = TimeOrDateTime.wrap(t) - assert_same(t, t2) - end - - def test_wrap_block_time - assert_equal(Time.utc(2006, 3, 24, 15, 32, 4), TimeOrDateTime.wrap(Time.utc(2006, 3, 24, 15, 32, 3)) {|t| - assert_instance_of(TimeOrDateTime, t) - assert_equal(Time.utc(2006, 3, 24, 15, 32, 3), t.to_orig) - t + 1 - }) - end - - def test_wrap_block_datetime - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 4), TimeOrDateTime.wrap(DateTime.new(2006, 3, 24, 15, 32, 3)) {|t| - assert_instance_of(TimeOrDateTime, t) - assert_equal(DateTime.new(2006, 3, 24, 15, 32, 3), t.to_orig) - t + 1 - }) - end - - def test_wrap_block_timestamp - assert_equal(1143214324, TimeOrDateTime.wrap(1143214323) {|t| - assert_instance_of(TimeOrDateTime, t) - assert_equal(1143214323, t.to_orig) - t + 1 - }) - end - - def test_wrap_block_timestamp_str - assert_equal(1143214324, TimeOrDateTime.wrap('1143214323') {|t| - assert_instance_of(TimeOrDateTime, t) - assert_equal(1143214323, t.to_orig) - t + 1 - }) - end - - def test_wrap_block_timeordatetime - t1 = TimeOrDateTime.new(1143214323) - - t2 = TimeOrDateTime.wrap(t1) {|t| - assert_same(t1, t) - t + 1 - } - - assert t2 - assert_instance_of(TimeOrDateTime, t2) - assert_equal(1143214324, t2.to_orig) - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_timezone_definition.rb ruby-tzinfo-2.0.4/test/tc_timezone_definition.rb --- ruby-tzinfo-1.2.6/test/tc_timezone_definition.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_timezone_definition.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,113 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') - -include TZInfo - -class TCTimezoneDefinition < Minitest::Test - - module DataTest - include TimezoneDefinition - - timezone 'Test/Data/Zone' do |tz| - tz.offset :o0, -75, 0, :LMT - tz.offset :o1, 0, 0, :GMT - - tz.transition 1847, 12, :o1, 2760187969, 1152 - end - end - - module LinkedTest - include TimezoneDefinition - - linked_timezone 'Test/Linked/Zone', 'Test/Linked_To/Zone' - end - - module DoubleDataTest - include TimezoneDefinition - - timezone 'Test/Data/Zone1' do |tz| - tz.offset :o0, -75, 0, :LMT - tz.offset :o1, 0, 0, :GMT - - tz.transition 1847, 12, :o1, 2760187969, 1152 - end - - timezone 'Test/Data/Zone2' do |tz| - tz.offset :o0, 75, 0, :LMT - tz.offset :o1, 0, 0, :GMT - - tz.transition 1847, 12, :o1, 2760187969, 1152 - end - end - - module DoubleLinkedTest - include TimezoneDefinition - - linked_timezone 'Test/Linked/Zone1', 'Test/Linked_To/Zone1' - linked_timezone 'Test/Linked/Zone2', 'Test/Linked_To/Zone2' - end - - module DataLinkedTest - include TimezoneDefinition - - timezone 'Test/Data/Zone1' do |tz| - tz.offset :o0, -75, 0, :LMT - tz.offset :o1, 0, 0, :GMT - - tz.transition 1847, 12, :o1, 2760187969, 1152 - end - - linked_timezone 'Test/Linked/Zone2', 'Test/Linked_To/Zone2' - end - - module LinkedDataTest - include TimezoneDefinition - - linked_timezone 'Test/Linked/Zone1', 'Test/Linked_To/Zone1' - - timezone 'Test/Data/Zone2' do |tz| - tz.offset :o0, -75, 0, :LMT - tz.offset :o1, 0, 0, :GMT - - tz.transition 1847, 12, :o1, 2760187969, 1152 - end - end - - def test_data - assert_kind_of(TransitionDataTimezoneInfo, DataTest.get) - assert_equal('Test/Data/Zone', DataTest.get.identifier) - assert_equal(:LMT, DataTest.get.period_for_utc(DateTime.new(1847,12,1,0,1,14)).abbreviation) - assert_equal(:GMT, DataTest.get.period_for_utc(DateTime.new(1847,12,1,0,1,15)).abbreviation) - end - - def test_linked - assert_kind_of(LinkedTimezoneInfo, LinkedTest.get) - assert_equal('Test/Linked/Zone', LinkedTest.get.identifier) - assert_equal('Test/Linked_To/Zone', LinkedTest.get.link_to_identifier) - end - - def test_double_data - assert_kind_of(TransitionDataTimezoneInfo, DoubleDataTest.get) - assert_equal('Test/Data/Zone2', DoubleDataTest.get.identifier) - assert_equal(:LMT, DoubleDataTest.get.period_for_utc(DateTime.new(1847,12,1,0,1,14)).abbreviation) - assert_equal(:GMT, DoubleDataTest.get.period_for_utc(DateTime.new(1847,12,1,0,1,15)).abbreviation) - end - - def test_double_linked - assert_kind_of(LinkedTimezoneInfo, DoubleLinkedTest.get) - assert_equal('Test/Linked/Zone2', DoubleLinkedTest.get.identifier) - assert_equal('Test/Linked_To/Zone2', DoubleLinkedTest.get.link_to_identifier) - end - - def test_data_linked - assert_kind_of(LinkedTimezoneInfo, DataLinkedTest.get) - assert_equal('Test/Linked/Zone2', DataLinkedTest.get.identifier) - assert_equal('Test/Linked_To/Zone2', DataLinkedTest.get.link_to_identifier) - end - - def test_linked_data - assert_kind_of(TransitionDataTimezoneInfo, LinkedDataTest.get) - assert_equal('Test/Data/Zone2', LinkedDataTest.get.identifier) - assert_equal(:LMT, LinkedDataTest.get.period_for_utc(DateTime.new(1847,12,1,0,1,14)).abbreviation) - assert_equal(:GMT, LinkedDataTest.get.period_for_utc(DateTime.new(1847,12,1,0,1,15)).abbreviation) - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_timezone_index_definition.rb ruby-tzinfo-2.0.4/test/tc_timezone_index_definition.rb --- ruby-tzinfo-1.2.6/test/tc_timezone_index_definition.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_timezone_index_definition.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,73 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') - -include TZInfo - -class TCTimezoneIndexDefinition < Minitest::Test - - module TimezonesTest1 - include TimezoneIndexDefinition - - timezone 'Test/One' - timezone 'Test/Two' - linked_timezone 'Test/Three' - timezone 'Another/Zone' - linked_timezone 'And/Yet/Another' - end - - module TimezonesTest2 - include TimezoneIndexDefinition - - timezone 'Test/A/One' - timezone 'Test/A/Two' - timezone 'Test/A/Three' - end - - module TimezonesTest3 - include TimezoneIndexDefinition - - linked_timezone 'Test/B/One' - linked_timezone 'Test/B/Two' - linked_timezone 'Test/B/Three' - end - - module TimezonesTest4 - include TimezoneIndexDefinition - - end - - def test_timezones - assert_equal(['Test/One', 'Test/Two', 'Test/Three', 'Another/Zone', 'And/Yet/Another'], TimezonesTest1.timezones) - assert_equal(['Test/A/One', 'Test/A/Two', 'Test/A/Three'], TimezonesTest2.timezones) - assert_equal(['Test/B/One', 'Test/B/Two', 'Test/B/Three'], TimezonesTest3.timezones) - assert_equal([], TimezonesTest4.timezones) - - assert_equal(true, TimezonesTest1.timezones.frozen?) - assert_equal(true, TimezonesTest2.timezones.frozen?) - assert_equal(true, TimezonesTest3.timezones.frozen?) - assert_equal(true, TimezonesTest4.timezones.frozen?) - end - - def test_data_timezones - assert_equal(['Test/One', 'Test/Two', 'Another/Zone'], TimezonesTest1.data_timezones) - assert_equal(['Test/A/One', 'Test/A/Two', 'Test/A/Three'], TimezonesTest2.data_timezones) - assert_equal([], TimezonesTest3.data_timezones) - assert_equal([], TimezonesTest4.data_timezones) - - assert_equal(true, TimezonesTest1.data_timezones.frozen?) - assert_equal(true, TimezonesTest2.data_timezones.frozen?) - assert_equal(true, TimezonesTest3.data_timezones.frozen?) - assert_equal(true, TimezonesTest4.data_timezones.frozen?) - end - - def test_linked_timezones - assert_equal(['Test/Three', 'And/Yet/Another'], TimezonesTest1.linked_timezones) - assert_equal([], TimezonesTest2.linked_timezones) - assert_equal(['Test/B/One', 'Test/B/Two', 'Test/B/Three'], TimezonesTest3.linked_timezones) - assert_equal([], TimezonesTest4.linked_timezones) - - assert_equal(true, TimezonesTest1.linked_timezones.frozen?) - assert_equal(true, TimezonesTest2.linked_timezones.frozen?) - assert_equal(true, TimezonesTest3.linked_timezones.frozen?) - assert_equal(true, TimezonesTest4.linked_timezones.frozen?) - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_timezone_info.rb ruby-tzinfo-2.0.4/test/tc_timezone_info.rb --- ruby-tzinfo-1.2.6/test/tc_timezone_info.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_timezone_info.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') - -include TZInfo - -class TCTimezoneInfo < Minitest::Test - - def test_identifier - ti = TimezoneInfo.new('Test/Zone') - assert_equal('Test/Zone', ti.identifier) - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_timezone_london.rb ruby-tzinfo-2.0.4/test/tc_timezone_london.rb --- ruby-tzinfo-1.2.6/test/tc_timezone_london.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_timezone_london.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,143 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') - -include TZInfo - -class TCTimezoneLondon < Minitest::Test - def test_2004 - #Europe/London Sun Mar 28 00:59:59 2004 UTC = Sun Mar 28 00:59:59 2004 GMT isdst=0 gmtoff=0 - #Europe/London Sun Mar 28 01:00:00 2004 UTC = Sun Mar 28 02:00:00 2004 BST isdst=1 gmtoff=3600 - #Europe/London Sun Oct 31 00:59:59 2004 UTC = Sun Oct 31 01:59:59 2004 BST isdst=1 gmtoff=3600 - #Europe/London Sun Oct 31 01:00:00 2004 UTC = Sun Oct 31 01:00:00 2004 GMT isdst=0 gmtoff=0 - - tz = Timezone.get('Europe/London') - assert_equal(DateTime.new(2004,3,28,0,59,59), tz.utc_to_local(DateTime.new(2004,3,28,0,59,59))) - assert_equal(DateTime.new(2004,3,28,2,0,0), tz.utc_to_local(DateTime.new(2004,3,28,1,0,0))) - assert_equal(DateTime.new(2004,10,31,1,59,59), tz.utc_to_local(DateTime.new(2004,10,31,0,59,59))) - assert_equal(DateTime.new(2004,10,31,1,0,0), tz.utc_to_local(DateTime.new(2004,10,31,1,0,0))) - - assert_equal(DateTime.new(2004,3,28,0,59,59), tz.local_to_utc(DateTime.new(2004,3,28,0,59,59))) - assert_equal(DateTime.new(2004,3,28,1,0,0), tz.local_to_utc(DateTime.new(2004,3,28,2,0,0))) - assert_equal(DateTime.new(2004,10,31,0,59,59), tz.local_to_utc(DateTime.new(2004,10,31,1,59,59), true)) - assert_equal(DateTime.new(2004,10,31,1,59,59), tz.local_to_utc(DateTime.new(2004,10,31,1,59,59), false)) - assert_equal(DateTime.new(2004,10,31,0,0,0), tz.local_to_utc(DateTime.new(2004,10,31,1,0,0), true)) - assert_equal(DateTime.new(2004,10,31,1,0,0), tz.local_to_utc(DateTime.new(2004,10,31,1,0,0), false)) - - assert_raises(PeriodNotFound) { tz.local_to_utc(DateTime.new(2004,3,28,1,0,0)) } - assert_raises(AmbiguousTime) { tz.local_to_utc(DateTime.new(2004,10,31,1,0,0)) } - - assert_equal(:GMT, tz.period_for_utc(DateTime.new(2004,3,28,0,59,59)).zone_identifier) - assert_equal(:BST, tz.period_for_utc(DateTime.new(2004,3,28,1,0,0)).zone_identifier) - assert_equal(:BST, tz.period_for_utc(DateTime.new(2004,10,31,0,59,59)).zone_identifier) - assert_equal(:GMT, tz.period_for_utc(DateTime.new(2004,10,31,1,0,0)).zone_identifier) - - assert_equal(:GMT, tz.period_for_local(DateTime.new(2004,3,28,0,59,59)).zone_identifier) - assert_equal(:BST, tz.period_for_local(DateTime.new(2004,3,28,2,0,0)).zone_identifier) - assert_equal(:BST, tz.period_for_local(DateTime.new(2004,10,31,1,59,59), true).zone_identifier) - assert_equal(:GMT, tz.period_for_local(DateTime.new(2004,10,31,1,59,59), false).zone_identifier) - assert_equal(:BST, tz.period_for_local(DateTime.new(2004,10,31,1,0,0), true).zone_identifier) - assert_equal(:GMT, tz.period_for_local(DateTime.new(2004,10,31,1,0,0), false).zone_identifier) - - assert_equal(0, tz.period_for_utc(DateTime.new(2004,3,28,0,59,59)).utc_total_offset) - assert_equal(3600, tz.period_for_utc(DateTime.new(2004,3,28,1,0,0)).utc_total_offset) - assert_equal(3600, tz.period_for_utc(DateTime.new(2004,10,31,0,59,59)).utc_total_offset) - assert_equal(0, tz.period_for_utc(DateTime.new(2004,10,31,1,0,0)).utc_total_offset) - - assert_equal(0, tz.period_for_local(DateTime.new(2004,3,28,0,59,59)).utc_total_offset) - assert_equal(3600, tz.period_for_local(DateTime.new(2004,3,28,2,0,0)).utc_total_offset) - assert_equal(3600, tz.period_for_local(DateTime.new(2004,10,31,1,59,59), true).utc_total_offset) - assert_equal(0, tz.period_for_local(DateTime.new(2004,10,31,1,59,59), false).utc_total_offset) - assert_equal(3600, tz.period_for_local(DateTime.new(2004,10,31,1,0,0), true).utc_total_offset) - assert_equal(0, tz.period_for_local(DateTime.new(2004,10,31,1,0,0), false).utc_total_offset) - - transitions = tz.transitions_up_to(DateTime.new(2005,1,1,0,0,0), DateTime.new(2004,1,1,0,0,0)) - assert_equal(2, transitions.length) - assert_equal(TimeOrDateTime.new(DateTime.new(2004,3,28,1,0,0)), transitions[0].at) - assert_equal(TimezoneOffset.new(0, 0, :GMT), transitions[0].previous_offset) - assert_equal(TimezoneOffset.new(0, 3600, :BST), transitions[0].offset) - assert_equal(TimeOrDateTime.new(DateTime.new(2004,10,31,1,0,0)), transitions[1].at) - assert_equal(TimezoneOffset.new(0, 3600, :BST), transitions[1].previous_offset) - assert_equal(TimezoneOffset.new(0, 0, :GMT), transitions[1].offset) - - offsets = tz.offsets_up_to(DateTime.new(2005,1,1,0,0,0), DateTime.new(2004,1,1,0,0,0)) - assert_array_same_items([TimezoneOffset.new(0, 0, :GMT), TimezoneOffset.new(0, 3600, :BST)], offsets) - end - - def test_1961 - # This test cannot be run when using ZoneinfoDataSource on platforms - # that don't support Times before the epoch (i.e. Ruby < 1.9 on Windows) - # because it relates to the year 1961. - - if !DataSource.get.kind_of?(ZoneinfoDataSource) || RubyCoreSupport.time_supports_negative - #Europe/London Sun Mar 26 01:59:59 1961 UTC = Sun Mar 26 01:59:59 1961 GMT isdst=0 gmtoff=0 - #Europe/London Sun Mar 26 02:00:00 1961 UTC = Sun Mar 26 03:00:00 1961 BST isdst=1 gmtoff=3600 - #Europe/London Sun Oct 29 01:59:59 1961 UTC = Sun Oct 29 02:59:59 1961 BST isdst=1 gmtoff=3600 - #Europe/London Sun Oct 29 02:00:00 1961 UTC = Sun Oct 29 02:00:00 1961 GMT isdst=0 gmtoff=0 - - tz = Timezone.get('Europe/London') - assert_equal(DateTime.new(1961,3,26,1,59,59), tz.utc_to_local(DateTime.new(1961,3,26,1,59,59))) - assert_equal(DateTime.new(1961,3,26,3,0,0), tz.utc_to_local(DateTime.new(1961,3,26,2,0,0))) - assert_equal(DateTime.new(1961,10,29,2,59,59), tz.utc_to_local(DateTime.new(1961,10,29,1,59,59))) - assert_equal(DateTime.new(1961,10,29,2,0,0), tz.utc_to_local(DateTime.new(1961,10,29,2,0,0))) - - assert_equal(DateTime.new(1961,3,26,1,59,59), tz.local_to_utc(DateTime.new(1961,3,26,1,59,59))) - assert_equal(DateTime.new(1961,3,26,2,0,0), tz.local_to_utc(DateTime.new(1961,3,26,3,0,0))) - assert_equal(DateTime.new(1961,10,29,1,59,59), tz.local_to_utc(DateTime.new(1961,10,29,2,59,59), true)) - assert_equal(DateTime.new(1961,10,29,2,59,59), tz.local_to_utc(DateTime.new(1961,10,29,2,59,59), false)) - assert_equal(DateTime.new(1961,10,29,1,0,0), tz.local_to_utc(DateTime.new(1961,10,29,2,0,0), true)) - assert_equal(DateTime.new(1961,10,29,2,0,0), tz.local_to_utc(DateTime.new(1961,10,29,2,0,0), false)) - - assert_raises(PeriodNotFound) { tz.local_to_utc(DateTime.new(1961,3,26,2,0,0)) } - assert_raises(AmbiguousTime) { tz.local_to_utc(DateTime.new(1961,10,29,2,0,0)) } - - assert_equal(:GMT, tz.period_for_utc(DateTime.new(1961,3,26,1,59,59)).zone_identifier) - assert_equal(:BST, tz.period_for_utc(DateTime.new(1961,3,26,2,0,0)).zone_identifier) - assert_equal(:BST, tz.period_for_utc(DateTime.new(1961,10,29,1,59,59)).zone_identifier) - assert_equal(:GMT, tz.period_for_utc(DateTime.new(1961,10,29,2,0,0)).zone_identifier) - - assert_equal(:GMT, tz.period_for_local(DateTime.new(1961,3,26,1,59,59)).zone_identifier) - assert_equal(:BST, tz.period_for_local(DateTime.new(1961,3,26,3,0,0)).zone_identifier) - assert_equal(:BST, tz.period_for_local(DateTime.new(1961,10,29,2,59,59), true).zone_identifier) - assert_equal(:GMT, tz.period_for_local(DateTime.new(1961,10,29,2,59,59), false).zone_identifier) - assert_equal(:BST, tz.period_for_local(DateTime.new(1961,10,29,2,0,0), true).zone_identifier) - assert_equal(:GMT, tz.period_for_local(DateTime.new(1961,10,29,2,0,0), false).zone_identifier) - - assert_equal(0, tz.period_for_utc(DateTime.new(1961,3,26,1,59,59)).utc_total_offset) - assert_equal(3600, tz.period_for_utc(DateTime.new(1961,3,26,2,0,0)).utc_total_offset) - assert_equal(3600, tz.period_for_utc(DateTime.new(1961,10,29,1,59,59)).utc_total_offset) - assert_equal(0, tz.period_for_utc(DateTime.new(1961,10,29,2,0,0)).utc_total_offset) - - assert_equal(0, tz.period_for_local(DateTime.new(1961,3,26,1,59,59)).utc_total_offset) - assert_equal(3600, tz.period_for_local(DateTime.new(1961,3,26,3,0,0)).utc_total_offset) - assert_equal(3600, tz.period_for_local(DateTime.new(1961,10,29,2,59,59), true).utc_total_offset) - assert_equal(0, tz.period_for_local(DateTime.new(1961,10,29,2,59,59), false).utc_total_offset) - assert_equal(3600, tz.period_for_local(DateTime.new(1961,10,29,2,0,0), true).utc_total_offset) - assert_equal(0, tz.period_for_local(DateTime.new(1961,10,29,2,0,0), false).utc_total_offset) - - - transitions = tz.transitions_up_to(DateTime.new(1962,1,1,0,0,0), DateTime.new(1961,1,1,0,0,0)) - assert_equal(2, transitions.length) - assert_equal(TimeOrDateTime.new(DateTime.new(1961,3,26,2,0,0)), transitions[0].at) - assert_equal(TimezoneOffset.new(0, 0, :GMT), transitions[0].previous_offset) - assert_equal(TimezoneOffset.new(0, 3600, :BST), transitions[0].offset) - assert_equal(TimeOrDateTime.new(DateTime.new(1961,10,29,2,0,0)), transitions[1].at) - assert_equal(TimezoneOffset.new(0, 3600, :BST), transitions[1].previous_offset) - assert_equal(TimezoneOffset.new(0, 0, :GMT), transitions[1].offset) - - offsets = tz.offsets_up_to(DateTime.new(1962,1,1,0,0,0), DateTime.new(1961,1,1,0,0,0)) - assert_array_same_items([TimezoneOffset.new(0, 0, :GMT), TimezoneOffset.new(0, 3600, :BST)], offsets) - end - end - - def test_time_boundary - #Europe/London Sat Oct 26 23:00:00 1968 UTC = Sun Oct 27 00:00:00 1968 GMT isdst=0 gmtoff=3600 - #Europe/London Sun Oct 31 01:59:59 1971 UTC = Sun Oct 31 02:59:59 1971 GMT isdst=0 gmtoff=3600 - - tz = Timezone.get('Europe/London') - assert_equal(DateTime.new(1970,1,1,1,0,0), tz.utc_to_local(DateTime.new(1970,1,1,0,0,0))) - assert_equal(DateTime.new(1970,1,1,0,0,0), tz.local_to_utc(DateTime.new(1970,1,1,1,0,0))) - assert_equal(Time.utc(1970,1,1,1,0,0), tz.utc_to_local(Time.utc(1970,1,1,0,0,0))) - assert_equal(Time.utc(1970,1,1,0,0,0), tz.local_to_utc(Time.utc(1970,1,1,1,0,0))) - assert_equal(3600, tz.utc_to_local(0)) - assert_equal(0, tz.local_to_utc(3600)) - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_timezone_melbourne.rb ruby-tzinfo-2.0.4/test/tc_timezone_melbourne.rb --- ruby-tzinfo-1.2.6/test/tc_timezone_melbourne.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_timezone_melbourne.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,142 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') - -include TZInfo - -class TCTimezoneMelbourne < Minitest::Test - def test_2004 - #Australia/Melbourne Sat Mar 27 15:59:59 2004 UTC = Sun Mar 28 02:59:59 2004 AEDT isdst=1 gmtoff=39600 - #Australia/Melbourne Sat Mar 27 16:00:00 2004 UTC = Sun Mar 28 02:00:00 2004 AEST isdst=0 gmtoff=36000 - #Australia/Melbourne Sat Oct 30 15:59:59 2004 UTC = Sun Oct 31 01:59:59 2004 AEST isdst=0 gmtoff=36000 - #Australia/Melbourne Sat Oct 30 16:00:00 2004 UTC = Sun Oct 31 03:00:00 2004 AEDT isdst=1 gmtoff=39600 - - tz = Timezone.get('Australia/Melbourne') - assert_equal(DateTime.new(2004,3,28,2,59,59), tz.utc_to_local(DateTime.new(2004,3,27,15,59,59))) - assert_equal(DateTime.new(2004,3,28,2,0,0), tz.utc_to_local(DateTime.new(2004,3,27,16,0,0))) - assert_equal(DateTime.new(2004,10,31,1,59,59), tz.utc_to_local(DateTime.new(2004,10,30,15,59,59))) - assert_equal(DateTime.new(2004,10,31,3,0,0), tz.utc_to_local(DateTime.new(2004,10,30,16,0,0))) - - assert_equal(DateTime.new(2004,3,27,15,59,59), tz.local_to_utc(DateTime.new(2004,3,28,2,59,59), true)) - assert_equal(DateTime.new(2004,3,27,16,59,59), tz.local_to_utc(DateTime.new(2004,3,28,2,59,59), false)) - assert_equal(DateTime.new(2004,3,27,15,0,0), tz.local_to_utc(DateTime.new(2004,3,28,2,0,0), true)) - assert_equal(DateTime.new(2004,3,27,16,0,0), tz.local_to_utc(DateTime.new(2004,3,28,2,0,0), false)) - assert_equal(DateTime.new(2004,10,30,15,59,59), tz.local_to_utc(DateTime.new(2004,10,31,1,59,59))) - assert_equal(DateTime.new(2004,10,30,16,0,0), tz.local_to_utc(DateTime.new(2004,10,31,3,0,0))) - - assert_raises(PeriodNotFound) { tz.local_to_utc(DateTime.new(2004,10,31,2,0,0)) } - assert_raises(AmbiguousTime) { tz.local_to_utc(DateTime.new(2004,3,28,2,0,0)) } - - assert_equal(:AEDT, tz.period_for_utc(DateTime.new(2004,3,27,15,59,59)).zone_identifier) - assert_equal(:AEST, tz.period_for_utc(DateTime.new(2004,3,27,16,0,0)).zone_identifier) - assert_equal(:AEST, tz.period_for_utc(DateTime.new(2004,10,30,15,59,59)).zone_identifier) - assert_equal(:AEDT, tz.period_for_utc(DateTime.new(2004,10,30,16,0,0)).zone_identifier) - - assert_equal(:AEDT, tz.period_for_local(DateTime.new(2004,3,28,2,59,59), true).zone_identifier) - assert_equal(:AEST, tz.period_for_local(DateTime.new(2004,3,28,2,59,59), false).zone_identifier) - assert_equal(:AEDT, tz.period_for_local(DateTime.new(2004,3,28,2,0,0), true).zone_identifier) - assert_equal(:AEST, tz.period_for_local(DateTime.new(2004,3,28,2,0,0), false).zone_identifier) - assert_equal(:AEST, tz.period_for_local(DateTime.new(2004,10,31,1,59,59)).zone_identifier) - assert_equal(:AEDT, tz.period_for_local(DateTime.new(2004,10,31,3,0,0)).zone_identifier) - - assert_equal(39600, tz.period_for_utc(DateTime.new(2004,3,27,15,59,59)).utc_total_offset) - assert_equal(36000, tz.period_for_utc(DateTime.new(2004,3,27,16,0,0)).utc_total_offset) - assert_equal(36000, tz.period_for_utc(DateTime.new(2004,10,30,15,59,59)).utc_total_offset) - assert_equal(39600, tz.period_for_utc(DateTime.new(2004,10,30,16,0,0)).utc_total_offset) - - assert_equal(39600, tz.period_for_local(DateTime.new(2004,3,28,2,59,59), true).utc_total_offset) - assert_equal(36000, tz.period_for_local(DateTime.new(2004,3,28,2,59,59), false).utc_total_offset) - assert_equal(39600, tz.period_for_local(DateTime.new(2004,3,28,2,0,0), true).utc_total_offset) - assert_equal(36000, tz.period_for_local(DateTime.new(2004,3,28,2,0,0), false).utc_total_offset) - assert_equal(36000, tz.period_for_local(DateTime.new(2004,10,31,1,59,59)).utc_total_offset) - assert_equal(39600, tz.period_for_local(DateTime.new(2004,10,31,3,0,0)).utc_total_offset) - - transitions = tz.transitions_up_to(DateTime.new(2005,1,1,0,0,0), DateTime.new(2004,1,1,0,0,0)) - assert_equal(2, transitions.length) - assert_equal(TimeOrDateTime.new(DateTime.new(2004,3,27,16,0,0)), transitions[0].at) - assert_equal(TimezoneOffset.new(36000, 3600, :AEDT), transitions[0].previous_offset) - assert_equal(TimezoneOffset.new(36000, 0, :AEST), transitions[0].offset) - assert_equal(TimeOrDateTime.new(DateTime.new(2004,10,30,16,0,0)), transitions[1].at) - assert_equal(TimezoneOffset.new(36000, 0, :AEST), transitions[1].previous_offset) - assert_equal(TimezoneOffset.new(36000, 3600, :AEDT), transitions[1].offset) - - offsets = tz.offsets_up_to(DateTime.new(2005,1,1,0,0,0), DateTime.new(2004,1,1,0,0,0)) - assert_array_same_items([TimezoneOffset.new(36000, 0, :AEST), TimezoneOffset.new(36000, 3600, :AEDT)], offsets) - end - - def test_1942 - # This test cannot be run when using ZoneinfoDataSource on platforms - # that don't support Times before the epoch (i.e. Ruby < 1.9 on Windows) - # because it relates to the year 1942. - - if !DataSource.get.kind_of?(ZoneinfoDataSource) || RubyCoreSupport.time_supports_negative - #Australia/Melbourne Sat Mar 28 14:59:59 1942 UTC = Sun Mar 29 01:59:59 1942 AEDT isdst=1 gmtoff=39600 - #Australia/Melbourne Sat Mar 28 15:00:00 1942 UTC = Sun Mar 29 01:00:00 1942 AEST isdst=0 gmtoff=36000 - #Australia/Melbourne Sat Sep 26 15:59:59 1942 UTC = Sun Sep 27 01:59:59 1942 AEST isdst=0 gmtoff=36000 - #Australia/Melbourne Sat Sep 26 16:00:00 1942 UTC = Sun Sep 27 03:00:00 1942 AEDT isdst=1 gmtoff=39600 - - tz = Timezone.get('Australia/Melbourne') - assert_equal(DateTime.new(1942,3,29,1,59,59), tz.utc_to_local(DateTime.new(1942,3,28,14,59,59))) - assert_equal(DateTime.new(1942,3,29,1,0,0), tz.utc_to_local(DateTime.new(1942,3,28,15,0,0))) - assert_equal(DateTime.new(1942,9,27,1,59,59), tz.utc_to_local(DateTime.new(1942,9,26,15,59,59))) - assert_equal(DateTime.new(1942,9,27,3,0,0), tz.utc_to_local(DateTime.new(1942,9,26,16,0,0))) - - assert_equal(DateTime.new(1942,3,28,14,59,59), tz.local_to_utc(DateTime.new(1942,3,29,1,59,59), true)) - assert_equal(DateTime.new(1942,3,28,15,59,59), tz.local_to_utc(DateTime.new(1942,3,29,1,59,59), false)) - assert_equal(DateTime.new(1942,3,28,14,0,0), tz.local_to_utc(DateTime.new(1942,3,29,1,0,0), true)) - assert_equal(DateTime.new(1942,3,28,15,0,0), tz.local_to_utc(DateTime.new(1942,3,29,1,0,0), false)) - assert_equal(DateTime.new(1942,9,26,15,59,59), tz.local_to_utc(DateTime.new(1942,9,27,1,59,59))) - assert_equal(DateTime.new(1942,9,26,16,0,0), tz.local_to_utc(DateTime.new(1942,9,27,3,0,0))) - - assert_raises(PeriodNotFound) { tz.local_to_utc(DateTime.new(1942,9,27,2,0,0)) } - assert_raises(AmbiguousTime) { tz.local_to_utc(DateTime.new(1942,3,29,1,0,0)) } - - assert_equal(:AEDT, tz.period_for_utc(DateTime.new(1942,3,28,14,59,59)).zone_identifier) - assert_equal(:AEST, tz.period_for_utc(DateTime.new(1942,3,28,15,0,0)).zone_identifier) - assert_equal(:AEST, tz.period_for_utc(DateTime.new(1942,9,26,15,59,59)).zone_identifier) - assert_equal(:AEDT, tz.period_for_utc(DateTime.new(1942,9,26,16,0,0)).zone_identifier) - - assert_equal(:AEDT, tz.period_for_local(DateTime.new(1942,3,29,1,59,59), true).zone_identifier) - assert_equal(:AEST, tz.period_for_local(DateTime.new(1942,3,29,1,59,59), false).zone_identifier) - assert_equal(:AEDT, tz.period_for_local(DateTime.new(1942,3,29,1,0,0), true).zone_identifier) - assert_equal(:AEST, tz.period_for_local(DateTime.new(1942,3,29,1,0,0), false).zone_identifier) - assert_equal(:AEST, tz.period_for_local(DateTime.new(1942,9,27,1,59,59)).zone_identifier) - assert_equal(:AEDT, tz.period_for_local(DateTime.new(1942,9,27,3,0,0)).zone_identifier) - - assert_equal(39600, tz.period_for_utc(DateTime.new(1942,3,28,14,59,59)).utc_total_offset) - assert_equal(36000, tz.period_for_utc(DateTime.new(1942,3,28,15,0,0)).utc_total_offset) - assert_equal(36000, tz.period_for_utc(DateTime.new(1942,9,26,15,59,59)).utc_total_offset) - assert_equal(39600, tz.period_for_utc(DateTime.new(1942,9,26,16,0,0)).utc_total_offset) - - assert_equal(39600, tz.period_for_local(DateTime.new(1942,3,29,1,59,59), true).utc_total_offset) - assert_equal(36000, tz.period_for_local(DateTime.new(1942,3,29,1,59,59), false).utc_total_offset) - assert_equal(39600, tz.period_for_local(DateTime.new(1942,3,29,1,0,0), true).utc_total_offset) - assert_equal(36000, tz.period_for_local(DateTime.new(1942,3,29,1,0,0), false).utc_total_offset) - assert_equal(36000, tz.period_for_local(DateTime.new(1942,9,27,1,59,59)).utc_total_offset) - assert_equal(39600, tz.period_for_local(DateTime.new(1942,9,27,3,0,0)).utc_total_offset) - - transitions = tz.transitions_up_to(DateTime.new(1943,1,1,0,0,0), DateTime.new(1942,1,1,0,0,0)) - assert_equal(2, transitions.length) - assert_equal(TimeOrDateTime.new(DateTime.new(1942,3,28,15,0,0)), transitions[0].at) - assert_equal(TimezoneOffset.new(36000, 3600, :AEDT), transitions[0].previous_offset) - assert_equal(TimezoneOffset.new(36000, 0, :AEST), transitions[0].offset) - assert_equal(TimeOrDateTime.new(DateTime.new(1942,9,26,16,0,0)), transitions[1].at) - assert_equal(TimezoneOffset.new(36000, 0, :AEST), transitions[1].previous_offset) - assert_equal(TimezoneOffset.new(36000, 3600, :AEDT), transitions[1].offset) - - offsets = tz.offsets_up_to(DateTime.new(1943,1,1,0,0,0), DateTime.new(1942,1,1,0,0,0)) - assert_array_same_items([TimezoneOffset.new(36000, 0, :AEST), TimezoneOffset.new(36000, 3600, :AEDT)], offsets) - end - end - - def test_time_boundary - #Australia/Melbourne Sat Mar 25 15:00:00 1944 UTC = Sun Mar 26 01:00:00 1944 AEST isdst=0 gmtoff=36000 - #Australia/Melbourne Sat Oct 30 15:59:59 1971 UTC = Sun Oct 31 01:59:59 1971 AEST isdst=0 gmtoff=36000 - - tz = Timezone.get('Australia/Melbourne') - assert_equal(DateTime.new(1970,1,1,10,0,0), tz.utc_to_local(DateTime.new(1970,1,1,0,0,0))) - assert_equal(DateTime.new(1970,1,1,0,0,0), tz.local_to_utc(DateTime.new(1970,1,1,10,0,0))) - assert_equal(Time.utc(1970,1,1,10,0,0), tz.utc_to_local(Time.utc(1970,1,1,0,0,0))) - assert_equal(Time.utc(1970,1,1,0,0,0), tz.local_to_utc(Time.utc(1970,1,1,10,0,0))) - assert_equal(36000, tz.utc_to_local(0)) - assert_equal(0, tz.local_to_utc(36000)) - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_timezone_new_york.rb ruby-tzinfo-2.0.4/test/tc_timezone_new_york.rb --- ruby-tzinfo-1.2.6/test/tc_timezone_new_york.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_timezone_new_york.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,142 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') - -include TZInfo - -class TCTimezoneNewYork < Minitest::Test - def test_2004 - #America/New_York Sun Apr 4 06:59:59 2004 UTC = Sun Apr 4 01:59:59 2004 EST isdst=0 gmtoff=-18000 - #America/New_York Sun Apr 4 07:00:00 2004 UTC = Sun Apr 4 03:00:00 2004 EDT isdst=1 gmtoff=-14400 - #America/New_York Sun Oct 31 05:59:59 2004 UTC = Sun Oct 31 01:59:59 2004 EDT isdst=1 gmtoff=-14400 - #America/New_York Sun Oct 31 06:00:00 2004 UTC = Sun Oct 31 01:00:00 2004 EST isdst=0 gmtoff=-18000 - - tz = Timezone.get('America/New_York') - assert_equal(DateTime.new(2004,4,4,1,59,59), tz.utc_to_local(DateTime.new(2004,4,4,6,59,59))) - assert_equal(DateTime.new(2004,4,4,3,0,0), tz.utc_to_local(DateTime.new(2004,4,4,7,0,0))) - assert_equal(DateTime.new(2004,10,31,1,59,59), tz.utc_to_local(DateTime.new(2004,10,31,5,59,59))) - assert_equal(DateTime.new(2004,10,31,1,0,0), tz.utc_to_local(DateTime.new(2004,10,31,6,0,0))) - - assert_equal(DateTime.new(2004,4,4,6,59,59), tz.local_to_utc(DateTime.new(2004,4,4,1,59,59))) - assert_equal(DateTime.new(2004,4,4,7,0,0), tz.local_to_utc(DateTime.new(2004,4,4,3,0,0))) - assert_equal(DateTime.new(2004,10,31,5,59,59), tz.local_to_utc(DateTime.new(2004,10,31,1,59,59), true)) - assert_equal(DateTime.new(2004,10,31,6,59,59), tz.local_to_utc(DateTime.new(2004,10,31,1,59,59), false)) - assert_equal(DateTime.new(2004,10,31,5,0,0), tz.local_to_utc(DateTime.new(2004,10,31,1,0,0), true)) - assert_equal(DateTime.new(2004,10,31,6,0,0), tz.local_to_utc(DateTime.new(2004,10,31,1,0,0), false)) - - assert_raises(PeriodNotFound) { tz.local_to_utc(DateTime.new(2004,4,4,2,0,0)) } - assert_raises(AmbiguousTime) { tz.local_to_utc(DateTime.new(2004,10,31,1,0,0)) } - - assert_equal(:EST, tz.period_for_utc(DateTime.new(2004,4,4,6,59,59)).zone_identifier) - assert_equal(:EDT, tz.period_for_utc(DateTime.new(2004,4,4,7,0,0)).zone_identifier) - assert_equal(:EDT, tz.period_for_utc(DateTime.new(2004,10,31,5,59,59)).zone_identifier) - assert_equal(:EST, tz.period_for_utc(DateTime.new(2004,10,31,6,0,0)).zone_identifier) - - assert_equal(:EST, tz.period_for_local(DateTime.new(2004,4,4,1,59,59)).zone_identifier) - assert_equal(:EDT, tz.period_for_local(DateTime.new(2004,4,4,3,0,0)).zone_identifier) - assert_equal(:EDT, tz.period_for_local(DateTime.new(2004,10,31,1,59,59), true).zone_identifier) - assert_equal(:EST, tz.period_for_local(DateTime.new(2004,10,31,1,59,59), false).zone_identifier) - assert_equal(:EDT, tz.period_for_local(DateTime.new(2004,10,31,1,0,0), true).zone_identifier) - assert_equal(:EST, tz.period_for_local(DateTime.new(2004,10,31,1,0,0), false).zone_identifier) - - assert_equal(-18000, tz.period_for_utc(DateTime.new(2004,4,4,6,59,59)).utc_total_offset) - assert_equal(-14400, tz.period_for_utc(DateTime.new(2004,4,4,7,0,0)).utc_total_offset) - assert_equal(-14400, tz.period_for_utc(DateTime.new(2004,10,31,5,59,59)).utc_total_offset) - assert_equal(-18000, tz.period_for_utc(DateTime.new(2004,10,31,6,0,0)).utc_total_offset) - - assert_equal(-18000, tz.period_for_local(DateTime.new(2004,4,4,1,59,59)).utc_total_offset) - assert_equal(-14400, tz.period_for_local(DateTime.new(2004,4,4,3,0,0)).utc_total_offset) - assert_equal(-14400, tz.period_for_local(DateTime.new(2004,10,31,1,59,59), true).utc_total_offset) - assert_equal(-18000, tz.period_for_local(DateTime.new(2004,10,31,1,59,59), false).utc_total_offset) - assert_equal(-14400, tz.period_for_local(DateTime.new(2004,10,31,1,0,0), true).utc_total_offset) - assert_equal(-18000, tz.period_for_local(DateTime.new(2004,10,31,1,0,0), false).utc_total_offset) - - transitions = tz.transitions_up_to(DateTime.new(2005,1,1,0,0,0), DateTime.new(2004,1,1,0,0,0)) - assert_equal(2, transitions.length) - assert_equal(TimeOrDateTime.new(DateTime.new(2004,4,4,7,0,0)), transitions[0].at) - assert_equal(TimezoneOffset.new(-18000, 0, :EST), transitions[0].previous_offset) - assert_equal(TimezoneOffset.new(-18000, 3600, :EDT), transitions[0].offset) - assert_equal(TimeOrDateTime.new(DateTime.new(2004,10,31,6,0,0)), transitions[1].at) - assert_equal(TimezoneOffset.new(-18000, 3600, :EDT), transitions[1].previous_offset) - assert_equal(TimezoneOffset.new(-18000, 0, :EST), transitions[1].offset) - - offsets = tz.offsets_up_to(DateTime.new(2005,1,1,0,0,0), DateTime.new(2004,1,1,0,0,0)) - assert_array_same_items([TimezoneOffset.new(-18000, 0, :EST), TimezoneOffset.new(-18000, 3600, :EDT)], offsets) - end - - def test_1957 - # This test cannot be run when using ZoneinfoDataSource on platforms - # that don't support Times before the epoch (i.e. Ruby < 1.9 on Windows) - # because it relates to the year 1957. - - if !DataSource.get.kind_of?(ZoneinfoDataSource) || RubyCoreSupport.time_supports_negative - #America/New_York Sun Apr 28 06:59:59 1957 UTC = Sun Apr 28 01:59:59 1957 EST isdst=0 gmtoff=-18000 - #America/New_York Sun Apr 28 07:00:00 1957 UTC = Sun Apr 28 03:00:00 1957 EDT isdst=1 gmtoff=-14400 - #America/New_York Sun Oct 27 05:59:59 1957 UTC = Sun Oct 27 01:59:59 1957 EDT isdst=1 gmtoff=-14400 - #America/New_York Sun Oct 27 06:00:00 1957 UTC = Sun Oct 27 01:00:00 1957 EST isdst=0 gmtoff=-18000 - - tz = Timezone.get('America/New_York') - assert_equal(DateTime.new(1957,4,28,1,59,59), tz.utc_to_local(DateTime.new(1957,4,28,6,59,59))) - assert_equal(DateTime.new(1957,4,28,3,0,0), tz.utc_to_local(DateTime.new(1957,4,28,7,0,0))) - assert_equal(DateTime.new(1957,10,27,1,59,59), tz.utc_to_local(DateTime.new(1957,10,27,5,59,59))) - assert_equal(DateTime.new(1957,10,27,1,0,0), tz.utc_to_local(DateTime.new(1957,10,27,6,0,0))) - - assert_equal(DateTime.new(1957,4,28,6,59,59), tz.local_to_utc(DateTime.new(1957,4,28,1,59,59))) - assert_equal(DateTime.new(1957,4,28,7,0,0), tz.local_to_utc(DateTime.new(1957,4,28,3,0,0))) - assert_equal(DateTime.new(1957,10,27,5,59,59), tz.local_to_utc(DateTime.new(1957,10,27,1,59,59), true)) - assert_equal(DateTime.new(1957,10,27,6,59,59), tz.local_to_utc(DateTime.new(1957,10,27,1,59,59), false)) - assert_equal(DateTime.new(1957,10,27,5,0,0), tz.local_to_utc(DateTime.new(1957,10,27,1,0,0), true)) - assert_equal(DateTime.new(1957,10,27,6,0,0), tz.local_to_utc(DateTime.new(1957,10,27,1,0,0), false)) - - assert_raises(PeriodNotFound) { tz.local_to_utc(DateTime.new(1957,4,28,2,0,0)) } - assert_raises(AmbiguousTime) { tz.local_to_utc(DateTime.new(1957,10,27,1,0,0)) } - - assert_equal(:EST, tz.period_for_utc(DateTime.new(1957,4,28,6,59,59)).zone_identifier) - assert_equal(:EDT, tz.period_for_utc(DateTime.new(1957,4,28,7,0,0)).zone_identifier) - assert_equal(:EDT, tz.period_for_utc(DateTime.new(1957,10,27,5,59,59)).zone_identifier) - assert_equal(:EST, tz.period_for_utc(DateTime.new(1957,10,27,6,0,0)).zone_identifier) - - assert_equal(:EST, tz.period_for_local(DateTime.new(1957,4,28,1,59,59)).zone_identifier) - assert_equal(:EDT, tz.period_for_local(DateTime.new(1957,4,28,3,0,0)).zone_identifier) - assert_equal(:EDT, tz.period_for_local(DateTime.new(1957,10,27,1,59,59), true).zone_identifier) - assert_equal(:EST, tz.period_for_local(DateTime.new(1957,10,27,1,59,59), false).zone_identifier) - assert_equal(:EDT, tz.period_for_local(DateTime.new(1957,10,27,1,0,0), true).zone_identifier) - assert_equal(:EST, tz.period_for_local(DateTime.new(1957,10,27,1,0,0), false).zone_identifier) - - assert_equal(-18000, tz.period_for_utc(DateTime.new(1957,4,28,6,59,59)).utc_total_offset) - assert_equal(-14400, tz.period_for_utc(DateTime.new(1957,4,28,7,0,0)).utc_total_offset) - assert_equal(-14400, tz.period_for_utc(DateTime.new(1957,10,27,5,59,59)).utc_total_offset) - assert_equal(-18000, tz.period_for_utc(DateTime.new(1957,10,27,6,0,0)).utc_total_offset) - - assert_equal(-18000, tz.period_for_local(DateTime.new(1957,4,28,1,59,59)).utc_total_offset) - assert_equal(-14400, tz.period_for_local(DateTime.new(1957,4,28,3,0,0)).utc_total_offset) - assert_equal(-14400, tz.period_for_local(DateTime.new(1957,10,27,1,59,59), true).utc_total_offset) - assert_equal(-18000, tz.period_for_local(DateTime.new(1957,10,27,1,59,59), false).utc_total_offset) - assert_equal(-14400, tz.period_for_local(DateTime.new(1957,10,27,1,0,0), true).utc_total_offset) - assert_equal(-18000, tz.period_for_local(DateTime.new(1957,10,27,1,0,0), false).utc_total_offset) - - transitions = tz.transitions_up_to(DateTime.new(1958,1,1,0,0,0), DateTime.new(1957,1,1,0,0,0)) - assert_equal(2, transitions.length) - assert_equal(TimeOrDateTime.new(DateTime.new(1957,4,28,7,0,0)), transitions[0].at) - assert_equal(TimezoneOffset.new(-18000, 0, :EST), transitions[0].previous_offset) - assert_equal(TimezoneOffset.new(-18000, 3600, :EDT), transitions[0].offset) - assert_equal(TimeOrDateTime.new(DateTime.new(1957,10,27,6,0,0)), transitions[1].at) - assert_equal(TimezoneOffset.new(-18000, 3600, :EDT), transitions[1].previous_offset) - assert_equal(TimezoneOffset.new(-18000, 0, :EST), transitions[1].offset) - - offsets = tz.offsets_up_to(DateTime.new(1958,1,1,0,0,0), DateTime.new(1957,1,1,0,0,0)) - assert_array_same_items([TimezoneOffset.new(-18000, 0, :EST), TimezoneOffset.new(-18000, 3600, :EDT)], offsets) - end - end - - def test_time_boundary - #America/New_York Sun Oct 26 06:00:00 1969 UTC = Sun Oct 26 01:00:00 1969 EST isdst=0 gmtoff=-18000 - #America/New_York Sun Apr 26 06:59:59 1970 UTC = Sun Apr 26 01:59:59 1970 EST isdst=0 gmtoff=-18000 - - tz = Timezone.get('America/New_York') - assert_equal(DateTime.new(1970,1,1,0,0,0), tz.utc_to_local(DateTime.new(1970,1,1,5,0,0))) - assert_equal(DateTime.new(1970,1,1,5,0,0), tz.local_to_utc(DateTime.new(1970,1,1,0,0,0))) - assert_equal(Time.utc(1970,1,1,0,0,0), tz.utc_to_local(Time.utc(1970,1,1,5,0,0))) - assert_equal(Time.utc(1970,1,1,5,0,0), tz.local_to_utc(Time.utc(1970,1,1,0,0,0))) - assert_equal(0, tz.utc_to_local(18000)) - assert_equal(18000, tz.local_to_utc(0)) - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_timezone_offset.rb ruby-tzinfo-2.0.4/test/tc_timezone_offset.rb --- ruby-tzinfo-1.2.6/test/tc_timezone_offset.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_timezone_offset.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,126 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') - -include TZInfo - -class TCTimezoneOffset < Minitest::Test - - def test_utc_offset - o1 = TimezoneOffset.new(18000, 0, :TEST) - o2 = TimezoneOffset.new(-3600, 3600, :TEST2) - - assert_equal(18000, o1.utc_offset) - assert_equal(-3600, o2.utc_offset) - end - - def test_std_offset - o1 = TimezoneOffset.new(18000, 0, :TEST) - o2 = TimezoneOffset.new(-3600, 3600, :TEST2) - - assert_equal(0, o1.std_offset) - assert_equal(3600, o2.std_offset) - end - - def test_utc_total_offset - o1 = TimezoneOffset.new(18000, 0, :TEST) - o2 = TimezoneOffset.new(-3600, 3600, :TEST2) - - assert_equal(18000, o1.utc_total_offset) - assert_equal(0, o2.utc_total_offset) - end - - def test_abbreviation - o1 = TimezoneOffset.new(18000, 0, :TEST) - o2 = TimezoneOffset.new(-3600, 3600, :TEST2) - - assert_equal(:TEST, o1.abbreviation) - assert_equal(:TEST2, o2.abbreviation) - end - - def test_dst - o1 = TimezoneOffset.new(18000, 0, :TEST) - o2 = TimezoneOffset.new(-3600, 3600, :TEST2) - - assert_equal(false, o1.dst?) - assert_equal(true, o2.dst?) - end - - def test_to_local - o1 = TimezoneOffset.new(18000, 0, :TEST) - o2 = TimezoneOffset.new(-3600, 3600, :TEST2) - - assert_equal(1148949080, o1.to_local(1148931080)) - assert_equal(Time.utc(2006, 5, 30, 0, 31, 20), o1.to_local(Time.utc(2006, 5, 29, 19, 31, 20))) - assert_equal(Time.utc(2006, 5, 30, 0, 31, 20, 782000), o1.to_local(Time.utc(2006, 5, 29, 19, 31, 20, 782000))) - assert_equal(DateTime.new(2006, 5, 30, 0, 31, 20), o1.to_local(DateTime.new(2006, 5, 29, 19, 31, 20))) - assert_equal(DateTime.new(2006, 5, 30, 0, 31, 20 + Rational(782, 1000)), o1.to_local(DateTime.new(2006, 5, 29, 19, 31, 20 + Rational(782, 1000)))) - assert_equal(1148949080, o1.to_local(1148931080)) - assert(TimeOrDateTime.new(1148949080).eql?(o1.to_local(TimeOrDateTime.new(1148931080)))) - - assert_equal(1148931080, o2.to_local(1148931080)) - assert_equal(Time.utc(2006, 5, 29, 19, 31, 20), o2.to_local(Time.utc(2006, 5, 29, 19, 31, 20))) - assert_equal(Time.utc(2006, 5, 29, 19, 31, 20, 123000), o2.to_local(Time.utc(2006, 5, 29, 19, 31, 20, 123000))) - assert_equal(DateTime.new(2006, 5, 29, 19, 31, 20), o2.to_local(DateTime.new(2006, 5, 29, 19, 31, 20))) - assert_equal(DateTime.new(2006, 5, 29, 19, 31, 20 + Rational(123, 1000)), o2.to_local(DateTime.new(2006, 5, 29, 19, 31, 20 + Rational(123, 1000)))) - assert_equal(1148931080, o2.to_local(1148931080)) - assert(TimeOrDateTime.new(1148931080).eql?(o2.to_local(TimeOrDateTime.new(1148931080)))) - end - - def test_to_utc - o1 = TimezoneOffset.new(18000, 0, :TEST) - o2 = TimezoneOffset.new(-3600, 3600, :TEST2) - - assert_equal(1148913080, o1.to_utc(1148931080)) - assert_equal(Time.utc(2006, 5, 29, 14, 31, 20), o1.to_utc(Time.utc(2006, 5, 29, 19, 31, 20))) - assert_equal(Time.utc(2006, 5, 29, 14, 31, 20, 913000), o1.to_utc(Time.utc(2006, 5, 29, 19, 31, 20, 913000))) - assert_equal(DateTime.new(2006, 5, 29, 14, 31, 20), o1.to_utc(DateTime.new(2006, 5, 29, 19, 31, 20))) - assert_equal(DateTime.new(2006, 5, 29, 14, 31, 20 + Rational(913,1000)), o1.to_utc(DateTime.new(2006, 5, 29, 19, 31, 20 + Rational(913,1000)))) - assert_equal(1148913080, o1.to_utc(1148931080)) - assert(TimeOrDateTime.new(1148913080).eql?(o1.to_utc(TimeOrDateTime.new(1148931080)))) - - assert_equal(1148931080, o2.to_local(1148931080)) - assert_equal(Time.utc(2006, 5, 29, 19, 31, 20), o2.to_local(Time.utc(2006, 5, 29, 19, 31, 20))) - assert_equal(Time.utc(2006, 5, 29, 19, 31, 20, 323000), o2.to_local(Time.utc(2006, 5, 29, 19, 31, 20, 323000))) - assert_equal(DateTime.new(2006, 5, 29, 19, 31, 20), o2.to_local(DateTime.new(2006, 5, 29, 19, 31, 20))) - assert_equal(DateTime.new(2006, 5, 29, 19, 31, 20 + Rational(323, 1000)), o2.to_local(DateTime.new(2006, 5, 29, 19, 31, 20 + Rational(323, 1000)))) - assert_equal(1148931080, o2.to_utc(1148931080)) - assert(TimeOrDateTime.new(1148931080).eql?(o2.to_local(TimeOrDateTime.new(1148931080)))) - end - - def test_equality - o1 = TimezoneOffset.new(18000, 0, :TEST) - o2 = TimezoneOffset.new(18000, 0, :TEST) - o3 = TimezoneOffset.new(18001, 0, :TEST) - o4 = TimezoneOffset.new(18000, 1, :TEST) - o5 = TimezoneOffset.new(18000, 0, :TEST2) - - assert_equal(true, o1 == o1) - assert_equal(true, o1 == o2) - assert_equal(false, o1 == o3) - assert_equal(false, o1 == o4) - assert_equal(false, o1 == o5) - assert_equal(false, o1 == Object.new) - end - - def test_eql - o1 = TimezoneOffset.new(18000, 0, :TEST) - o2 = TimezoneOffset.new(18000, 0, :TEST) - o3 = TimezoneOffset.new(18001, 0, :TEST) - o4 = TimezoneOffset.new(18000, 1, :TEST) - o5 = TimezoneOffset.new(18000, 0, :TEST2) - - assert_equal(true, o1.eql?(o1)) - assert_equal(true, o1.eql?(o2)) - assert_equal(false, o1.eql?(o3)) - assert_equal(false, o1.eql?(o4)) - assert_equal(false, o1.eql?(o5)) - assert_equal(false, o1.eql?(Object.new)) - end - - def test_hash - o1 = TimezoneOffset.new(18000, 0, :TEST) - o2 = TimezoneOffset.new(-3600, 3600, :TEST2) - - assert_equal(18000.hash ^ 0.hash ^ :TEST.hash, o1.hash) - assert_equal(-3600.hash ^ 3600.hash ^ :TEST2.hash, o2.hash) - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_timezone_period.rb ruby-tzinfo-2.0.4/test/tc_timezone_period.rb --- ruby-tzinfo-1.2.6/test/tc_timezone_period.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_timezone_period.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,555 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') - -include TZInfo - -class TCTimezonePeriod < Minitest::Test - - class TestTimezoneTransition < TimezoneTransition - def initialize(offset, previous_offset, at) - super(offset, previous_offset) - @at = TimeOrDateTime.wrap(at) - end - - def at - @at - end - end - - def test_initialize_start_end - std = TimezoneOffset.new(-7200, 0, :TEST) - dst = TimezoneOffset.new(-7200, 3600, :TEST) - start_t = TestTimezoneTransition.new(dst, std, 1136073600) - end_t = TestTimezoneTransition.new(std, dst, 1136160000) - - p = TimezonePeriod.new(start_t, end_t) - - assert_same(start_t, p.start_transition) - assert_same(end_t, p.end_transition) - assert_same(dst, p.offset) - assert_equal(DateTime.new(2006,1,1,0,0,0), p.utc_start) - assert_equal(Time.utc(2006,1,1,0,0,0), p.utc_start_time) - assert_equal(DateTime.new(2006,1,2,0,0,0), p.utc_end) - assert_equal(Time.utc(2006,1,2,0,0,0), p.utc_end_time) - assert_equal(-7200, p.utc_offset) - assert_equal(3600, p.std_offset) - assert_equal(-3600, p.utc_total_offset) - assert_equal(Rational(-3600, 86400), p.utc_total_offset_rational) - assert_equal(:TEST, p.zone_identifier) - assert_equal(:TEST, p.abbreviation) - assert_equal(DateTime.new(2005,12,31,23,0,0), p.local_start) - assert_equal(Time.utc(2005,12,31,23,0,0), p.local_start_time) - assert_equal(DateTime.new(2006,1,1,23,0,0), p.local_end) - assert_equal(Time.utc(2006,1,1,23,0,0), p.local_end_time) - end - - def test_initialize_start_end_offset - std = TimezoneOffset.new(-7200, 0, :TEST) - dst = TimezoneOffset.new(-7200, 3600, :TEST) - special = TimezoneOffset.new(0, 0, :SPECIAL) - start_t = TestTimezoneTransition.new(dst, std, 1136073600) - end_t = TestTimezoneTransition.new(std, dst, 1136160000) - - assert_raises(ArgumentError) { TimezonePeriod.new(start_t, end_t, special) } - end - - def test_initialize_start - std = TimezoneOffset.new(-7200, 0, :TEST) - dst = TimezoneOffset.new(-7200, 3600, :TEST) - start_t = TestTimezoneTransition.new(dst, std, 1136073600) - - p = TimezonePeriod.new(start_t, nil) - - assert_same(start_t, p.start_transition) - assert_nil(p.end_transition) - assert_same(dst, p.offset) - assert_equal(DateTime.new(2006,1,1,0,0,0), p.utc_start) - assert_equal(Time.utc(2006,1,1,0,0,0), p.utc_start_time) - assert_nil(p.utc_end) - assert_nil(p.utc_end_time) - assert_equal(-7200, p.utc_offset) - assert_equal(3600, p.std_offset) - assert_equal(-3600, p.utc_total_offset) - assert_equal(Rational(-3600, 86400), p.utc_total_offset_rational) - assert_equal(:TEST, p.zone_identifier) - assert_equal(:TEST, p.abbreviation) - assert_equal(DateTime.new(2005,12,31,23,0,0), p.local_start) - assert_equal(Time.utc(2005,12,31,23,0,0), p.local_start_time) - assert_nil(p.local_end) - assert_nil(p.local_end_time) - end - - def test_initialize_start_offset - std = TimezoneOffset.new(-7200, 0, :TEST) - dst = TimezoneOffset.new(-7200, 3600, :TEST) - special = TimezoneOffset.new(0, 0, :SPECIAL) - start_t = TestTimezoneTransition.new(dst, std, 1136073600) - - assert_raises(ArgumentError) { TimezonePeriod.new(start_t, nil, special) } - end - - def test_initialize_end - std = TimezoneOffset.new(-7200, 0, :TEST) - dst = TimezoneOffset.new(-7200, 3600, :TEST) - end_t = TestTimezoneTransition.new(std, dst, 1136160000) - - p = TimezonePeriod.new(nil, end_t) - - assert_nil(p.start_transition) - assert_same(end_t, p.end_transition) - assert_same(dst, p.offset) - assert_nil(p.utc_start) - assert_nil(p.utc_start_time) - assert_equal(DateTime.new(2006,1,2,0,0,0), p.utc_end) - assert_equal(Time.utc(2006,1,2,0,0,0), p.utc_end_time) - assert_equal(-7200, p.utc_offset) - assert_equal(3600, p.std_offset) - assert_equal(-3600, p.utc_total_offset) - assert_equal(Rational(-3600, 86400), p.utc_total_offset_rational) - assert_equal(:TEST, p.zone_identifier) - assert_equal(:TEST, p.abbreviation) - assert_nil(p.local_start) - assert_nil(p.local_start_time) - assert_equal(DateTime.new(2006,1,1,23,0,0), p.local_end) - assert_equal(Time.utc(2006,1,1,23,0,0), p.local_end_time) - end - - def test_initialize_end_offset - std = TimezoneOffset.new(-7200, 0, :TEST) - dst = TimezoneOffset.new(-7200, 3600, :TEST) - special = TimezoneOffset.new(0, 0, :SPECIAL) - end_t = TestTimezoneTransition.new(std, dst, 1136160000) - - assert_raises(ArgumentError) { TimezonePeriod.new(nil, end_t, special) } - end - - def test_initialize - assert_raises(ArgumentError) { TimezonePeriod.new(nil, nil) } - end - - def test_initialize_offset - special = TimezoneOffset.new(0, 0, :SPECIAL) - - p = TimezonePeriod.new(nil, nil, special) - - assert_nil(p.start_transition) - assert_nil(p.end_transition) - assert_same(special, p.offset) - assert_nil(p.utc_start) - assert_nil(p.utc_start_time) - assert_nil(p.utc_end) - assert_nil(p.utc_end_time) - assert_equal(0, p.utc_offset) - assert_equal(0, p.std_offset) - assert_equal(0, p.utc_total_offset) - assert_equal(Rational(0, 86400), p.utc_total_offset_rational) - assert_equal(:SPECIAL, p.zone_identifier) - assert_equal(:SPECIAL, p.abbreviation) - assert_nil(p.local_start) - assert_nil(p.local_start_time) - assert_nil(p.local_end) - assert_nil(p.local_end_time) - end - - def test_utc_total_offset_rational_after_freeze - o = TimezoneOffset.new(3600, 0, :TEST) - p = TimezonePeriod.new(nil, nil, o) - p.freeze - assert_equal(Rational(1, 24), p.utc_total_offset_rational) - end - - def test_dst - p1 = TimezonePeriod.new(nil, nil, TimezoneOffset.new(-14400, 3600, :TEST)) - p2 = TimezonePeriod.new(nil, nil, TimezoneOffset.new(-14400, 0, :TEST)) - p3 = TimezonePeriod.new(nil, nil, TimezoneOffset.new(-14400, -3600, :TEST)) - p4 = TimezonePeriod.new(nil, nil, TimezoneOffset.new(-14400, 7200, :TEST)) - p5 = TimezonePeriod.new(nil, nil, TimezoneOffset.new(-14400, -7200, :TEST)) - - assert_equal(true, p1.dst?) - assert_equal(false, p2.dst?) - assert_equal(true, p3.dst?) - assert_equal(true, p4.dst?) - assert_equal(true, p5.dst?) - end - - def test_valid_for_utc - offset = TimezoneOffset.new(-7200, 3600, :TEST) - t1 = TestTimezoneTransition.new(offset, offset, 1104541261) - t2 = TestTimezoneTransition.new(offset, offset, 1107309722) - t3 = TestTimezoneTransition.new(offset, offset, DateTime.new(1960, 1, 1, 1, 1, 1)) - t4 = TestTimezoneTransition.new(offset, offset, DateTime.new(1960, 2, 2, 2, 2, 2)) - - p1 = TimezonePeriod.new(t1, t2) - p2 = TimezonePeriod.new(nil, t2) - p3 = TimezonePeriod.new(t1, nil) - p4 = TimezonePeriod.new(nil, nil, offset) - p5 = TimezonePeriod.new(t3, t4) - - assert_equal(true, p1.valid_for_utc?(DateTime.new(2005,1,1,1,1,1))) - assert_equal(true, p1.valid_for_utc?(Time.utc(2005,2,2,2,2,1))) - assert_equal(true, p1.valid_for_utc?(1104541262)) - assert_equal(true, p1.valid_for_utc?(DateTime.new(2005,2,2,2,2,0))) - assert_equal(false, p1.valid_for_utc?(DateTime.new(2005,1,1,1,1,0))) - assert_equal(false, p1.valid_for_utc?(DateTime.new(2005,2,2,2,2,3))) - assert_equal(false, p1.valid_for_utc?(DateTime.new(1960,1,1,1,1,0))) - assert_equal(false, p1.valid_for_utc?(DateTime.new(2040,1,1,1,1,0))) - - assert_equal(true, p2.valid_for_utc?(DateTime.new(2005,1,1,1,1,1))) - assert_equal(true, p2.valid_for_utc?(Time.utc(2005,2,2,2,2,1))) - assert_equal(true, p2.valid_for_utc?(1104541262)) - assert_equal(true, p2.valid_for_utc?(DateTime.new(2005,2,2,2,2,0))) - assert_equal(true, p2.valid_for_utc?(DateTime.new(2005,1,1,1,1,0))) - assert_equal(false, p2.valid_for_utc?(DateTime.new(2005,2,2,2,2,3))) - assert_equal(true, p2.valid_for_utc?(DateTime.new(1960,1,1,1,1,0))) - assert_equal(false, p2.valid_for_utc?(DateTime.new(2040,1,1,1,1,0))) - - assert_equal(true, p3.valid_for_utc?(DateTime.new(2005,1,1,1,1,1))) - assert_equal(true, p3.valid_for_utc?(Time.utc(2005,2,2,2,2,1))) - assert_equal(true, p3.valid_for_utc?(1104541262)) - assert_equal(true, p3.valid_for_utc?(DateTime.new(2005,2,2,2,2,0))) - assert_equal(false, p3.valid_for_utc?(DateTime.new(2005,1,1,1,1,0))) - assert_equal(true, p3.valid_for_utc?(DateTime.new(2005,2,2,2,2,3))) - assert_equal(false, p3.valid_for_utc?(DateTime.new(1960,1,1,1,1,0))) - assert_equal(true, p3.valid_for_utc?(DateTime.new(2040,1,1,1,1,0))) - - assert_equal(true, p4.valid_for_utc?(DateTime.new(2005,1,1,1,1,1))) - assert_equal(true, p4.valid_for_utc?(Time.utc(2005,2,2,2,2,1))) - assert_equal(true, p4.valid_for_utc?(1104541262)) - assert_equal(true, p4.valid_for_utc?(DateTime.new(2005,2,2,2,2,0))) - assert_equal(true, p4.valid_for_utc?(DateTime.new(2005,1,1,1,1,0))) - assert_equal(true, p4.valid_for_utc?(DateTime.new(2005,2,2,2,2,3))) - assert_equal(true, p4.valid_for_utc?(DateTime.new(1960,1,1,1,1,0))) - assert_equal(true, p4.valid_for_utc?(DateTime.new(2040,1,1,1,1,0))) - - assert_equal(false, p5.valid_for_utc?(Time.utc(2005,1,1,1,1,1))) - assert_equal(false, p5.valid_for_utc?(1104541262)) - end - - def test_utc_after_start - offset = TimezoneOffset.new(-7200, 3600, :TEST) - t1 = TestTimezoneTransition.new(offset, offset, 1104541261) - t2 = TestTimezoneTransition.new(offset, offset, 1107309722) - t3 = TestTimezoneTransition.new(offset, offset, DateTime.new(1945, 1, 1, 1, 1, 1)) - t4 = TestTimezoneTransition.new(offset, offset, DateTime.new(1945, 2, 2, 2, 2, 2)) - - p1 = TimezonePeriod.new(t1, t2) - p2 = TimezonePeriod.new(nil, t2) - p3 = TimezonePeriod.new(t3, t4) - - assert_equal(true, p1.utc_after_start?(DateTime.new(2005,1,1,1,1,1))) - assert_equal(true, p1.utc_after_start?(Time.utc(2005,1,1,1,1,2))) - assert_equal(false, p1.utc_after_start?(1104541260)) - assert_equal(true, p1.utc_after_start?(DateTime.new(2045,1,1,1,1,0))) - assert_equal(false, p1.utc_after_start?(DateTime.new(1955,1,1,1,1,0))) - - assert_equal(true, p2.utc_after_start?(DateTime.new(2005,1,1,1,1,1))) - assert_equal(true, p2.utc_after_start?(Time.utc(2005,1,1,1,1,2))) - assert_equal(true, p2.utc_after_start?(1104541260)) - - assert_equal(true, p3.utc_after_start?(Time.utc(2005,1,2,1,1,1))) - assert_equal(true, p3.utc_after_start?(1104627661)) - end - - def test_utc_before_end - offset = TimezoneOffset.new(-7200, 3600, :TEST) - t1 = TestTimezoneTransition.new(offset, offset, 1104541261) - t2 = TestTimezoneTransition.new(offset, offset, 1107309722) - t3 = TestTimezoneTransition.new(offset, offset, DateTime.new(1945, 1, 1, 1, 1, 1)) - t4 = TestTimezoneTransition.new(offset, offset, DateTime.new(1945, 2, 2, 2, 2, 2)) - - p1 = TimezonePeriod.new(t1, t2) - p2 = TimezonePeriod.new(t1, nil) - p3 = TimezonePeriod.new(t3, t4) - - assert_equal(true, p1.utc_before_end?(DateTime.new(2005,2,2,2,2,1))) - assert_equal(true, p1.utc_before_end?(Time.utc(2005,2,2,2,2,0))) - assert_equal(false, p1.utc_before_end?(1107309723)) - assert_equal(false, p1.utc_before_end?(DateTime.new(2045,1,1,1,1,0))) - assert_equal(true, p1.utc_before_end?(DateTime.new(1955,1,1,1,1,0))) - - assert_equal(true, p2.utc_before_end?(DateTime.new(2005,2,2,2,2,1))) - assert_equal(true, p2.utc_before_end?(Time.utc(2005,2,2,2,2,0))) - assert_equal(true, p2.utc_before_end?(1107309723)) - - assert_equal(false, p3.utc_before_end?(Time.utc(2005,1,2,1,1,1))) - assert_equal(false, p3.utc_before_end?(1104627661)) - end - - def test_valid_for_local - offset = TimezoneOffset.new(-7200, 3600, :TEST) - t1 = TestTimezoneTransition.new(offset, offset, 1104544861) - t2 = TestTimezoneTransition.new(offset, offset, 1107313322) - t3 = TestTimezoneTransition.new(offset, offset, 1104544861) - t4 = TestTimezoneTransition.new(offset, offset, DateTime.new(1960, 1, 1, 1, 1, 1)) - t5 = TestTimezoneTransition.new(offset, offset, DateTime.new(1960, 2, 2, 2, 2, 2)) - - p1 = TimezonePeriod.new(t1, t2) - p2 = TimezonePeriod.new(nil, t2) - p3 = TimezonePeriod.new(t3, nil) - p4 = TimezonePeriod.new(nil, nil, offset) - p5 = TimezonePeriod.new(t4, t5) - - assert_equal(true, p1.valid_for_local?(DateTime.new(2005,1,1,1,1,1))) - assert_equal(true, p1.valid_for_local?(Time.utc(2005,2,2,2,2,1))) - assert_equal(true, p1.valid_for_local?(1104541262)) - assert_equal(true, p1.valid_for_local?(DateTime.new(2005,2,2,2,2,0))) - assert_equal(false, p1.valid_for_local?(DateTime.new(2005,1,1,1,1,0))) - assert_equal(false, p1.valid_for_local?(DateTime.new(2005,2,2,2,2,3))) - assert_equal(false, p1.valid_for_local?(DateTime.new(1960,1,1,1,1,0))) - assert_equal(false, p1.valid_for_local?(DateTime.new(2040,1,1,1,1,0))) - - assert_equal(true, p2.valid_for_local?(DateTime.new(2005,1,1,1,1,1))) - assert_equal(true, p2.valid_for_local?(DateTime.new(2005,2,2,2,2,1))) - assert_equal(true, p2.valid_for_local?(1104541262)) - assert_equal(true, p2.valid_for_local?(DateTime.new(2005,2,2,2,2,0))) - assert_equal(true, p2.valid_for_local?(DateTime.new(2005,1,1,1,1,0))) - assert_equal(false, p2.valid_for_local?(DateTime.new(2005,2,2,2,2,3))) - assert_equal(true, p2.valid_for_local?(DateTime.new(1960,1,1,1,1,0))) - assert_equal(false, p2.valid_for_local?(DateTime.new(2040,1,1,1,1,0))) - - assert_equal(true, p3.valid_for_local?(DateTime.new(2005,1,1,1,1,1))) - assert_equal(true, p3.valid_for_local?(DateTime.new(2005,2,2,2,2,1))) - assert_equal(true, p3.valid_for_local?(1104541262)) - assert_equal(true, p3.valid_for_local?(DateTime.new(2005,2,2,2,2,0))) - assert_equal(false, p3.valid_for_local?(DateTime.new(2005,1,1,1,1,0))) - assert_equal(true, p3.valid_for_local?(DateTime.new(2005,2,2,2,2,3))) - assert_equal(false, p3.valid_for_local?(DateTime.new(1960,1,1,1,1,0))) - assert_equal(true, p3.valid_for_local?(DateTime.new(2040,1,1,1,1,0))) - - assert_equal(true, p4.valid_for_local?(DateTime.new(2005,1,1,1,1,1))) - assert_equal(true, p4.valid_for_local?(DateTime.new(2005,2,2,2,2,1))) - assert_equal(true, p4.valid_for_local?(1104541262)) - assert_equal(true, p4.valid_for_local?(DateTime.new(2005,2,2,2,2,0))) - assert_equal(true, p4.valid_for_local?(DateTime.new(2005,1,1,1,1,0))) - assert_equal(true, p4.valid_for_local?(DateTime.new(2005,2,2,2,2,3))) - assert_equal(true, p4.valid_for_local?(DateTime.new(1960,1,1,1,1,0))) - assert_equal(true, p4.valid_for_local?(DateTime.new(2040,1,1,1,1,0))) - - assert_equal(false, p5.valid_for_utc?(Time.utc(2005,1,1,1,1,1))) - assert_equal(false, p5.valid_for_utc?(1104541262)) - end - - def test_local_after_start - offset = TimezoneOffset.new(-7200, 3600, :TEST) - t1 = TestTimezoneTransition.new(offset, offset, 1104544861) - t2 = TestTimezoneTransition.new(offset, offset, 1107313322) - t3 = TestTimezoneTransition.new(offset, offset, DateTime.new(1945, 1, 1, 1, 1, 1)) - t4 = TestTimezoneTransition.new(offset, offset, DateTime.new(1945, 2, 2, 2, 2, 2)) - - p1 = TimezonePeriod.new(t1, t2) - p2 = TimezonePeriod.new(nil, t2) - p3 = TimezonePeriod.new(t3, t4) - - assert_equal(true, p1.local_after_start?(DateTime.new(2005,1,1,1,1,1))) - assert_equal(true, p1.local_after_start?(Time.utc(2005,1,1,1,1,2))) - assert_equal(false, p1.local_after_start?(1104541260)) - assert_equal(true, p1.local_after_start?(DateTime.new(2045,1,1,1,1,0))) - assert_equal(false, p1.local_after_start?(DateTime.new(1955,1,1,1,1,0))) - - assert_equal(true, p2.local_after_start?(DateTime.new(2005,1,1,1,1,1))) - assert_equal(true, p2.local_after_start?(Time.utc(2005,1,1,1,1,2))) - assert_equal(true, p2.local_after_start?(1104541260)) - - assert_equal(true, p3.local_after_start?(Time.utc(2005,1,2,1,1,1))) - assert_equal(true, p3.local_after_start?(1104627661)) - end - - def test_local_before_end - offset = TimezoneOffset.new(-7200, 3600, :TEST) - t1 = TestTimezoneTransition.new(offset, offset, 1104544861) - t2 = TestTimezoneTransition.new(offset, offset, 1107313322) - t3 = TestTimezoneTransition.new(offset, offset, DateTime.new(1945, 1, 1, 1, 1, 1)) - t4 = TestTimezoneTransition.new(offset, offset, DateTime.new(1945, 2, 2, 2, 2, 2)) - - p1 = TimezonePeriod.new(t1, t2) - p2 = TimezonePeriod.new(t1, nil) - p3 = TimezonePeriod.new(t3, t4) - - assert_equal(true, p1.local_before_end?(DateTime.new(2005,2,2,2,2,1))) - assert_equal(true, p1.local_before_end?(Time.utc(2005,2,2,2,2,0))) - assert_equal(false, p1.local_before_end?(1107309723)) - assert_equal(false, p1.local_before_end?(DateTime.new(2045,1,1,1,1,0))) - assert_equal(true, p1.local_before_end?(DateTime.new(1955,1,1,1,1,0))) - - assert_equal(true, p2.local_before_end?(DateTime.new(2005,2,2,2,2,1))) - assert_equal(true, p2.local_before_end?(Time.utc(2005,2,2,2,2,0))) - assert_equal(true, p2.local_before_end?(1107309723)) - - assert_equal(false, p3.local_before_end?(Time.utc(2005,1,2,1,1,1))) - assert_equal(false, p3.local_before_end?(1104627661)) - end - - def test_to_local - p1 = TimezonePeriod.new(nil, nil, TimezoneOffset.new(-14400, 3600, :TEST)) - p2 = TimezonePeriod.new(nil, nil, TimezoneOffset.new(-14400, 0, :TEST)) - p3 = TimezonePeriod.new(nil, nil, TimezoneOffset.new(7200, 3600, :TEST)) - - assert_equal(DateTime.new(2005,1,19,22,0,0), p1.to_local(DateTime.new(2005,1,20,1,0,0))) - assert_equal(DateTime.new(2005,1,19,22,0,0 + Rational(512,1000)), p1.to_local(DateTime.new(2005,1,20,1,0,0 + Rational(512,1000)))) - assert_equal(Time.utc(2005,1,19,21,0,0), p2.to_local(Time.utc(2005,1,20,1,0,0))) - assert_equal(Time.utc(2005,1,19,21,0,0,512000), p2.to_local(Time.utc(2005,1,20,1,0,0,512000))) - assert_equal(1106193600, p3.to_local(1106182800)) - end - - def test_to_utc - p1 = TimezonePeriod.new(nil, nil, TimezoneOffset.new(-14400, 3600, :TEST)) - p2 = TimezonePeriod.new(nil, nil, TimezoneOffset.new(-14400, 0, :TEST)) - p3 = TimezonePeriod.new(nil, nil, TimezoneOffset.new(7200, 3600, :TEST)) - - assert_equal(DateTime.new(2005,1,20,4,0,0), p1.to_utc(DateTime.new(2005,1,20,1,0,0))) - assert_equal(DateTime.new(2005,1,20,4,0,0 + Rational(571,1000)), p1.to_utc(DateTime.new(2005,1,20,1,0,0 + Rational(571,1000)))) - assert_equal(Time.utc(2005,1,20,5,0,0), p2.to_utc(Time.utc(2005,1,20,1,0,0))) - assert_equal(Time.utc(2005,1,20,5,0,0,571000), p2.to_utc(Time.utc(2005,1,20,1,0,0,571000))) - assert_equal(1106172000, p3.to_utc(1106182800)) - end - - def test_time_boundary_start - o1 = TimezoneOffset.new(-3600, 0, :TEST) - o2 = TimezoneOffset.new(-3600, 3600, :TEST) - t1 = TestTimezoneTransition.new(o1, o2, 0) - - p1 = TimezonePeriod.new(t1, nil) - - assert_equal(DateTime.new(1969,12,31,23,0,0), p1.local_start) - - # Conversion to Time will fail on systems that don't support negative times. - if RubyCoreSupport.time_supports_negative - assert_equal(Time.utc(1969,12,31,23,0,0), p1.local_start_time) - end - end - - def test_time_boundary_end - o1 = TimezoneOffset.new(0, 3600, :TEST) - o2 = TimezoneOffset.new(0, 0, :TEST) - t1 = TestTimezoneTransition.new(o2, o1, 2147482800) - - p1 = TimezonePeriod.new(nil, t1) - - assert_equal(DateTime.new(2038,1,19,4,0,0), p1.local_end) - - # Conversion to Time will fail on systems that don't support 64-bit times - if RubyCoreSupport.time_supports_64bit - assert_equal(Time.utc(2038,1,19,4,0,0), p1.local_end_time) - end - end - - def test_equality - o1 = TimezoneOffset.new(0, 3600, :TEST) - o2 = TimezoneOffset.new(0, 0, :TEST) - t1 = TestTimezoneTransition.new(o1, o2, 1149368400) - t2 = TestTimezoneTransition.new(o1, o2, DateTime.new(2006, 6, 3, 21, 0, 0)) - t3 = TestTimezoneTransition.new(o1, o2, 1149454800) - t4 = TestTimezoneTransition.new(o1, o2, 1149541200) - - p1 = TimezonePeriod.new(t1, t3) - p2 = TimezonePeriod.new(t1, t3) - p3 = TimezonePeriod.new(t2, t3) - p4 = TimezonePeriod.new(t3, nil) - p5 = TimezonePeriod.new(t3, nil) - p6 = TimezonePeriod.new(t4, nil) - p7 = TimezonePeriod.new(nil, t3) - p8 = TimezonePeriod.new(nil, t3) - p9 = TimezonePeriod.new(nil, t4) - p10 = TimezonePeriod.new(nil, nil, o1) - p11 = TimezonePeriod.new(nil, nil, o1) - p12 = TimezonePeriod.new(nil, nil, o2) - - assert_equal(true, p1 == p1) - assert_equal(true, p1 == p2) - assert_equal(true, p1 == p3) - assert_equal(false, p1 == p4) - assert_equal(false, p1 == p5) - assert_equal(false, p1 == p6) - assert_equal(false, p1 == p7) - assert_equal(false, p1 == p8) - assert_equal(false, p1 == p9) - assert_equal(false, p1 == p10) - assert_equal(false, p1 == p11) - assert_equal(false, p1 == p12) - assert_equal(false, p1 == Object.new) - - assert_equal(true, p4 == p4) - assert_equal(true, p4 == p5) - assert_equal(false, p4 == p6) - assert_equal(false, p4 == Object.new) - - assert_equal(true, p7 == p7) - assert_equal(true, p7 == p8) - assert_equal(false, p7 == p9) - assert_equal(false, p7 == Object.new) - - assert_equal(true, p10 == p10) - assert_equal(true, p10 == p11) - assert_equal(false, p10 == p12) - assert_equal(false, p10 == Object.new) - end - - def test_eql - o1 = TimezoneOffset.new(0, 3600, :TEST) - o2 = TimezoneOffset.new(0, 0, :TEST) - t1 = TestTimezoneTransition.new(o1, o2, 1149368400) - t2 = TestTimezoneTransition.new(o1, o2, DateTime.new(2006, 6, 3, 21, 0, 0)) - t3 = TestTimezoneTransition.new(o1, o2, 1149454800) - t4 = TestTimezoneTransition.new(o1, o2, 1149541200) - - p1 = TimezonePeriod.new(t1, t3) - p2 = TimezonePeriod.new(t1, t3) - p3 = TimezonePeriod.new(t2, t3) - p4 = TimezonePeriod.new(t3, nil) - p5 = TimezonePeriod.new(t3, nil) - p6 = TimezonePeriod.new(t4, nil) - p7 = TimezonePeriod.new(nil, t3) - p8 = TimezonePeriod.new(nil, t3) - p9 = TimezonePeriod.new(nil, t4) - p10 = TimezonePeriod.new(nil, nil, o1) - p11 = TimezonePeriod.new(nil, nil, o1) - p12 = TimezonePeriod.new(nil, nil, o2) - - assert_equal(true, p1.eql?(p1)) - assert_equal(true, p1.eql?(p2)) - assert_equal(false, p1.eql?(p3)) - assert_equal(false, p1.eql?(p4)) - assert_equal(false, p1.eql?(p5)) - assert_equal(false, p1.eql?(p6)) - assert_equal(false, p1.eql?(p7)) - assert_equal(false, p1.eql?(p8)) - assert_equal(false, p1.eql?(p9)) - assert_equal(false, p1.eql?(p10)) - assert_equal(false, p1.eql?(p11)) - assert_equal(false, p1.eql?(p12)) - assert_equal(false, p1.eql?(Object.new)) - - assert_equal(true, p4.eql?(p4)) - assert_equal(true, p4.eql?(p5)) - assert_equal(false, p4.eql?(p6)) - assert_equal(false, p4.eql?(Object.new)) - - assert_equal(true, p7.eql?(p7)) - assert_equal(true, p7.eql?(p8)) - assert_equal(false, p7.eql?(p9)) - assert_equal(false, p7.eql?(Object.new)) - - assert_equal(true, p10.eql?(p10)) - assert_equal(true, p10.eql?(p11)) - assert_equal(false, p10.eql?(p12)) - assert_equal(false, p10.eql?(Object.new)) - end - - def test_hash - o1 = TimezoneOffset.new(0, 3600, :TEST) - o2 = TimezoneOffset.new(0, 0, :TEST) - t1 = TestTimezoneTransition.new(o1, o2, 1149368400) - t2 = TestTimezoneTransition.new(o1, o2, DateTime.new(2006, 6, 3, 21, 0, 0)) - t3 = TestTimezoneTransition.new(o1, o2, 1149454800) - t4 = TestTimezoneTransition.new(o1, o2, 1149541200) - - p1 = TimezonePeriod.new(t1, t3) - p2 = TimezonePeriod.new(t2, nil) - p3 = TimezonePeriod.new(nil, t4) - p4 = TimezonePeriod.new(nil, nil, o1) - - assert_equal(t1.hash ^ t3.hash, p1.hash) - assert_equal(t2.hash ^ nil.hash, p2.hash) - assert_equal(nil.hash ^ t4.hash, p3.hash) - assert_equal(nil.hash ^ nil.hash ^ o1.hash, p4.hash) - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_timezone_proxy.rb ruby-tzinfo-2.0.4/test/tc_timezone_proxy.rb --- ruby-tzinfo-1.2.6/test/tc_timezone_proxy.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_timezone_proxy.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,136 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') - -include TZInfo - -class TCTimezoneProxy < Minitest::Test - def test_not_exist - proxy = TimezoneProxy.new('Nothing/Special') - t = Time.utc(2006,1,1,0,0,0) - assert_equal('Nothing/Special', proxy.identifier) - assert_equal('Nothing/Special', proxy.name) - assert_equal('Nothing - Special', proxy.friendly_identifier) - assert_equal('Nothing - Special', proxy.to_s) - - assert_raises(InvalidTimezoneIdentifier) { proxy.canonical_identifier } - assert_raises(InvalidTimezoneIdentifier) { proxy.canonical_zone } - assert_raises(InvalidTimezoneIdentifier) { proxy.current_period } - assert_raises(InvalidTimezoneIdentifier) { proxy.current_period_and_time } - assert_raises(InvalidTimezoneIdentifier) { proxy.current_time_and_period } - assert_raises(InvalidTimezoneIdentifier) { proxy.local_to_utc(t) } - assert_raises(InvalidTimezoneIdentifier) { proxy.now } - assert_raises(InvalidTimezoneIdentifier) { proxy.offsets_up_to(t) } - assert_raises(InvalidTimezoneIdentifier) { proxy.period_for_local(t) } - assert_raises(InvalidTimezoneIdentifier) { proxy.period_for_utc(t) } - assert_raises(InvalidTimezoneIdentifier) { proxy.periods_for_local(t) } - assert_raises(InvalidTimezoneIdentifier) { proxy.strftime('%Z', t) } - assert_raises(InvalidTimezoneIdentifier) { proxy.transitions_up_to(t) } - assert_raises(InvalidTimezoneIdentifier) { proxy.utc_to_local(t) } - end - - def test_valid - proxy = TimezoneProxy.new('Europe/London') - real = Timezone.get('Europe/London') - - t1 = Time.utc(2005,8,1,0,0,0) - t2 = Time.utc(2004,8,1,0,0,0) - - assert_equal(real.canonical_identifier, proxy.canonical_identifier) - assert_same(real.canonical_zone, proxy.canonical_zone) - assert_nothing_raised { proxy.current_period } - assert_nothing_raised { proxy.current_period_and_time } - assert_nothing_raised { proxy.current_time_and_period } - assert_equal(real.friendly_identifier(true), proxy.friendly_identifier(true)) - assert_equal(real.friendly_identifier(false), proxy.friendly_identifier(false)) - assert_equal(real.friendly_identifier, proxy.friendly_identifier) - assert_equal(real.identifier, proxy.identifier) - assert_equal(real.local_to_utc(t1), proxy.local_to_utc(t1)) - assert_equal(real.name, proxy.name) - assert_nothing_raised { proxy.now } - assert_equal(real.offsets_up_to(t1), proxy.offsets_up_to(t1)) - assert_equal(real.offsets_up_to(t1, t2), proxy.offsets_up_to(t1, t2)) - assert_equal(real.period_for_local(t1), proxy.period_for_local(t1)) - assert_equal(real.period_for_utc(t1), proxy.period_for_utc(t1)) - assert_equal(real.periods_for_local(t1), proxy.periods_for_local(t1)) - assert_equal(real.strftime('%Z', t1), proxy.strftime('%Z', t1)) - assert_equal(real.to_s, proxy.to_s) - assert_equal(real.transitions_up_to(t1), proxy.transitions_up_to(t1)) - assert_equal(real.transitions_up_to(t1, t2), proxy.transitions_up_to(t1, t2)) - assert_equal(real.utc_to_local(t1), proxy.utc_to_local(t1)) - - - assert(real == proxy) - assert(proxy == real) - assert_equal(0, real <=> proxy) - assert_equal(0, proxy <=> real) - end - - def test_canonical_linked - # Test that the implementation of canonical_zone and canonical_identifier - # are actually calling the real timezone and not just returning it and - # its identifier. - - real = Timezone.get('UTC') - proxy = TimezoneProxy.new('UTC') - - # ZoneinfoDataSource doesn't return LinkedTimezoneInfo instances for any - # timezone. - if real.kind_of?(LinkedTimezone) - assert_equal('Etc/UTC', proxy.canonical_identifier) - assert_same(Timezone.get('Etc/UTC'), proxy.canonical_zone) - else - if DataSource.get.kind_of?(RubyDataSource) - # Not got a LinkedTimezone despite using a DataSource that supports it. - # Raise an exception as this shouldn't happen. - raise 'Non-LinkedTimezone instance returned for UTC using RubyDataSource' - end - - assert_equal('UTC', proxy.canonical_identifier) - assert_same(Timezone.get('UTC'), proxy.canonical_zone) - end - end - - def test_after_freeze - proxy = TimezoneProxy.new('Europe/London') - real = Timezone.get('Europe/London') - t = Time.utc(2017, 6, 1) - proxy.freeze - assert_equal('Europe/London', proxy.identifier) - assert_equal(real.utc_to_local(t), proxy.utc_to_local(t)) - end - - def test_equals - assert_equal(true, TimezoneProxy.new('Europe/London') == TimezoneProxy.new('Europe/London')) - assert_equal(false, TimezoneProxy.new('Europe/London') == TimezoneProxy.new('Europe/Paris')) - assert(!(TimezoneProxy.new('Europe/London') == Object.new)) - end - - def test_compare - assert_equal(0, TimezoneProxy.new('Europe/London') <=> TimezoneProxy.new('Europe/London')) - assert_equal(0, Timezone.get('Europe/London') <=> TimezoneProxy.new('Europe/London')) - assert_equal(0, TimezoneProxy.new('Europe/London') <=> Timezone.get('Europe/London')) - assert_equal(-1, TimezoneProxy.new('Europe/London') <=> TimezoneProxy.new('Europe/Paris')) - assert_equal(-1, Timezone.get('Europe/London') <=> TimezoneProxy.new('Europe/Paris')) - assert_equal(-1, TimezoneProxy.new('Europe/London') <=> Timezone.get('Europe/Paris')) - assert_equal(1, TimezoneProxy.new('Europe/Paris') <=> TimezoneProxy.new('Europe/London')) - assert_equal(1, Timezone.get('Europe/Paris') <=> TimezoneProxy.new('Europe/London')) - assert_equal(1, TimezoneProxy.new('Europe/Paris') <=> Timezone.get('Europe/London')) - assert_equal(-1, TimezoneProxy.new('America/New_York') <=> TimezoneProxy.new('Europe/Paris')) - assert_equal(-1, Timezone.get('America/New_York') <=> TimezoneProxy.new('Europe/Paris')) - assert_equal(-1, TimezoneProxy.new('America/New_York') <=> Timezone.get('Europe/Paris')) - assert_equal(1, TimezoneProxy.new('Europe/Paris') <=> TimezoneProxy.new('America/New_York')) - assert_equal(1, Timezone.get('Europe/Paris') <=> TimezoneProxy.new('America/New_York')) - assert_equal(1, TimezoneProxy.new('Europe/Paris') <=> Timezone.get('America/New_York')) - end - - def test_kind - assert_kind_of(Timezone, TimezoneProxy.new('America/New_York')) - end - - def test_marshal - tp = TimezoneProxy.new('Europe/London') - tp2 = Marshal.load(Marshal.dump(tp)) - - assert_kind_of(TimezoneProxy, tp2) - assert_equal('Europe/London', tp2.identifier) - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_timezone.rb ruby-tzinfo-2.0.4/test/tc_timezone.rb --- ruby-tzinfo-1.2.6/test/tc_timezone.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_timezone.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,1359 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') - -include TZInfo - -using TaintExt if Module.const_defined?(:TaintExt) - -class TCTimezone < Minitest::Test - - class BlockCalled < StandardError - end - - class TestTimezone < Timezone - def self.new(identifier, period_for_utc = nil, periods_for_local = nil, expected = nil) - t = super() - t.send(:setup, identifier, period_for_utc, periods_for_local, expected) - t - end - - def identifier - @identifier - end - - def period_for_utc(utc) - utc = TimeOrDateTime.wrap(utc) - raise "Unexpected utc #{utc} in period_for_utc" unless @expected.eql?(utc) - @period_for_utc - end - - def periods_for_local(local) - local = TimeOrDateTime.wrap(local) - raise "Unexpected local #{local} in periods_for_local" unless @expected.eql?(local) - @periods_for_local.clone - end - - def transitions_up_to(utc_to, utc_from = nil) - raise 'transitions_up_to called' - end - - private - def setup(identifier, period_for_utc, periods_for_local, expected) - @identifier = identifier - @period_for_utc = period_for_utc - @periods_for_local = periods_for_local || [] - @expected = TimeOrDateTime.wrap(expected) - end - end - - class OffsetsUpToTestTimezone < Timezone - def self.new(identifier, expected_utc_to, expected_utc_from, transitions_up_to) - t = super() - t.send(:setup, identifier, expected_utc_to, expected_utc_from, transitions_up_to) - t - end - - def identifier - @identifier - end - - def period_for_utc(utc) - raise 'period_for_utc called' - end - - def periods_for_local(local) - raise 'periods_for_local called' - end - - def transitions_up_to(utc_to, utc_from = nil) - utc_to = TimeOrDateTime.wrap(utc_to) - raise "Unexpected utc_to #{utc_to || 'nil'} in transitions_up_to" unless @expected_utc_to.eql?(utc_to) - - utc_from = utc_from ? TimeOrDateTime.wrap(utc_from) : nil - raise "Unexpected utc_from #{utc_from || 'nil'} in transitions_up_to" unless @expected_utc_from.eql?(utc_from) - - if utc_from && utc_to <= utc_from - raise ArgumentError, 'utc_to must be greater than utc_from' - end - - @transitions_up_to - end - - private - - def setup(identifier, expected_utc_to, expected_utc_from, transitions_up_to) - @identifier = identifier - @expected_utc_to = TimeOrDateTime.wrap(expected_utc_to) - @expected_utc_from = expected_utc_from ? TimeOrDateTime.wrap(expected_utc_from) : nil - @transitions_up_to = transitions_up_to - end - end - - class OffsetsUpToNoTransitionsTestTimezone < Timezone - def self.new(identifier, expected_utc_to, expected_utc_from, period_for_utc) - t = super() - t.send(:setup, identifier, expected_utc_to, expected_utc_from, period_for_utc) - t - end - - def identifier - @identifier - end - - def period_for_utc(utc) - utc = TimeOrDateTime.wrap(utc) - - raise "Unexpected utc #{utc} in period_for_utc (should be utc_from)" if @expected_utc_from && !@expected_utc_from.eql?(utc) - raise "Unexpected utc #{utc} in period_for_utc (should be < utc_to)" if !@expected_utc_from && @expected_utc_to <= utc - - @period_for_utc - end - - def periods_for_local(local) - raise 'periods_for_local called' - end - - def transitions_up_to(utc_to, utc_from = nil) - utc_to = TimeOrDateTime.wrap(utc_to) - raise "Unexpected utc_to #{utc_to || 'nil'} in transitions_up_to" unless @expected_utc_to.eql?(utc_to) - - utc_from = utc_from ? TimeOrDateTime.wrap(utc_from) : nil - raise "Unexpected utc_from #{utc_from || 'nil'} in transitions_up_to" unless @expected_utc_from.eql?(utc_from) - - if utc_from && utc_to <= utc_from - raise ArgumentError, 'utc_to must be greater than utc_from' - end - - [] - end - - private - - def setup(identifier, expected_utc_to, expected_utc_from, period_for_utc) - @identifier = identifier - @expected_utc_to = TimeOrDateTime.wrap(expected_utc_to) - @expected_utc_from = expected_utc_from ? TimeOrDateTime.wrap(expected_utc_from) : nil - @period_for_utc = period_for_utc - end - end - - class TestTimezoneTransition < TimezoneTransition - def initialize(offset, previous_offset, at) - super(offset, previous_offset) - @at = TimeOrDateTime.wrap(at) - end - - def at - @at - end - end - - def setup - @orig_default_dst = Timezone.default_dst - @orig_data_source = DataSource.get - Timezone.send :init_loaded_zones - end - - def teardown - Timezone.default_dst = @orig_default_dst - DataSource.set(@orig_data_source) - end - - def test_default_dst_initial_value - assert_nil(Timezone.default_dst) - end - - def test_set_default_dst - Timezone.default_dst = true - assert_equal(true, Timezone.default_dst) - Timezone.default_dst = false - assert_equal(false, Timezone.default_dst) - Timezone.default_dst = nil - assert_nil(Timezone.default_dst) - Timezone.default_dst = 0 - assert_equal(true, Timezone.default_dst) - end - - def test_get_valid_1 - tz = Timezone.get('Europe/London') - - assert_kind_of(DataTimezone, tz) - assert_equal('Europe/London', tz.identifier) - end - - def test_get_valid_2 - tz = Timezone.get('UTC') - - # ZoneinfoDataSource doesn't return LinkedTimezoneInfo for any timezone. - if DataSource.get.load_timezone_info('UTC').kind_of?(LinkedTimezoneInfo) - assert_kind_of(LinkedTimezone, tz) - else - assert_kind_of(DataTimezone, tz) - end - - assert_equal('UTC', tz.identifier) - end - - def test_get_valid_3 - tz = Timezone.get('America/Argentina/Buenos_Aires') - - assert_kind_of(DataTimezone, tz) - assert_equal('America/Argentina/Buenos_Aires', tz.identifier) - end - - def test_get_same_instance - tz1 = Timezone.get('Europe/London') - tz2 = Timezone.get('Europe/London') - assert_same(tz1, tz2) - end - - def test_get_not_exist - assert_raises(InvalidTimezoneIdentifier) { Timezone.get('Nowhere/Special') } - end - - def test_get_invalid - assert_raises(InvalidTimezoneIdentifier) { Timezone.get('../Definitions/UTC') } - end - - def test_get_nil - assert_raises(InvalidTimezoneIdentifier) { Timezone.get(nil) } - end - - def test_get_case - Timezone.get('Europe/Prague') - assert_raises(InvalidTimezoneIdentifier) { Timezone.get('Europe/prague') } - end - - def test_get_proxy_valid - proxy = Timezone.get_proxy('Europe/London') - assert_kind_of(TimezoneProxy, proxy) - assert_equal('Europe/London', proxy.identifier) - end - - def test_get_proxy_not_exist - proxy = Timezone.get_proxy('Not/There') - assert_kind_of(TimezoneProxy, proxy) - assert_equal('Not/There', proxy.identifier) - end - - def test_get_proxy_invalid - proxy = Timezone.get_proxy('../Invalid/Identifier') - assert_kind_of(TimezoneProxy, proxy) - assert_equal('../Invalid/Identifier', proxy.identifier) - end - - def test_get_tainted_loaded - Timezone.get('Europe/Andorra') - - safe_test(:unavailable => :skip) do - identifier = 'Europe/Andorra'.dup.taint - assert(identifier.tainted?) - tz = Timezone.get(identifier) - assert_equal('Europe/Andorra', tz.identifier) - assert(identifier.tainted?) - end - end - - def test_get_tainted_and_frozen_loaded - Timezone.get('Europe/Andorra') - - safe_test do - tz = Timezone.get('Europe/Andorra'.dup.taint.freeze) - assert_equal('Europe/Andorra', tz.identifier) - end - end - - def test_get_tainted_not_previously_loaded - skip_if_has_bug_14060 - - safe_test(:unavailable => :skip) do - identifier = 'Europe/Andorra'.dup.taint - assert(identifier.tainted?) - tz = Timezone.get(identifier) - assert_equal('Europe/Andorra', tz.identifier) - assert(identifier.tainted?) - end - end - - def test_get_tainted_and_frozen_not_previously_loaded - skip_if_has_bug_14060 - - safe_test do - tz = Timezone.get('Europe/Amsterdam'.dup.taint.freeze) - assert_equal('Europe/Amsterdam', tz.identifier) - end - end - - def test_new_no_args - tz = Timezone.new - - assert_raises(UnknownTimezone) { tz.identifier } - assert_raises(UnknownTimezone) { tz.friendly_identifier } - assert_raises(UnknownTimezone) { tz.utc_to_local(DateTime.new(2006,1,1,1,0,0)) } - assert_raises(UnknownTimezone) { tz.local_to_utc(DateTime.new(2006,1,1,1,0,0)) } - assert_raises(UnknownTimezone) { tz.period_for_utc(DateTime.new(2006,1,1,1,0,0)) } - assert_raises(UnknownTimezone) { tz.periods_for_local(DateTime.new(2006,1,1,1,0,0)) } - assert_raises(UnknownTimezone) { tz.period_for_local(DateTime.new(2006,1,1,1,0,0)) } - assert_raises(UnknownTimezone) { tz.now } - assert_raises(UnknownTimezone) { tz.current_period_and_time } - assert_raises(UnknownTimezone) { tz.transitions_up_to(DateTime.new(2006,1,1,1,0,0)) } - assert_raises(UnknownTimezone) { tz.canonical_identifier } - assert_raises(UnknownTimezone) { tz.canonical_zone } - end - - def test_new_nil - tz = Timezone.new(nil) - - assert_raises(UnknownTimezone) { tz.identifier } - assert_raises(UnknownTimezone) { tz.friendly_identifier } - assert_raises(UnknownTimezone) { tz.utc_to_local(DateTime.new(2006,1,1,1,0,0)) } - assert_raises(UnknownTimezone) { tz.local_to_utc(DateTime.new(2006,1,1,1,0,0)) } - assert_raises(UnknownTimezone) { tz.period_for_utc(DateTime.new(2006,1,1,1,0,0)) } - assert_raises(UnknownTimezone) { tz.periods_for_local(DateTime.new(2006,1,1,1,0,0)) } - assert_raises(UnknownTimezone) { tz.period_for_local(DateTime.new(2006,1,1,1,0,0)) } - assert_raises(UnknownTimezone) { tz.now } - assert_raises(UnknownTimezone) { tz.current_period_and_time } - assert_raises(UnknownTimezone) { tz.transitions_up_to(DateTime.new(2006,1,1,1,0,0)) } - assert_raises(UnknownTimezone) { tz.canonical_identifier } - assert_raises(UnknownTimezone) { tz.canonical_zone } - end - - def test_new_arg - tz = Timezone.new('Europe/London') - assert_same(Timezone.get('Europe/London'), tz) - end - - def test_new_arg_not_exist - assert_raises(InvalidTimezoneIdentifier) { Timezone.new('Nowhere/Special') } - end - - def test_all - all = Timezone.all - expected = DataSource.get.timezone_identifiers.collect {|identifier| Timezone.get_proxy(identifier)} - assert_equal(expected, all) - end - - def test_all_identifiers - all = Timezone.all_identifiers - assert_equal(DataSource.get.timezone_identifiers, all) - end - - def test_all_data_zones - all_data = Timezone.all_data_zones - expected = DataSource.get.data_timezone_identifiers.collect {|identifier| Timezone.get_proxy(identifier)} - assert_equal(expected, all_data) - end - - def test_all_data_zone_identifiers - all_data = Timezone.all_data_zone_identifiers - assert_equal(DataSource.get.data_timezone_identifiers, all_data) - end - - def test_all_linked_zones - all_linked = Timezone.all_linked_zones - expected = DataSource.get.linked_timezone_identifiers.collect {|identifier| Timezone.get_proxy(identifier)} - assert_equal(expected, all_linked) - end - - def test_all_linked_zone_identifiers - all_linked = Timezone.all_linked_zone_identifiers - assert_equal(DataSource.get.linked_timezone_identifiers, all_linked) - end - - def test_all_country_zones - # Probably should relax this test - just need all the zones, don't care - # about order. - expected = Country.all.inject([]) {|result,country| - result += country.zones - } - expected.uniq! - - all_country_zones = Timezone.all_country_zones - assert_equal(expected, all_country_zones) - - all_country_zone_identifiers = Timezone.all_country_zone_identifiers - assert_equal(all_country_zone_identifiers.length, all_country_zones.length) - - all_country_zones.each {|zone| - assert_kind_of(TimezoneProxy, zone) - assert(all_country_zone_identifiers.include?(zone.identifier)) - } - end - - def test_all_country_zone_identifiers - # Probably should relax this test - just need all the zones, don't care - # about order. - expected = Country.all.inject([]) {|result,country| - result += country.zone_identifiers - } - expected.uniq! - - assert_equal(expected, Timezone.all_country_zone_identifiers) - end - - def test_us_zones - # Probably should relax this test - just need all the zones, don't care - # about order. - us_zones = Timezone.us_zones - assert_equal(Country.get('US').zones.uniq, us_zones) - - us_zone_identifiers = Timezone.us_zone_identifiers - assert_equal(us_zone_identifiers.length, us_zones.length) - - us_zones.each {|zone| - assert_kind_of(TimezoneProxy, zone) - assert(us_zone_identifiers.include?(zone.identifier)) - } - end - - def test_us_zone_identifiers - # Probably should relax this test - just need all the zones, don't care - # about order. - assert_equal(Country.get('US').zone_identifiers.uniq, Timezone.us_zone_identifiers) - end - - def test_identifier - assert_raises(UnknownTimezone) { Timezone.new.identifier } - assert_equal('Europe/Paris', TestTimezone.new('Europe/Paris').identifier) - end - - def test_name - assert_raises(UnknownTimezone) { Timezone.new.name } - assert_equal('Europe/Paris', TestTimezone.new('Europe/Paris').name) - end - - def test_friendly_identifier - assert_equal('Paris', TestTimezone.new('Europe/Paris').friendly_identifier(true)) - assert_equal('Europe - Paris', TestTimezone.new('Europe/Paris').friendly_identifier(false)) - assert_equal('Europe - Paris', TestTimezone.new('Europe/Paris').friendly_identifier) - assert_equal('Knox, Indiana', TestTimezone.new('America/Indiana/Knox').friendly_identifier(true)) - assert_equal('America - Knox, Indiana', TestTimezone.new('America/Indiana/Knox').friendly_identifier(false)) - assert_equal('America - Knox, Indiana', TestTimezone.new('America/Indiana/Knox').friendly_identifier) - assert_equal('Dumont D\'Urville', TestTimezone.new('Antarctica/DumontDUrville').friendly_identifier(true)) - assert_equal('Antarctica - Dumont D\'Urville', TestTimezone.new('Antarctica/DumontDUrville').friendly_identifier(false)) - assert_equal('Antarctica - Dumont D\'Urville', TestTimezone.new('Antarctica/DumontDUrville').friendly_identifier) - assert_equal('McMurdo', TestTimezone.new('Antarctica/McMurdo').friendly_identifier(true)) - assert_equal('Antarctica - McMurdo', TestTimezone.new('Antarctica/McMurdo').friendly_identifier(false)) - assert_equal('Antarctica - McMurdo', TestTimezone.new('Antarctica/McMurdo').friendly_identifier) - assert_equal('GMT+1', TestTimezone.new('Etc/GMT+1').friendly_identifier(true)) - assert_equal('Etc - GMT+1', TestTimezone.new('Etc/GMT+1').friendly_identifier(false)) - assert_equal('Etc - GMT+1', TestTimezone.new('Etc/GMT+1').friendly_identifier) - assert_equal('UTC', TestTimezone.new('UTC').friendly_identifier(true)) - assert_equal('UTC', TestTimezone.new('UTC').friendly_identifier(false)) - assert_equal('UTC', TestTimezone.new('UTC').friendly_identifier) - end - - if defined?(Encoding) - def test_friendly_identifier_non_binary_encoding - refute_equal(Encoding::ASCII_8BIT, TestTimezone.new('Europe/Paris').friendly_identifier(true).encoding) - refute_equal(Encoding::ASCII_8BIT, TestTimezone.new('Europe/Paris').friendly_identifier(false).encoding) - end - end - - def test_to_s - assert_equal('Europe - Paris', TestTimezone.new('Europe/Paris').to_s) - assert_equal('America - Knox, Indiana', TestTimezone.new('America/Indiana/Knox').to_s) - assert_equal('Antarctica - Dumont D\'Urville', TestTimezone.new('Antarctica/DumontDUrville').to_s) - assert_equal('Antarctica - McMurdo', TestTimezone.new('Antarctica/McMurdo').to_s) - assert_equal('Etc - GMT+1', TestTimezone.new('Etc/GMT+1').to_s) - assert_equal('UTC', TestTimezone.new('UTC').to_s) - end - - def test_period_for_local - dt = DateTime.new(2005,2,18,16,24,23) - dt2 = DateTime.new(2005,2,18,16,24,23).new_offset(Rational(5,24)) - dt3 = DateTime.new(2005,2,18,16,24,23 + Rational(789, 1000)) - t = Time.utc(2005,2,18,16,24,23) - t2 = Time.local(2005,2,18,16,24,23) - t3 = Time.utc(2005,2,18,16,24,23,789000) - ts = t.to_i - - o1 = TimezoneOffset.new(0, 0, :GMT) - o2 = TimezoneOffset.new(0, 3600, :BST) - - period = TimezonePeriod.new( - TestTimezoneTransition.new(o1, o2, 1099184400), - TestTimezoneTransition.new(o2, o1, 1111885200)) - - dt_period = TestTimezone.new('Europe/London', nil, [period], dt).period_for_local(dt) - dt2_period = TestTimezone.new('Europe/London', nil, [period], dt2).period_for_local(dt2) - dt3_period = TestTimezone.new('Europe/London', nil, [period], dt3).period_for_local(dt3) - t_period = TestTimezone.new('Europe/London', nil, [period], t).period_for_local(t) - t2_period = TestTimezone.new('Europe/London', nil, [period], t2).period_for_local(t2) - t3_period = TestTimezone.new('Europe/London', nil, [period], t3).period_for_local(t3) - ts_period = TestTimezone.new('Europe/London', nil, [period], ts).period_for_local(ts) - - assert_equal(period, dt_period) - assert_equal(period, dt2_period) - assert_equal(period, dt3_period) - assert_equal(period, t_period) - assert_equal(period, t2_period) - assert_equal(period, t3_period) - assert_equal(period, ts_period) - end - - def test_period_for_local_invalid - dt = DateTime.new(2004,4,4,2,30,0) - tz = TestTimezone.new('America/New_York', nil, [], dt) - - assert_raises(PeriodNotFound) do - tz.period_for_local(dt) - end - end - - def test_period_for_local_ambiguous - o1 = TimezoneOffset.new(-18000, 0, :EST) - o2 = TimezoneOffset.new(-18000, 3600, :EDT) - - t1 = TestTimezoneTransition.new(o2, o1, 1081062000) - t2 = TestTimezoneTransition.new(o1, o2, 1099202400) - t3 = TestTimezoneTransition.new(o2, o1, 1112511600) - - p1 = TimezonePeriod.new(t1, t2) - p2 = TimezonePeriod.new(t2, t3) - - dt = DateTime.new(2004,10,31,1,0,0) - dt2 = DateTime.new(2004,10,31,1,0,Rational(555,1000)) - t = Time.utc(2004,10,31,1,30,0) - t2 = Time.utc(2004,10,31,1,30,0,555000) - i = Time.utc(2004,10,31,1,59,59).to_i - - dt_tz = TestTimezone.new('America/New_York', nil, [p1, p2], dt) - dt2_tz = TestTimezone.new('America/New_York', nil, [p1, p2], dt2) - t_tz = TestTimezone.new('America/New_York', nil, [p1, p2], t) - t2_tz = TestTimezone.new('America/New_York', nil, [p1, p2], t2) - i_tz = TestTimezone.new('America/New_York', nil, [p1, p2], i) - - assert_raises(AmbiguousTime) { dt_tz.period_for_local(dt) } - assert_raises(AmbiguousTime) { dt2_tz.period_for_local(dt2) } - assert_raises(AmbiguousTime) { t_tz.period_for_local(t) } - assert_raises(AmbiguousTime) { t2_tz.period_for_local(t2) } - assert_raises(AmbiguousTime) { i_tz.period_for_local(i) } - end - - def test_period_for_local_not_found - dt = DateTime.new(2004,4,4,2,0,0) - dt2 = DateTime.new(2004,4,4,2,0,Rational(987,1000)) - t = Time.utc(2004,4,4,2,30,0) - t2 = Time.utc(2004,4,4,2,30,0,987000) - i = Time.utc(2004,4,4,2,59,59).to_i - - dt_tz = TestTimezone.new('America/New_York', nil, [], dt) - dt2_tz = TestTimezone.new('America/New_York', nil, [], dt2) - t_tz = TestTimezone.new('America/New_York', nil, [], t) - t2_tz = TestTimezone.new('America/New_York', nil, [], t2) - i_tz = TestTimezone.new('America/New_York', nil, [], i) - - assert_raises(PeriodNotFound) { dt_tz.period_for_local(dt) } - assert_raises(PeriodNotFound) { dt2_tz.period_for_local(dt2) } - assert_raises(PeriodNotFound) { t_tz.period_for_local(t) } - assert_raises(PeriodNotFound) { t2_tz.period_for_local(t2) } - assert_raises(PeriodNotFound) { i_tz.period_for_local(i) } - end - - def test_period_for_local_default_dst_set_true - Timezone.default_dst = true - - o1 = TimezoneOffset.new(-18000, 0, :EST) - o2 = TimezoneOffset.new(-18000, 3600, :EDT) - - t1 = TestTimezoneTransition.new(o2, o1, 1081062000) - t2 = TestTimezoneTransition.new(o1, o2, 1099202400) - t3 = TestTimezoneTransition.new(o2, o1, 1112511600) - - p1 = TimezonePeriod.new(t1, t2) - p2 = TimezonePeriod.new(t2, t3) - - dt = DateTime.new(2004,10,31,1,30,0) - - tz = TestTimezone.new('America/New_York', nil, [p1, p2], dt) - - assert_equal(p1, tz.period_for_local(dt)) - assert_equal(p1, tz.period_for_local(dt, true)) - assert_equal(p2, tz.period_for_local(dt, false)) - assert_raises(AmbiguousTime) { tz.period_for_local(dt, nil) } - end - - def test_period_for_local_default_dst_set_false - Timezone.default_dst = false - - o1 = TimezoneOffset.new(-18000, 0, :EST) - o2 = TimezoneOffset.new(-18000, 3600, :EDT) - - t1 = TestTimezoneTransition.new(o2, o1, 1081062000) - t2 = TestTimezoneTransition.new(o1, o2, 1099202400) - t3 = TestTimezoneTransition.new(o2, o1, 1112511600) - - p1 = TimezonePeriod.new(t1, t2) - p2 = TimezonePeriod.new(t2, t3) - - dt = DateTime.new(2004,10,31,1,30,0) - - tz = TestTimezone.new('America/New_York', nil, [p1, p2], dt) - - assert_equal(p2, tz.period_for_local(dt)) - assert_equal(p1, tz.period_for_local(dt, true)) - assert_equal(p2, tz.period_for_local(dt, false)) - assert_raises(AmbiguousTime) { tz.period_for_local(dt, nil) } - end - - def test_period_for_local_dst_flag_resolved - o1 = TimezoneOffset.new(-18000, 0, :EST) - o2 = TimezoneOffset.new(-18000, 3600, :EDT) - - t1 = TestTimezoneTransition.new(o2, o1, 1081062000) - t2 = TestTimezoneTransition.new(o1, o2, 1099202400) - t3 = TestTimezoneTransition.new(o2, o1, 1112511600) - - p1 = TimezonePeriod.new(t1, t2) - p2 = TimezonePeriod.new(t2, t3) - - dt = DateTime.new(2004,10,31,1,30,0) - - tz = TestTimezone.new('America/New_York', nil, [p1, p2], dt) - - assert_equal(p1, tz.period_for_local(dt, true)) - assert_equal(p2, tz.period_for_local(dt, false)) - assert_equal(p1, tz.period_for_local(dt, true) {|periods| raise BlockCalled, 'should not be called' }) - assert_equal(p2, tz.period_for_local(dt, false) {|periods| raise BlockCalled, 'should not be called' }) - end - - def test_period_for_local_dst_block_called - o1 = TimezoneOffset.new(-18000, 0, :EST) - o2 = TimezoneOffset.new(-18000, 3600, :EDT) - - t1 = TestTimezoneTransition.new(o2, o1, 1081062000) - t2 = TestTimezoneTransition.new(o1, o2, 1099202400) - t3 = TestTimezoneTransition.new(o2, o1, 1112511600) - - p1 = TimezonePeriod.new(t1, t2) - p2 = TimezonePeriod.new(t2, t3) - - dt = DateTime.new(2004,10,31,1,30,0) - - tz = TestTimezone.new('America/New_York', nil, [p1, p2], dt) - - assert_raises(BlockCalled) { - tz.period_for_local(dt) {|periods| - assert_equal([p1, p2], periods) - - # raise exception to test that the block was called - raise BlockCalled, 'should be raised' - } - } - - assert_equal(p1, tz.period_for_local(dt) {|periods| periods.first}) - assert_equal(p2, tz.period_for_local(dt) {|periods| periods.last}) - assert_equal(p1, tz.period_for_local(dt) {|periods| [periods.first]}) - assert_equal(p2, tz.period_for_local(dt) {|periods| [periods.last]}) - end - - def test_period_for_local_dst_cannot_resolve - # At midnight local time on Aug 5 1915 in Warsaw, the clocks were put back - # 24 minutes and both periods were non-DST. Hence the block should be - # called regardless of the value of the Boolean dst parameter. - - o0 = TimezoneOffset.new(5040, 0, :LMT) - o1 = TimezoneOffset.new(5040, 0, :WMT) - o2 = TimezoneOffset.new(3600, 0, :CET) - o3 = TimezoneOffset.new(3600, 3600, :CEST) - - t1 = TestTimezoneTransition.new(o1, o0, DateTime.new(1879, 12, 31, 22, 36, 0)) - t2 = TestTimezoneTransition.new(o2, o1, DateTime.new(1915, 8, 4, 22, 36, 0)) - t3 = TestTimezoneTransition.new(o3, o2, DateTime.new(1916, 4, 30, 22, 0, 0)) - - p1 = TimezonePeriod.new(t1, t2) - p2 = TimezonePeriod.new(t2, t3) - - dt = DateTime.new(1915,8,4,23,40,0) - - tz = TestTimezone.new('Europe/Warsaw', nil, [p1, p2], dt) - - assert_raises(BlockCalled) { - tz.period_for_local(dt, true) {|periods| - assert_equal([p1, p2], periods) - raise BlockCalled, 'should be raised' - } - } - - assert_raises(BlockCalled) { - tz.period_for_local(dt, false) {|periods| - assert_equal([p1, p2], periods) - raise BlockCalled, 'should be raised' - } - } - end - - def test_period_for_local_block_ambiguous - o1 = TimezoneOffset.new(-18000, 0, :EST) - o2 = TimezoneOffset.new(-18000, 3600, :EDT) - - t1 = TestTimezoneTransition.new(o2, o1, 1081062000) - t2 = TestTimezoneTransition.new(o1, o2, 1099202400) - t3 = TestTimezoneTransition.new(o2, o1, 1112511600) - - p1 = TimezonePeriod.new(t1, t2) - p2 = TimezonePeriod.new(t2, t3) - - dt = DateTime.new(2004,10,31,1,30,0) - - tz = TestTimezone.new('America/New_York', nil, [p1, p2], dt) - - assert_raises(AmbiguousTime) do - tz.period_for_local(dt) {|periods| nil} - end - - assert_raises(AmbiguousTime) do - tz.period_for_local(dt) {|periods| periods} - end - - assert_raises(AmbiguousTime) do - tz.period_for_local(dt) {|periods| []} - end - - assert_raises(AmbiguousTime) do - tz.period_for_local(dt) {|periods| raise AmbiguousTime, 'Ambiguous time'} - end - end - - def test_utc_to_local - dt = DateTime.new(2005,6,18,16,24,23) - dt2 = DateTime.new(2005,6,18,16,24,23).new_offset(Rational(5,24)) - dtu = DateTime.new(2005,6,18,16,24,23 + Rational(567,1000)) - dtu2 = DateTime.new(2005,6,18,16,24,23 + Rational(567,1000)).new_offset(Rational(5,24)) - t = Time.utc(2005,6,18,16,24,23) - t2 = Time.local(2005,6,18,16,24,23) - tu = Time.utc(2005,6,18,16,24,23,567000) - tu2 = Time.local(2005,6,18,16,24,23,567000) - ts = t.to_i - - o1 = TimezoneOffset.new(0, 0, :GMT) - o2 = TimezoneOffset.new(0, 3600, :BST) - - period = TimezonePeriod.new( - TestTimezoneTransition.new(o2, o1, 1111885200), - TestTimezoneTransition.new(o1, o2, 1130634000)) - - assert_equal(DateTime.new(2005,6,18,17,24,23), TestTimezone.new('Europe/London', period, [], dt).utc_to_local(dt)) - assert_equal(DateTime.new(2005,6,18,17,24,23), TestTimezone.new('Europe/London', period, [], dt2).utc_to_local(dt2)) - assert_equal(DateTime.new(2005,6,18,17,24,23 + Rational(567,1000)), TestTimezone.new('Europe/London', period, [], dtu).utc_to_local(dtu)) - assert_equal(DateTime.new(2005,6,18,17,24,23 + Rational(567,1000)), TestTimezone.new('Europe/London', period, [], dtu2).utc_to_local(dtu2)) - assert_equal(Time.utc(2005,6,18,17,24,23), TestTimezone.new('Europe/London', period, [], t).utc_to_local(t)) - assert_equal(Time.utc(2005,6,18,17,24,23), TestTimezone.new('Europe/London', period, [], t2).utc_to_local(t2)) - assert_equal(Time.utc(2005,6,18,17,24,23,567000), TestTimezone.new('Europe/London', period, [], tu).utc_to_local(tu)) - assert_equal(Time.utc(2005,6,18,17,24,23,567000), TestTimezone.new('Europe/London', period, [], tu2).utc_to_local(tu2)) - assert_equal(Time.utc(2005,6,18,17,24,23).to_i, TestTimezone.new('Europe/London', period, [], ts).utc_to_local(ts)) - end - - def test_utc_to_local_offset - dt = DateTime.new(2005,6,18,16,24,23) - dt2 = DateTime.new(2005,6,18,16,24,23).new_offset(Rational(5,24)) - dtu = DateTime.new(2005,6,18,16,24,23 + Rational(567,1000)) - dtu2 = DateTime.new(2005,6,18,16,24,23 + Rational(567,1000)).new_offset(Rational(5,24)) - t = Time.utc(2005,6,18,16,24,23) - t2 = Time.local(2005,6,18,16,24,23) - tu = Time.utc(2005,6,18,16,24,23,567000) - tu2 = Time.local(2005,6,18,16,24,23,567000) - - o1 = TimezoneOffset.new(0, 0, :GMT) - o2 = TimezoneOffset.new(0, 3600, :BST) - - period = TimezonePeriod.new( - TestTimezoneTransition.new(o2, o1, 1111885200), - TestTimezoneTransition.new(o1, o2, 1130634000)) - - assert_equal(0, TestTimezone.new('Europe/London', period, [], dt).utc_to_local(dt).offset) - assert_equal(0, TestTimezone.new('Europe/London', period, [], dt2).utc_to_local(dt2).offset) - assert_equal(0, TestTimezone.new('Europe/London', period, [], dtu).utc_to_local(dtu).offset) - assert_equal(0, TestTimezone.new('Europe/London', period, [], dtu2).utc_to_local(dtu2).offset) - assert_equal(0, TestTimezone.new('Europe/London', period, [], t).utc_to_local(t).utc_offset) - assert(TestTimezone.new('Europe/London', period, [], t).utc_to_local(t).utc?) - assert_equal(0, TestTimezone.new('Europe/London', period, [], t2).utc_to_local(t2).utc_offset) - assert(TestTimezone.new('Europe/London', period, [], t2).utc_to_local(t2).utc?) - assert_equal(0, TestTimezone.new('Europe/London', period, [], tu).utc_to_local(tu).utc_offset) - assert(TestTimezone.new('Europe/London', period, [], tu).utc_to_local(tu).utc?) - assert_equal(0, TestTimezone.new('Europe/London', period, [], tu2).utc_to_local(tu2).utc_offset) - assert(TestTimezone.new('Europe/London', period, [], tu2).utc_to_local(tu2).utc?) - end - - def test_local_to_utc - dt = DateTime.new(2005,6,18,16,24,23) - dt2 = DateTime.new(2005,6,18,16,24,23).new_offset(Rational(5, 24)) - dtu = DateTime.new(2005,6,18,16,24,23 + Rational(567,1000)) - dtu2 = DateTime.new(2005,6,18,16,24,23 + Rational(567,1000)).new_offset(Rational(5, 24)) - t = Time.utc(2005,6,18,16,24,23) - t2 = Time.local(2005,6,18,16,24,23) - tu = Time.utc(2005,6,18,16,24,23,567000) - tu2 = Time.local(2005,6,18,16,24,23,567000) - ts = t.to_i - - o1 = TimezoneOffset.new(0, 0, :GMT) - o2 = TimezoneOffset.new(0, 3600, :BST) - - period = TimezonePeriod.new( - TestTimezoneTransition.new(o2, o1, 1111885200), - TestTimezoneTransition.new(o1, o2, 1130634000)) - - assert_equal(DateTime.new(2005,6,18,15,24,23), TestTimezone.new('Europe/London', nil, [period], dt).local_to_utc(dt)) - assert_equal(DateTime.new(2005,6,18,15,24,23), TestTimezone.new('Europe/London', nil, [period], dt2).local_to_utc(dt2)) - assert_equal(DateTime.new(2005,6,18,15,24,23 + Rational(567,1000)), TestTimezone.new('Europe/London', nil, [period], dtu).local_to_utc(dtu)) - assert_equal(DateTime.new(2005,6,18,15,24,23 + Rational(567,1000)), TestTimezone.new('Europe/London', nil, [period], dtu2).local_to_utc(dtu2)) - assert_equal(Time.utc(2005,6,18,15,24,23), TestTimezone.new('Europe/London', nil, [period], t).local_to_utc(t)) - assert_equal(Time.utc(2005,6,18,15,24,23), TestTimezone.new('Europe/London', nil, [period], t2).local_to_utc(t2)) - assert_equal(Time.utc(2005,6,18,15,24,23,567000), TestTimezone.new('Europe/London', nil, [period], tu).local_to_utc(tu)) - assert_equal(Time.utc(2005,6,18,15,24,23,567000), TestTimezone.new('Europe/London', nil, [period], tu2).local_to_utc(tu2)) - assert_equal(Time.utc(2005,6,18,15,24,23).to_i, TestTimezone.new('Europe/London', nil, [period], ts).local_to_utc(ts)) - end - - def test_local_to_utc_offset - dt = DateTime.new(2005,6,18,16,24,23) - dt2 = DateTime.new(2005,6,18,16,24,23).new_offset(Rational(5, 24)) - dtu = DateTime.new(2005,6,18,16,24,23 + Rational(567,1000)) - dtu2 = DateTime.new(2005,6,18,16,24,23 + Rational(567,1000)).new_offset(Rational(5, 24)) - t = Time.utc(2005,6,18,16,24,23) - t2 = Time.local(2005,6,18,16,24,23) - tu = Time.utc(2005,6,18,16,24,23,567000) - tu2 = Time.local(2005,6,18,16,24,23,567000) - - o1 = TimezoneOffset.new(0, 0, :GMT) - o2 = TimezoneOffset.new(0, 3600, :BST) - - period = TimezonePeriod.new( - TestTimezoneTransition.new(o2, o1, 1111885200), - TestTimezoneTransition.new(o1, o2, 1130634000)) - - assert_equal(0, TestTimezone.new('Europe/London', nil, [period], dt).local_to_utc(dt).offset) - assert_equal(0, TestTimezone.new('Europe/London', nil, [period], dt2).local_to_utc(dt2).offset) - assert_equal(0, TestTimezone.new('Europe/London', nil, [period], dtu).local_to_utc(dtu).offset) - assert_equal(0, TestTimezone.new('Europe/London', nil, [period], dtu2).local_to_utc(dtu2).offset) - assert_equal(0, TestTimezone.new('Europe/London', nil, [period], t).local_to_utc(t).utc_offset) - assert(TestTimezone.new('Europe/London', nil, [period], t).local_to_utc(t).utc?) - assert_equal(0, TestTimezone.new('Europe/London', nil, [period], t2).local_to_utc(t2).utc_offset) - assert(TestTimezone.new('Europe/London', nil, [period], t2).local_to_utc(t2).utc?) - assert_equal(0, TestTimezone.new('Europe/London', nil, [period], tu).local_to_utc(tu).utc_offset) - assert(TestTimezone.new('Europe/London', nil, [period], tu).local_to_utc(tu).utc?) - assert_equal(0, TestTimezone.new('Europe/London', nil, [period], tu2).local_to_utc(tu2).utc_offset) - assert(TestTimezone.new('Europe/London', nil, [period], tu2).local_to_utc(tu2).utc?) - end - - def test_local_to_utc_utc_local_returns_utc - # Check that UTC time instances are always returned even if the system - # is using UTC as the time zone. - - # Note that this will only test will only work correctly on platforms where - # setting the TZ environment variable has an effect. If setting TZ has no - # effect, then this test will still pass. - - old_tz = ENV['TZ'] - begin - ENV['TZ'] = 'UTC' - - tz = Timezone.get('America/New_York') - - t = tz.local_to_utc(Time.local(2014, 1, 11, 17, 18, 41)) - assert_equal(Time.utc(2014, 1, 11, 22, 18, 41), t) - assert(t.utc?) - ensure - ENV['TZ'] = old_tz - end - end - - def test_local_to_utc_invalid - dt = DateTime.new(2004,4,4,2,30,0) - tz = TestTimezone.new('America/New_York', nil, [], dt) - assert_raises(PeriodNotFound) { tz.local_to_utc(dt) } - - t = Time.utc(2004,4,4,2,30,0) - tz = TestTimezone.new('America/New_York', nil, [], t) - assert_raises(PeriodNotFound) { tz.local_to_utc(t) } - - i = Time.utc(2004,4,4,2,30,0).to_i - tz = TestTimezone.new('America/New_York', nil, [], i) - assert_raises(PeriodNotFound) { tz.local_to_utc(i) } - end - - def test_local_to_utc_ambiguous - o1 = TimezoneOffset.new(-18000, 0, :EST) - o2 = TimezoneOffset.new(-18000, 3600, :EDT) - - t1 = TestTimezoneTransition.new(o2, o1, 1081062000) - t2 = TestTimezoneTransition.new(o1, o2, 1099202400) - t3 = TestTimezoneTransition.new(o2, o1, 1112511600) - - p1 = TimezonePeriod.new(t1, t2) - p2 = TimezonePeriod.new(t2, t3) - - dt = DateTime.new(2004,10,31,1,30,0) - tz = TestTimezone.new('America/New_York', nil, [p1, p2], dt) - assert_raises(AmbiguousTime) { tz.local_to_utc(dt) } - - t = Time.utc(2004,10,31,1,30,0) - tz = TestTimezone.new('America/New_York', nil, [p1, p2], t) - assert_raises(AmbiguousTime) { tz.local_to_utc(t) } - - i = Time.utc(2004,10,31,1,30,0).to_i - tz = TestTimezone.new('America/New_York', nil, [p1, p2], i) - assert_raises(AmbiguousTime) { tz.local_to_utc(i) } - - f = Time.utc(2004,10,31,1,30,0,501).to_i - tz = TestTimezone.new('America/New_York', nil, [p1, p2], f) - assert_raises(AmbiguousTime) { tz.local_to_utc(f) } - end - - def test_local_to_utc_not_found - dt = DateTime.new(2004,4,4,2,0,0) - t = Time.utc(2004,4,4,2,30,0) - i = Time.utc(2004,4,4,2,59,59).to_i - - dt_tz = TestTimezone.new('America/New_York', nil, [], dt) - t_tz = TestTimezone.new('America/New_York', nil, [], t) - i_tz = TestTimezone.new('America/New_York', nil, [], i) - - assert_raises(PeriodNotFound) { dt_tz.local_to_utc(dt) } - assert_raises(PeriodNotFound) { t_tz.local_to_utc(t) } - assert_raises(PeriodNotFound) { i_tz.local_to_utc(i) } - end - - def test_local_to_utc_default_dst_set_true - Timezone.default_dst = true - - o1 = TimezoneOffset.new(-18000, 0, :EST) - o2 = TimezoneOffset.new(-18000, 3600, :EDT) - - t1 = TestTimezoneTransition.new(o2, o1, 1081062000) - t2 = TestTimezoneTransition.new(o1, o2, 1099202400) - t3 = TestTimezoneTransition.new(o2, o1, 1112511600) - - p1 = TimezonePeriod.new(t1, t2) - p2 = TimezonePeriod.new(t2, t3) - - dt = DateTime.new(2004,10,31,1,30,0) - tz = TestTimezone.new('America/New_York', nil, [p1, p2], dt) - - assert_equal(DateTime.new(2004,10,31,5,30,0), tz.local_to_utc(dt)) - assert_equal(DateTime.new(2004,10,31,5,30,0), tz.local_to_utc(dt, true)) - assert_equal(DateTime.new(2004,10,31,6,30,0), tz.local_to_utc(dt, false)) - assert_raises(AmbiguousTime) { tz.local_to_utc(dt, nil) } - assert_equal(DateTime.new(2004,10,31,5,30,0), tz.local_to_utc(dt) {|periods| raise BlockCalled, 'should not be called' }) - end - - def test_local_to_utc_default_dst_set_false - Timezone.default_dst = false - - o1 = TimezoneOffset.new(-18000, 0, :EST) - o2 = TimezoneOffset.new(-18000, 3600, :EDT) - - t1 = TestTimezoneTransition.new(o2, o1, 1081062000) - t2 = TestTimezoneTransition.new(o1, o2, 1099202400) - t3 = TestTimezoneTransition.new(o2, o1, 1112511600) - - p1 = TimezonePeriod.new(t1, t2) - p2 = TimezonePeriod.new(t2, t3) - - dt = DateTime.new(2004,10,31,1,30,0) - tz = TestTimezone.new('America/New_York', nil, [p1, p2], dt) - - assert_equal(DateTime.new(2004,10,31,6,30,0), tz.local_to_utc(dt)) - assert_equal(DateTime.new(2004,10,31,6,30,0), tz.local_to_utc(dt, false)) - assert_equal(DateTime.new(2004,10,31,5,30,0), tz.local_to_utc(dt, true)) - assert_raises(AmbiguousTime) { tz.local_to_utc(dt, nil) } - assert_equal(DateTime.new(2004,10,31,6,30,0), tz.local_to_utc(dt) {|periods| raise BlockCalled, 'should not be called' }) - end - - def test_local_to_utc_dst_flag_resolved - o1 = TimezoneOffset.new(-18000, 0, :EST) - o2 = TimezoneOffset.new(-18000, 3600, :EDT) - - t1 = TestTimezoneTransition.new(o2, o1, 1081062000) - t2 = TestTimezoneTransition.new(o1, o2, 1099202400) - t3 = TestTimezoneTransition.new(o2, o1, 1112511600) - - p1 = TimezonePeriod.new(t1, t2) - p2 = TimezonePeriod.new(t2, t3) - - dt = DateTime.new(2004,10,31,1,30,0) - tz = TestTimezone.new('America/New_York', nil, [p1, p2], dt) - - assert_equal(DateTime.new(2004,10,31,5,30,0), tz.local_to_utc(dt, true)) - assert_equal(DateTime.new(2004,10,31,6,30,0), tz.local_to_utc(dt, false)) - assert_equal(DateTime.new(2004,10,31,5,30,0), tz.local_to_utc(dt, true) {|periods| raise BlockCalled, 'should not be called' }) - assert_equal(DateTime.new(2004,10,31,6,30,0), tz.local_to_utc(dt, false) {|periods| raise BlockCalled, 'should not be called' }) - end - - def test_local_to_utc_dst_block_called - o1 = TimezoneOffset.new(-18000, 0, :EST) - o2 = TimezoneOffset.new(-18000, 3600, :EDT) - - t1 = TestTimezoneTransition.new(o2, o1, 1081062000) - t2 = TestTimezoneTransition.new(o1, o2, 1099202400) - t3 = TestTimezoneTransition.new(o2, o1, 1112511600) - - p1 = TimezonePeriod.new(t1, t2) - p2 = TimezonePeriod.new(t2, t3) - - dt = DateTime.new(2004,10,31,1,30,0) - tz = TestTimezone.new('America/New_York', nil, [p1, p2], dt) - - assert_raises(BlockCalled) { - tz.local_to_utc(dt) {|periods| - assert_equal([p1, p2], periods) - - # raise exception to test that the block was called - raise BlockCalled, 'should be raised' - } - } - - assert_equal(DateTime.new(2004,10,31,5,30,0), tz.local_to_utc(dt) {|periods| periods.first}) - assert_equal(DateTime.new(2004,10,31,6,30,0), tz.local_to_utc(dt) {|periods| periods.last}) - assert_equal(DateTime.new(2004,10,31,5,30,0), tz.local_to_utc(dt) {|periods| [periods.first]}) - assert_equal(DateTime.new(2004,10,31,6,30,0), tz.local_to_utc(dt) {|periods| [periods.last]}) - end - - def test_local_to_utc_dst_cannot_resolve - # At midnight local time on Aug 5 1915 in Warsaw, the clocks were put back - # 24 minutes and both periods were non-DST. Hence the block should be - # called regardless of the value of the Boolean dst parameter. - - o0 = TimezoneOffset.new(5040, 0, :LMT) - o1 = TimezoneOffset.new(5040, 0, :WMT) - o2 = TimezoneOffset.new(3600, 0, :CET) - o3 = TimezoneOffset.new(3600, 3600, :CEST) - - t1 = TestTimezoneTransition.new(o1, o0, DateTime.new(1879, 12, 31, 22, 36, 0)) - t2 = TestTimezoneTransition.new(o2, o1, DateTime.new(1915, 8, 4, 22, 36, 0)) - t3 = TestTimezoneTransition.new(o3, o2, DateTime.new(1916, 4, 30, 22, 0, 0)) - - p1 = TimezonePeriod.new(t1, t2) - p2 = TimezonePeriod.new(t2, t3) - - dt = DateTime.new(1915,8,4,23,40,0) - - tz = TestTimezone.new('Europe/Warsaw', nil, [p1, p2], dt) - - assert_raises(BlockCalled) do - tz.local_to_utc(dt, true) do |periods| - assert_equal([p1, p2], periods) - raise BlockCalled, 'should be raised' - end - end - - assert_raises(BlockCalled) do - tz.local_to_utc(dt, false) do |periods| - assert_equal([p1, p2], periods) - raise BlockCalled, 'should be raised' - end - end - - assert_equal(DateTime.new(1915,8,4,22,16,0), tz.local_to_utc(dt) {|periods| periods.first}) - assert_equal(DateTime.new(1915,8,4,22,40,0), tz.local_to_utc(dt) {|periods| periods.last}) - assert_equal(DateTime.new(1915,8,4,22,16,0), tz.local_to_utc(dt) {|periods| [periods.first]}) - assert_equal(DateTime.new(1915,8,4,22,40,0), tz.local_to_utc(dt) {|periods| [periods.last]}) - end - - def test_local_to_utc_block_ambiguous - o1 = TimezoneOffset.new(-18000, 0, :EST) - o2 = TimezoneOffset.new(-18000, 3600, :EDT) - - t1 = TestTimezoneTransition.new(o2, o1, 1081062000) - t2 = TestTimezoneTransition.new(o1, o2, 1099202400) - t3 = TestTimezoneTransition.new(o2, o1, 1112511600) - - p1 = TimezonePeriod.new(t1, t2) - p2 = TimezonePeriod.new(t2, t3) - - dt = DateTime.new(2004,10,31,1,30,0) - tz = TestTimezone.new('America/New_York', nil, [p1, p2], dt) - - assert_raises(AmbiguousTime) { tz.local_to_utc(dt) {|periods| nil} } - assert_raises(AmbiguousTime) { tz.local_to_utc(dt) {|periods| periods} } - assert_raises(AmbiguousTime) { tz.local_to_utc(dt) {|periods| []} } - assert_raises(AmbiguousTime) { tz.local_to_utc(dt) {|periods| raise AmbiguousTime, 'Ambiguous time'} } - end - - def test_offsets_up_to - o1 = TimezoneOffset.new(-17900, 0, :TESTLMT) - o2 = TimezoneOffset.new(-18000, 3600, :TESTD) - o3 = TimezoneOffset.new(-18000, 0, :TESTS) - o4 = TimezoneOffset.new(-21600, 3600, :TESTD) - o5 = TimezoneOffset.new(-21600, 0, :TESTS) - - t1 = TestTimezoneTransition.new(o2, o1, Time.utc(2010, 4,1,1,0,0).to_i) - t2 = TestTimezoneTransition.new(o3, o2, Time.utc(2010,10,1,1,0,0).to_i) - t3 = TestTimezoneTransition.new(o2, o3, Time.utc(2011, 3,1,1,0,0).to_i) - t4 = TestTimezoneTransition.new(o4, o2, Time.utc(2011, 4,1,1,0,0).to_i) - t5 = TestTimezoneTransition.new(o3, o4, Time.utc(2011,10,1,1,0,0).to_i) - t6 = TestTimezoneTransition.new(o5, o3, Time.utc(2012, 3,1,1,0,0).to_i) - - assert_array_same_items([o1, o2, o3, o4, o5], - OffsetsUpToTestTimezone.new('Test/Zone', Time.utc(2012,3,1,1,0,1), nil, [t1, t2, t3, t4, t5, t6]). - offsets_up_to(Time.utc(2012,3,1,1,0,1))) - assert_array_same_items([o2, o3, o4, o5], - OffsetsUpToTestTimezone.new('Test/Zone', Time.utc(2012,3,1,1,0,1), Time.utc(2010,4,1,1,0,0), [t1, t2, t3, t4, t5, t6]). - offsets_up_to(Time.utc(2012,3,1,1,0,1), Time.utc(2010,4,1,1,0,0))) - assert_array_same_items([o1, o2, o3, o4], - OffsetsUpToTestTimezone.new('Test/Zone', Time.utc(2012,3,1,1,0,0), nil, [t1, t2, t3, t4, t5]). - offsets_up_to(Time.utc(2012,3,1,1,0,0))) - assert_array_same_items([o2, o3, o4, o5], - OffsetsUpToTestTimezone.new('Test/Zone', Time.utc(2012,3,1,1,0,1), Time.utc(2010,4,1,1,0,1), [t2, t3, t4, t5, t6]). - offsets_up_to(Time.utc(2012,3,1,1,0,1), Time.utc(2010,4,1,1,0,1))) - assert_array_same_items([o2, o3], - OffsetsUpToTestTimezone.new('Test/Zone', Time.utc(2011,3,1,2,0,0), Time.utc(2011,3,1,0,0,0), [t3]). - offsets_up_to(Time.utc(2011,3,1,2,0,0), Time.utc(2011,3,1,0,0,0))) - assert_array_same_items([o3, o4], - OffsetsUpToTestTimezone.new('Test/Zone', Time.utc(2012,3,1,1,0,0), Time.utc(2011,4,1,1,0,0), [t4, t5]). - offsets_up_to(Time.utc(2012,3,1,1,0,0), Time.utc(2011,4,1,1,0,0))) - - assert_array_same_items([o1, o2, o3, o4, o5], - OffsetsUpToTestTimezone.new('Test/Zone', Time.utc(2012,3,1,1,0,1).to_i, nil, [t1, t2, t3, t4, t5, t6]). - offsets_up_to(Time.utc(2012,3,1,1,0,1).to_i)) - assert_array_same_items([o2, o3, o4, o5], - OffsetsUpToTestTimezone.new('Test/Zone', Time.utc(2012,3,1,1,0,1).to_i, Time.utc(2010,4,1,1,0,0).to_i, [t1, t2, t3, t4, t5, t6]). - offsets_up_to(Time.utc(2012,3,1,1,0,1).to_i, Time.utc(2010,4,1,1,0,0).to_i)) - assert_array_same_items([o1, o2, o3, o4], - OffsetsUpToTestTimezone.new('Test/Zone', Time.utc(2012,3,1,1,0,0).to_i, nil, [t1, t2, t3, t4, t5]). - offsets_up_to(Time.utc(2012,3,1,1,0,0).to_i)) - assert_array_same_items([o2, o3, o4, o5], - OffsetsUpToTestTimezone.new('Test/Zone', Time.utc(2012,3,1,1,0,1).to_i, Time.utc(2010,4,1,1,0,1).to_i, [t2, t3, t4, t5, t6]). - offsets_up_to(Time.utc(2012,3,1,1,0,1).to_i, Time.utc(2010,4,1,1,0,1).to_i)) - assert_array_same_items([o2, o3], - OffsetsUpToTestTimezone.new('Test/Zone', Time.utc(2011,3,1,2,0,0).to_i, Time.utc(2011,3,1,0,0,0).to_i, [t3]). - offsets_up_to(Time.utc(2011,3,1,2,0,0).to_i, Time.utc(2011,3,1,0,0,0).to_i)) - assert_array_same_items([o3, o4], - OffsetsUpToTestTimezone.new('Test/Zone', Time.utc(2012,3,1,1,0,0).to_i, Time.utc(2011,4,1,1,0,0).to_i, [t4, t5]). - offsets_up_to(Time.utc(2012,3,1,1,0,0).to_i, Time.utc(2011,4,1,1,0,0).to_i)) - - assert_array_same_items([o1, o2, o3, o4, o5], - OffsetsUpToTestTimezone.new('Test/Zone', DateTime.new(2012,3,1,1,0,1), nil, [t1, t2, t3, t4, t5, t6]). - offsets_up_to(DateTime.new(2012,3,1,1,0,1))) - assert_array_same_items([o2, o3, o4, o5], - OffsetsUpToTestTimezone.new('Test/Zone', DateTime.new(2012,3,1,1,0,1), DateTime.new(2010,4,1,1,0,0), [t1, t2, t3, t4, t5, t6]). - offsets_up_to(DateTime.new(2012,3,1,1,0,1), DateTime.new(2010,4,1,1,0,0))) - assert_array_same_items([o1, o2, o3, o4], - OffsetsUpToTestTimezone.new('Test/Zone', DateTime.new(2012,3,1,1,0,0), nil, [t1, t2, t3, t4, t5]). - offsets_up_to(DateTime.new(2012,3,1,1,0,0))) - assert_array_same_items([o2, o3, o4, o5], - OffsetsUpToTestTimezone.new('Test/Zone', DateTime.new(2012,3,1,1,0,1), DateTime.new(2010,4,1,1,0,1), [t2, t3, t4, t5, t6]). - offsets_up_to(DateTime.new(2012,3,1,1,0,1), DateTime.new(2010,4,1,1,0,1))) - assert_array_same_items([o2, o3], - OffsetsUpToTestTimezone.new('Test/Zone', DateTime.new(2011,3,1,2,0,0), DateTime.new(2011,3,1,0,0,0), [t3]). - offsets_up_to(DateTime.new(2011,3,1,2,0,0), DateTime.new(2011,3,1,0,0,0))) - assert_array_same_items([o3, o4], - OffsetsUpToTestTimezone.new('Test/Zone', DateTime.new(2012,3,1,1,0,0), DateTime.new(2011,4,1,1,0,0), [t4, t5]). - offsets_up_to(DateTime.new(2012,3,1,1,0,0), DateTime.new(2011,4,1,1,0,0))) - end - - def test_offsets_up_to_no_transitions - o = TimezoneOffset.new(600, 0, :LMT) - p = TimezonePeriod.new(nil, nil, o) - - assert_array_same_items([o], - OffsetsUpToNoTransitionsTestTimezone.new('Test/Zone', Time.utc(2000,1,1,1,0,0), nil, p). - offsets_up_to(Time.utc(2000,1,1,1,0,0))) - assert_array_same_items([o], - OffsetsUpToNoTransitionsTestTimezone.new('Test/Zone', Time.utc(2000,1,1,1,0,0), Time.utc(1990,1,1,1,0,0), p). - offsets_up_to(Time.utc(2000,1,1,1,0,0), Time.utc(1990,1,1,1,0,0))) - - assert_array_same_items([o], - OffsetsUpToNoTransitionsTestTimezone.new('Test/Zone', Time.utc(2000,1,1,1,0,0).to_i, nil, p). - offsets_up_to(Time.utc(2000,1,1,1,0,0).to_i)) - assert_array_same_items([o], - OffsetsUpToNoTransitionsTestTimezone.new('Test/Zone', Time.utc(2000,1,1,1,0,0).to_i, Time.utc(1990,1,1,1,0,0).to_i, p). - offsets_up_to(Time.utc(2000,1,1,1,0,0).to_i, Time.utc(1990,1,1,1,0,0).to_i)) - - assert_array_same_items([o], - OffsetsUpToNoTransitionsTestTimezone.new('Test/Zone', DateTime.new(2000,1,1,1,0,0), nil, p). - offsets_up_to(DateTime.new(2000,1,1,1,0,0))) - assert_array_same_items([o], - OffsetsUpToNoTransitionsTestTimezone.new('Test/Zone', DateTime.new(2000,1,1,1,0,0), DateTime.new(1990,1,1,1,0,0), p). - offsets_up_to(DateTime.new(2000,1,1,1,0,0), DateTime.new(1990,1,1,1,0,0))) - end - - def test_offsets_up_to_utc_to_not_greater_than_utc_from - assert_raises(ArgumentError) do - OffsetsUpToTestTimezone.new('Test/Zone', Time.utc(2012,8,1,0,0,0), Time.utc(2012,8,1,0,0,0), []). - offsets_up_to(Time.utc(2012,8,1,0,0,0), Time.utc(2012,8,1,0,0,0)) - end - - assert_raises(ArgumentError) do - OffsetsUpToTestTimezone.new('Test/Zone', Time.utc(2012,8,1,0,0,0).to_i, Time.utc(2012,8,1,0,0,0).to_i, []). - offsets_up_to(Time.utc(2012,8,1,0,0,0).to_i, Time.utc(2012,8,1,0,0,0).to_i) - end - - assert_raises(ArgumentError) do - OffsetsUpToTestTimezone.new('Test/Zone', DateTime.new(2012,8,1,0,0,0), DateTime.new(2012,8,1,0,0,0), []). - offsets_up_to(DateTime.new(2012,8,1,0,0,0), DateTime.new(2012,8,1,0,0,0)) - end - end - - def test_now - assert_kind_of(Time, Timezone.get('Europe/London').now) - end - - def test_current_period - assert_kind_of(TimezonePeriod, Timezone.get('Europe/London').current_period) - end - - def test_current_period_and_time - current = Timezone.get('Europe/London').current_period_and_time - assert_equal(2, current.length) - assert_kind_of(Time, current[0]) - assert_kind_of(TimezonePeriod, current[1]) - end - - def test_current_time_and_period - current = Timezone.get('Europe/London').current_time_and_period - assert_equal(2, current.length) - assert_kind_of(Time, current[0]) - assert_kind_of(TimezonePeriod, current[1]) - end - - def test_compare - assert_equal(0, TestTimezone.new('Europe/London') <=> TestTimezone.new('Europe/London')) - assert_equal(-1, TestTimezone.new('Europe/London') <=> TestTimezone.new('Europe/london')) - assert_equal(-1, TestTimezone.new('Europe/London') <=> TestTimezone.new('Europe/Paris')) - assert_equal(1, TestTimezone.new('Europe/Paris') <=> TestTimezone.new('Europe/London')) - assert_equal(-1, TestTimezone.new('America/New_York') <=> TestTimezone.new('Europe/Paris')) - assert_equal(1, TestTimezone.new('Europe/Paris') <=> TestTimezone.new('America/New_York')) - end - - def test_compare_non_comparable - assert_nil(TestTimezone.new('Europe/London') <=> Object.new) - end - - def test_equality - assert_equal(true, TestTimezone.new('Europe/London') == TestTimezone.new('Europe/London')) - assert_equal(false, TestTimezone.new('Europe/London') == TestTimezone.new('Europe/london')) - assert_equal(false, TestTimezone.new('Europe/London') == TestTimezone.new('Europe/Paris')) - assert(!(TestTimezone.new('Europe/London') == Object.new)) - end - - def test_eql - assert_equal(true, TestTimezone.new('Europe/London').eql?(TestTimezone.new('Europe/London'))) - assert_equal(false, TestTimezone.new('Europe/London').eql?(TestTimezone.new('Europe/london'))) - assert_equal(false, TestTimezone.new('Europe/London').eql?(TestTimezone.new('Europe/Paris'))) - assert(!TestTimezone.new('Europe/London').eql?(Object.new)) - end - - def test_hash - assert_equal('Europe/London'.hash, TestTimezone.new('Europe/London').hash) - assert_equal('America/New_York'.hash, TestTimezone.new('America/New_York').hash) - end - - def test_marshal_data - tz = Timezone.get('Europe/London') - assert_kind_of(DataTimezone, tz) - assert_same(tz, Marshal.load(Marshal.dump(tz))) - end - - def test_marshal_linked - tz = Timezone.get('UTC') - - # ZoneinfoDataSource doesn't return LinkedTimezoneInfo for any timezone. - if DataSource.get.load_timezone_info('UTC').kind_of?(LinkedTimezoneInfo) - assert_kind_of(LinkedTimezone, tz) - else - assert_kind_of(DataTimezone, tz) - end - - assert_same(tz, Marshal.load(Marshal.dump(tz))) - end - - def test_strftime_datetime - tz = Timezone.get('Europe/London') - dt = DateTime.new(2006, 7, 15, 22, 12, 2) - assert_equal('23:12:02 BST', tz.strftime('%H:%M:%S %Z', dt)) - assert_equal('BST', tz.strftime('%Z', dt)) - assert_equal('%ZBST', tz.strftime('%%Z%Z', dt)) - assert_equal('BST BST', tz.strftime('%Z %Z', dt)) - assert_equal('BST %Z %BST %%Z %%BST', tz.strftime('%Z %%Z %%%Z %%%%Z %%%%%Z', dt)) - assert_equal('+0100 +01:00 +01:00:00 +01 %::::z', tz.strftime('%z %:z %::z %:::z %::::z', dt)) - assert_equal('1153001522 %s %1153001522', tz.strftime('%s %%s %%%s', dt)) - end - - def test_strftime_time - tz = Timezone.get('Europe/London') - t = Time.utc(2006, 7, 15, 22, 12, 2) - assert_equal('23:12:02 BST', tz.strftime('%H:%M:%S %Z', t)) - assert_equal('BST', tz.strftime('%Z', t)) - assert_equal('%ZBST', tz.strftime('%%Z%Z', t)) - assert_equal('BST BST', tz.strftime('%Z %Z', t)) - assert_equal('BST %Z %BST %%Z %%BST', tz.strftime('%Z %%Z %%%Z %%%%Z %%%%%Z', t)) - assert_equal('+0100 +01:00 +01:00:00 +01 %::::z', tz.strftime('%z %:z %::z %:::z %::::z', t)) - assert_equal('1153001522 %s %1153001522', tz.strftime('%s %%s %%%s', t)) - end - - def test_strftime_int - tz = Timezone.get('Europe/London') - i = Time.utc(2006, 7, 15, 22, 12, 2).to_i - assert_equal('23:12:02 BST', tz.strftime('%H:%M:%S %Z', i)) - assert_equal('BST', tz.strftime('%Z', i)) - assert_equal('%ZBST', tz.strftime('%%Z%Z', i)) - assert_equal('BST BST', tz.strftime('%Z %Z', i)) - assert_equal('BST %Z %BST %%Z %%BST', tz.strftime('%Z %%Z %%%Z %%%%Z %%%%%Z', i)) - assert_equal('+0100 +01:00 +01:00:00 +01 %::::z', tz.strftime('%z %:z %::z %:::z %::::z', i)) - assert_equal('1153001522 %s %1153001522', tz.strftime('%s %%s %%%s', i)) - end - - def test_get_missing_data_source - DataSource.set(DataSource.new) - - assert_raises(InvalidDataSource) do - Timezone.get('Europe/London') - end - end - - def test_new_missing_data_source - DataSource.set(DataSource.new) - - assert_raises(InvalidDataSource) do - Timezone.new('Europe/London') - end - end - - def test_all_missing_data_source - DataSource.set(DataSource.new) - - assert_raises(InvalidDataSource) do - Timezone.all - end - end - - def test_all_identifiers_missing_data_source - DataSource.set(DataSource.new) - - assert_raises(InvalidDataSource) do - Timezone.all_identifiers - end - end - - def test_all_data_zones_missing_data_source - DataSource.set(DataSource.new) - - assert_raises(InvalidDataSource) do - Timezone.all_data_zones - end - end - - def test_all_data_zone_identifiers_missing_data_source - DataSource.set(DataSource.new) - - assert_raises(InvalidDataSource) do - Timezone.all_data_zone_identifiers - end - end - - def test_all_linked_zones_missing_data_source - DataSource.set(DataSource.new) - - assert_raises(InvalidDataSource) do - Timezone.all_linked_zones - end - end - - def test_all_linked_zone_identifiers_missing_data_source - DataSource.set(DataSource.new) - - assert_raises(InvalidDataSource) do - Timezone.all_linked_zone_identifiers - end - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_timezone_transition_definition.rb ruby-tzinfo-2.0.4/test/tc_timezone_transition_definition.rb --- ruby-tzinfo-1.2.6/test/tc_timezone_transition_definition.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_timezone_transition_definition.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,295 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') -require 'date' - -include TZInfo - -class TCTimezoneTransitionDefinition < Minitest::Test - def test_initialize_timestamp_only - assert_nothing_raised do - TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - end - end - - def test_initialize_timestamp_and_datetime - assert_nothing_raised do - TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080, 5300392727, 2160) - end - end - - def test_initialize_datetime_only - assert_nothing_raised do - TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 5300392727, 2160) - end - end - - def test_at - t1 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - t2 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 5300392727, 2160) - t3 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080, 5300392727, 2160) - - assert(TimeOrDateTime.new(1148949080).eql?(t1.at)) - assert(TimeOrDateTime.new(DateTime.new(2006, 5, 30, 0, 31, 20)).eql?(t2.at)) - assert(TimeOrDateTime.new(1148949080).eql?(t3.at)) - end - - def test_at_before_negative_32_bit - t = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), -2147483649, 69573092117, 28800) - - if RubyCoreSupport.time_supports_negative && RubyCoreSupport.time_supports_64bit - assert(TimeOrDateTime.new(-2147483649).eql?(t.at)) - else - assert(TimeOrDateTime.new(DateTime.new(1901, 12, 13, 20, 45, 51)).eql?(t.at)) - end - end - - def test_at_before_epoch - t = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), -1, 210866759999, 86400) - - if RubyCoreSupport.time_supports_negative - assert(TimeOrDateTime.new(-1).eql?(t.at)) - else - assert(TimeOrDateTime.new(DateTime.new(1969, 12, 31, 23, 59, 59)).eql?(t.at)) - end - end - - def test_at_after_32bit - t = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 2147483648, 3328347557, 1350) - - if RubyCoreSupport.time_supports_64bit - assert(TimeOrDateTime.new(2147483648).eql?(t.at)) - else - assert(TimeOrDateTime.new(DateTime.new(2038, 1, 19, 3, 14, 8)).eql?(t.at)) - end - end - - def test_at_after_freeze - t1 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - t2 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 5300392727, 2160) - t1.freeze - t2.freeze - assert(TimeOrDateTime.new(1148949080).eql?(t1.at)) - assert(TimeOrDateTime.new(DateTime.new(2006, 5, 30, 0, 31, 20)).eql?(t2.at)) - end - - def test_eql_timestamp - t1 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - t2 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - t3 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 5300392727, 2160) - t4 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080, 5300392727, 2160) - t5 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949081) - t6 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3601, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - t7 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3601, 0, :TST), 1148949080) - - assert_equal(true, t1.eql?(t1)) - assert_equal(true, t1.eql?(t2)) - assert_equal(false, t1.eql?(t3)) - assert_equal(true, t1.eql?(t4)) - assert_equal(false, t1.eql?(t5)) - assert_equal(false, t1.eql?(t6)) - assert_equal(false, t1.eql?(t7)) - assert_equal(false, t1.eql?(Object.new)) - end - - def test_eql_datetime - t1 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 5300392727, 2160) - t2 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 5300392727, 2160) - t3 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - t4 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080, 5300392727, 2160) - t5 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 7852433803, 3200) - t6 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3601, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 5300392727, 2160) - t7 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3601, 0, :TST), 5300392727, 2160) - - assert_equal(true, t1.eql?(t1)) - assert_equal(true, t1.eql?(t2)) - assert_equal(false, t1.eql?(t3)) - assert_equal(false, t1.eql?(t4)) - assert_equal(false, t1.eql?(t5)) - assert_equal(false, t1.eql?(t6)) - assert_equal(false, t1.eql?(t7)) - assert_equal(false, t1.eql?(Object.new)) - end - - def test_eql_timestamp_and_datetime - t1 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080, 5300392727, 2160) - t2 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080, 5300392727, 2160) - t3 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - t4 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 5300392727, 2160) - t5 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148952681, 7852433803, 3200) - t6 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3601, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080, 5300392727, 2160) - t7 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3601, 0, :TST), 1148949080, 5300392727, 2160) - - assert_equal(true, t1.eql?(t1)) - assert_equal(true, t1.eql?(t2)) - assert_equal(true, t1.eql?(t3)) - assert_equal(false, t1.eql?(t4)) - assert_equal(false, t1.eql?(t5)) - assert_equal(false, t1.eql?(t6)) - assert_equal(false, t1.eql?(t7)) - assert_equal(false, t1.eql?(Object.new)) - end - - def test_eql_timestamp_and_datetime_before_negative_32bit - t1 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), -2147483649, 69573092117, 28800) - t2 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), -2147483649, 69573092117, 28800) - t3 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), -2147483649) - t4 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 69573092117, 28800) - - assert_equal(true, t1.eql?(t1)) - assert_equal(true, t1.eql?(t2)) - - if RubyCoreSupport.time_supports_negative && RubyCoreSupport.time_supports_64bit - assert_equal(true, t1.eql?(t3)) - assert_equal(false, t1.eql?(t4)) - assert_equal(true, t3.eql?(t1)) - assert_equal(false, t4.eql?(t1)) - else - assert_equal(false, t1.eql?(t3)) - assert_equal(true, t1.eql?(t4)) - assert_equal(false, t3.eql?(t1)) - assert_equal(true, t4.eql?(t1)) - end - end - - def test_eql_timestamp_and_datetime_before_epoch - t1 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), -1, 210866759999, 86400) - t2 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), -1, 210866759999, 86400) - t3 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), -1) - t4 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 210866759999, 86400) - - assert_equal(true, t1.eql?(t1)) - assert_equal(true, t1.eql?(t2)) - - if RubyCoreSupport.time_supports_negative - assert_equal(true, t1.eql?(t3)) - assert_equal(false, t1.eql?(t4)) - assert_equal(true, t3.eql?(t1)) - assert_equal(false, t4.eql?(t1)) - else - assert_equal(false, t1.eql?(t3)) - assert_equal(true, t1.eql?(t4)) - assert_equal(false, t3.eql?(t1)) - assert_equal(true, t4.eql?(t1)) - end - end - - def test_eql_timestamp_and_datetime_after_32bit - t1 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 2147483648, 3328347557, 1350) - t2 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 2147483648, 3328347557, 1350) - t3 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 2147483648) - t4 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 3328347557, 1350) - - assert_equal(true, t1.eql?(t1)) - assert_equal(true, t1.eql?(t2)) - - if RubyCoreSupport.time_supports_64bit - assert_equal(true, t1.eql?(t3)) - assert_equal(false, t1.eql?(t4)) - assert_equal(true, t3.eql?(t1)) - assert_equal(false, t4.eql?(t1)) - else - assert_equal(false, t1.eql?(t3)) - assert_equal(true, t1.eql?(t4)) - assert_equal(false, t3.eql?(t1)) - assert_equal(true, t4.eql?(t1)) - end - end - - def test_hash - t1 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - t2 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 5300392727, 2160) - t3 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080, 5300392727, 2160) - t4 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), -2147483649, 69573092117, 28800) - t5 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), -1, 210866759999, 86400) - t6 = TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 2147483648, 3328347557, 1350) - - assert_equal(TimezoneOffset.new(3600, 3600, :TDT).hash ^ - TimezoneOffset.new(3600, 0, :TST).hash ^ 1148949080.hash ^ nil.hash, - t1.hash) - assert_equal(TimezoneOffset.new(3600, 3600, :TDT).hash ^ - TimezoneOffset.new(3600, 0, :TST).hash ^ 5300392727.hash ^ 2160.hash, - t2.hash) - assert_equal(TimezoneOffset.new(3600, 3600, :TDT).hash ^ - TimezoneOffset.new(3600, 0, :TST).hash ^ 1148949080.hash ^ nil.hash, - t3.hash) - - if RubyCoreSupport.time_supports_negative && RubyCoreSupport.time_supports_64bit - assert_equal(TimezoneOffset.new(3600, 3600, :TDT).hash ^ - TimezoneOffset.new(3600, 0, :TST).hash ^ -2147483649.hash ^ nil.hash, - t4.hash) - else - assert_equal(TimezoneOffset.new(3600, 3600, :TDT).hash ^ - TimezoneOffset.new(3600, 0, :TST).hash ^ 69573092117.hash ^ 28800.hash, - t4.hash) - end - - if RubyCoreSupport.time_supports_negative - assert_equal(TimezoneOffset.new(3600, 3600, :TDT).hash ^ - TimezoneOffset.new(3600, 0, :TST).hash ^ -1.hash ^ nil.hash, - t5.hash) - else - assert_equal(TimezoneOffset.new(3600, 3600, :TDT).hash ^ - TimezoneOffset.new(3600, 0, :TST).hash ^ 210866759999.hash ^ 86400.hash, - t5.hash) - end - - if RubyCoreSupport.time_supports_64bit - assert_equal(TimezoneOffset.new(3600, 3600, :TDT).hash ^ - TimezoneOffset.new(3600, 0, :TST).hash ^ 2147483648.hash ^ nil.hash, - t6.hash) - else - assert_equal(TimezoneOffset.new(3600, 3600, :TDT).hash ^ - TimezoneOffset.new(3600, 0, :TST).hash ^ 3328347557.hash ^ 1350.hash, - t6.hash) - end - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_timezone_transition.rb ruby-tzinfo-2.0.4/test/tc_timezone_transition.rb --- ruby-tzinfo-1.2.6/test/tc_timezone_transition.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_timezone_transition.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,366 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') -require 'date' - -include TZInfo - -class TCTimezoneTransition < Minitest::Test - - class TestTimezoneTransition < TimezoneTransition - def initialize(offset, previous_offset, at) - super(offset, previous_offset) - @at = TimeOrDateTime.wrap(at) - end - - def at - @at - end - end - - def test_offset - t = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - - assert_equal(TimezoneOffset.new(3600, 3600, :TDT), t.offset) - end - - def test_previous_offset - t = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - - assert_equal(TimezoneOffset.new(3600, 0, :TST), t.previous_offset) - end - - def test_datetime - t1 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - t2 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), DateTime.new(2006, 5, 30, 0, 31, 20)) - t3 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), Time.utc(2006, 5, 30, 0, 31, 20)) - - assert_equal(DateTime.new(2006, 5, 30, 0, 31, 20), t1.datetime) - assert_equal(DateTime.new(2006, 5, 30, 0, 31, 20), t2.datetime) - assert_equal(DateTime.new(2006, 5, 30, 0, 31, 20), t3.datetime) - end - - def test_time - t1 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - t2 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), DateTime.new(2006, 5, 30, 0, 31, 20)) - t3 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), Time.utc(2006, 5, 30, 0, 31, 20)) - - assert_equal(Time.utc(2006, 5, 30, 0, 31, 20), t1.time) - assert_equal(Time.utc(2006, 5, 30, 0, 31, 20), t2.time) - assert_equal(Time.utc(2006, 5, 30, 0, 31, 20), t3.time) - end - - def test_local_end_at - t1 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - t2 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), DateTime.new(2006, 5, 30, 0, 31, 20)) - t3 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), Time.utc(2006, 5, 30, 0, 31, 20)) - - assert(TimeOrDateTime.new(1148952680).eql?(t1.local_end_at)) - assert(TimeOrDateTime.new(DateTime.new(2006, 5, 30, 1, 31, 20)).eql?(t2.local_end_at)) - assert(TimeOrDateTime.new(Time.utc(2006, 5, 30, 1, 31, 20)).eql?(t3.local_end_at)) - end - - def test_local_end_at_after_freeze - t = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - t.freeze - assert(TimeOrDateTime.new(1148952680).eql?(t.local_end_at)) - end - - def test_local_end - t1 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - t2 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), DateTime.new(2006, 5, 30, 0, 31, 20)) - t3 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), Time.utc(2006, 5, 30, 0, 31, 20)) - - assert_equal(DateTime.new(2006, 5, 30, 1, 31, 20), t1.local_end) - assert_equal(DateTime.new(2006, 5, 30, 1, 31, 20), t2.local_end) - assert_equal(DateTime.new(2006, 5, 30, 1, 31, 20), t3.local_end) - end - - def test_local_end_time - t1 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - t2 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), DateTime.new(2006, 5, 30, 0, 31, 20)) - t3 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), Time.utc(2006, 5, 30, 0, 31, 20)) - - assert_equal(Time.utc(2006, 5, 30, 1, 31, 20), t1.local_end_time) - assert_equal(Time.utc(2006, 5, 30, 1, 31, 20), t2.local_end_time) - assert_equal(Time.utc(2006, 5, 30, 1, 31, 20), t3.local_end_time) - end - - def test_local_start_at - t1 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - t2 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), DateTime.new(2006, 5, 30, 0, 31, 20)) - t3 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), Time.utc(2006, 5, 30, 0, 31, 20)) - - assert(TimeOrDateTime.new(1148956280).eql?(t1.local_start_at)) - assert(TimeOrDateTime.new(DateTime.new(2006, 5, 30, 2, 31, 20)).eql?(t2.local_start_at)) - assert(TimeOrDateTime.new(Time.utc(2006, 5, 30, 2, 31, 20)).eql?(t3.local_start_at)) - end - - def test_local_start_at_after_freeze - t = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - t.freeze - assert(TimeOrDateTime.new(1148956280).eql?(t.local_start_at)) - end - - def test_local_start - t1 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - t2 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), DateTime.new(2006, 5, 30, 0, 31, 20)) - t3 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), Time.utc(2006, 5, 30, 0, 31, 20)) - - assert_equal(DateTime.new(2006, 5, 30, 2, 31, 20), t1.local_start) - assert_equal(DateTime.new(2006, 5, 30, 2, 31, 20), t2.local_start) - assert_equal(DateTime.new(2006, 5, 30, 2, 31, 20), t3.local_start) - end - - def test_local_start_time - t1 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - t2 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), DateTime.new(2006, 5, 30, 0, 31, 20)) - t3 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), Time.utc(2006, 5, 30, 0, 31, 20)) - - assert_equal(Time.utc(2006, 5, 30, 2, 31, 20), t1.local_start_time) - assert_equal(Time.utc(2006, 5, 30, 2, 31, 20), t2.local_start_time) - assert_equal(Time.utc(2006, 5, 30, 2, 31, 20), t3.local_start_time) - end - - if RubyCoreSupport.time_supports_negative - def test_local_end_at_before_negative_32bit - t = TestTimezoneTransition.new(TimezoneOffset.new(-7200, 3600, :TDT), - TimezoneOffset.new(-7200, 0, :TST), -2147482800) - - if RubyCoreSupport.time_supports_64bit - assert(TimeOrDateTime.new(-2147490000).eql?(t.local_end_at)) - else - assert(TimeOrDateTime.new(DateTime.new(1901, 12, 13, 19, 0, 0)).eql?(t.local_end_at)) - end - end - - def test_local_start_at_before_negative_32bit - t = TestTimezoneTransition.new(TimezoneOffset.new(-7200, 3600, :TDT), - TimezoneOffset.new(-7200, 0, :TST), -2147482800) - - if RubyCoreSupport.time_supports_64bit - assert(TimeOrDateTime.new(-2147486400).eql?(t.local_start_at)) - else - assert(TimeOrDateTime.new(DateTime.new(1901, 12, 13, 20, 0, 0)).eql?(t.local_start_at)) - end - end - end - - def test_local_end_at_before_epoch - t = TestTimezoneTransition.new(TimezoneOffset.new(-7200, 3600, :TDT), - TimezoneOffset.new(-7200, 0, :TST), 1800) - - if RubyCoreSupport.time_supports_negative - assert(TimeOrDateTime.new(-5400).eql?(t.local_end_at)) - else - assert(TimeOrDateTime.new(DateTime.new(1969, 12, 31, 22, 30, 0)).eql?(t.local_end_at)) - end - end - - def test_local_start_at_before_epoch - t = TestTimezoneTransition.new(TimezoneOffset.new(-7200, 3600, :TDT), - TimezoneOffset.new(-7200, 0, :TST), 1800) - - if RubyCoreSupport.time_supports_negative - assert(TimeOrDateTime.new(-1800).eql?(t.local_start_at)) - else - assert(TimeOrDateTime.new(DateTime.new(1969, 12, 31, 23, 30, 0)).eql?(t.local_start_at)) - end - end - - def test_local_end_at_after_32bit - t = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 2147482800) - - if RubyCoreSupport.time_supports_64bit - assert(TimeOrDateTime.new(2147486400).eql?(t.local_end_at)) - else - assert(TimeOrDateTime.new(DateTime.new(2038, 1, 19, 4, 0, 0)).eql?(t.local_end_at)) - end - end - - def test_local_start_at_after_32bit - t = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 2147482800) - - if RubyCoreSupport.time_supports_64bit - assert(TimeOrDateTime.new(2147490000).eql?(t.local_start_at)) - else - assert(TimeOrDateTime.new(DateTime.new(2038, 1, 19, 5, 0, 0)).eql?(t.local_start_at)) - end - end - - def test_equality_timestamp - t1 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - t2 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - t3 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), DateTime.new(2006, 5, 30, 0, 31, 20)) - t4 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), Time.utc(2006, 5, 30, 0, 31, 20)) - t5 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949081) - t6 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), DateTime.new(2006, 5, 30, 1, 31, 21)) - t7 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), Time.utc(2006, 5, 30, 1, 31, 21)) - t8 = TestTimezoneTransition.new(TimezoneOffset.new(3601, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - t9 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3601, 0, :TST), 1148949080) - - assert_equal(true, t1 == t1) - assert_equal(true, t1 == t2) - assert_equal(true, t1 == t3) - assert_equal(true, t1 == t4) - assert_equal(false, t1 == t5) - assert_equal(false, t1 == t6) - assert_equal(false, t1 == t7) - assert_equal(false, t1 == t8) - assert_equal(false, t1 == t9) - assert_equal(false, t1 == Object.new) - - assert_equal(true, t1.eql?(t1)) - assert_equal(true, t1.eql?(t2)) - assert_equal(false, t1.eql?(t3)) - assert_equal(false, t1.eql?(t4)) - assert_equal(false, t1.eql?(t5)) - assert_equal(false, t1.eql?(t6)) - assert_equal(false, t1.eql?(t7)) - assert_equal(false, t1.eql?(t8)) - assert_equal(false, t1.eql?(t9)) - assert_equal(false, t1.eql?(Object.new)) - end - - def test_equality_datetime - t1 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), DateTime.new(2006, 5, 30, 0, 31, 20)) - t2 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), DateTime.new(2006, 5, 30, 0, 31, 20)) - t3 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - t4 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), Time.utc(2006, 5, 30, 0, 31, 20)) - t5 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), DateTime.new(2006, 5, 30, 1, 31, 21)) - t6 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949081) - t7 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), Time.utc(2006, 5, 30, 1, 31, 21)) - t8 = TestTimezoneTransition.new(TimezoneOffset.new(3601, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), DateTime.new(2006, 5, 30, 0, 31, 20)) - t9 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3601, 0, :TST), DateTime.new(2006, 5, 30, 0, 31, 20)) - - assert_equal(true, t1 == t1) - assert_equal(true, t1 == t2) - assert_equal(true, t1 == t3) - assert_equal(true, t1 == t4) - assert_equal(false, t1 == t5) - assert_equal(false, t1 == t6) - assert_equal(false, t1 == t7) - assert_equal(false, t1 == t8) - assert_equal(false, t1 == t9) - assert_equal(false, t1 == Object.new) - - assert_equal(true, t1.eql?(t1)) - assert_equal(true, t1.eql?(t2)) - assert_equal(false, t1.eql?(t3)) - assert_equal(false, t1.eql?(t4)) - assert_equal(false, t1.eql?(t5)) - assert_equal(false, t1.eql?(t6)) - assert_equal(false, t1.eql?(t7)) - assert_equal(false, t1.eql?(t8)) - assert_equal(false, t1.eql?(t9)) - assert_equal(false, t1.eql?(Object.new)) - end - - def test_equality_time - t1 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), Time.utc(2006, 5, 30, 0, 31, 20)) - t2 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), Time.utc(2006, 5, 30, 0, 31, 20)) - t3 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), DateTime.new(2006, 5, 30, 0, 31, 20)) - t4 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - t5 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), Time.utc(2006, 5, 30, 0, 31, 21)) - t6 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), DateTime.new(2006, 5, 30, 1, 31, 21)) - t7 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949081) - t8 = TestTimezoneTransition.new(TimezoneOffset.new(3601, 3600, :TDT), - TimezoneOffset.new(3600, 0, :TST), 1148949080) - t9 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDT), - TimezoneOffset.new(3601, 0, :TST), 1148949080) - - assert_equal(true, t1 == t1) - assert_equal(true, t1 == t2) - assert_equal(true, t1 == t3) - assert_equal(true, t1 == t4) - assert_equal(false, t1 == t5) - assert_equal(false, t1 == t6) - assert_equal(false, t1 == t7) - assert_equal(false, t1 == t8) - assert_equal(false, t1 == t9) - assert_equal(false, t1 == Object.new) - - assert_equal(true, t1.eql?(t1)) - assert_equal(true, t1.eql?(t2)) - assert_equal(false, t1.eql?(t3)) - assert_equal(false, t1.eql?(t4)) - assert_equal(false, t1.eql?(t5)) - assert_equal(false, t1.eql?(t6)) - assert_equal(false, t1.eql?(t7)) - assert_equal(false, t1.eql?(t8)) - assert_equal(false, t1.eql?(t9)) - assert_equal(false, t1.eql?(Object.new)) - end - - def test_hash - t1 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDTA), - TimezoneOffset.new(3600, 0, :TSTA), 1148949080) - t2 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDTB), - TimezoneOffset.new(3600, 0, :TSTB), DateTime.new(2006, 5, 30, 1, 31, 20)) - t3 = TestTimezoneTransition.new(TimezoneOffset.new(3600, 3600, :TDTC), - TimezoneOffset.new(3600, 0, :TSTC), Time.utc(2006, 5, 30, 1, 31, 20)) - - assert_equal(TimezoneOffset.new(3600, 3600, :TDTA).hash ^ - TimezoneOffset.new(3600, 0, :TSTA).hash ^ TimeOrDateTime.new(1148949080).hash, - t1.hash) - assert_equal(TimezoneOffset.new(3600, 3600, :TDTB).hash ^ - TimezoneOffset.new(3600, 0, :TSTB).hash ^ TimeOrDateTime.new(DateTime.new(2006, 5, 30, 1, 31, 20)).hash, - t2.hash) - assert_equal(TimezoneOffset.new(3600, 3600, :TDTC).hash ^ - TimezoneOffset.new(3600, 0, :TSTC).hash ^ TimeOrDateTime.new(Time.utc(2006, 5, 30, 1, 31, 20)).hash, - t3.hash) - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_timezone_utc.rb ruby-tzinfo-2.0.4/test/tc_timezone_utc.rb --- ruby-tzinfo-1.2.6/test/tc_timezone_utc.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_timezone_utc.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') - -include TZInfo - -class TCTimezoneUTC < Minitest::Test - def test_2004 - tz = Timezone.get('UTC') - - assert_equal(DateTime.new(2004,1,1,0,0,0), tz.utc_to_local(DateTime.new(2004,1,1,0,0,0))) - assert_equal(DateTime.new(2004,12,31,23,59,59), tz.utc_to_local(DateTime.new(2004,12,31,23,59,59))) - - assert_equal(DateTime.new(2004,1,1,0,0,0), tz.local_to_utc(DateTime.new(2004,1,1,0,0,0))) - assert_equal(DateTime.new(2004,12,31,23,59,59), tz.local_to_utc(DateTime.new(2004,12,31,23,59,59))) - - assert_equal(:UTC, tz.period_for_utc(DateTime.new(2004,1,1,0,0,0)).zone_identifier) - assert_equal(:UTC, tz.period_for_utc(DateTime.new(2004,12,31,23,59,59)).zone_identifier) - - assert_equal(:UTC, tz.period_for_local(DateTime.new(2004,1,1,0,0,0)).zone_identifier) - assert_equal(:UTC, tz.period_for_local(DateTime.new(2004,12,31,23,59,59)).zone_identifier) - - assert_equal(0, tz.period_for_utc(DateTime.new(2004,1,1,0,0,0)).utc_total_offset) - assert_equal(0, tz.period_for_utc(DateTime.new(2004,12,31,23,59,59)).utc_total_offset) - - assert_equal(0, tz.period_for_local(DateTime.new(2004,1,1,0,0,0)).utc_total_offset) - assert_equal(0, tz.period_for_local(DateTime.new(2004,12,31,23,59,59)).utc_total_offset) - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_transition_data_timezone_info.rb ruby-tzinfo-2.0.4/test/tc_transition_data_timezone_info.rb --- ruby-tzinfo-1.2.6/test/tc_transition_data_timezone_info.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_transition_data_timezone_info.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,433 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') - -include TZInfo - -class TCTransitionDataTimezoneInfo < Minitest::Test - - def test_identifier - dti = TransitionDataTimezoneInfo.new('Test/Zone') - assert_equal('Test/Zone', dti.identifier) - end - - def test_offset - dti = TransitionDataTimezoneInfo.new('Test/Zone') - - assert_nothing_raised do - dti.offset :o1, -18000, 3600, :TEST - end - end - - def test_offset_already_defined - dti = TransitionDataTimezoneInfo.new('Test/Zone') - dti.offset :o1, 3600, 0, :TEST - dti.offset :o2, 1800, 0, :TEST2 - - assert_raises(ArgumentError) { dti.offset :o1, 3600, 3600, :TESTD } - end - - def test_transition_timestamp - dti = TransitionDataTimezoneInfo.new('Test/Zone') - dti.offset :o1, -18000, 3600, :TEST - - assert_nothing_raised do - dti.transition 2006, 6, :o1, 1149368400 - end - end - - def test_transition_datetime - dti = TransitionDataTimezoneInfo.new('Test/Zone') - dti.offset :o1, -18000, 3600, :TEST - - assert_nothing_raised do - dti.transition 2006, 6, :o1, 19631123, 8 - end - end - - def test_transition_timestamp_and_datetime - dti = TransitionDataTimezoneInfo.new('Test/Zone') - dti.offset :o1, -18000, 3600, :TEST - - assert_nothing_raised do - dti.transition 2006, 6, :o1, 1149368400, 19631123, 8 - end - end - - def test_transition_invalid_offset - dti = TransitionDataTimezoneInfo.new('Test/Zone') - dti.offset :o1, -18000, 3600, :TEST - - dti.transition 2006, 6, :o1, 1149368400 - - assert_raises(ArgumentError) { dti.transition 2006, 6, :o2, 1149454800 } - end - - def test_transition_no_offsets - dti = TransitionDataTimezoneInfo.new('Test/Zone') - - assert_raises(ArgumentError) { dti.transition 2006, 6, :o1, 1149368400 } - end - - def test_transition_invalid_order_month - dti = TransitionDataTimezoneInfo.new('Test/Zone') - dti.offset :o1, -18000, 3600, :TEST - - dti.transition 2006, 6, :o1, 1149368400 - - assert_raises(ArgumentError) { dti.transition 2006, 5, :o2, 1146690000 } - end - - def test_transition_invalid_order_year - dti = TransitionDataTimezoneInfo.new('Test/Zone') - dti.offset :o1, -18000, 3600, :TEST - - dti.transition 2006, 6, :o1, 1149368400 - - assert_raises(ArgumentError) { dti.transition 2005, 7, :o2, 1120424400 } - end - - def test_period_for_utc - dti = TransitionDataTimezoneInfo.new('Test/Zone') - dti.offset :o1, -17900, 0, :TESTLMT - dti.offset :o2, -18000, 3600, :TESTD - dti.offset :o3, -18000, 0, :TESTS - dti.offset :o4, -21600, 3600, :TESTD - - dti.transition 2000, 4, :o2, Time.utc(2000, 4,1,1,0,0).to_i - dti.transition 2000, 10, :o3, Time.utc(2000,10,1,1,0,0).to_i - dti.transition 2001, 3, :o2, 58847269, 24 # (2001, 3,1,1,0,0) - dti.transition 2001, 4, :o4, Time.utc(2001, 4,1,1,0,0).to_i, 58848013, 24 - dti.transition 2001, 10, :o3, Time.utc(2001,10,1,1,0,0).to_i - dti.transition 2002, 10, :o3, Time.utc(2002,10,1,1,0,0).to_i - dti.transition 2003, 2, :o2, Time.utc(2003, 2,1,1,0,0).to_i - dti.transition 2003, 3, :o3, Time.utc(2003, 3,1,1,0,0).to_i - - o1 = TimezoneOffset.new(-17900, 0, :TESTLMT) - o2 = TimezoneOffset.new(-18000, 3600, :TESTD) - o3 = TimezoneOffset.new(-18000, 0, :TESTS) - o4 = TimezoneOffset.new(-21600, 3600, :TESTD) - - t1 = TimezoneTransitionDefinition.new(o2, o1, Time.utc(2000, 4,1,1,0,0).to_i) - t2 = TimezoneTransitionDefinition.new(o3, o2, Time.utc(2000,10,1,1,0,0).to_i) - t3 = TimezoneTransitionDefinition.new(o2, o3, Time.utc(2001, 3,1,1,0,0).to_i) - t4 = TimezoneTransitionDefinition.new(o4, o2, Time.utc(2001, 4,1,1,0,0).to_i) - t5 = TimezoneTransitionDefinition.new(o3, o4, Time.utc(2001,10,1,1,0,0).to_i) - t6 = TimezoneTransitionDefinition.new(o3, o3, Time.utc(2002,10,1,1,0,0).to_i) - t7 = TimezoneTransitionDefinition.new(o2, o3, Time.utc(2003, 2,1,1,0,0).to_i) - t8 = TimezoneTransitionDefinition.new(o3, o2, Time.utc(2003, 3,1,1,0,0).to_i) - - assert_equal(TimezonePeriod.new(nil, t1), dti.period_for_utc(DateTime.new(1960, 1,1,1, 0, 0))) - assert_equal(TimezonePeriod.new(nil, t1), dti.period_for_utc(DateTime.new(1999,12,1,0, 0, 0))) - assert_equal(TimezonePeriod.new(nil, t1), dti.period_for_utc(Time.utc( 2000, 4,1,0,59,59))) - assert_equal(TimezonePeriod.new(t1, t2), dti.period_for_utc(DateTime.new(2000, 4,1,1, 0, 0))) - assert_equal(TimezonePeriod.new(t1, t2), dti.period_for_utc(Time.utc( 2000,10,1,0,59,59).to_i)) - assert_equal(TimezonePeriod.new(t2, t3), dti.period_for_utc(Time.utc( 2000,10,1,1, 0, 0))) - assert_equal(TimezonePeriod.new(t2, t3), dti.period_for_utc(Time.utc( 2001, 3,1,0,59,59))) - assert_equal(TimezonePeriod.new(t3, t4), dti.period_for_utc(Time.utc( 2001, 3,1,1, 0, 0))) - assert_equal(TimezonePeriod.new(t3, t4), dti.period_for_utc(Time.utc( 2001, 4,1,0,59,59))) - assert_equal(TimezonePeriod.new(t4, t5), dti.period_for_utc(Time.utc( 2001, 4,1,1, 0, 0))) - assert_equal(TimezonePeriod.new(t4, t5), dti.period_for_utc(Time.utc( 2001,10,1,0,59,59))) - assert_equal(TimezonePeriod.new(t5, t6), dti.period_for_utc(Time.utc( 2001,10,1,1, 0, 0))) - assert_equal(TimezonePeriod.new(t5, t6), dti.period_for_utc(Time.utc( 2002, 2,1,1, 0, 0))) - assert_equal(TimezonePeriod.new(t5, t6), dti.period_for_utc(Time.utc( 2002,10,1,0,59,59))) - assert_equal(TimezonePeriod.new(t6, t7), dti.period_for_utc(Time.utc( 2002,10,1,1, 0, 0))) - assert_equal(TimezonePeriod.new(t6, t7), dti.period_for_utc(Time.utc( 2003, 2,1,0,59,59))) - assert_equal(TimezonePeriod.new(t7, t8), dti.period_for_utc(Time.utc( 2003, 2,1,1, 0, 0))) - assert_equal(TimezonePeriod.new(t7, t8), dti.period_for_utc(Time.utc( 2003, 3,1,0,59,59))) - assert_equal(TimezonePeriod.new(t8, nil), dti.period_for_utc(Time.utc( 2003, 3,1,1, 0, 0))) - assert_equal(TimezonePeriod.new(t8, nil), dti.period_for_utc(Time.utc( 2004, 1,1,1, 0, 0))) - assert_equal(TimezonePeriod.new(t8, nil), dti.period_for_utc(DateTime.new(2050, 1,1,1, 0, 0))) - end - - def test_period_for_utc_no_transitions - dti = TransitionDataTimezoneInfo.new('Test/Zone') - dti.offset :o1, -17900, 0, :TESTLMT - dti.offset :o2, -18000, 0, :TEST - - o1 = TimezoneOffset.new(-17900, 0, :TESTLMT) - - assert_equal(TimezonePeriod.new(nil, nil, o1), dti.period_for_utc(DateTime.new(2005,1,1,0,0,0))) - assert_equal(TimezonePeriod.new(nil, nil, o1), dti.period_for_utc(Time.utc(2005,1,1,0,0,0))) - assert_equal(TimezonePeriod.new(nil, nil, o1), dti.period_for_utc(Time.utc(2005,1,1,0,0,0).to_i)) - end - - def test_period_for_utc_no_offsets - dti = TransitionDataTimezoneInfo.new('Test/Zone') - - assert_raises(NoOffsetsDefined) { dti.period_for_utc(DateTime.new(2005,1,1,0,0,0)) } - assert_raises(NoOffsetsDefined) { dti.period_for_utc(Time.utc(2005,1,1,0,0,0)) } - assert_raises(NoOffsetsDefined) { dti.period_for_utc(Time.utc(2005,1,1,0,0,0).to_i) } - end - - def test_periods_for_local - dti = TransitionDataTimezoneInfo.new('Test/Zone') - dti.offset :o1, -17900, 0, :TESTLMT - dti.offset :o2, -18000, 3600, :TESTD - dti.offset :o3, -18000, 0, :TESTS - dti.offset :o4, -21600, 3600, :TESTD - - dti.transition 2000, 4, :o2, 58839277, 24 # 2000,4,2,1,0,0 - dti.transition 2000, 10, :o3, Time.utc(2000,10,2,1,0,0).to_i, 58843669, 24 - dti.transition 2001, 3, :o2, Time.utc(2001, 3,2,1,0,0).to_i - dti.transition 2001, 4, :o4, Time.utc(2001, 4,2,1,0,0).to_i - dti.transition 2001, 10, :o3, Time.utc(2001,10,2,1,0,0).to_i - dti.transition 2002, 10, :o3, 58861189, 24 # 2002,10,2,1,0,0 - dti.transition 2003, 2, :o2, Time.utc(2003, 2,2,1,0,0).to_i - - o1 = TimezoneOffset.new(-17900, 0, :TESTLMT) - o2 = TimezoneOffset.new(-18000, 3600, :TESTD) - o3 = TimezoneOffset.new(-18000, 0, :TESTS) - o4 = TimezoneOffset.new(-21600, 3600, :TESTD) - - t1 = TimezoneTransitionDefinition.new(o2, o1, Time.utc(2000, 4,2,1,0,0).to_i) - t2 = TimezoneTransitionDefinition.new(o3, o2, Time.utc(2000,10,2,1,0,0).to_i) - t3 = TimezoneTransitionDefinition.new(o2, o3, Time.utc(2001, 3,2,1,0,0).to_i) - t4 = TimezoneTransitionDefinition.new(o4, o2, Time.utc(2001, 4,2,1,0,0).to_i) - t5 = TimezoneTransitionDefinition.new(o3, o4, Time.utc(2001,10,2,1,0,0).to_i) - t6 = TimezoneTransitionDefinition.new(o3, o3, Time.utc(2002,10,2,1,0,0).to_i) - t7 = TimezoneTransitionDefinition.new(o2, o3, Time.utc(2003, 2,2,1,0,0).to_i) - - - assert_equal([TimezonePeriod.new(nil, t1)], dti.periods_for_local(DateTime.new(1960, 1, 1, 1, 0, 0))) - assert_equal([TimezonePeriod.new(nil, t1)], dti.periods_for_local(DateTime.new(1999,12, 1, 0, 0, 0))) - assert_equal([TimezonePeriod.new(nil, t1)], dti.periods_for_local(Time.utc( 2000, 1, 1,10, 0, 0))) - assert_equal([TimezonePeriod.new(nil, t1)], dti.periods_for_local(Time.utc( 2000, 4, 1,20, 1,39))) - assert_equal([], dti.periods_for_local(Time.utc( 2000, 4, 1,20, 1,40))) - assert_equal([], dti.periods_for_local(Time.utc( 2000, 4, 1,20,59,59))) - assert_equal([TimezonePeriod.new(t1, t2)], dti.periods_for_local(Time.utc( 2000, 4, 1,21, 0, 0))) - assert_equal([TimezonePeriod.new(t1, t2)], dti.periods_for_local(DateTime.new(2000,10, 1,19,59,59))) - assert_equal([TimezonePeriod.new(t1, t2), - TimezonePeriod.new(t2, t3)], dti.periods_for_local(Time.utc( 2000,10, 1,20, 0, 0).to_i)) - assert_equal([TimezonePeriod.new(t1, t2), - TimezonePeriod.new(t2, t3)], dti.periods_for_local(DateTime.new(2000,10, 1,20,59,59))) - assert_equal([TimezonePeriod.new(t2, t3)], dti.periods_for_local(Time.utc( 2000,10, 1,21, 0, 0))) - assert_equal([TimezonePeriod.new(t2, t3)], dti.periods_for_local(Time.utc( 2001, 3, 1,19,59,59))) - assert_equal([], dti.periods_for_local(Time.utc( 2001, 3, 1,20, 0, 0))) - assert_equal([], dti.periods_for_local(DateTime.new(2001, 3, 1,20, 30, 0))) - assert_equal([], dti.periods_for_local(Time.utc( 2001, 3, 1,20,59,59).to_i)) - assert_equal([TimezonePeriod.new(t3, t4)], dti.periods_for_local(Time.utc( 2001, 3, 1,21, 0, 0))) - assert_equal([TimezonePeriod.new(t3, t4)], dti.periods_for_local(Time.utc( 2001, 4, 1,19,59,59))) - assert_equal([TimezonePeriod.new(t3, t4), - TimezonePeriod.new(t4, t5)], dti.periods_for_local(DateTime.new(2001, 4, 1,20, 0, 0))) - assert_equal([TimezonePeriod.new(t3, t4), - TimezonePeriod.new(t4, t5)], dti.periods_for_local(Time.utc( 2001, 4, 1,20,59,59))) - assert_equal([TimezonePeriod.new(t4, t5)], dti.periods_for_local(Time.utc( 2001, 4, 1,21, 0, 0))) - assert_equal([TimezonePeriod.new(t4, t5)], dti.periods_for_local(Time.utc( 2001,10, 1,19,59,59))) - assert_equal([TimezonePeriod.new(t5, t6)], dti.periods_for_local(Time.utc( 2001,10, 1,20, 0, 0))) - assert_equal([TimezonePeriod.new(t5, t6)], dti.periods_for_local(Time.utc( 2002, 2, 1,20, 0, 0))) - assert_equal([TimezonePeriod.new(t5, t6)], dti.periods_for_local(Time.utc( 2002,10, 1,19,59,59))) - assert_equal([TimezonePeriod.new(t6, t7)], dti.periods_for_local(Time.utc( 2002,10, 1,20, 0, 0))) - assert_equal([TimezonePeriod.new(t6, t7)], dti.periods_for_local(Time.utc( 2003, 2, 1,19,59,59))) - assert_equal([], dti.periods_for_local(Time.utc( 2003, 2, 1,20, 0, 0))) - assert_equal([], dti.periods_for_local(Time.utc( 2003, 2, 1,20,59,59))) - assert_equal([TimezonePeriod.new(t7, nil)], dti.periods_for_local(Time.utc( 2003, 2, 1,21, 0, 0))) - assert_equal([TimezonePeriod.new(t7, nil)], dti.periods_for_local(Time.utc( 2004, 2, 1,20, 0, 0))) - assert_equal([TimezonePeriod.new(t7, nil)], dti.periods_for_local(DateTime.new(2040, 2, 1,20, 0, 0))) - end - - def test_periods_for_local_warsaw - dti = TransitionDataTimezoneInfo.new('Test/Europe/Warsaw') - dti.offset :o1, 5040, 0, :LMT - dti.offset :o2, 5040, 0, :WMT - dti.offset :o3, 3600, 0, :CET - dti.offset :o4, 3600, 3600, :CEST - - dti.transition 1879, 12, :o2, 288925853, 120 # 1879,12,31,22,36,0 - dti.transition 1915, 8, :o3, 290485733, 120 # 1915, 8, 4,22,36,0 - dti.transition 1916, 4, :o4, 29051813, 12 # 1916, 4,30,22, 0,0 - - o1 = TimezoneOffset.new(5040, 0, :LMT) - o2 = TimezoneOffset.new(5040, 0, :WMT) - o3 = TimezoneOffset.new(3600, 0, :CET) - o4 = TimezoneOffset.new(3600, 3600, :CEST) - - t1 = TimezoneTransitionDefinition.new(o2, o1, 288925853, 120) - t2 = TimezoneTransitionDefinition.new(o3, o2, 290485733, 120) - t3 = TimezoneTransitionDefinition.new(o4, o3, 29051813, 12) - - assert_equal([TimezonePeriod.new(t1, t2), - TimezonePeriod.new(t2, t3)], dti.periods_for_local(DateTime.new(1915,8,4,23,40,0))) - end - - def test_periods_for_local_boundary - dti = TransitionDataTimezoneInfo.new('Test/Zone') - dti.offset :o1, -3600, 0, :TESTD - dti.offset :o2, -3600, 0, :TESTS - - dti.transition 2000, 7, :o2, Time.utc(2000,7,1,0,0,0).to_i - - o1 = TimezoneOffset.new(-3600, 0, :TESTD) - o2 = TimezoneOffset.new(-3600, 0, :TESTS) - - t1 = TimezoneTransitionDefinition.new(o2, o1, Time.utc(2000,7,1,0,0,0).to_i) - - # 2000-07-01 00:00:00 UTC is 2000-06-30 23:00:00 UTC-1 - # hence to find periods for local times between 2000-06-30 23:00:00 - # and 2000-07-01 00:00:00 a search has to be carried out in the next half - # year to the one containing the date we are looking for - - assert_equal([TimezonePeriod.new(nil, t1)], dti.periods_for_local(Time.utc(2000,6,30,22,59,59))) - assert_equal([TimezonePeriod.new(t1, nil)], dti.periods_for_local(Time.utc(2000,6,30,23, 0, 0))) - assert_equal([TimezonePeriod.new(t1, nil)], dti.periods_for_local(Time.utc(2000,7, 1, 0, 0, 0))) - end - - def test_periods_for_local_no_transitions - dti = TransitionDataTimezoneInfo.new('Test/Zone') - dti.offset :o1, -17900, 0, :TESTLMT - dti.offset :o2, -18000, 0, :TEST - - o1 = TimezoneOffset.new(-17900, 0, :TESTLMT) - - assert_equal([TimezonePeriod.new(nil, nil, o1)], dti.periods_for_local(DateTime.new(2005,1,1,0,0,0))) - assert_equal([TimezonePeriod.new(nil, nil, o1)], dti.periods_for_local(Time.utc(2005,1,1,0,0,0))) - assert_equal([TimezonePeriod.new(nil, nil, o1)], dti.periods_for_local(Time.utc(2005,1,1,0,0,0).to_i)) - end - - def test_periods_for_local_no_offsets - dti = TransitionDataTimezoneInfo.new('Test/Zone') - - assert_raises(NoOffsetsDefined) { dti.periods_for_local(DateTime.new(2005,1,1,0,0,0)) } - assert_raises(NoOffsetsDefined) { dti.periods_for_local(Time.utc(2005,1,1,0,0,0)) } - assert_raises(NoOffsetsDefined) { dti.periods_for_local(Time.utc(2005,1,1,0,0,0).to_i) } - end - - def test_transitions_up_to - dti = TransitionDataTimezoneInfo.new('Test/Zone') - dti.offset :o1, -17900, 0, :TESTLMT - dti.offset :o2, -18000, 3600, :TESTD - dti.offset :o3, -18000, 0, :TESTS - dti.offset :o4, -21600, 3600, :TESTD - - dti.transition 2010, 4, :o2, Time.utc(2010, 4,1,1,0,0).to_i - dti.transition 2010, 10, :o3, Time.utc(2010,10,1,1,0,0).to_i - dti.transition 2011, 3, :o2, 58934917, 24 # (2011, 3,1,1,0,0) - dti.transition 2011, 4, :o4, Time.utc(2011, 4,1,1,0,0).to_i, 58935661, 24 - dti.transition 2011, 10, :o3, Time.utc(2011,10,1,1,0,0).to_i - - o1 = TimezoneOffset.new(-17900, 0, :TESTLMT) - o2 = TimezoneOffset.new(-18000, 3600, :TESTD) - o3 = TimezoneOffset.new(-18000, 0, :TESTS) - o4 = TimezoneOffset.new(-21600, 3600, :TESTD) - - t1 = TimezoneTransitionDefinition.new(o2, o1, Time.utc(2010, 4,1,1,0,0).to_i) - t2 = TimezoneTransitionDefinition.new(o3, o2, Time.utc(2010,10,1,1,0,0).to_i) - t3 = TimezoneTransitionDefinition.new(o2, o3, Time.utc(2011, 3,1,1,0,0).to_i) - t4 = TimezoneTransitionDefinition.new(o4, o2, Time.utc(2011, 4,1,1,0,0).to_i) - t5 = TimezoneTransitionDefinition.new(o3, o4, Time.utc(2011,10,1,1,0,0).to_i) - - assert_equal([], dti.transitions_up_to(Time.utc(2010,4,1,1,0,0))) - assert_equal([], dti.transitions_up_to(Time.utc(2010,4,1,1,0,0), Time.utc(2000,1,1,0,0,0))) - assert_equal([t1], dti.transitions_up_to(Time.utc(2010,4,1,1,0,1))) - assert_equal([t1], dti.transitions_up_to(Time.utc(2010,4,1,1,0,1), Time.utc(2000,1,1,0,0,0))) - assert_equal([t2,t3,t4], dti.transitions_up_to(Time.utc(2011,4,1,1,0,1), Time.utc(2010,10,1,1,0,0))) - assert_equal([t2,t3,t4], dti.transitions_up_to(Time.utc(2011,10,1,1,0,0), Time.utc(2010,4,1,1,0,1))) - assert_equal([t3], dti.transitions_up_to(Time.utc(2011,4,1,1,0,0), Time.utc(2010,10,1,1,0,1))) - assert_equal([], dti.transitions_up_to(Time.utc(2011,3,1,1,0,0), Time.utc(2010,10,1,1,0,1))) - assert_equal([t1,t2,t3,t4], dti.transitions_up_to(Time.utc(2011,10,1,1,0,0))) - assert_equal([t1,t2,t3,t4,t5], dti.transitions_up_to(Time.utc(2011,10,1,1,0,1))) - assert_equal([t1,t2,t3,t4,t5], dti.transitions_up_to(Time.utc(2011,10,1,1,0,0,1))) - assert_equal([t1,t2,t3,t4,t5], dti.transitions_up_to(Time.utc(2011,10,1,1,0,1), Time.utc(2010,4,1,1,0,0))) - assert_equal([t2,t3,t4,t5], dti.transitions_up_to(Time.utc(2011,10,1,1,0,1), Time.utc(2010,4,1,1,0,1))) - assert_equal([t2,t3,t4,t5], dti.transitions_up_to(Time.utc(2011,10,1,1,0,1), Time.utc(2010,4,1,1,0,0,1))) - assert_equal([t5], dti.transitions_up_to(Time.utc(2015,1,1,0,0,0), Time.utc(2011,10,1,1,0,0))) - assert_equal([], dti.transitions_up_to(Time.utc(2015,1,1,0,0,0), Time.utc(2011,10,1,1,0,1))) - - assert_equal([], dti.transitions_up_to(Time.utc(2010,4,1,1,0,0).to_i)) - assert_equal([], dti.transitions_up_to(Time.utc(2010,4,1,1,0,0).to_i, Time.utc(2000,1,1,0,0,0).to_i)) - assert_equal([t1], dti.transitions_up_to(Time.utc(2010,4,1,1,0,1).to_i)) - assert_equal([t1], dti.transitions_up_to(Time.utc(2010,4,1,1,0,1).to_i, Time.utc(2000,1,1,0,0,0).to_i)) - assert_equal([t2,t3,t4], dti.transitions_up_to(Time.utc(2011,4,1,1,0,1).to_i, Time.utc(2010,10,1,1,0,0).to_i)) - assert_equal([t2,t3,t4], dti.transitions_up_to(Time.utc(2011,10,1,1,0,0).to_i, Time.utc(2010,4,1,1,0,1).to_i)) - assert_equal([t3], dti.transitions_up_to(Time.utc(2011,4,1,1,0,0).to_i, Time.utc(2010,10,1,1,0,1).to_i)) - assert_equal([], dti.transitions_up_to(Time.utc(2011,3,1,1,0,0).to_i, Time.utc(2010,10,1,1,0,1).to_i)) - assert_equal([t1,t2,t3,t4], dti.transitions_up_to(Time.utc(2011,10,1,1,0,0).to_i)) - assert_equal([t1,t2,t3,t4,t5], dti.transitions_up_to(Time.utc(2011,10,1,1,0,1).to_i)) - assert_equal([t1,t2,t3,t4,t5], dti.transitions_up_to(Time.utc(2011,10,1,1,0,1).to_i, Time.utc(2010,4,1,1,0,0).to_i)) - assert_equal([t2,t3,t4,t5], dti.transitions_up_to(Time.utc(2011,10,1,1,0,1).to_i, Time.utc(2010,4,1,1,0,1).to_i)) - assert_equal([t5], dti.transitions_up_to(Time.utc(2015,1,1,0,0,0).to_i, Time.utc(2011,10,1,1,0,0).to_i)) - assert_equal([], dti.transitions_up_to(Time.utc(2015,1,1,0,0,0).to_i, Time.utc(2011,10,1,1,0,1).to_i)) - - assert_equal([], dti.transitions_up_to(DateTime.new(2010,4,1,1,0,0))) - assert_equal([], dti.transitions_up_to(DateTime.new(2010,4,1,1,0,0), DateTime.new(2000,1,1,0,0,0))) - assert_equal([t1], dti.transitions_up_to(DateTime.new(2010,4,1,1,0,1))) - assert_equal([t1], dti.transitions_up_to(DateTime.new(2010,4,1,1,0,1), DateTime.new(2000,1,1,0,0,0))) - assert_equal([t2,t3,t4], dti.transitions_up_to(DateTime.new(2011,4,1,1,0,1), DateTime.new(2010,10,1,1,0,0))) - assert_equal([t2,t3,t4], dti.transitions_up_to(DateTime.new(2011,10,1,1,0,0), DateTime.new(2010,4,1,1,0,1))) - assert_equal([t3], dti.transitions_up_to(DateTime.new(2011,4,1,1,0,0), DateTime.new(2010,10,1,1,0,1))) - assert_equal([], dti.transitions_up_to(DateTime.new(2011,3,1,1,0,0), DateTime.new(2010,10,1,1,0,1))) - assert_equal([t1,t2,t3,t4], dti.transitions_up_to(DateTime.new(2011,10,1,1,0,0))) - assert_equal([t1,t2,t3,t4,t5], dti.transitions_up_to(DateTime.new(2011,10,1,1,0,1))) - assert_equal([t1,t2,t3,t4,t5], dti.transitions_up_to(DateTime.new(2011,10,1,1,0,Rational(DATETIME_RESOLUTION,1000000)))) - assert_equal([t1,t2,t3,t4,t5], dti.transitions_up_to(DateTime.new(2011,10,1,1,0,1), DateTime.new(2010,4,1,1,0,0))) - assert_equal([t2,t3,t4,t5], dti.transitions_up_to(DateTime.new(2011,10,1,1,0,1), DateTime.new(2010,4,1,1,0,1))) - - # Ruby 1.8.7 (built with GCC 8.3.0 on Ubuntu 19.04) fails to perform - # DateTime comparisons correctly when sub-seconds are used. - to = DateTime.new(2011,10,1,1,0,1) - from = DateTime.new(2010,4,1,1,0,Rational(DATETIME_RESOLUTION,1000000)) - if to > from - assert_equal([t2,t3,t4,t5], dti.transitions_up_to(to, from)) - else - puts "This platform does not consider the DateTime #{to.strftime('%Y-%m-%d %H:%m:%S.%N')} to be later than the DateTime #{from.strftime('%Y-%m-%d %H:%m:%S.%N')}" - end - - assert_equal([t5], dti.transitions_up_to(DateTime.new(2015,1,1,0,0,0), DateTime.new(2011,10,1,1,0,0))) - assert_equal([], dti.transitions_up_to(DateTime.new(2015,1,1,0,0,0), DateTime.new(2011,10,1,1,0,1))) - end - - def test_transitions_up_to_no_transitions - dti = TransitionDataTimezoneInfo.new('Test/Zone') - dti.offset :o1, -17900, 0, :TESTLMT - - assert_equal([], dti.transitions_up_to(Time.utc(2015,1,1,0,0,0))) - assert_equal([], dti.transitions_up_to(Time.utc(2015,1,1,0,0,0).to_i)) - assert_equal([], dti.transitions_up_to(DateTime.new(2015,1,1,0,0,0))) - end - - def test_transitions_up_to_utc_to_not_greater_than_utc_from - dti = TransitionDataTimezoneInfo.new('Test/Zone') - dti.offset :o1, -17900, 0, :TESTLMT - - assert_raises(ArgumentError) do - dti.transitions_up_to(Time.utc(2012,8,1,0,0,0), Time.utc(2013,8,1,0,0,0)) - end - - assert_raises(ArgumentError) do - dti.transitions_up_to(Time.utc(2012,8,1,0,0,0).to_i, Time.utc(2012,8,1,0,0,0).to_i) - end - - assert_raises(ArgumentError) do - dti.transitions_up_to(DateTime.new(2012,8,1,0,0,0), DateTime.new(2012,8,1,0,0,0)) - end - end - - def test_datetime_and_timestamp_use - dti = TransitionDataTimezoneInfo.new('Test/Zone') - dti.offset :o1, 0, 0, :TESTS - dti.offset :o2, 0, 3600, :TESTD - - dti.transition 1901, 12, :o2, -2147483649, 69573092117, 28800 - dti.transition 1969, 12, :o1, -1, 210866759999, 86400 - dti.transition 2001, 9, :o2, 1000000000, 529666909, 216 - dti.transition 2038, 1, :o1, 2147483648, 3328347557, 1350 - - if RubyCoreSupport.time_supports_negative && RubyCoreSupport.time_supports_64bit - assert(dti.period_for_utc(DateTime.new(1901,12,13,20,45,51)).start_transition.at.eql?(TimeOrDateTime.new(-2147483649))) - else - assert(dti.period_for_utc(DateTime.new(1901,12,13,20,45,51)).start_transition.at.eql?(TimeOrDateTime.new(DateTime.new(1901,12,13,20,45,51)))) - end - - if RubyCoreSupport.time_supports_negative - assert(dti.period_for_utc(DateTime.new(1969,12,31,23,59,59)).start_transition.at.eql?(TimeOrDateTime.new(-1))) - else - assert(dti.period_for_utc(DateTime.new(1969,12,31,23,59,59)).start_transition.at.eql?(TimeOrDateTime.new(DateTime.new(1969,12,31,23,59,59)))) - end - - assert(dti.period_for_utc(DateTime.new(2001,9,9,2,46,40)).start_transition.at.eql?(TimeOrDateTime.new(1000000000))) - - if RubyCoreSupport.time_supports_64bit - assert(dti.period_for_utc(DateTime.new(2038,1,19,3,14,8)).start_transition.at.eql?(TimeOrDateTime.new(2147483648))) - else - assert(dti.period_for_utc(DateTime.new(2038,1,19,3,14,8)).start_transition.at.eql?(TimeOrDateTime.new(DateTime.new(2038,1,19,3,14,8)))) - end - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_zoneinfo_country_info.rb ruby-tzinfo-2.0.4/test/tc_zoneinfo_country_info.rb --- ruby-tzinfo-1.2.6/test/tc_zoneinfo_country_info.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_zoneinfo_country_info.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,78 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') - -include TZInfo - -class TCZoneinfoCountryInfo < Minitest::Test - - def test_code - ci = ZoneinfoCountryInfo.new('ZZ', 'Zzz', []) {|c| } - assert_equal('ZZ', ci.code) - end - - def test_name - ci = ZoneinfoCountryInfo.new('ZZ', 'Zzz', []) {|c| } - assert_equal('Zzz', ci.name) - end - - def test_zone_identifiers_empty - ci = ZoneinfoCountryInfo.new('ZZ', 'Zzz', []) {|c| } - assert(ci.zone_identifiers.empty?) - assert(ci.zone_identifiers.frozen?) - end - - def test_zone_identifiers - zones = [ - CountryTimezone.new('ZZ/TimezoneB', Rational(1, 2), Rational(1, 2), 'Timezone B'), - CountryTimezone.new('ZZ/TimezoneA', Rational(1, 4), Rational(1, 4), 'Timezone A'), - CountryTimezone.new('ZZ/TimezoneC', Rational(-10, 3), Rational(-20, 7), 'C'), - CountryTimezone.new('ZZ/TimezoneD', Rational(-10, 3), Rational(-20, 7)) - ] - - ci = ZoneinfoCountryInfo.new('ZZ', 'Zzz', zones) - - assert_equal(['ZZ/TimezoneB', 'ZZ/TimezoneA', 'ZZ/TimezoneC', 'ZZ/TimezoneD'], ci.zone_identifiers) - assert(ci.zone_identifiers.frozen?) - assert(!ci.zones.equal?(zones)) - assert(!zones.frozen?) - end - - def test_zone_identifiers_after_freeze - zones = [ - CountryTimezone.new('ZZ/TimezoneB', Rational(1, 2), Rational(1, 2), 'Timezone B'), - CountryTimezone.new('ZZ/TimezoneA', Rational(1, 4), Rational(1, 4), 'Timezone A'), - CountryTimezone.new('ZZ/TimezoneC', Rational(-10, 3), Rational(-20, 7), 'C'), - CountryTimezone.new('ZZ/TimezoneD', Rational(-10, 3), Rational(-20, 7)) - ] - - ci = ZoneinfoCountryInfo.new('ZZ', 'Zzz', zones) - ci.freeze - - assert_equal(['ZZ/TimezoneB', 'ZZ/TimezoneA', 'ZZ/TimezoneC', 'ZZ/TimezoneD'], ci.zone_identifiers) - end - - def test_zones_empty - ci = ZoneinfoCountryInfo.new('ZZ', 'Zzz', []) - assert(ci.zones.empty?) - assert(ci.zones.frozen?) - end - - def test_zones - zones = [ - CountryTimezone.new('ZZ/TimezoneB', Rational(1, 2), Rational(1, 2), 'Timezone B'), - CountryTimezone.new('ZZ/TimezoneA', Rational(1, 4), Rational(1, 4), 'Timezone A'), - CountryTimezone.new('ZZ/TimezoneC', Rational(-10, 3), Rational(-20, 7), 'C'), - CountryTimezone.new('ZZ/TimezoneD', Rational(-10, 3), Rational(-20, 7)) - ] - - ci = ZoneinfoCountryInfo.new('ZZ', 'Zzz', zones) - - assert_equal([CountryTimezone.new('ZZ/TimezoneB', Rational(1, 2), Rational(1, 2), 'Timezone B'), - CountryTimezone.new('ZZ/TimezoneA', Rational(1, 4), Rational(1, 4), 'Timezone A'), - CountryTimezone.new('ZZ/TimezoneC', Rational(-10, 3), Rational(-20, 7), 'C'), - CountryTimezone.new('ZZ/TimezoneD', Rational(-10, 3), Rational(-20, 7))], - ci.zones) - assert(ci.zones.frozen?) - assert(!ci.zones.equal?(zones)) - assert(!zones.frozen?) - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_zoneinfo_data_source.rb ruby-tzinfo-2.0.4/test/tc_zoneinfo_data_source.rb --- ruby-tzinfo-1.2.6/test/tc_zoneinfo_data_source.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_zoneinfo_data_source.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,1204 +0,0 @@ -# encoding: UTF-8 - -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') -require 'fileutils' -require 'pathname' -require 'tmpdir' - -include TZInfo - -# Use send as a workaround for an issue on JRuby 9.2.9.0 where using the -# refinement causes calls to RubyCoreSupport.file_open to fail to pass the block -# parameter. -# -# https://travis-ci.org/tzinfo/tzinfo/jobs/628812051#L1931 -# https://github.com/jruby/jruby/issues/6009 -send(:using, TZInfo::RubyCoreSupport::UntaintExt) if TZInfo::RubyCoreSupport.const_defined?(:UntaintExt) -send(:using, TaintExt) if Module.const_defined?(:TaintExt) - -class TCZoneinfoDataSource < Minitest::Test - ZONEINFO_DIR = File.join(File.expand_path(File.dirname(__FILE__)), 'zoneinfo').untaint - - def setup - @orig_search_path = ZoneinfoDataSource.search_path.clone - @orig_alternate_iso3166_tab_search_path = ZoneinfoDataSource.alternate_iso3166_tab_search_path.clone - @orig_pwd = FileUtils.pwd - - # A zoneinfo directory containing files needed by the tests. - # The symlinks in this directory are set up in test_utils.rb. - @data_source = ZoneinfoDataSource.new(ZONEINFO_DIR) - end - - def teardown - ZoneinfoDataSource.search_path = @orig_search_path - ZoneinfoDataSource.alternate_iso3166_tab_search_path = @orig_alternate_iso3166_tab_search_path - FileUtils.chdir(@orig_pwd) - end - - def test_default_search_path - assert_equal(['/usr/share/zoneinfo', '/usr/share/lib/zoneinfo', '/etc/zoneinfo'], ZoneinfoDataSource.search_path) - assert_equal(false, ZoneinfoDataSource.search_path.frozen?) - end - - def test_set_search_path_default - ZoneinfoDataSource.search_path = ['/tmp/zoneinfo1', '/tmp/zoneinfo2'] - assert_equal(['/tmp/zoneinfo1', '/tmp/zoneinfo2'], ZoneinfoDataSource.search_path) - - ZoneinfoDataSource.search_path = nil - assert_equal(['/usr/share/zoneinfo', '/usr/share/lib/zoneinfo', '/etc/zoneinfo'], ZoneinfoDataSource.search_path) - assert_equal(false, ZoneinfoDataSource.search_path.frozen?) - end - - def test_set_search_path_array - path = ['/tmp/zoneinfo1', '/tmp/zoneinfo2'] - ZoneinfoDataSource.search_path = path - assert_equal(['/tmp/zoneinfo1', '/tmp/zoneinfo2'], ZoneinfoDataSource.search_path) - refute_same(path, ZoneinfoDataSource.search_path) - end - - def test_set_search_path_array_to_s - ZoneinfoDataSource.search_path = [Pathname.new('/tmp/zoneinfo3')] - assert_equal(['/tmp/zoneinfo3'], ZoneinfoDataSource.search_path) - end - - def test_set_search_path_string - ZoneinfoDataSource.search_path = ['/tmp/zoneinfo4', '/tmp/zoneinfo5'].join(File::PATH_SEPARATOR) - assert_equal(['/tmp/zoneinfo4', '/tmp/zoneinfo5'], ZoneinfoDataSource.search_path) - end - - def test_default_alternate_iso3166_tab_search_path - assert_equal(['/usr/share/misc/iso3166.tab', '/usr/share/misc/iso3166'], ZoneinfoDataSource.alternate_iso3166_tab_search_path) - assert_equal(false, ZoneinfoDataSource.alternate_iso3166_tab_search_path.frozen?) - end - - def test_set_alternate_iso3166_tab_search_path_default - ZoneinfoDataSource.alternate_iso3166_tab_search_path = ['/tmp/iso3166.tab', '/tmp/iso3166'] - assert_equal(['/tmp/iso3166.tab', '/tmp/iso3166'], ZoneinfoDataSource.alternate_iso3166_tab_search_path) - - ZoneinfoDataSource.alternate_iso3166_tab_search_path = nil - assert_equal(['/usr/share/misc/iso3166.tab', '/usr/share/misc/iso3166'], ZoneinfoDataSource.alternate_iso3166_tab_search_path) - assert_equal(false, ZoneinfoDataSource.alternate_iso3166_tab_search_path.frozen?) - end - - def test_set_alternate_iso3166_tab_search_path_array - path = ['/tmp/iso3166.tab', '/tmp/iso3166'] - ZoneinfoDataSource.alternate_iso3166_tab_search_path = path - assert_equal(['/tmp/iso3166.tab', '/tmp/iso3166'], ZoneinfoDataSource.alternate_iso3166_tab_search_path) - refute_same(path, ZoneinfoDataSource.alternate_iso3166_tab_search_path) - end - - def test_set_alternate_iso3166_tab_search_path_array_to_s - ZoneinfoDataSource.alternate_iso3166_tab_search_path = [Pathname.new('/tmp/iso3166.tab')] - assert_equal(['/tmp/iso3166.tab'], ZoneinfoDataSource.alternate_iso3166_tab_search_path) - end - - def test_set_alternate_iso3166_tab_search_path_string - ZoneinfoDataSource.alternate_iso3166_tab_search_path = ['/tmp/iso3166.tab', '/tmp/iso3166'].join(File::PATH_SEPARATOR) - assert_equal(['/tmp/iso3166.tab', '/tmp/iso3166'], ZoneinfoDataSource.alternate_iso3166_tab_search_path) - end - - def test_new_search - Dir.mktmpdir('tzinfo_test_dir1') do |dir1| - Dir.mktmpdir('tzinfo_test_dir2') do |dir2| - Dir.mktmpdir('tzinfo_test_dir3') do |dir3| - Dir.mktmpdir('tzinfo_test_dir4') do |dir4| - file = File.join(dir1, 'file') - FileUtils.touch(File.join(dir2, 'zone.tab')) - FileUtils.touch(File.join(dir3, 'iso3166.tab')) - FileUtils.touch(File.join(dir4, 'zone.tab')) - FileUtils.touch(File.join(dir4, 'iso3166.tab')) - - ZoneinfoDataSource.search_path = [file, dir2, dir3, dir4] - ZoneinfoDataSource.alternate_iso3166_tab_search_path = [] - - data_source = ZoneinfoDataSource.new - assert_equal(dir4, data_source.zoneinfo_dir) - end - end - end - end - end - - def test_new_search_zone1970 - Dir.mktmpdir('tzinfo_test_dir1') do |dir1| - Dir.mktmpdir('tzinfo_test_dir2') do |dir2| - Dir.mktmpdir('tzinfo_test_dir3') do |dir3| - Dir.mktmpdir('tzinfo_test_dir4') do |dir4| - file = File.join(dir1, 'file') - FileUtils.touch(File.join(dir2, 'zone1970.tab')) - FileUtils.touch(File.join(dir3, 'iso3166.tab')) - FileUtils.touch(File.join(dir4, 'zone1970.tab')) - FileUtils.touch(File.join(dir4, 'iso3166.tab')) - - ZoneinfoDataSource.search_path = [file, dir2, dir3, dir4] - ZoneinfoDataSource.alternate_iso3166_tab_search_path = [] - - data_source = ZoneinfoDataSource.new - assert_equal(dir4, data_source.zoneinfo_dir) - end - end - end - end - end - - def test_new_search_solaris_tab_files - # Solaris names the tab files 'tab/country.tab' (iso3166.tab) and - # 'tab/zone_sun.tab' (zone.tab). - - Dir.mktmpdir('tzinfo_test_dir') do |dir| - tab = File.join(dir, 'tab') - FileUtils.mkdir(tab) - FileUtils.touch(File.join(tab, 'country.tab')) - FileUtils.touch(File.join(tab, 'zone_sun.tab')) - - ZoneinfoDataSource.search_path = [dir] - ZoneinfoDataSource.alternate_iso3166_tab_search_path = [] - - data_source = ZoneinfoDataSource.new - assert_equal(dir, data_source.zoneinfo_dir) - end - end - - def test_new_search_alternate_iso3166_path - Dir.mktmpdir('tzinfo_test_dir_zoneinfo') do |zoneinfo_dir| - Dir.mktmpdir('tzinfo_test_dir_tab') do |tab_dir| - FileUtils.touch(File.join(zoneinfo_dir, 'zone.tab')) - - tab_file = File.join(tab_dir, 'iso3166') - - ZoneinfoDataSource.search_path = [zoneinfo_dir] - ZoneinfoDataSource.alternate_iso3166_tab_search_path = [tab_file] - - assert_raises(ZoneinfoDirectoryNotFound) do - ZoneinfoDataSource.new - end - - FileUtils.touch(tab_file) - - data_source = ZoneinfoDataSource.new - assert_equal(zoneinfo_dir, data_source.zoneinfo_dir) - end - end - end - - def test_new_search_not_found - Dir.mktmpdir('tzinfo_test_dir1') do |dir1| - Dir.mktmpdir('tzinfo_test_dir2') do |dir2| - Dir.mktmpdir('tzinfo_test_dir3') do |dir3| - Dir.mktmpdir('tzinfo_test_dir4') do |dir4| - Dir.mktmpdir('tzinfo_test_dir5') do |dir5| - file = File.join(dir1, 'file') - FileUtils.touch(file) - FileUtils.touch(File.join(dir2, 'zone.tab')) - FileUtils.touch(File.join(dir3, 'zone1970.tab')) - FileUtils.touch(File.join(dir4, 'iso3166.tab')) - - ZoneinfoDataSource.search_path = [file, dir2, dir3, dir4, dir5] - ZoneinfoDataSource.alternate_iso3166_tab_search_path = [] - - assert_raises(ZoneinfoDirectoryNotFound) do - ZoneinfoDataSource.new - end - end - end - end - end - end - end - - def test_new_search_relative - Dir.mktmpdir('tzinfo_test') do |dir| - FileUtils.touch(File.join(dir, 'zone.tab')) - FileUtils.touch(File.join(dir, 'iso3166.tab')) - - FileUtils.chdir(dir) - - ZoneinfoDataSource.search_path = ['.'] - ZoneinfoDataSource.alternate_iso3166_tab_search_path = [] - data_source = ZoneinfoDataSource.new - assert_equal(Pathname.new(dir).realpath.to_s, data_source.zoneinfo_dir) - - # Change out of the directory to allow it to be deleted on Windows. - FileUtils.chdir(@orig_pwd) - end - end - - def test_new_dir - Dir.mktmpdir('tzinfo_test') do |dir| - FileUtils.touch(File.join(dir, 'zone.tab')) - FileUtils.touch(File.join(dir, 'iso3166.tab')) - - data_source = ZoneinfoDataSource.new(dir) - assert_equal(dir, data_source.zoneinfo_dir) - end - end - - def test_new_dir_zone1970 - Dir.mktmpdir('tzinfo_test') do |dir| - FileUtils.touch(File.join(dir, 'zone1970.tab')) - FileUtils.touch(File.join(dir, 'iso3166.tab')) - - data_source = ZoneinfoDataSource.new(dir) - assert_equal(dir, data_source.zoneinfo_dir) - end - end - - def test_new_dir_solaris_tab_files - # Solaris names the tab files 'tab/country.tab' (iso3166.tab) and - # 'tab/zone_sun.tab' (zone.tab). - - Dir.mktmpdir('tzinfo_test') do |dir| - tab = File.join(dir, 'tab') - FileUtils.mkdir(tab) - FileUtils.touch(File.join(tab, 'country.tab')) - FileUtils.touch(File.join(tab, 'zone_sun.tab')) - - data_source = ZoneinfoDataSource.new(dir) - assert_equal(dir, data_source.zoneinfo_dir) - end - end - - def test_new_dir_alternate_iso3166_path - Dir.mktmpdir('tzinfo_test_dir_zoneinfo') do |zoneinfo_dir| - Dir.mktmpdir('tzinfo_test_dir_tab') do |tab_dir| - FileUtils.touch(File.join(zoneinfo_dir, 'zone.tab')) - - tab_file = File.join(tab_dir, 'iso3166') - FileUtils.touch(tab_file) - - ZoneinfoDataSource.alternate_iso3166_tab_search_path = [tab_file] - - assert_raises(InvalidZoneinfoDirectory) do - # The alternate_iso3166_tab_search_path should not be used. This should raise - # an exception. - ZoneinfoDataSource.new(zoneinfo_dir) - end - - data_source = ZoneinfoDataSource.new(zoneinfo_dir, tab_file) - assert_equal(zoneinfo_dir, data_source.zoneinfo_dir) - end - end - end - - def test_new_dir_invalid - Dir.mktmpdir('tzinfo_test') do |dir| - assert_raises(InvalidZoneinfoDirectory) do - ZoneinfoDataSource.new(dir) - end - end - end - - def test_new_dir_invalid_alternate_iso3166_path - Dir.mktmpdir('tzinfo_test_dir_zoneinfo') do |zoneinfo_dir| - Dir.mktmpdir('tzinfo_test_dir_tab') do |tab_dir| - FileUtils.touch(File.join(zoneinfo_dir, 'zone.tab')) - - assert_raises(InvalidZoneinfoDirectory) do - ZoneinfoDataSource.new(zoneinfo_dir, File.join(tab_dir, 'iso3166')) - end - end - end - end - - def test_new_dir_invalid_alternate_iso3166_path_overrides_valid - Dir.mktmpdir('tzinfo_test_dir_zoneinfo') do |zoneinfo_dir| - Dir.mktmpdir('tzinfo_test_dir_tab') do |tab_dir| - FileUtils.touch(File.join(zoneinfo_dir, 'iso3166.tab')) - FileUtils.touch(File.join(zoneinfo_dir, 'zone.tab')) - - assert_raises(InvalidZoneinfoDirectory) do - ZoneinfoDataSource.new(zoneinfo_dir, File.join(tab_dir, 'iso3166')) - end - end - end - end - - def test_new_file - Dir.mktmpdir('tzinfo_test') do |dir| - file = File.join(dir, 'file') - FileUtils.touch(file) - - assert_raises(InvalidZoneinfoDirectory) do - ZoneinfoDataSource.new(file) - end - end - end - - def test_new_dir_relative - Dir.mktmpdir('tzinfo_test') do |dir| - FileUtils.touch(File.join(dir, 'zone.tab')) - FileUtils.touch(File.join(dir, 'iso3166.tab')) - - FileUtils.chdir(dir) - - data_source = ZoneinfoDataSource.new('.') - assert_equal(Pathname.new(dir).realpath.to_s, data_source.zoneinfo_dir) - - # Change out of the directory to allow it to be deleted on Windows. - FileUtils.chdir(@orig_pwd) - end - end - - def test_zoneinfo_dir - Dir.mktmpdir('tzinfo_test') do |dir| - FileUtils.touch(File.join(dir, 'zone.tab')) - FileUtils.touch(File.join(dir, 'iso3166.tab')) - - data_source = ZoneinfoDataSource.new(dir) - assert_equal(dir, data_source.zoneinfo_dir) - assert_equal(true, data_source.zoneinfo_dir.frozen?) - end - end - - def test_load_timezone_info_data - info = @data_source.load_timezone_info('Europe/London') - assert_kind_of(ZoneinfoTimezoneInfo, info) - assert_equal('Europe/London', info.identifier) - end - - def test_load_timezone_info_linked - info = @data_source.load_timezone_info('UTC') - - # On platforms that don't support symlinks, 'UTC' will be created as a copy. - # Either way, a ZoneinfoTimezoneInfo should be returned. - - assert_kind_of(ZoneinfoTimezoneInfo, info) - assert_equal('UTC', info.identifier) - end - - def test_load_timezone_info_does_not_exist - assert_raises(InvalidTimezoneIdentifier) do - @data_source.load_timezone_info('Nowhere/Special') - end - end - - def test_load_timezone_info_invalid - assert_raises(InvalidTimezoneIdentifier) do - @data_source.load_timezone_info('../Definitions/Europe/London') - end - end - - %w(leapseconds localtime).each do |file_name| - define_method("test_load_timezone_info_ignored_#{file_name}_file") do - assert_raises(InvalidTimezoneIdentifier) do - @data_source.load_timezone_info(file_name) - end - end - end - - def test_load_timezone_info_ignored_plus_version_file - # Mac OS X includes a file named +VERSION containing the tzdata version. - - Dir.mktmpdir('tzinfo_test') do |dir| - FileUtils.touch(File.join(dir, 'zone.tab')) - FileUtils.touch(File.join(dir, 'iso3166.tab')) - - File.open(File.join(dir, '+VERSION'), 'w') do |f| - f.binmode - f.write("2013a\n") - end - - data_source = ZoneinfoDataSource.new(dir) - - assert_raises(InvalidTimezoneIdentifier) do - data_source.load_timezone_info('+VERSION') - end - end - end - - def test_load_timezone_info_ignored_timeconfig_symlink - # Slackware includes a symlink named timeconfig that points at /usr/sbin/timeconfig. - - Dir.mktmpdir('tzinfo_test_target') do |target_dir| - target_path = File.join(target_dir, 'timeconfig') - - File.open(target_path, 'w') do |f| - f.write("#!/bin/sh\n") - f.write("#\n") - f.write('# timeconfig Slackware Linux timezone configuration utility.\n') - end - - Dir.mktmpdir('tzinfo_test') do |dir| - FileUtils.touch(File.join(dir, 'zone.tab')) - FileUtils.touch(File.join(dir, 'iso3166.tab')) - FileUtils.cp(File.join(@data_source.zoneinfo_dir, 'EST'), File.join(dir, 'EST')) - - symlink_path = File.join(dir, 'timeconfig') - begin - FileUtils.ln_s(target_path, symlink_path) - rescue NotImplementedError, Errno::EACCES - # Symlinks not supported on this platform, or permission denied - # (administrative rights are required on Windows). Copy instead. - FileUtils.cp(target_path, symlink_path) - end - - data_source = ZoneinfoDataSource.new(dir) - - assert_raises(InvalidTimezoneIdentifier) do - data_source.load_timezone_info('timeconfig') - end - end - end - end - - def test_load_timezone_info_nil - assert_raises(InvalidTimezoneIdentifier) do - @data_source.load_timezone_info(nil) - end - end - - def test_load_timezone_info_case - assert_raises(InvalidTimezoneIdentifier) do - @data_source.load_timezone_info('europe/london') - end - end - - def test_load_timezone_info_permission_denied - Dir.mktmpdir('tzinfo_test') do |dir| - FileUtils.touch(File.join(dir, 'zone.tab')) - FileUtils.touch(File.join(dir, 'iso3166.tab')) - - file = File.join(dir, 'UTC') - FileUtils.touch(file) - FileUtils.chmod(0200, file) - - data_source = ZoneinfoDataSource.new(dir) - - assert_raises(InvalidTimezoneIdentifier) do - data_source.load_timezone_info('UTC') - end - end - end - - def test_load_timezone_info_directory - Dir.mktmpdir('tzinfo_test') do |dir| - FileUtils.touch(File.join(dir, 'zone.tab')) - FileUtils.touch(File.join(dir, 'iso3166.tab')) - - subdir = File.join(dir, 'Subdir') - FileUtils.mkdir(subdir) - - data_source = ZoneinfoDataSource.new(dir) - - assert_raises(InvalidTimezoneIdentifier) do - data_source.load_timezone_info('Subdir') - end - end - end - - def test_load_timezone_info_linked_absolute_outside - Dir.mktmpdir('tzinfo_test') do |dir| - Dir.mktmpdir('tzinfo_test') do |outside| - outside_file = File.join(outside, 'EST') - FileUtils.cp(File.join(@data_source.zoneinfo_dir, 'EST'), outside_file) - - FileUtils.touch(File.join(dir, 'zone.tab')) - FileUtils.touch(File.join(dir, 'iso3166.tab')) - - file = File.join(dir, 'EST') - - begin - FileUtils.ln_s(outside_file, file) - rescue NotImplementedError, Errno::EACCES - # Symlinks not supported on this platform, or permission denied - # (administrative rights are required on Windows). Skip test. - return - end - - data_source = ZoneinfoDataSource.new(dir) - - info = data_source.load_timezone_info('EST') - assert_kind_of(ZoneinfoTimezoneInfo, info) - assert_equal('EST', info.identifier) - end - end - end - - def test_load_timezone_info_linked_absolute_inside - Dir.mktmpdir('tzinfo_test') do |dir| - FileUtils.touch(File.join(dir, 'zone.tab')) - FileUtils.touch(File.join(dir, 'iso3166.tab')) - - FileUtils.cp(File.join(@data_source.zoneinfo_dir, 'EST'), File.join(dir, 'EST')) - - link = File.join(dir, 'Link') - - begin - FileUtils.ln_s(File.join(File.expand_path(dir), 'EST'), link) - rescue NotImplementedError, Errno::EACCES - # Symlinks not supported on this platform, or permission denied - # (administrative rights are required on Windows). Skip test. - return - end - - data_source = ZoneinfoDataSource.new(dir) - - info = data_source.load_timezone_info('Link') - assert_kind_of(ZoneinfoTimezoneInfo, info) - assert_equal('Link', info.identifier) - end - end - - def test_load_timezone_info_linked_relative_outside - Dir.mktmpdir('tzinfo_test') do |root| - FileUtils.cp(File.join(@data_source.zoneinfo_dir, 'EST'), File.join(root, 'outside')) - - dir = File.join(root, 'zoneinfo') - FileUtils.mkdir(dir) - - FileUtils.touch(File.join(dir, 'zone.tab')) - FileUtils.touch(File.join(dir, 'iso3166.tab')) - - link = File.join(dir, 'Link') - - begin - FileUtils.ln_s('../outside', link) - rescue NotImplementedError, Errno::EACCES - # Symlinks not supported on this platform, or permission denied - # (administrative rights are required on Windows). Skip test. - return - end - - subdir = File.join(dir, 'Subdir') - subdir_link = File.join(subdir, 'Link') - FileUtils.mkdir(subdir) - FileUtils.ln_s('../../outside', subdir_link) - - data_source = ZoneinfoDataSource.new(dir) - - info = data_source.load_timezone_info('Link') - assert_kind_of(ZoneinfoTimezoneInfo, info) - assert_equal('Link', info.identifier) - - info = data_source.load_timezone_info('Subdir/Link') - assert_kind_of(ZoneinfoTimezoneInfo, info) - assert_equal('Subdir/Link', info.identifier) - end - end - - def test_load_timezone_info_linked_relative_parent_inside - Dir.mktmpdir('tzinfo_test') do |dir| - FileUtils.touch(File.join(dir, 'zone.tab')) - FileUtils.touch(File.join(dir, 'iso3166.tab')) - - FileUtils.cp(File.join(@data_source.zoneinfo_dir, 'EST'), File.join(dir, 'EST')) - - subdir = File.join(dir, 'Subdir') - FileUtils.mkdir(subdir) - FileUtils.cp(File.join(@data_source.zoneinfo_dir, 'EST'), File.join(subdir, 'EST')) - - subdir_link = File.join(subdir, 'Link') - begin - FileUtils.ln_s('../Subdir/EST', subdir_link) - rescue NotImplementedError, Errno::EACCES - # Symlinks not supported on this platform, or permission denied - # (administrative rights are required on Windows). Skip test. - return - end - - subdir_link2 = File.join(subdir, 'Link2') - FileUtils.ln_s('../EST', subdir_link2) - - subdir2 = File.join(dir, 'Subdir2') - FileUtils.mkdir(subdir2) - subdir2_link = File.join(subdir2, 'Link') - FileUtils.ln_s('../Subdir/EST', subdir2_link) - - data_source = ZoneinfoDataSource.new(dir) - - info = data_source.load_timezone_info('Subdir/Link') - assert_kind_of(ZoneinfoTimezoneInfo, info) - assert_equal('Subdir/Link', info.identifier) - - info = data_source.load_timezone_info('Subdir/Link2') - assert_kind_of(ZoneinfoTimezoneInfo, info) - assert_equal('Subdir/Link2', info.identifier) - - info = data_source.load_timezone_info('Subdir2/Link') - assert_kind_of(ZoneinfoTimezoneInfo, info) - assert_equal('Subdir2/Link', info.identifier) - end - end - - def test_load_timezone_info_invalid_file - Dir.mktmpdir('tzinfo_test') do |dir| - FileUtils.touch(File.join(dir, 'zone.tab')) - FileUtils.touch(File.join(dir, 'iso3166.tab')) - - File.open(File.join(dir, 'Zone'), 'wb') do |file| - file.write('NotAValidTZifFile') - end - - data_source = ZoneinfoDataSource.new(dir) - - assert_raises(InvalidTimezoneIdentifier) do - data_source.load_timezone_info('Zone') - end - end - end - - def test_load_timezone_info_invalid_file_2 - Dir.mktmpdir('tzinfo_test') do |dir| - FileUtils.touch(File.join(dir, 'zone.tab')) - FileUtils.touch(File.join(dir, 'iso3166.tab')) - - zone = File.join(dir, 'Zone') - - File.open(File.join(@data_source.zoneinfo_dir, 'EST')) do |src| - # Change header to TZif1 (which is not a valid header). - File.open(zone, 'wb') do |dest| - dest.write('TZif1') - src.pos = 5 - FileUtils.copy_stream(src, dest) - end - end - - data_source = ZoneinfoDataSource.new(dir) - - assert_raises(InvalidTimezoneIdentifier) do - data_source.load_timezone_info('Zone') - end - end - end - - def test_load_timezone_info_tainted - safe_test(:unavailable => :skip) do - identifier = 'Europe/Amsterdam'.dup.taint - assert(identifier.tainted?) - info = @data_source.load_timezone_info(identifier) - assert_equal('Europe/Amsterdam', info.identifier) - assert(identifier.tainted?) - end - end - - def test_load_timezone_info_tainted_and_frozen - safe_test do - info = @data_source.load_timezone_info('Europe/Amsterdam'.dup.taint.freeze) - assert_equal('Europe/Amsterdam', info.identifier) - end - end - - def test_load_timezone_info_tainted_zoneinfo_dir_safe_mode - safe_test(:unavailable => :skip) do - assert_raises(SecurityError) do - ZoneinfoDataSource.new(@data_source.zoneinfo_dir.dup.taint) - end - end - end - - def test_load_timezone_info_tainted_zoneinfo_dir - data_source = ZoneinfoDataSource.new(@data_source.zoneinfo_dir.dup.taint) - info = data_source.load_timezone_info('Europe/London') - assert_kind_of(ZoneinfoTimezoneInfo, info) - assert_equal('Europe/London', info.identifier) - end - - def get_timezone_filenames(directory) - entries = Dir.glob(File.join(directory, '**', '*')) - - entries = entries.select do |file| - file.untaint - File.file?(file) - end - - entries = entries.collect {|file| file[directory.length + File::SEPARATOR.length, file.length - directory.length - File::SEPARATOR.length]} - - # Exclude right (with leapseconds) and posix (copy) directories; .tab files; leapseconds, localtime and posixrules files. - entries = entries.select do |file| - file !~ /\A(posix|right)\// && - file !~ /\.tab\z/ && - !%w(leapseconds localtime posixrules).include?(file) - end - - entries.sort - end - - def test_timezone_identifiers - expected = get_timezone_filenames(@data_source.zoneinfo_dir) - all = @data_source.timezone_identifiers - assert_kind_of(Array, all) - assert_array_same_items(expected, all) - assert_equal(true, all.frozen?) - end - - def test_data_timezone_identifiers - expected = get_timezone_filenames(@data_source.zoneinfo_dir) - all_data = @data_source.data_timezone_identifiers - assert_kind_of(Array, all_data) - assert_array_same_items(expected, all_data) - assert_equal(true, all_data.frozen?) - end - - def test_linked_timezone_identifiers - all_linked = @data_source.linked_timezone_identifiers - assert_kind_of(Array, all_linked) - assert_equal(true, all_linked.empty?) - assert_equal(true, all_linked.frozen?) - end - - def test_timezone_identifiers_safe_mode - safe_test do - expected = get_timezone_filenames(@data_source.zoneinfo_dir) - all = @data_source.timezone_identifiers - assert_kind_of(Array, all) - assert_array_same_items(expected, all) - assert_equal(true, all.frozen?) - end - end - - def test_timezone_identifiers_ignored_plus_version_file - # Mac OS X includes a file named +VERSION containing the tzdata version. - - Dir.mktmpdir('tzinfo_test') do |dir| - FileUtils.touch(File.join(dir, 'zone.tab')) - FileUtils.touch(File.join(dir, 'iso3166.tab')) - FileUtils.cp(File.join(@data_source.zoneinfo_dir, 'EST'), File.join(dir, 'EST')) - - File.open(File.join(dir, '+VERSION'), 'w') do |f| - f.binmode - f.write("2013a\n") - end - - data_source = ZoneinfoDataSource.new(dir) - assert_array_same_items(['EST'], data_source.timezone_identifiers) - end - end - - def test_timezone_identifiers_ignored_timeconfig_symlink - # Slackware includes a symlink named timeconfig that points at /usr/sbin/timeconfig. - - Dir.mktmpdir('tzinfo_test_target') do |target_dir| - target_path = File.join(target_dir, 'timeconfig') - - File.open(target_path, 'w') do |f| - f.write("#!/bin/sh\n") - f.write("#\n") - f.write('# timeconfig Slackware Linux timezone configuration utility.\n') - end - - Dir.mktmpdir('tzinfo_test') do |dir| - FileUtils.touch(File.join(dir, 'zone.tab')) - FileUtils.touch(File.join(dir, 'iso3166.tab')) - FileUtils.cp(File.join(@data_source.zoneinfo_dir, 'EST'), File.join(dir, 'EST')) - - symlink_path = File.join(dir, 'timeconfig') - begin - FileUtils.ln_s(target_path, symlink_path) - rescue NotImplementedError, Errno::EACCES - # Symlinks not supported on this platform, or permission denied - # (administrative rights are required on Windows). Copy instead. - FileUtils.cp(target_path, symlink_path) - end - - data_source = ZoneinfoDataSource.new(dir) - assert_array_same_items(['EST'], data_source.timezone_identifiers) - end - end - end - - def test_timezone_identifiers_ignored_src_directory - # Solaris includes a src directory containing the source timezone data files - # from the tzdata distribution. These should be ignored. - - Dir.mktmpdir('tzinfo_test') do |dir| - FileUtils.touch(File.join(dir, 'zone.tab')) - FileUtils.touch(File.join(dir, 'iso3166.tab')) - FileUtils.cp(File.join(@data_source.zoneinfo_dir, 'EST'), File.join(dir, 'EST')) - - src_dir = File.join(dir, 'src') - FileUtils.mkdir(src_dir) - - File.open(File.join(src_dir, 'europe'), 'w') do |f| - f.binmode - f.write("Zone\tEurope/London\t0:00\tEU\tGMT/BST\n") - end - - data_source = ZoneinfoDataSource.new(dir) - assert_array_same_items(['EST'], data_source.timezone_identifiers) - end - end - - def test_load_country_info - info = @data_source.load_country_info('GB') - assert_equal('GB', info.code) - assert_equal('Britain (UK)', info.name) - end - - def test_load_country_info_not_exist - assert_raises(InvalidCountryCode) do - @data_source.load_country_info('ZZ') - end - end - - def test_load_country_info_invalid - assert_raises(InvalidCountryCode) do - @data_source.load_country_info('../Countries/GB') - end - end - - def test_load_country_info_nil - assert_raises(InvalidCountryCode) do - @data_source.load_country_info(nil) - end - end - - def test_load_country_info_case - assert_raises(InvalidCountryCode) do - @data_source.load_country_info('gb') - end - end - - def test_load_country_info_tainted - safe_test(:unavailable => :skip) do - code = 'NL'.dup.taint - assert(code.tainted?) - info = @data_source.load_country_info(code) - assert_equal('NL', info.code) - assert(code.tainted?) - end - end - - def test_load_country_info_tainted_and_frozen - safe_test do - info = @data_source.load_country_info('NL'.dup.taint.freeze) - assert_equal('NL', info.code) - end - end - - def test_load_country_info_check_zones - Dir.mktmpdir('tzinfo_test') do |dir| - RubyCoreSupport.open_file(File.join(dir, 'iso3166.tab'), 'w', :external_encoding => 'UTF-8') do |iso3166| - iso3166.puts('# iso3166.tab') - iso3166.puts('') - iso3166.puts("FC\tFake Country") - iso3166.puts("OC\tOther Country") - end - - RubyCoreSupport.open_file(File.join(dir, 'zone.tab'), 'w', :external_encoding => 'UTF-8') do |zone| - zone.puts('# zone.tab') - zone.puts('') - zone.puts("FC\t+513030-0000731\tFake/One\tDescription of one") - zone.puts("FC\t+353916+1394441\tFake/Two\tAnother description") - zone.puts("FC\t-2332-04637\tFake/Three\tThis is Three") - zone.puts("OC\t+5005+01426\tOther/One") - end - - data_source = ZoneinfoDataSource.new(dir) - - info = data_source.load_country_info('FC') - assert_equal('FC', info.code) - assert_equal('Fake Country', info.name) - assert_equal(['Fake/One', 'Fake/Two', 'Fake/Three'], info.zone_identifiers) - assert_equal(true, info.zone_identifiers.frozen?) - assert_equal([ - CountryTimezone.new('Fake/One', Rational(6181, 120), Rational(-451, 3600), 'Description of one'), - CountryTimezone.new('Fake/Two', Rational(32089, 900), Rational(503081, 3600), 'Another description'), - CountryTimezone.new('Fake/Three', Rational(-353, 15), Rational(-2797, 60), 'This is Three')], info.zones) - assert_equal(true, info.zones.frozen?) - - info = data_source.load_country_info('OC') - assert_equal('OC', info.code) - assert_equal('Other Country', info.name) - assert_equal(['Other/One'], info.zone_identifiers) - assert_equal(true, info.zone_identifiers.frozen?) - assert_equal([CountryTimezone.new('Other/One', Rational(601, 12), Rational(433, 30))], info.zones) - assert_equal(true, info.zones.frozen?) - end - end - - def test_load_country_info_check_zones_zone1970 - Dir.mktmpdir('tzinfo_test') do |dir| - RubyCoreSupport.open_file(File.join(dir, 'iso3166.tab'), 'w', :external_encoding => 'UTF-8') do |iso3166| - iso3166.puts('# iso3166.tab') - iso3166.puts('') - iso3166.puts("AC\tAnother Country") - iso3166.puts("FC\tFake Country") - iso3166.puts("OC\tOther Country") - end - - # zone.tab will be ignored. - RubyCoreSupport.open_file(File.join(dir, 'zone.tab'), 'w', :external_encoding => 'UTF-8') do |zone| - zone.puts('# zone.tab') - zone.puts('') - zone.puts("FC\t+513030-0000731\tFake/One\tDescription of one") - zone.puts("FC\t+353916+1394441\tFake/Two\tAnother description") - zone.puts("FC\t-2332-04637\tFake/Three\tThis is Three") - zone.puts("OC\t+5005+01426\tOther/One") - end - - # zone1970.tab will be used. - RubyCoreSupport.open_file(File.join(dir, 'zone1970.tab'), 'w', :external_encoding => 'UTF-8') do |zone| - zone.puts('# zone1970.tab') - zone.puts('') - zone.puts("AC,OC\t+0000+00000\tMiddle/Another/One\tAnother's One") - zone.puts("FC\t+513030-0000731\tFake/One\tDescription of one") - zone.puts("FC,OC\t+353916+1394441\tFake/Two\tAnother description") - zone.puts("FC,OC\t-2332-04637\tFake/Three\tThis is Three") - zone.puts("OC\t+5005+01426\tOther/One") - zone.puts("OC\t+5015+11426\tOther/Two") - end - - data_source = ZoneinfoDataSource.new(dir) - - info = data_source.load_country_info('AC') - assert_equal('AC', info.code) - assert_equal('Another Country', info.name) - assert_equal(['Middle/Another/One'], info.zone_identifiers) - assert_equal(true, info.zone_identifiers.frozen?) - assert_equal([CountryTimezone.new('Middle/Another/One', Rational(0, 1), Rational(0, 1), "Another's One")], info.zones) - assert_equal(true, info.zones.frozen?) - - info = data_source.load_country_info('FC') - assert_equal('FC', info.code) - assert_equal('Fake Country', info.name) - assert_equal(['Fake/One', 'Fake/Two', 'Fake/Three'], info.zone_identifiers) - assert_equal(true, info.zone_identifiers.frozen?) - assert_equal([ - CountryTimezone.new('Fake/One', Rational(6181, 120), Rational(-451, 3600), 'Description of one'), - CountryTimezone.new('Fake/Two', Rational(32089, 900), Rational(503081, 3600), 'Another description'), - CountryTimezone.new('Fake/Three', Rational(-353, 15), Rational(-2797, 60), 'This is Three')], info.zones) - assert_equal(true, info.zones.frozen?) - - # Testing the ordering of zones. A zone can either be primary (country - # code is the first in the first column), or secondary (country code is - # not the first). Should return all the primaries first in the order they - # appeared in the file, followed by all the secondaries in the order they - # appeared in file. - - info = data_source.load_country_info('OC') - assert_equal('OC', info.code) - assert_equal('Other Country', info.name) - assert_equal(['Other/One', 'Other/Two', 'Middle/Another/One', 'Fake/Two', 'Fake/Three'], info.zone_identifiers) - assert_equal(true, info.zone_identifiers.frozen?) - assert_equal([ - CountryTimezone.new('Other/One', Rational(601, 12), Rational( 433, 30)), - CountryTimezone.new('Other/Two', Rational(201, 4), Rational(3433, 30)), - CountryTimezone.new('Middle/Another/One', Rational(0, 1), Rational(0, 1), "Another's One"), - CountryTimezone.new('Fake/Two', Rational(32089, 900), Rational(503081, 3600), 'Another description'), - CountryTimezone.new('Fake/Three', Rational(-353, 15), Rational(-2797, 60), 'This is Three')], info.zones) - assert_equal(true, info.zones.frozen?) - end - end - - def test_load_country_info_check_zones_solaris_tab_files - # Solaris uses 5 columns instead of the usual 4 in zone_sun.tab. - # An extra column before the comment gives an optional linked/alternate - # timezone identifier (or '-' if not set). - # - # Additionally, there is a section at the end of the file for timezones - # covering regions. These are given lower-case "country" codes. The timezone - # identifier column refers to a continent instead of an identifier. These - # lines will be ignored by TZInfo. - - Dir.mktmpdir('tzinfo_test') do |dir| - tab_dir = File.join(dir, 'tab') - FileUtils.mkdir(tab_dir) - - RubyCoreSupport.open_file(File.join(tab_dir, 'country.tab'), 'w', :external_encoding => 'UTF-8') do |country| - country.puts('# country.tab') - country.puts('# Solaris') - country.puts("FC\tFake Country") - country.puts("OC\tOther Country") - end - - RubyCoreSupport.open_file(File.join(tab_dir, 'zone_sun.tab'), 'w', :external_encoding => 'UTF-8') do |zone_sun| - zone_sun.puts('# zone_sun.tab') - zone_sun.puts('# Solaris') - zone_sun.puts('# Countries') - zone_sun.puts("FC\t+513030-0000731\tFake/One\t-\tDescription of one") - zone_sun.puts("FC\t+353916+1394441\tFake/Two\tFake/Alias/Two\tAnother description") - zone_sun.puts("FC\t-2332-04637\tFake/Three\tFake/Alias/Three\tThis is Three") - zone_sun.puts("OC\t+5005+01426\tOther/One\tOther/Linked/One") - zone_sun.puts("OC\t+5015+01436\tOther/Two\t-") - zone_sun.puts('# Regions') - zone_sun.puts("ee\t+0000+00000\tEurope/\tEET") - zone_sun.puts("me\t+0000+00000\tEurope/\tMET") - zone_sun.puts("we\t+0000+00000\tEurope/\tWET") - end - - data_source = ZoneinfoDataSource.new(dir) - - info = data_source.load_country_info('FC') - assert_equal('FC', info.code) - assert_equal('Fake Country', info.name) - assert_equal(['Fake/One', 'Fake/Two', 'Fake/Three'], info.zone_identifiers) - assert_equal(true, info.zone_identifiers.frozen?) - assert_equal([ - CountryTimezone.new('Fake/One', Rational(6181, 120), Rational(-451, 3600), 'Description of one'), - CountryTimezone.new('Fake/Two', Rational(32089, 900), Rational(503081, 3600), 'Another description'), - CountryTimezone.new('Fake/Three', Rational(-353, 15), Rational(-2797, 60), 'This is Three')], info.zones) - assert_equal(true, info.zones.frozen?) - - info = data_source.load_country_info('OC') - assert_equal('OC', info.code) - assert_equal('Other Country', info.name) - assert_equal(['Other/One', 'Other/Two'], info.zone_identifiers) - assert_equal(true, info.zone_identifiers.frozen?) - assert_equal([ - CountryTimezone.new('Other/One', Rational(601, 12), Rational(433, 30)), - CountryTimezone.new('Other/Two', Rational(201, 4), Rational(73, 5))], info.zones) - assert_equal(true, info.zones.frozen?) - end - end - - def test_load_country_info_check_zones_alternate_iso3166_file - Dir.mktmpdir('tzinfo_test') do |dir| - zoneinfo_dir = File.join(dir, 'zoneinfo') - tab_dir = File.join(dir, 'tab') - FileUtils.mkdir(zoneinfo_dir) - FileUtils.mkdir(tab_dir) - - tab_file = File.join(tab_dir, 'iso3166') - RubyCoreSupport.open_file(tab_file, 'w', :external_encoding => 'UTF-8') do |iso3166| - # Use the BSD 4 column format (alternate iso3166 is used on BSD). - iso3166.puts("FC\tFCC\t001\tFake Country") - iso3166.puts("OC\tOCC\t002\tOther Country") - end - - RubyCoreSupport.open_file(File.join(zoneinfo_dir, 'zone.tab'), 'w', :external_encoding => 'UTF-8') do |zone| - zone.puts("FC\t+513030-0000731\tFake/One\tDescription of one") - zone.puts("FC\t+353916+1394441\tFake/Two\tAnother description") - zone.puts("FC\t-2332-04637\tFake/Three\tThis is Three") - zone.puts("OC\t+5005+01426\tOther/One") - end - - data_source = ZoneinfoDataSource.new(zoneinfo_dir, tab_file) - - info = data_source.load_country_info('FC') - assert_equal('FC', info.code) - assert_equal('Fake Country', info.name) - assert_equal(['Fake/One', 'Fake/Two', 'Fake/Three'], info.zone_identifiers) - assert_equal(true, info.zone_identifiers.frozen?) - assert_equal([ - CountryTimezone.new('Fake/One', Rational(6181, 120), Rational(-451, 3600), 'Description of one'), - CountryTimezone.new('Fake/Two', Rational(32089, 900), Rational(503081, 3600), 'Another description'), - CountryTimezone.new('Fake/Three', Rational(-353, 15), Rational(-2797, 60), 'This is Three')], info.zones) - assert_equal(true, info.zones.frozen?) - - info = data_source.load_country_info('OC') - assert_equal('OC', info.code) - assert_equal('Other Country', info.name) - assert_equal(['Other/One'], info.zone_identifiers) - assert_equal(true, info.zone_identifiers.frozen?) - assert_equal([CountryTimezone.new('Other/One', Rational(601, 12), Rational(433, 30))], info.zones) - assert_equal(true, info.zones.frozen?) - end - end - - def test_load_country_info_four_column_iso31611 - # OpenBSD and FreeBSD use a 4 column iso3166.tab file that includes - # alpha-3 and numeric-3 codes in addition to the alpha-2 and name in the - # tz database version. - - Dir.mktmpdir('tzinfo_test') do |dir| - RubyCoreSupport.open_file(File.join(dir, 'iso3166.tab'), 'w', :external_encoding => 'UTF-8') do |iso3166| - iso3166.puts("FC\tFCC\t001\tFake Country") - iso3166.puts("OC\tOCC\t002\tOther Country") - end - - RubyCoreSupport.open_file(File.join(dir, 'zone.tab'), 'w', :external_encoding => 'UTF-8') do |zone| - zone.puts("FC\t+513030-0000731\tFake/One\tDescription of one") - zone.puts("OC\t+5005+01426\tOther/One") - end - - data_source = ZoneinfoDataSource.new(dir) - - info = data_source.load_country_info('FC') - assert_equal('FC', info.code) - assert_equal('Fake Country', info.name) - - info = data_source.load_country_info('OC') - assert_equal('OC', info.code) - assert_equal('Other Country', info.name) - end - end - - def test_load_country_info_utf8 - # iso3166.tab is currently in ASCII (as of tzdata 2014f), but will be - # changed to UTF-8 in the future. - - # zone.tab is in ASCII, with no plans to change. Since ASCII is a subset of - # UTF-8, test that this is loaded in UTF-8 anyway. - - Dir.mktmpdir('tzinfo_test') do |dir| - RubyCoreSupport.open_file(File.join(dir, 'iso3166.tab'), 'w', :external_encoding => 'UTF-8') do |iso3166| - iso3166.puts("UT\tUnicode Test ✓") - end - - RubyCoreSupport.open_file(File.join(dir, 'zone.tab'), 'w', :external_encoding => 'UTF-8') do |zone| - zone.puts("UT\t+513030-0000731\tUnicode✓/One\tUnicode Description ✓") - end - - data_source = ZoneinfoDataSource.new(dir) - - info = data_source.load_country_info('UT') - assert_equal('UT', info.code) - assert_equal('Unicode Test ✓', info.name) - assert_equal(['Unicode✓/One'], info.zone_identifiers) - assert_equal([CountryTimezone.new('Unicode✓/One', Rational(6181, 120), Rational(-451, 3600), 'Unicode Description ✓')], info.zones) - end - end - - def test_load_country_info_utf8_zone1970 - # iso3166.tab is currently in ASCII (as of tzdata 2014f), but will be - # changed to UTF-8 in the future. - - # zone1970.tab is in UTF-8. - - Dir.mktmpdir('tzinfo_test') do |dir| - RubyCoreSupport.open_file(File.join(dir, 'iso3166.tab'), 'w', :external_encoding => 'UTF-8') do |iso3166| - iso3166.puts("UT\tUnicode Test ✓") - end - - RubyCoreSupport.open_file(File.join(dir, 'zone1970.tab'), 'w', :external_encoding => 'UTF-8') do |zone| - zone.puts("UT\t+513030-0000731\tUnicode✓/One\tUnicode Description ✓") - end - - data_source = ZoneinfoDataSource.new(dir) - - info = data_source.load_country_info('UT') - assert_equal('UT', info.code) - assert_equal('Unicode Test ✓', info.name) - assert_equal(['Unicode✓/One'], info.zone_identifiers) - assert_equal([CountryTimezone.new('Unicode✓/One', Rational(6181, 120), Rational(-451, 3600), 'Unicode Description ✓')], info.zones) - end - end - - def test_country_codes - file_codes = [] - - RubyCoreSupport.open_file(File.join(@data_source.zoneinfo_dir, 'iso3166.tab'), 'r', :external_encoding => 'UTF-8', :internal_encoding => 'UTF-8') do |file| - file.each_line do |line| - line.chomp! - file_codes << $1 if line =~ /\A([A-Z]{2})\t/ - end - end - - codes = @data_source.country_codes - assert_array_same_items(file_codes, codes) - assert_equal(true, codes.frozen?) - end - - def test_country_codes_four_column_iso3166 - # OpenBSD and FreeBSD use a 4 column iso3166.tab file that includes - # alpha-3 and numeric-3 codes in addition to the alpha-2 and name in the - # tz database version. - - Dir.mktmpdir('tzinfo_test') do |dir| - RubyCoreSupport.open_file(File.join(dir, 'iso3166.tab'), 'w', :external_encoding => 'UTF-8') do |iso3166| - iso3166.puts("FC\tFCC\t001\tFake Country") - iso3166.puts("OC\tOCC\t002\tOther Country") - end - - RubyCoreSupport.open_file(File.join(dir, 'zone.tab'), 'w', :external_encoding => 'UTF-8') do |zone| - zone.puts("FC\t+513030-0000731\tFake/One\tDescription of one") - zone.puts("OC\t+5005+01426\tOther/One") - end - - data_source = ZoneinfoDataSource.new(dir) - - codes = data_source.country_codes - assert_array_same_items(%w(FC OC), codes) - end - end -end diff -Nru ruby-tzinfo-1.2.6/test/tc_zoneinfo_timezone_info.rb ruby-tzinfo-2.0.4/test/tc_zoneinfo_timezone_info.rb --- ruby-tzinfo-1.2.6/test/tc_zoneinfo_timezone_info.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tc_zoneinfo_timezone_info.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,1234 +0,0 @@ -# encoding: UTF-8 - -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') -require 'tempfile' - -include TZInfo - -using RubyCoreSupport::UntaintExt if RubyCoreSupport.const_defined?(:UntaintExt) - -class TCZoneinfoTimezoneInfo < Minitest::Test - - begin - Time.at(-2147483649) - Time.at(2147483648) - SUPPORTS_64BIT = true - rescue RangeError - SUPPORTS_64BIT = false - end - - begin - Time.at(-1) - Time.at(-2147483648) - SUPPORTS_NEGATIVE = true - rescue ArgumentError - SUPPORTS_NEGATIVE = false - end - - def assert_period(abbreviation, utc_offset, std_offset, dst, start_at, end_at, info) - if start_at - period = info.period_for_utc(start_at) - elsif end_at - period = info.period_for_utc(TimeOrDateTime.wrap(end_at).add_with_convert(-1).to_orig) - else - # no transitions, pick the epoch - period = info.period_for_utc(Time.utc(1970, 1, 1)) - end - - assert_equal(abbreviation, period.abbreviation) - assert_equal(utc_offset, period.utc_offset) - assert_equal(std_offset, period.std_offset) - assert_equal(dst, period.dst?) - - if start_at - refute_nil(period.utc_start_time) - assert_equal(start_at, period.utc_start_time) - else - assert_nil(period.utc_start_time) - end - - if end_at - refute_nil(period.utc_end_time) - assert_equal(end_at, period.utc_end_time) - else - assert_nil(period.utc_end_time) - end - end - - def convert_times_to_i(items, key = :at) - items.each do |item| - if item[key].kind_of?(Time) - item[key] = item[key].utc.to_i - end - end - end - - def select_with_32bit_values(items, key = :at) - items.select do |item| - i = item[key] - i >= -2147483648 && i <= 2147483647 - end - end - - def pack_int64_network_order(values) - values.collect {|value| [value >> 32, value & 0xFFFFFFFF]}.flatten.pack('NN' * values.length) - end - - def pack_int64_signed_network_order(values) - # Convert to the equivalent 64-bit unsigned integer with the same bit representation - pack_int64_network_order(values.collect {|value| value < 0 ? value + 0x10000000000000000 : value}) - end - - def write_tzif(format, offsets, transitions, leaps = [], options = {}) - - # Options for testing malformed zoneinfo files. - magic = options[:magic] - section2_magic = options[:section2_magic] - abbrev_separator = options[:abbrev_separator] || "\0" - abbrev_offset_base = options[:abbrev_offset_base] || 0 - - unless magic - if format == 1 - magic = "TZif\0" - elsif format >= 2 - magic = "TZif#{format}" - else - raise ArgumentError, 'Invalid format specified' - end - end - - if section2_magic.kind_of?(Proc) - section2_magic = section2_magic.call(format) - else - section2_magic = magic unless section2_magic - end - - convert_times_to_i(transitions) - convert_times_to_i(leaps) - - abbrevs = offsets.collect {|o| o[:abbrev]}.uniq - - if abbrevs.length > 0 - abbrevs = abbrevs.collect {|a| a.encode('UTF-8')} if abbrevs.first.respond_to?(:encode) - - if abbrevs.first.respond_to?(:bytesize) - abbrevs_length = abbrevs.inject(0) {|sum, a| sum + a.bytesize + abbrev_separator.bytesize} - else - abbrevs_length = abbrevs.inject(0) {|sum, a| sum + a.length + abbrev_separator.length} - end - else - abbrevs_length = 0 - end - - b32_transitions = select_with_32bit_values(transitions) - b32_leaps = select_with_32bit_values(leaps) - - Tempfile.open('tzinfo-test-zone') do |file| - file.binmode - - file.write( - [magic, offsets.length, offsets.length, leaps.length, - b32_transitions.length, offsets.length, abbrevs_length].pack('a5 x15 NNNNNN')) - - unless b32_transitions.empty? - file.write(b32_transitions.collect {|t| t[:at]}.pack('N' * b32_transitions.length)) - file.write(b32_transitions.collect {|t| t[:offset_index]}.pack('C' * b32_transitions.length)) - end - - offsets.each do |offset| - index = abbrevs.index(offset[:abbrev]) - abbrev_offset = abbrev_offset_base - 0.upto(index - 1) {|i| abbrev_offset += abbrevs[i].length + 1} - - file.write([offset[:gmtoff], offset[:isdst] ? 1 : 0, abbrev_offset].pack('NCC')) - end - - abbrevs.each do |a| - file.write(a) - file.write(abbrev_separator) - end - - b32_leaps.each do |leap| - file.write([leap[:at], leap[:seconds]].pack('NN')) - end - - unless offsets.empty? - file.write("\0" * offsets.length * 2) - end - - if format >= 2 - file.write( - [section2_magic, offsets.length, offsets.length, leaps.length, - transitions.length, offsets.length, abbrevs_length].pack('a5 x15 NNNNNN')) - - unless transitions.empty? - file.write(pack_int64_signed_network_order(transitions.collect {|t| t[:at]})) - file.write(transitions.collect {|t| t[:offset_index]}.pack('C' * transitions.length)) - end - - offsets.each do |offset| - index = abbrevs.index(offset[:abbrev]) - abbrev_offset = abbrev_offset_base - 0.upto(index - 1) {|i| abbrev_offset += abbrevs[i].length + 1} - - file.write([offset[:gmtoff], offset[:isdst] ? 1 : 0, abbrev_offset].pack('NCC')) - end - - abbrevs.each do |a| - file.write(a) - file.write(abbrev_separator) - end - - leaps.each do |leap| - file.write(pack_int64_signed_network_order([leap[:at]])) - file.write([leap[:seconds]].pack('N')) - end - - unless offsets.empty? - file.write("\0" * offsets.length * 2) - end - - # Empty POSIX timezone string - file.write("\n\n") - end - - file.flush - - yield file.path, format - end - end - - def tzif_test(offsets, transitions, leaps = [], options = {}, &block) - min_format = options[:min_format] || 1 - - min_format.upto(3) do |format| - write_tzif(format, offsets, transitions, leaps, options, &block) - end - end - - def test_load - offsets = [ - {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'}, - {:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'}, - {:gmtoff => 0, :isdst => false, :abbrev => 'XNST'}] - - transitions = [ - {:at => Time.utc(1971, 1, 2), :offset_index => 1}, - {:at => Time.utc(1980, 4, 22), :offset_index => 2}, - {:at => Time.utc(1980, 10, 21), :offset_index => 1}, - {:at => Time.utc(2000, 12, 31), :offset_index => 3}] - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/One', path) - assert_equal('Zone/One', info.identifier) - - assert_period(:LMT, 3542, 0, false, nil, Time.utc(1971, 1, 2), info) - assert_period(:XST, 3600, 0, false, Time.utc(1971, 1, 2), Time.utc(1980, 4, 22), info) - assert_period(:XDT, 3600, 3600, true, Time.utc(1980, 4, 22), Time.utc(1980, 10, 21), info) - assert_period(:XST, 3600, 0, false, Time.utc(1980, 10, 21), Time.utc(2000, 12, 31), info) - assert_period(:XNST, 0, 0, false, Time.utc(2000, 12, 31), nil, info) - end - end - - def test_load_negative_utc_offset - offsets = [ - {:gmtoff => -12492, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => -12000, :isdst => false, :abbrev => 'XST'}, - {:gmtoff => -8400, :isdst => true, :abbrev => 'XDT'}, - {:gmtoff => -8400, :isdst => false, :abbrev => 'XNST'}] - - transitions = [ - {:at => Time.utc(1971, 7, 9, 3, 0, 0), :offset_index => 1}, - {:at => Time.utc(1972, 10, 12, 3, 0, 0), :offset_index => 2}, - {:at => Time.utc(1973, 4, 29, 3, 0, 0), :offset_index => 1}, - {:at => Time.utc(1992, 4, 1, 4, 30, 0), :offset_index => 3}] - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/One', path) - assert_equal('Zone/One', info.identifier) - - assert_period(:LMT, -12492, 0, false, nil, Time.utc(1971, 7, 9, 3, 0, 0), info) - assert_period(:XST, -12000, 0, false, Time.utc(1971, 7, 9, 3, 0, 0), Time.utc(1972, 10, 12, 3, 0, 0), info) - assert_period(:XDT, -12000, 3600, true, Time.utc(1972, 10, 12, 3, 0, 0), Time.utc(1973, 4, 29, 3, 0, 0), info) - assert_period(:XST, -12000, 0, false, Time.utc(1973, 4, 29, 3, 0, 0), Time.utc(1992, 4, 1, 4, 30, 0), info) - assert_period(:XNST, -8400, 0, false, Time.utc(1992, 4, 1, 4, 30, 0), nil, info) - end - end - - def test_load_dst_first - offsets = [ - {:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'}, - {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'}, - {:gmtoff => 0, :isdst => false, :abbrev => 'XNST'}] - - transitions = [ - {:at => Time.utc(1979, 1, 2), :offset_index => 2}, - {:at => Time.utc(1980, 4, 22), :offset_index => 0}, - {:at => Time.utc(1980, 10, 21), :offset_index => 2}, - {:at => Time.utc(2000, 12, 31), :offset_index => 3}] - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/Two', path) - assert_equal('Zone/Two', info.identifier) - - assert_period(:LMT, 3542, 0, false, nil, Time.utc(1979, 1, 2), info) - end - end - - def test_load_no_transitions - offsets = [{:gmtoff => -12094, :isdst => false, :abbrev => 'LT'}] - - tzif_test(offsets, []) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/three', path) - assert_equal('Zone/three', info.identifier) - - assert_period(:LT, -12094, 0, false, nil, nil, info) - end - end - - def test_load_no_offsets - offsets = [] - transitions = [{:at => Time.utc(2000, 12, 31), :offset_index => 0}] - - tzif_test(offsets, transitions) do |path, format| - assert_raises(InvalidZoneinfoFile) do - ZoneinfoTimezoneInfo.new('Zone', path) - end - end - end - - def test_load_invalid_offset_index - offsets = [{:gmtoff => -0, :isdst => false, :abbrev => 'LMT'}] - transitions = [{:at => Time.utc(2000, 12, 31), :offset_index => 2}] - - tzif_test(offsets, transitions) do |path, format| - assert_raises(InvalidZoneinfoFile) do - ZoneinfoTimezoneInfo.new('Zone', path) - end - end - end - - def test_load_with_leap_seconds - offsets = [{:gmtoff => -0, :isdst => false, :abbrev => 'LMT'}] - leaps = [{:at => Time.utc(1972,6,30,23,59,60), :seconds => 1}] - - tzif_test(offsets, [], leaps) do |path, format| - assert_raises(InvalidZoneinfoFile) do - ZoneinfoTimezoneInfo.new('Zone', path) - end - end - end - - def test_load_invalid_magic - ['TZif4', 'tzif2', '12345'].each do |magic| - offsets = [{:gmtoff => -12094, :isdst => false, :abbrev => 'LT'}] - - tzif_test(offsets, [], [], :magic => magic) do |path, format| - assert_raises(InvalidZoneinfoFile) do - ZoneinfoTimezoneInfo.new('Zone2', path) - end - end - end - end - - # These tests can only be run if the platform supports 64-bit Times. When - # 64-bit support is unavailable, the second section will not be read, so no - # error will be raised. - if SUPPORTS_64BIT - def test_load_invalid_section2_magic - ['TZif4', 'tzif2', '12345'].each do |section2_magic| - offsets = [{:gmtoff => -12094, :isdst => false, :abbrev => 'LT'}] - - tzif_test(offsets, [], [], :min_format => 2, :section2_magic => section2_magic) do |path, format| - assert_raises(InvalidZoneinfoFile) do - ZoneinfoTimezoneInfo.new('Zone4', path) - end - end - end - end - - def test_load_mismatched_section2_magic - minus_one = Proc.new {|f| f == 2 ? "TZif\0" : "TZif#{f - 1}" } - plus_one = Proc.new {|f| "TZif#{f + 1}" } - - [minus_one, plus_one].each do |section2_magic| - offsets = [{:gmtoff => -12094, :isdst => false, :abbrev => 'LT'}] - - tzif_test(offsets, [], [], :min_format => 2, :section2_magic => section2_magic) do |path, format| - assert_raises(InvalidZoneinfoFile) do - ZoneinfoTimezoneInfo.new('Zone5', path) - end - end - end - end - end - - def test_load_invalid_format - Tempfile.open('tzinfo-test-zone') do |file| - file.write('Invalid') - file.flush - - assert_raises(InvalidZoneinfoFile) do - ZoneinfoTimezoneInfo.new('Zone3', file.path) - end - end - end - - def test_load_missing_abbrev_null_termination - offsets = [ - {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'}] - - transitions = [ - {:at => Time.utc(2000, 1, 1), :offset_index => 1}] - - tzif_test(offsets, transitions, [], :abbrev_separator => '^') do |path, format| - assert_raises(InvalidZoneinfoFile) do - ZoneinfoTimezoneInfo.new('Zone', path) - end - end - end - - def test_load_out_of_range_abbrev_offsets - offsets = [ - {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'}] - - transitions = [ - {:at => Time.utc(2000, 1, 1), :offset_index => 1}] - - tzif_test(offsets, transitions, [], :abbrev_offset_base => 8) do |path, format| - assert_raises(InvalidZoneinfoFile) do - ZoneinfoTimezoneInfo.new('Zone', path) - end - end - end - - def test_load_before_epoch - # Some platforms don't support negative timestamps for times before the - # epoch. Check that they are returned when supported and skipped when not. - - # Note the last transition before the epoch (and within the 32-bit range) is - # moved to the epoch on platforms that do not support negative timestamps. - - offsets = [ - {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'}, - {:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'}, - {:gmtoff => 0, :isdst => false, :abbrev => 'XNST'}] - - transitions = [ - {:at => -694224000, :offset_index => 1}, # Time.utc(1948, 1, 2) - {:at => -21945600, :offset_index => 2}, # Time.utc(1969, 4, 22) - {:at => Time.utc(1970, 10, 21), :offset_index => 1}, - {:at => Time.utc(2000, 12, 31), :offset_index => 3}] - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/Negative', path) - assert_equal('Zone/Negative', info.identifier) - - if SUPPORTS_NEGATIVE - assert_period(:LMT, 3542, 0, false, nil, Time.utc(1948, 1, 2), info) - assert_period(:XST, 3600, 0, false, Time.utc(1948, 1, 2), Time.utc(1969, 4, 22), info) - assert_period(:XDT, 3600, 3600, true, Time.utc(1969, 4, 22), Time.utc(1970, 10, 21), info) - else - assert_period(:LMT, 3542, 0, false, nil, Time.utc(1970, 1, 1), info) - assert_period(:XDT, 3600, 3600, true, Time.utc(1970, 1, 1), Time.utc(1970, 10, 21), info) - end - - assert_period(:XST, 3600, 0, false, Time.utc(1970, 10, 21), Time.utc(2000, 12, 31), info) - assert_period(:XNST, 0, 0, false, Time.utc(2000, 12, 31), nil, info) - end - end - - def test_load_on_epoch - offsets = [ - {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'}, - {:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'}, - {:gmtoff => 0, :isdst => false, :abbrev => 'XNST'}] - - transitions = [ - {:at => -694224000, :offset_index => 1}, # Time.utc(1948, 1, 2) - {:at => -21945600, :offset_index => 2}, # Time.utc(1969, 4, 22) - {:at => Time.utc(1970, 1, 1), :offset_index => 1}, - {:at => Time.utc(2000, 12, 31), :offset_index => 3}] - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/Negative', path) - assert_equal('Zone/Negative', info.identifier) - - if SUPPORTS_NEGATIVE - assert_period(:LMT, 3542, 0, false, nil, Time.utc(1948, 1, 2), info) - assert_period(:XST, 3600, 0, false, Time.utc(1948, 1, 2), Time.utc(1969, 4, 22), info) - assert_period(:XDT, 3600, 3600, true, Time.utc(1969, 4, 22), Time.utc(1970, 1, 1), info) - else - assert_period(:LMT, 3542, 0, false, nil, Time.utc(1970, 1, 1), info) - end - - assert_period(:XST, 3600, 0, false, Time.utc(1970, 1, 1), Time.utc(2000, 12, 31), info) - assert_period(:XNST, 0, 0, false, Time.utc(2000, 12, 31), nil, info) - end - end - - def test_load_64bit - # Some platforms support 64-bit Times, others only 32-bit. The TZif version - # 2 and later format contains both 32-bit and 64-bit times. - - # Where 64-bit is supported and a TZif 2 or later file is provided, the - # 64-bit times should be used, otherwise the 32-bit information should be - # used. - - offsets = [ - {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'}, - {:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'}, - {:gmtoff => 0, :isdst => false, :abbrev => 'XNST'}] - - transitions = [ - {:at => -3786739200, :offset_index => 1}, # Time.utc(1850, 1, 2) - {:at => Time.utc(2003, 4, 22), :offset_index => 2}, - {:at => Time.utc(2003, 10, 21), :offset_index => 1}, - {:at => 2240524800, :offset_index => 3}] # Time.utc(2040, 12, 31) - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/SixtyFour', path) - assert_equal('Zone/SixtyFour', info.identifier) - - if SUPPORTS_64BIT && format >= 2 - assert_period(:LMT, 3542, 0, false, nil, Time.utc(1850, 1, 2), info) - assert_period(:XST, 3600, 0, false, Time.utc(1850, 1, 2), Time.utc(2003, 4, 22), info) - assert_period(:XDT, 3600, 3600, true, Time.utc(2003, 4, 22), Time.utc(2003, 10, 21), info) - assert_period(:XST, 3600, 0, false, Time.utc(2003, 10, 21), Time.utc(2040, 12, 31), info) - assert_period(:XNST, 0, 0, false, Time.utc(2040, 12, 31), nil, info) - else - assert_period(:LMT, 3542, 0, false, nil, Time.utc(2003, 4, 22), info) - assert_period(:XDT, 3600, 3600, true, Time.utc(2003, 4, 22), Time.utc(2003, 10, 21), info) - assert_period(:XST, 3600, 0, false, Time.utc(2003, 10, 21), nil, info) - end - end - end - - def test_load_64bit_range - # The full range of 64 bit timestamps is not currently supported because of - # the way transitions are indexed. Transitions outside the supported range - # will be ignored. - - offsets = [ - {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'}, - {:gmtoff => 7200, :isdst => false, :abbrev => 'XNST'}] - - transitions = [ - {:at => -2**63, :offset_index => 1}, - {:at => Time.utc(2014, 5, 27), :offset_index => 2}, - {:at => 2**63 - 1, :offset_index => 0}] - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/SixtyFourRange', path) - assert_equal('Zone/SixtyFourRange', info.identifier) - - if SUPPORTS_64BIT && format >= 2 - # When the full range is supported, the following periods will be defined: - #assert_period(:LMT, 3542, 0, false, nil, Time.at(-2**63).utc, info) - #assert_period(:XST, 3600, 0, false, Time.at(-2**63).utc, Time.utc(2014, 5, 27), info) - #assert_period(:XNST, 7200, 0, false, Time.utc(2014, 5, 27), Time.at(2**63 - 1).utc, info) - #assert_period(:LMT, 3542, 0, false, Time.at(2**63 - 1).utc, nil, info) - - # Without full range support, the following periods will be defined: - assert_period(:LMT, 3542, 0, false, nil, Time.utc(2014, 5, 27), info) - assert_period(:XNST, 7200, 0, false, Time.utc(2014, 5, 27), nil, info) - else - assert_period(:LMT, 3542, 0, false, nil, Time.utc(2014, 5, 27), info) - assert_period(:XNST, 7200, 0, false, Time.utc(2014, 5, 27), nil, info) - end - end - end - - def test_load_supported_64bit_range - # The full range of 64 bit timestamps is not currently supported because of - # the way transitions are indexed. Transitions outside the supported range - # will be ignored. - - min_timestamp = -8520336000 # Time.utc(1700, 1, 1).to_i - max_timestamp = 16725225600 # Time.utc(2500, 1, 1).to_i - - offsets = [ - {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'}, - {:gmtoff => 7200, :isdst => false, :abbrev => 'XNST'}] - - transitions = [ - {:at => min_timestamp, :offset_index => 1}, - {:at => Time.utc(2014, 5, 27), :offset_index => 2}, - {:at => max_timestamp - 1, :offset_index => 0}] - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/SupportedSixtyFourRange', path) - assert_equal('Zone/SupportedSixtyFourRange', info.identifier) - - if SUPPORTS_64BIT && format >= 2 - assert_period(:LMT, 3542, 0, false, nil, Time.at(min_timestamp).utc, info) - assert_period(:XST, 3600, 0, false, Time.at(min_timestamp).utc, Time.utc(2014, 5, 27), info) - assert_period(:XNST, 7200, 0, false, Time.utc(2014, 5, 27), Time.at(max_timestamp - 1).utc, info) - assert_period(:LMT, 3542, 0, false, Time.at(max_timestamp - 1).utc, nil, info) - else - assert_period(:LMT, 3542, 0, false, nil, Time.utc(2014, 5, 27), info) - assert_period(:XNST, 7200, 0, false, Time.utc(2014, 5, 27), nil, info) - end - end - end - - def test_load_32bit_range - offsets = [ - {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'}, - {:gmtoff => 7200, :isdst => false, :abbrev => 'XNST'}] - - transitions = [ - {:at => -2**31, :offset_index => 1}, - {:at => Time.utc(2014, 5, 27), :offset_index => 2}, - {:at => 2**31 - 1, :offset_index => 0}] - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/ThirtyTwoRange', path) - assert_equal('Zone/ThirtyTwoRange', info.identifier) - - if SUPPORTS_NEGATIVE - assert_period(:LMT, 3542, 0, false, nil, Time.at(-2**31).utc, info) - assert_period(:XST, 3600, 0, false, Time.at(-2**31).utc, Time.utc(2014, 5, 27), info) - assert_period(:XNST, 7200, 0, false, Time.utc(2014, 5, 27), Time.at(2**31 - 1).utc, info) - assert_period(:LMT, 3542, 0, false, Time.at(2**31 - 1).utc, nil, info) - else - assert_period(:XST, 3600, 0, false, Time.utc(1970, 1, 1), Time.utc(2014, 5, 27), info) - assert_period(:XNST, 7200, 0, false, Time.utc(2014, 5, 27), Time.at(2**31 - 1).utc, info) - assert_period(:LMT, 3542, 0, false, Time.at(2**31 - 1).utc, nil, info) - end - end - end - - def test_load_std_offset_changes - # The zoneinfo files don't include the offset from standard time, so this - # has to be derived by looking at changes in the total UTC offset. - - offsets = [ - {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'}, - {:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'}, - {:gmtoff => 10800, :isdst => true, :abbrev => 'XDDT'}] - - transitions = [ - {:at => Time.utc(2000, 1, 1), :offset_index => 1}, - {:at => Time.utc(2000, 2, 1), :offset_index => 2}, - {:at => Time.utc(2000, 3, 1), :offset_index => 3}, - {:at => Time.utc(2000, 4, 1), :offset_index => 1}] - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/DoubleDaylight', path) - assert_equal('Zone/DoubleDaylight', info.identifier) - - assert_period(:LMT, 3542, 0, false, nil, Time.utc(2000, 1, 1), info) - assert_period(:XST, 3600, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info) - assert_period(:XDT, 3600, 3600, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info) - assert_period(:XDDT, 3600, 7200, true, Time.utc(2000, 3, 1), Time.utc(2000, 4, 1), info) - assert_period(:XST, 3600, 0, false, Time.utc(2000, 4, 1), nil, info) - end - end - - def test_load_std_offset_changes_jump_to_double_dst - # The zoneinfo files don't include the offset from standard time, so this - # has to be derived by looking at changes in the total UTC offset. - - offsets = [ - {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'}, - {:gmtoff => 10800, :isdst => true, :abbrev => 'XDDT'}] - - transitions = [ - {:at => Time.utc(2000, 4, 1), :offset_index => 1}, - {:at => Time.utc(2000, 5, 1), :offset_index => 2}, - {:at => Time.utc(2000, 6, 1), :offset_index => 1}] - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/DoubleDaylight', path) - assert_equal('Zone/DoubleDaylight', info.identifier) - - assert_period(:LMT, 3542, 0, false, nil, Time.utc(2000, 4, 1), info) - assert_period(:XST, 3600, 0, false, Time.utc(2000, 4, 1), Time.utc(2000, 5, 1), info) - assert_period(:XDDT, 3600, 7200, true, Time.utc(2000, 5, 1), Time.utc(2000, 6, 1), info) - assert_period(:XST, 3600, 0, false, Time.utc(2000, 6, 1), nil, info) - end - end - - def test_load_std_offset_changes_negative - # The zoneinfo files don't include the offset from standard time, so this - # has to be derived by looking at changes in the total UTC offset. - - offsets = [ - {:gmtoff => -10821, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => -10800, :isdst => false, :abbrev => 'XST'}, - {:gmtoff => -7200, :isdst => true, :abbrev => 'XDT'}, - {:gmtoff => -3600, :isdst => true, :abbrev => 'XDDT'}] - - transitions = [ - {:at => Time.utc(2000, 1, 1), :offset_index => 1}, - {:at => Time.utc(2000, 2, 1), :offset_index => 2}, - {:at => Time.utc(2000, 3, 1), :offset_index => 3}, - {:at => Time.utc(2000, 4, 1), :offset_index => 1}, - {:at => Time.utc(2000, 5, 1), :offset_index => 3}, - {:at => Time.utc(2000, 6, 1), :offset_index => 1}] - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/DoubleDaylight', path) - assert_equal('Zone/DoubleDaylight', info.identifier) - - assert_period(:LMT, -10821, 0, false, nil, Time.utc(2000, 1, 1), info) - assert_period(:XST, -10800, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info) - assert_period(:XDT, -10800, 3600, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info) - assert_period(:XDDT, -10800, 7200, true, Time.utc(2000, 3, 1), Time.utc(2000, 4, 1), info) - assert_period(:XST, -10800, 0, false, Time.utc(2000, 4, 1), Time.utc(2000, 5, 1), info) - assert_period(:XDDT, -10800, 7200, true, Time.utc(2000, 5, 1), Time.utc(2000, 6, 1), info) - assert_period(:XST, -10800, 0, false, Time.utc(2000, 6, 1), nil, info) - end - end - - def test_load_starts_two_hour_std_offset - # The zoneinfo files don't include the offset from standard time, so this - # has to be derived by looking at changes in the total UTC offset. - - offsets = [ - {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'}, - {:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'}, - {:gmtoff => 10800, :isdst => true, :abbrev => 'XDDT'}] - - transitions = [ - {:at => Time.utc(2000, 1, 1), :offset_index => 3}, - {:at => Time.utc(2000, 2, 1), :offset_index => 2}, - {:at => Time.utc(2000, 3, 1), :offset_index => 1}] - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/DoubleDaylight', path) - assert_equal('Zone/DoubleDaylight', info.identifier) - - assert_period(:LMT, 3542, 0, false, nil, Time.utc(2000, 1, 1), info) - assert_period(:XDDT, 3600, 7200, true, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info) - assert_period(:XDT, 3600, 3600, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info) - assert_period(:XST, 3600, 0, false, Time.utc(2000, 3, 1), nil, info) - end - end - - def test_load_starts_only_dst_transition_with_lmt - # The zoneinfo files don't include the offset from standard time, so this - # has to be derived by looking at changes in the total UTC offset. - - offsets = [ - {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'}] - - transitions = [{:at => Time.utc(2000, 1, 1), :offset_index => 1}] - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/OnlyDST', path) - assert_equal('Zone/OnlyDST', info.identifier) - - assert_period(:LMT, 3542, 0, false, nil, Time.utc(2000, 1, 1), info) - assert_period(:XDT, 3542, 3658, true, Time.utc(2000, 1, 1), nil, info) - end - end - - def test_load_starts_only_dst_transition_without_lmt - # The zoneinfo files don't include the offset from standard time, so this - # has to be derived by looking at changes in the total UTC offset. - - offsets = [{:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'}] - - transitions = [{:at => Time.utc(2000, 1, 1), :offset_index => 0}] - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/OnlyDST', path) - assert_equal('Zone/OnlyDST', info.identifier) - - assert_period(:XDT, 3600, 3600, true, nil, Time.utc(2000, 1, 1), info) - assert_period(:XDT, 3600, 3600, true, Time.utc(2000, 1, 1), nil, info) - end - end - - def test_load_switch_to_dst_and_change_utc_offset - # The zoneinfo files don't include the offset from standard time, so this - # has to be derived by looking at changes in the total UTC offset. - - # Switch from non-DST to DST at the same time as moving the UTC offset - # back an hour (i.e. wall clock time doesn't change). - - offsets = [ - {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 3600, :isdst => false, :abbrev => 'YST'}, - {:gmtoff => 3600, :isdst => true, :abbrev => 'XDT'}] - - transitions = [ - {:at => Time.utc(2000, 1, 1), :offset_index => 1}, - {:at => Time.utc(2000, 2, 1), :offset_index => 2}] - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/DoubleDaylight', path) - assert_equal('Zone/DoubleDaylight', info.identifier) - - assert_period(:LMT, 3542, 0, false, nil, Time.utc(2000, 1, 1), info) - assert_period(:YST, 3600, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info) - assert_period(:XDT, 0, 3600, true, Time.utc(2000, 2, 1), nil, info) - end - end - - def test_load_apia_international_dateline_change - # The zoneinfo files don't include the offset from standard time, so this - # has to be derived by looking at changes in the total UTC offset. - - # Pacific/Apia moved across the International Date Line whilst observing - # daylight savings time. - - offsets = [ - {:gmtoff => 45184, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => -39600, :isdst => false, :abbrev => '-11'}, - {:gmtoff => -36000, :isdst => true, :abbrev => '-10'}, - {:gmtoff => 50400, :isdst => true, :abbrev => '+14'}, - {:gmtoff => 46800, :isdst => false, :abbrev => '+13'}] - - transitions = [ - {:at => Time.utc(2011, 4, 2, 14, 0, 0), :offset_index => 1}, - {:at => Time.utc(2011, 9, 24, 14, 0, 0), :offset_index => 2}, - {:at => Time.utc(2011, 12, 30, 10, 0, 0), :offset_index => 3}, - {:at => Time.utc(2012, 3, 31, 14, 0, 0), :offset_index => 4}] - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Test/Pacific/Apia', path) - assert_equal('Test/Pacific/Apia', info.identifier) - - assert_period( :LMT, 45184, 0, false, nil, Time.utc(2011, 4, 2, 14, 0, 0), info) - assert_period(:'-11', -39600, 0, false, Time.utc(2011, 4, 2, 14, 0, 0), Time.utc(2011, 9, 24, 14, 0, 0), info) - assert_period(:'-10', -39600, 3600, true, Time.utc(2011, 9, 24, 14, 0, 0), Time.utc(2011, 12, 30, 10, 0, 0), info) - assert_period(:'+14', 46800, 3600, true, Time.utc(2011, 12, 30, 10, 0, 0), Time.utc(2012, 3, 31, 14, 0, 0), info) - assert_period(:'+13', 46800, 0, false, Time.utc(2012, 3, 31, 14, 0, 0), nil, info) - end - end - - def test_load_offset_split_for_different_utc_offset - # The zoneinfo files don't include the offset from standard time, so this - # has to be derived by looking at changes in the total UTC offset. - - offsets = [ - {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 3600, :isdst => false, :abbrev => 'XST1'}, - {:gmtoff => 7200, :isdst => false, :abbrev => 'XST2'}, - {:gmtoff => 10800, :isdst => true, :abbrev => 'XDT'}] - - transitions = [ - {:at => Time.utc(2000, 1, 1), :offset_index => 1}, - {:at => Time.utc(2000, 2, 1), :offset_index => 3}, - {:at => Time.utc(2000, 3, 1), :offset_index => 1}, - {:at => Time.utc(2000, 4, 1), :offset_index => 2}, - {:at => Time.utc(2000, 5, 1), :offset_index => 3}, - {:at => Time.utc(2000, 6, 1), :offset_index => 2}, - {:at => Time.utc(2000, 7, 1), :offset_index => 1}, - {:at => Time.utc(2000, 8, 1), :offset_index => 3}, - {:at => Time.utc(2000, 9, 1), :offset_index => 1}, - {:at => Time.utc(2000, 10, 1), :offset_index => 2}, - {:at => Time.utc(2000, 11, 1), :offset_index => 3}, - {:at => Time.utc(2000, 12, 1), :offset_index => 2}] - - # XDT will be split and defined according to its surrounding standard time - # offsets. - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/SplitUtcOffset', path) - assert_equal('Zone/SplitUtcOffset', info.identifier) - - assert_period( :LMT, 3542, 0, false, nil, Time.utc(2000, 1, 1), info) - assert_period(:XST1, 3600, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info) - assert_period( :XDT, 3600, 7200, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info) - assert_period(:XST1, 3600, 0, false, Time.utc(2000, 3, 1), Time.utc(2000, 4, 1), info) - assert_period(:XST2, 7200, 0, false, Time.utc(2000, 4, 1), Time.utc(2000, 5, 1), info) - assert_period( :XDT, 7200, 3600, true, Time.utc(2000, 5, 1), Time.utc(2000, 6, 1), info) - assert_period(:XST2, 7200, 0, false, Time.utc(2000, 6, 1), Time.utc(2000, 7, 1), info) - assert_period(:XST1, 3600, 0, false, Time.utc(2000, 7, 1), Time.utc(2000, 8, 1), info) - assert_period( :XDT, 3600, 7200, true, Time.utc(2000, 8, 1), Time.utc(2000, 9, 1), info) - assert_period(:XST1, 3600, 0, false, Time.utc(2000, 9, 1), Time.utc(2000, 10, 1), info) - assert_period(:XST2, 7200, 0, false, Time.utc(2000, 10, 1), Time.utc(2000, 11, 1), info) - assert_period( :XDT, 7200, 3600, true, Time.utc(2000, 11, 1), Time.utc(2000, 12, 1), info) - assert_period(:XST2, 7200, 0, false, Time.utc(2000, 12, 1), nil, info) - - 1.upto(6) do |i| - assert_same(info.period_for_utc(Time.utc(2000, i, 1)).offset, info.period_for_utc(Time.utc(2000, i + 6, 1)).offset) - end - end - end - - def test_load_offset_utc_offset_taken_from_minimum_difference_minimum_after - # The zoneinfo files don't include the offset from standard time, so this - # has to be derived by looking at changes in the total UTC offset. - - offsets = [ - {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 3600, :isdst => false, :abbrev => 'XST1'}, - {:gmtoff => 7200, :isdst => false, :abbrev => 'XST2'}, - {:gmtoff => 10800, :isdst => true, :abbrev => 'XDT'}] - - transitions = [ - {:at => Time.utc(2000, 1, 1), :offset_index => 1}, - {:at => Time.utc(2000, 2, 1), :offset_index => 3}, - {:at => Time.utc(2000, 3, 1), :offset_index => 2}] - - # XDT should use the closest utc_offset (7200) (and not an equivalent - # utc_offset of 3600 and std_offset of 7200). - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/MinimumUtcOffset', path) - assert_equal('Zone/MinimumUtcOffset', info.identifier) - - assert_period( :LMT, 3542, 0, false, nil, Time.utc(2000, 1, 1), info) - assert_period(:XST1, 3600, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info) - assert_period( :XDT, 7200, 3600, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info) - assert_period(:XST2, 7200, 0, false, Time.utc(2000, 3, 1), nil, info) - end - end - - def test_load_offset_utc_offset_taken_from_minimum_difference_minimum_before - # The zoneinfo files don't include the offset from standard time, so this - # has to be derived by looking at changes in the total UTC offset. - - offsets = [ - {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 3600, :isdst => false, :abbrev => 'XST1'}, - {:gmtoff => 7200, :isdst => false, :abbrev => 'XST2'}, - {:gmtoff => 10800, :isdst => true, :abbrev => 'XDT'}] - - transitions = [ - {:at => Time.utc(2000, 1, 1), :offset_index => 2}, - {:at => Time.utc(2000, 2, 1), :offset_index => 3}, - {:at => Time.utc(2000, 3, 1), :offset_index => 1}] - - # XDT should use the closest utc_offset (7200) (and not an equivalent - # utc_offset of 3600 and std_offset of 7200). - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/MinimumUtcOffset', path) - assert_equal('Zone/MinimumUtcOffset', info.identifier) - - assert_period( :LMT, 3542, 0, false, nil, Time.utc(2000, 1, 1), info) - assert_period(:XST2, 7200, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info) - assert_period( :XDT, 7200, 3600, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info) - assert_period(:XST1, 3600, 0, false, Time.utc(2000, 3, 1), nil, info) - end - end - - def test_load_offset_does_not_use_equal_utc_total_offset_equal_after - # The zoneinfo files don't include the offset from standard time, so this - # has to be derived by looking at changes in the total UTC offset. - - offsets = [ - {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 3600, :isdst => false, :abbrev => 'XST1'}, - {:gmtoff => 7200, :isdst => false, :abbrev => 'XST2'}, - {:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'}] - - transitions = [ - {:at => Time.utc(2000, 1, 1), :offset_index => 1}, - {:at => Time.utc(2000, 2, 1), :offset_index => 3}, - {:at => Time.utc(2000, 3, 1), :offset_index => 2}] - - # XDT will be based on the utc_offset of XST1 even though XST2 has an - # equivalent (or greater) utc_total_offset. - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/UtcOffsetEqual', path) - assert_equal('Zone/UtcOffsetEqual', info.identifier) - - assert_period( :LMT, 3542, 0, false, nil, Time.utc(2000, 1, 1), info) - assert_period(:XST1, 3600, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info) - assert_period( :XDT, 3600, 3600, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info) - assert_period(:XST2, 7200, 0, false, Time.utc(2000, 3, 1), nil, info) - end - end - - def test_load_offset_does_not_use_equal_utc_total_offset_equal_before - # The zoneinfo files don't include the offset from standard time, so this - # has to be derived by looking at changes in the total UTC offset. - - offsets = [ - {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 3600, :isdst => false, :abbrev => 'XST1'}, - {:gmtoff => 7200, :isdst => false, :abbrev => 'XST2'}, - {:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'}] - - transitions = [ - {:at => Time.utc(2000, 1, 1), :offset_index => 2}, - {:at => Time.utc(2000, 2, 1), :offset_index => 3}, - {:at => Time.utc(2000, 3, 1), :offset_index => 1}] - - # XDT will be based on the utc_offset of XST1 even though XST2 has an - # equivalent (or greater) utc_total_offset. - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/UtcOffsetEqual', path) - assert_equal('Zone/UtcOffsetEqual', info.identifier) - - assert_period( :LMT, 3542, 0, false, nil, Time.utc(2000, 1, 1), info) - assert_period(:XST2, 7200, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info) - assert_period( :XDT, 3600, 3600, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info) - assert_period(:XST1, 3600, 0, false, Time.utc(2000, 3, 1), nil, info) - end - end - - def test_load_offset_both_adjacent_non_dst_equal_utc_total_offset - # The zoneinfo files don't include the offset from standard time, so this - # has to be derived by looking at changes in the total UTC offset. - - offsets = [ - {:gmtoff => 7142, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 7200, :isdst => false, :abbrev => 'XST'}, - {:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'}] - - transitions = [ - {:at => Time.utc(2000, 1, 1), :offset_index => 1}, - {:at => Time.utc(2000, 2, 1), :offset_index => 2}, - {:at => Time.utc(2000, 3, 1), :offset_index => 1}] - - # XDT will just assume an std_offset of +1 hour and calculate the utc_offset - # from utc_total_offset - std_offset. - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/AdjacentEqual', path) - assert_equal('Zone/AdjacentEqual', info.identifier) - - assert_period(:LMT, 7142, 0, false, nil, Time.utc(2000, 1, 1), info) - assert_period(:XST, 7200, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info) - assert_period(:XDT, 3600, 3600, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info) - assert_period(:XST, 7200, 0, false, Time.utc(2000, 3, 1), nil, info) - end - end - - def test_load_offset_utc_offset_preserved_from_next - # The zoneinfo files don't include the offset from standard time, so this - # has to be derived by looking at changes in the total UTC offset. - - offsets = [ - {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 3600, :isdst => false, :abbrev => 'XST1'}, - {:gmtoff => 7200, :isdst => false, :abbrev => 'XST2'}, - {:gmtoff => 10800, :isdst => true, :abbrev => 'XDT1'}, - {:gmtoff => 10800, :isdst => true, :abbrev => 'XDT2'}] - - transitions = [ - {:at => Time.utc(2000, 1, 1), :offset_index => 1}, - {:at => Time.utc(2000, 2, 1), :offset_index => 3}, - {:at => Time.utc(2000, 3, 1), :offset_index => 4}, - {:at => Time.utc(2000, 4, 1), :offset_index => 2}] - - # Both XDT1 and XDT2 should both use the closest utc_offset (7200) (and not - # an equivalent utc_offset of 3600 and std_offset of 7200). - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/UtcOffsetPreserved', path) - assert_equal('Zone/UtcOffsetPreserved', info.identifier) - - assert_period( :LMT, 3542, 0, false, nil, Time.utc(2000, 1, 1), info) - assert_period(:XST1, 3600, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info) - assert_period(:XDT1, 7200, 3600, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info) - assert_period(:XDT2, 7200, 3600, true, Time.utc(2000, 3, 1), Time.utc(2000, 4, 1), info) - assert_period(:XST2, 7200, 0, false, Time.utc(2000, 4, 1), nil, info) - end - end - - def test_load_offset_utc_offset_preserved_from_previous - # The zoneinfo files don't include the offset from standard time, so this - # has to be derived by looking at changes in the total UTC offset. - - offsets = [ - {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 3600, :isdst => false, :abbrev => 'XST1'}, - {:gmtoff => 7200, :isdst => false, :abbrev => 'XST2'}, - {:gmtoff => 10800, :isdst => true, :abbrev => 'XDT1'}, - {:gmtoff => 10800, :isdst => true, :abbrev => 'XDT2'}] - - transitions = [ - {:at => Time.utc(2000, 1, 1), :offset_index => 2}, - {:at => Time.utc(2000, 2, 1), :offset_index => 3}, - {:at => Time.utc(2000, 3, 1), :offset_index => 4}, - {:at => Time.utc(2000, 4, 1), :offset_index => 1}] - - # Both XDT1 and XDT2 should both use the closest utc_offset (7200) (and not - # an equivalent utc_offset of 3600 and std_offset of 7200). - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/UtcOffsetPreserved', path) - assert_equal('Zone/UtcOffsetPreserved', info.identifier) - - assert_period( :LMT, 3542, 0, false, nil, Time.utc(2000, 1, 1), info) - assert_period(:XST2, 7200, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info) - assert_period(:XDT1, 7200, 3600, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info) - assert_period(:XDT2, 7200, 3600, true, Time.utc(2000, 3, 1), Time.utc(2000, 4, 1), info) - assert_period(:XST1, 3600, 0, false, Time.utc(2000, 4, 1), nil, info) - end - end - - def test_read_offset_negative_std_offset_dst - # The zoneinfo files don't include the offset from standard time, so this - # has to be derived by looking at changes in the total UTC offset. - - offsets = [ - {:gmtoff => -100, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'}, - {:gmtoff => 0, :isdst => true, :abbrev => 'XWT'}] - - transitions = [ - {:at => Time.utc(2000, 1, 1), :offset_index => 1}, - {:at => Time.utc(2000, 2, 1), :offset_index => 2}, - {:at => Time.utc(2000, 3, 1), :offset_index => 1}, - {:at => Time.utc(2000, 4, 1), :offset_index => 2}, - {:at => Time.utc(2000, 5, 1), :offset_index => 1}] - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/NegativeStdOffsetDst', path) - assert_equal('Zone/NegativeStdOffsetDst', info.identifier) - - assert_period(:LMT, -100, 0, false, nil, Time.utc(2000, 1, 1), info) - assert_period(:XST, 3600, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info) - assert_period(:XWT, 3600, -3600, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info) - assert_period(:XST, 3600, 0, false, Time.utc(2000, 3, 1), Time.utc(2000, 4, 1), info) - assert_period(:XWT, 3600, -3600, true, Time.utc(2000, 4, 1), Time.utc(2000, 5, 1), info) - assert_period(:XST, 3600, 0, false, Time.utc(2000, 5, 1), nil, info) - end - end - - def test_read_offset_negative_std_offset_dst_initial_dst - # The zoneinfo files don't include the offset from standard time, so this - # has to be derived by looking at changes in the total UTC offset. - - offsets = [ - {:gmtoff => -100, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 0, :isdst => true, :abbrev => 'XWT'}, - {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'}] - - transitions = [ - {:at => Time.utc(2000, 1, 1), :offset_index => 1}, - {:at => Time.utc(2000, 2, 1), :offset_index => 2}, - {:at => Time.utc(2000, 3, 1), :offset_index => 1}, - {:at => Time.utc(2000, 4, 1), :offset_index => 2}, - {:at => Time.utc(2000, 5, 1), :offset_index => 1}] - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/NegativeStdOffsetDstInitialDst', path) - assert_equal('Zone/NegativeStdOffsetDstInitialDst', info.identifier) - - assert_period(:LMT, -100, 0, false, nil, Time.utc(2000, 1, 1), info) - assert_period(:XWT, 3600, -3600, true, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info) - assert_period(:XST, 3600, 0, false, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info) - assert_period(:XWT, 3600, -3600, true, Time.utc(2000, 3, 1), Time.utc(2000, 4, 1), info) - assert_period(:XST, 3600, 0, false, Time.utc(2000, 4, 1), Time.utc(2000, 5, 1), info) - assert_period(:XWT, 3600, -3600, true, Time.utc(2000, 5, 1), nil, info) - end - end - - def test_read_offset_prefer_base_offset_moves_to_dst_not_hour - offsets = [ - {:gmtoff => -100, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 0, :isdst => false, :abbrev => 'XST'}, - {:gmtoff => 1800, :isdst => true, :abbrev => 'XDT'}, - {:gmtoff => 1800, :isdst => false, :abbrev => 'XST'}] - - transitions = [ - {:at => Time.utc(2000, 1, 1), :offset_index => 1}, - {:at => Time.utc(2000, 2, 1), :offset_index => 2}, - {:at => Time.utc(2000, 3, 1), :offset_index => 3}] - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/BaseOffsetMovesToDstNotHour', path) - assert_equal('Zone/BaseOffsetMovesToDstNotHour', info.identifier) - - assert_period(:LMT, -100, 0, false, nil, Time.utc(2000, 1, 1), info) - assert_period(:XST, 0, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info) - assert_period(:XDT, 0, 1800, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info) - assert_period(:XST, 1800, 0, false, Time.utc(2000, 3, 1), nil, info) - end - end - - def test_read_offset_prefer_base_offset_moves_from_dst_not_hour - offsets = [ - {:gmtoff => -100, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 1800, :isdst => false, :abbrev => 'XST'}, - {:gmtoff => 1800, :isdst => true, :abbrev => 'XDT'}, - {:gmtoff => 0, :isdst => false, :abbrev => 'XST'}] - - transitions = [ - {:at => Time.utc(2000, 1, 1), :offset_index => 1}, - {:at => Time.utc(2000, 2, 1), :offset_index => 2}, - {:at => Time.utc(2000, 3, 1), :offset_index => 3}] - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/BaseOffsetMovesFromDstNotHour', path) - assert_equal('Zone/BaseOffsetMovesFromDstNotHour', info.identifier) - - assert_period(:LMT, -100, 0, false, nil, Time.utc(2000, 1, 1), info) - assert_period(:XST, 1800, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info) - assert_period(:XDT, 0, 1800, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info) - assert_period(:XST, 0, 0, false, Time.utc(2000, 3, 1), nil, info) - end - end - - def test_load_in_safe_mode - offsets = [{:gmtoff => -12094, :isdst => false, :abbrev => 'LT'}] - - tzif_test(offsets, []) do |path, format| - # untaint only required for Ruby 1.9.2 - path.untaint - - safe_test do - info = ZoneinfoTimezoneInfo.new('Zone/three', path) - assert_equal('Zone/three', info.identifier) - - assert_period(:LT, -12094, 0, false, nil, nil, info) - end - end - end - - def test_load_encoding - # tzfile.5 doesn't specify an encoding, but the source data is in ASCII. - # ZoneinfoTimezoneInfo will load as UTF-8 (a superset of ASCII). - - offsets = [ - {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 3600, :isdst => false, :abbrev => 'XST©'}] - - transitions = [ - {:at => Time.utc(1971, 1, 2), :offset_index => 1}] - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/One', path) - assert_equal('Zone/One', info.identifier) - - assert_period(:LMT, 3542, 0, false, nil, Time.utc(1971, 1, 2), info) - assert_period(:"XST©", 3600, 0, false, Time.utc(1971, 1, 2), nil, info) - end - end - - def test_load_binmode - offsets = [ - {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'}] - - # Transition time that includes CRLF (4EFF0D0A). - # Test that this doesn't get corrupted by translating CRLF to LF. - transitions = [ - {:at => Time.utc(2011, 12, 31, 13, 24, 26), :offset_index => 1}] - - tzif_test(offsets, transitions) do |path, format| - info = ZoneinfoTimezoneInfo.new('Zone/One', path) - assert_equal('Zone/One', info.identifier) - - assert_period(:LMT, 3542, 0, false, nil, Time.utc(2011, 12, 31, 13, 24, 26), info) - assert_period(:XST, 3600, 0, false, Time.utc(2011, 12, 31, 13, 24, 26), nil, info) - end - end -end diff -Nru ruby-tzinfo-1.2.6/test/test_utils.rb ruby-tzinfo-2.0.4/test/test_utils.rb --- ruby-tzinfo-1.2.6/test/test_utils.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/test_utils.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,188 +0,0 @@ -tests_dir = File.expand_path(File.dirname(__FILE__)) -tests_dir.untaint if RUBY_VERSION < '2.7' -TESTS_DIR = tests_dir -TZINFO_LIB_DIR = File.expand_path(File.join(TESTS_DIR, '..', 'lib')) -TZINFO_TEST_DATA_DIR = File.join(TESTS_DIR, 'tzinfo-data') -TZINFO_TEST_ZONEINFO_DIR = File.join(TESTS_DIR, 'zoneinfo') - -$:.unshift(TZINFO_LIB_DIR) unless $:.include?(TZINFO_LIB_DIR) - -# tzinfo-data contains a cut down copy of tzinfo-data for use in the tests. -# Add it to the load path. -$:.unshift(TZINFO_TEST_DATA_DIR) unless $:.include?(TZINFO_TEST_DATA_DIR) - -require 'minitest/autorun' -require 'tzinfo' -require 'fileutils' -require 'rbconfig' - -module TestUtils - ZONEINFO_SYMLINKS = [ - ['localtime', 'America/New_York'], - ['UTC', 'Etc/UTC']] - - - def self.prepare_test_zoneinfo_dir - ZONEINFO_SYMLINKS.each do |file, target| - path = File.join(TZINFO_TEST_ZONEINFO_DIR, file) - - File.delete(path) if File.exist?(path) - - begin - FileUtils.ln_s(target, path) - rescue NotImplementedError, Errno::EACCES - # Symlinks not supported on this platform, or permission denied - # (administrative rights are required on Windows). Copy instead. - target_path = File.join(TZINFO_TEST_ZONEINFO_DIR, target) - FileUtils.cp(target_path, path) - end - end - end -end - -TestUtils.prepare_test_zoneinfo_dir - - - -module Kernel - # Suppresses any warnings raised in a specified block. - def without_warnings - old_verbose = $VERBOSE - begin - $VERBOSE = nil - yield - ensure - $-v = old_verbose - end - end - - def safe_test(options = {}) - # Ruby >= 2.7, JRuby and Rubinus don't support SAFE levels. - available = RUBY_VERSION < '2.7' && !(defined?(RUBY_ENGINE) && %w(jruby rbx).include?(RUBY_ENGINE)) - - if available || options[:unavailable] != :skip - thread = Thread.new do - orig_diff = Minitest::Assertions.diff - - if available - orig_safe = $SAFE - $SAFE = options[:level] || 1 - end - begin - # Disable the use of external diff tools during safe mode tests (since - # safe mode will prevent their use). The initial value is retrieved - # before activating safe mode because the first time - # Minitest::Assertions.diff is called, it will attempt to find a diff - # tool. Finding the diff tool will also fail in safe mode. - Minitest::Assertions.diff = nil - begin - yield - ensure - Minitest::Assertions.diff = orig_diff - end - ensure - if available - # On Ruby < 2.6, setting $SAFE affects only the current thread - # and the $SAFE level cannot be downgraded. Catch and ignore the - # SecurityError. - # On Ruby >= 2.6, setting $SAFE is global, and the $SAFE level - # can be downgraded. Restore $SAFE back to the original level. - begin - $SAFE = orig_safe - rescue SecurityError - end - end - end - end - - thread.join - end - end - - def skip_if_has_bug_14060 - # On Ruby 2.4.4 in safe mode, require will fail with a SecurityError for - # any file that has not previously been loaded, regardless of whether the - # file name is tainted. - # See https://bugs.ruby-lang.org/issues/14060#note-5. - if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'ruby' && RUBY_VERSION == '2.4.4' - skip('Skipping test due to Ruby 2.4.4 being affected by Bug 14060 (see https://bugs.ruby-lang.org/issues/14060#note-5)') - end - end - - def assert_array_same_items(expected, actual, msg = nil) - full_message = message(msg, '') { diff(expected, actual) } - condition = (expected.size == actual.size) && (expected - actual == []) - assert(condition, full_message) - end - - def assert_sub_process_returns(expected_lines, code, extra_load_path = [], required = ['tzinfo']) - ruby = File.join(RbConfig::CONFIG['bindir'], - RbConfig::CONFIG['ruby_install_name'] + RbConfig::CONFIG['EXEEXT']) - - load_path = [TZINFO_LIB_DIR] + extra_load_path - - # If RubyGems is loaded in the current process, then require it in the - # sub-process, as it may be needed in order to require dependencies. - if defined?(Gem) && Gem.instance_of?(Module) - required = ['rubygems'] + required - end - - if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx' - # Stop Rubinus from operating as irb. - args = ' -' - else - args = '' - end - - IO.popen("\"#{ruby}\"#{args}", 'r+') do |process| - load_path.each do |p| - process.puts("$:.unshift('#{p.gsub("'", "\\\\'")}')") - end - - required.each do |r| - process.puts("require '#{r.gsub("'", "\\\\'")}'") - end - - process.puts(code) - process.flush - process.close_write - - actual_lines = process.readlines - actual_lines = actual_lines.collect {|l| l.chomp} - assert_equal(expected_lines, actual_lines) - end - end - - def assert_nothing_raised(msg = nil) - begin - yield - rescue => e - full_message = message(msg) { exception_details(e, 'Exception raised: ') } - assert(false, full_message) - end - end -end - - -# Object#taint is a deprecated no-op in Ruby 2.7 and outputs a warning. It will -# be removed in 3.0. Silence the warning or supply a replacement. -if TZInfo::RubyCoreSupport.const_defined?(:UntaintExt) - module TaintExt - refine Object do - def taint - self - end - end - end -end - - -# JRuby 1.7.5 to 1.7.9 consider DateTime instances that differ by less than -# 1 millisecond to be equivalent (https://github.com/jruby/jruby/issues/1311). -# -# A few test cases compare at a resolution of 1 microsecond, so this causes -# failures on JRuby 1.7.5 to 1.7.9. -# -# Determine what the platform supports and adjust the tests accordingly. -DATETIME_RESOLUTION = (0..5).collect {|i| 10**i}.find {|i| (DateTime.new(2013,1,1,0,0,0) <=> DateTime.new(2013,1,1,0,0,Rational(i,1000000))) < 0} -raise 'Unable to compare DateTimes at a resolution less than one second on this platform' unless DATETIME_RESOLUTION diff -Nru ruby-tzinfo-1.2.6/test/ts_all.rb ruby-tzinfo-2.0.4/test/ts_all.rb --- ruby-tzinfo-1.2.6/test/ts_all.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/ts_all.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -# Force a particular timezone to be local (helps find issues when local -# timezone isn't GMT). This won't work on Windows. -ENV['TZ'] = 'America/Los_Angeles' - -Dir[File.join(File.expand_path(File.dirname(__FILE__)), 'tc_*.rb')].each {|t| require t} - -puts "Using #{DataSource.get}" diff -Nru ruby-tzinfo-1.2.6/test/ts_all_ruby.rb ruby-tzinfo-2.0.4/test/ts_all_ruby.rb --- ruby-tzinfo-1.2.6/test/ts_all_ruby.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/ts_all_ruby.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils.rb') - -TZInfo::DataSource.set(:ruby) - -require File.join(File.expand_path(File.dirname(__FILE__)), 'ts_all.rb') diff -Nru ruby-tzinfo-1.2.6/test/ts_all_zoneinfo.rb ruby-tzinfo-2.0.4/test/ts_all_zoneinfo.rb --- ruby-tzinfo-1.2.6/test/ts_all_zoneinfo.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/ts_all_zoneinfo.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils.rb') - -# Use a zoneinfo directory containing files needed by the tests. -# The symlinks in this directory are set up in test_utils.rb. -zoneinfo_path = File.join(File.expand_path(File.dirname(__FILE__)), 'zoneinfo') -zoneinfo_path.untaint if RUBY_VERSION < '2.7' -TZInfo::DataSource.set(:zoneinfo, zoneinfo_path) - -require File.join(File.expand_path(File.dirname(__FILE__)), 'ts_all.rb') diff -Nru ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/definitions/America/Argentina/Buenos_Aires.rb ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/definitions/America/Argentina/Buenos_Aires.rb --- ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/definitions/America/Argentina/Buenos_Aires.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/definitions/America/Argentina/Buenos_Aires.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,89 +0,0 @@ -# encoding: UTF-8 - -# This file contains data derived from the IANA Time Zone Database -# (http://www.iana.org/time-zones). - -module TZInfo - module Data - module Definitions - module America - module Argentina - module Buenos_Aires - include TimezoneDefinition - - timezone 'America/Argentina/Buenos_Aires' do |tz| - tz.offset :o0, -14028, 0, :LMT - tz.offset :o1, -15408, 0, :CMT - tz.offset :o2, -14400, 0, :ART - tz.offset :o3, -14400, 3600, :ARST - tz.offset :o4, -10800, 0, :ART - tz.offset :o5, -10800, 3600, :ARST - - tz.transition 1894, 10, :o1, -2372097972, 17374555169, 7200 - tz.transition 1920, 5, :o2, -1567453392, 1453467407, 600 - tz.transition 1930, 12, :o3, -1233432000, 7278935, 3 - tz.transition 1931, 4, :o2, -1222981200, 19411461, 8 - tz.transition 1931, 10, :o3, -1205956800, 7279889, 3 - tz.transition 1932, 3, :o2, -1194037200, 19414141, 8 - tz.transition 1932, 11, :o3, -1172865600, 7281038, 3 - tz.transition 1933, 3, :o2, -1162501200, 19417061, 8 - tz.transition 1933, 11, :o3, -1141329600, 7282133, 3 - tz.transition 1934, 3, :o2, -1130965200, 19419981, 8 - tz.transition 1934, 11, :o3, -1109793600, 7283228, 3 - tz.transition 1935, 3, :o2, -1099429200, 19422901, 8 - tz.transition 1935, 11, :o3, -1078257600, 7284323, 3 - tz.transition 1936, 3, :o2, -1067806800, 19425829, 8 - tz.transition 1936, 11, :o3, -1046635200, 7285421, 3 - tz.transition 1937, 3, :o2, -1036270800, 19428749, 8 - tz.transition 1937, 11, :o3, -1015099200, 7286516, 3 - tz.transition 1938, 3, :o2, -1004734800, 19431669, 8 - tz.transition 1938, 11, :o3, -983563200, 7287611, 3 - tz.transition 1939, 3, :o2, -973198800, 19434589, 8 - tz.transition 1939, 11, :o3, -952027200, 7288706, 3 - tz.transition 1940, 3, :o2, -941576400, 19437517, 8 - tz.transition 1940, 7, :o3, -931032000, 7289435, 3 - tz.transition 1941, 6, :o2, -900882000, 19441285, 8 - tz.transition 1941, 10, :o3, -890337600, 7290848, 3 - tz.transition 1943, 8, :o2, -833749200, 19447501, 8 - tz.transition 1943, 10, :o3, -827265600, 7293038, 3 - tz.transition 1946, 3, :o2, -752274000, 19455045, 8 - tz.transition 1946, 10, :o3, -733780800, 7296284, 3 - tz.transition 1963, 10, :o2, -197326800, 19506429, 8 - tz.transition 1963, 12, :o3, -190843200, 7315136, 3 - tz.transition 1964, 3, :o2, -184194000, 19507645, 8 - tz.transition 1964, 10, :o3, -164491200, 7316051, 3 - tz.transition 1965, 3, :o2, -152658000, 19510565, 8 - tz.transition 1965, 10, :o3, -132955200, 7317146, 3 - tz.transition 1966, 3, :o2, -121122000, 19513485, 8 - tz.transition 1966, 10, :o3, -101419200, 7318241, 3 - tz.transition 1967, 4, :o2, -86821200, 19516661, 8 - tz.transition 1967, 10, :o3, -71092800, 7319294, 3 - tz.transition 1968, 4, :o2, -54766800, 19519629, 8 - tz.transition 1968, 10, :o3, -39038400, 7320407, 3 - tz.transition 1969, 4, :o2, -23317200, 19522541, 8 - tz.transition 1969, 10, :o4, -7588800, 7321499, 3 - tz.transition 1974, 1, :o5, 128142000 - tz.transition 1974, 5, :o4, 136605600 - tz.transition 1988, 12, :o5, 596948400 - tz.transition 1989, 3, :o4, 605066400 - tz.transition 1989, 10, :o5, 624423600 - tz.transition 1990, 3, :o4, 636516000 - tz.transition 1990, 10, :o5, 656478000 - tz.transition 1991, 3, :o4, 667965600 - tz.transition 1991, 10, :o5, 687927600 - tz.transition 1992, 3, :o4, 699415200 - tz.transition 1992, 10, :o5, 719377200 - tz.transition 1993, 3, :o4, 731469600 - tz.transition 1999, 10, :o3, 938919600 - tz.transition 2000, 3, :o4, 952052400 - tz.transition 2007, 12, :o5, 1198983600 - tz.transition 2008, 3, :o4, 1205632800 - tz.transition 2008, 10, :o5, 1224385200 - tz.transition 2009, 3, :o4, 1237082400 - end - end - end - end - end - end -end diff -Nru ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/definitions/America/New_York.rb ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/definitions/America/New_York.rb --- ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/definitions/America/New_York.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/definitions/America/New_York.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,315 +0,0 @@ -# encoding: UTF-8 - -# This file contains data derived from the IANA Time Zone Database -# (http://www.iana.org/time-zones). - -module TZInfo - module Data - module Definitions - module America - module New_York - include TimezoneDefinition - - timezone 'America/New_York' do |tz| - tz.offset :o0, -17762, 0, :LMT - tz.offset :o1, -18000, 0, :EST - tz.offset :o2, -18000, 3600, :EDT - tz.offset :o3, -18000, 3600, :EWT - tz.offset :o4, -18000, 3600, :EPT - - tz.transition 1883, 11, :o1, -2717650800, 57819197, 24 - tz.transition 1918, 3, :o2, -1633280400, 58120411, 24 - tz.transition 1918, 10, :o1, -1615140000, 9687575, 4 - tz.transition 1919, 3, :o2, -1601830800, 58129147, 24 - tz.transition 1919, 10, :o1, -1583690400, 9689031, 4 - tz.transition 1920, 3, :o2, -1570381200, 58137883, 24 - tz.transition 1920, 10, :o1, -1551636000, 9690515, 4 - tz.transition 1921, 4, :o2, -1536512400, 58147291, 24 - tz.transition 1921, 9, :o1, -1523210400, 9691831, 4 - tz.transition 1922, 4, :o2, -1504458000, 58156195, 24 - tz.transition 1922, 9, :o1, -1491760800, 9693287, 4 - tz.transition 1923, 4, :o2, -1473008400, 58164931, 24 - tz.transition 1923, 9, :o1, -1459706400, 9694771, 4 - tz.transition 1924, 4, :o2, -1441558800, 58173667, 24 - tz.transition 1924, 9, :o1, -1428256800, 9696227, 4 - tz.transition 1925, 4, :o2, -1410109200, 58182403, 24 - tz.transition 1925, 9, :o1, -1396807200, 9697683, 4 - tz.transition 1926, 4, :o2, -1378659600, 58191139, 24 - tz.transition 1926, 9, :o1, -1365357600, 9699139, 4 - tz.transition 1927, 4, :o2, -1347210000, 58199875, 24 - tz.transition 1927, 9, :o1, -1333908000, 9700595, 4 - tz.transition 1928, 4, :o2, -1315155600, 58208779, 24 - tz.transition 1928, 9, :o1, -1301853600, 9702079, 4 - tz.transition 1929, 4, :o2, -1283706000, 58217515, 24 - tz.transition 1929, 9, :o1, -1270404000, 9703535, 4 - tz.transition 1930, 4, :o2, -1252256400, 58226251, 24 - tz.transition 1930, 9, :o1, -1238954400, 9704991, 4 - tz.transition 1931, 4, :o2, -1220806800, 58234987, 24 - tz.transition 1931, 9, :o1, -1207504800, 9706447, 4 - tz.transition 1932, 4, :o2, -1189357200, 58243723, 24 - tz.transition 1932, 9, :o1, -1176055200, 9707903, 4 - tz.transition 1933, 4, :o2, -1157302800, 58252627, 24 - tz.transition 1933, 9, :o1, -1144605600, 9709359, 4 - tz.transition 1934, 4, :o2, -1125853200, 58261363, 24 - tz.transition 1934, 9, :o1, -1112551200, 9710843, 4 - tz.transition 1935, 4, :o2, -1094403600, 58270099, 24 - tz.transition 1935, 9, :o1, -1081101600, 9712299, 4 - tz.transition 1936, 4, :o2, -1062954000, 58278835, 24 - tz.transition 1936, 9, :o1, -1049652000, 9713755, 4 - tz.transition 1937, 4, :o2, -1031504400, 58287571, 24 - tz.transition 1937, 9, :o1, -1018202400, 9715211, 4 - tz.transition 1938, 4, :o2, -1000054800, 58296307, 24 - tz.transition 1938, 9, :o1, -986752800, 9716667, 4 - tz.transition 1939, 4, :o2, -968000400, 58305211, 24 - tz.transition 1939, 9, :o1, -955303200, 9718123, 4 - tz.transition 1940, 4, :o2, -936550800, 58313947, 24 - tz.transition 1940, 9, :o1, -923248800, 9719607, 4 - tz.transition 1941, 4, :o2, -905101200, 58322683, 24 - tz.transition 1941, 9, :o1, -891799200, 9721063, 4 - tz.transition 1942, 2, :o3, -880218000, 58329595, 24 - tz.transition 1945, 8, :o4, -769395600, 58360379, 24 - tz.transition 1945, 9, :o1, -765396000, 9726915, 4 - tz.transition 1946, 4, :o2, -747248400, 58366531, 24 - tz.transition 1946, 9, :o1, -733946400, 9728371, 4 - tz.transition 1947, 4, :o2, -715798800, 58375267, 24 - tz.transition 1947, 9, :o1, -702496800, 9729827, 4 - tz.transition 1948, 4, :o2, -684349200, 58384003, 24 - tz.transition 1948, 9, :o1, -671047200, 9731283, 4 - tz.transition 1949, 4, :o2, -652899600, 58392739, 24 - tz.transition 1949, 9, :o1, -639597600, 9732739, 4 - tz.transition 1950, 4, :o2, -620845200, 58401643, 24 - tz.transition 1950, 9, :o1, -608148000, 9734195, 4 - tz.transition 1951, 4, :o2, -589395600, 58410379, 24 - tz.transition 1951, 9, :o1, -576093600, 9735679, 4 - tz.transition 1952, 4, :o2, -557946000, 58419115, 24 - tz.transition 1952, 9, :o1, -544644000, 9737135, 4 - tz.transition 1953, 4, :o2, -526496400, 58427851, 24 - tz.transition 1953, 9, :o1, -513194400, 9738591, 4 - tz.transition 1954, 4, :o2, -495046800, 58436587, 24 - tz.transition 1954, 9, :o1, -481744800, 9740047, 4 - tz.transition 1955, 4, :o2, -463597200, 58445323, 24 - tz.transition 1955, 10, :o1, -447271200, 9741643, 4 - tz.transition 1956, 4, :o2, -431542800, 58454227, 24 - tz.transition 1956, 10, :o1, -415821600, 9743099, 4 - tz.transition 1957, 4, :o2, -400093200, 58462963, 24 - tz.transition 1957, 10, :o1, -384372000, 9744555, 4 - tz.transition 1958, 4, :o2, -368643600, 58471699, 24 - tz.transition 1958, 10, :o1, -352922400, 9746011, 4 - tz.transition 1959, 4, :o2, -337194000, 58480435, 24 - tz.transition 1959, 10, :o1, -321472800, 9747467, 4 - tz.transition 1960, 4, :o2, -305744400, 58489171, 24 - tz.transition 1960, 10, :o1, -289418400, 9748951, 4 - tz.transition 1961, 4, :o2, -273690000, 58498075, 24 - tz.transition 1961, 10, :o1, -257968800, 9750407, 4 - tz.transition 1962, 4, :o2, -242240400, 58506811, 24 - tz.transition 1962, 10, :o1, -226519200, 9751863, 4 - tz.transition 1963, 4, :o2, -210790800, 58515547, 24 - tz.transition 1963, 10, :o1, -195069600, 9753319, 4 - tz.transition 1964, 4, :o2, -179341200, 58524283, 24 - tz.transition 1964, 10, :o1, -163620000, 9754775, 4 - tz.transition 1965, 4, :o2, -147891600, 58533019, 24 - tz.transition 1965, 10, :o1, -131565600, 9756259, 4 - tz.transition 1966, 4, :o2, -116442000, 58541755, 24 - tz.transition 1966, 10, :o1, -100116000, 9757715, 4 - tz.transition 1967, 4, :o2, -84387600, 58550659, 24 - tz.transition 1967, 10, :o1, -68666400, 9759171, 4 - tz.transition 1968, 4, :o2, -52938000, 58559395, 24 - tz.transition 1968, 10, :o1, -37216800, 9760627, 4 - tz.transition 1969, 4, :o2, -21488400, 58568131, 24 - tz.transition 1969, 10, :o1, -5767200, 9762083, 4 - tz.transition 1970, 4, :o2, 9961200 - tz.transition 1970, 10, :o1, 25682400 - tz.transition 1971, 4, :o2, 41410800 - tz.transition 1971, 10, :o1, 57736800 - tz.transition 1972, 4, :o2, 73465200 - tz.transition 1972, 10, :o1, 89186400 - tz.transition 1973, 4, :o2, 104914800 - tz.transition 1973, 10, :o1, 120636000 - tz.transition 1974, 1, :o2, 126687600 - tz.transition 1974, 10, :o1, 152085600 - tz.transition 1975, 2, :o2, 162370800 - tz.transition 1975, 10, :o1, 183535200 - tz.transition 1976, 4, :o2, 199263600 - tz.transition 1976, 10, :o1, 215589600 - tz.transition 1977, 4, :o2, 230713200 - tz.transition 1977, 10, :o1, 247039200 - tz.transition 1978, 4, :o2, 262767600 - tz.transition 1978, 10, :o1, 278488800 - tz.transition 1979, 4, :o2, 294217200 - tz.transition 1979, 10, :o1, 309938400 - tz.transition 1980, 4, :o2, 325666800 - tz.transition 1980, 10, :o1, 341388000 - tz.transition 1981, 4, :o2, 357116400 - tz.transition 1981, 10, :o1, 372837600 - tz.transition 1982, 4, :o2, 388566000 - tz.transition 1982, 10, :o1, 404892000 - tz.transition 1983, 4, :o2, 420015600 - tz.transition 1983, 10, :o1, 436341600 - tz.transition 1984, 4, :o2, 452070000 - tz.transition 1984, 10, :o1, 467791200 - tz.transition 1985, 4, :o2, 483519600 - tz.transition 1985, 10, :o1, 499240800 - tz.transition 1986, 4, :o2, 514969200 - tz.transition 1986, 10, :o1, 530690400 - tz.transition 1987, 4, :o2, 544604400 - tz.transition 1987, 10, :o1, 562140000 - tz.transition 1988, 4, :o2, 576054000 - tz.transition 1988, 10, :o1, 594194400 - tz.transition 1989, 4, :o2, 607503600 - tz.transition 1989, 10, :o1, 625644000 - tz.transition 1990, 4, :o2, 638953200 - tz.transition 1990, 10, :o1, 657093600 - tz.transition 1991, 4, :o2, 671007600 - tz.transition 1991, 10, :o1, 688543200 - tz.transition 1992, 4, :o2, 702457200 - tz.transition 1992, 10, :o1, 719992800 - tz.transition 1993, 4, :o2, 733906800 - tz.transition 1993, 10, :o1, 752047200 - tz.transition 1994, 4, :o2, 765356400 - tz.transition 1994, 10, :o1, 783496800 - tz.transition 1995, 4, :o2, 796806000 - tz.transition 1995, 10, :o1, 814946400 - tz.transition 1996, 4, :o2, 828860400 - tz.transition 1996, 10, :o1, 846396000 - tz.transition 1997, 4, :o2, 860310000 - tz.transition 1997, 10, :o1, 877845600 - tz.transition 1998, 4, :o2, 891759600 - tz.transition 1998, 10, :o1, 909295200 - tz.transition 1999, 4, :o2, 923209200 - tz.transition 1999, 10, :o1, 941349600 - tz.transition 2000, 4, :o2, 954658800 - tz.transition 2000, 10, :o1, 972799200 - tz.transition 2001, 4, :o2, 986108400 - tz.transition 2001, 10, :o1, 1004248800 - tz.transition 2002, 4, :o2, 1018162800 - tz.transition 2002, 10, :o1, 1035698400 - tz.transition 2003, 4, :o2, 1049612400 - tz.transition 2003, 10, :o1, 1067148000 - tz.transition 2004, 4, :o2, 1081062000 - tz.transition 2004, 10, :o1, 1099202400 - tz.transition 2005, 4, :o2, 1112511600 - tz.transition 2005, 10, :o1, 1130652000 - tz.transition 2006, 4, :o2, 1143961200 - tz.transition 2006, 10, :o1, 1162101600 - tz.transition 2007, 3, :o2, 1173596400 - tz.transition 2007, 11, :o1, 1194156000 - tz.transition 2008, 3, :o2, 1205046000 - tz.transition 2008, 11, :o1, 1225605600 - tz.transition 2009, 3, :o2, 1236495600 - tz.transition 2009, 11, :o1, 1257055200 - tz.transition 2010, 3, :o2, 1268550000 - tz.transition 2010, 11, :o1, 1289109600 - tz.transition 2011, 3, :o2, 1299999600 - tz.transition 2011, 11, :o1, 1320559200 - tz.transition 2012, 3, :o2, 1331449200 - tz.transition 2012, 11, :o1, 1352008800 - tz.transition 2013, 3, :o2, 1362898800 - tz.transition 2013, 11, :o1, 1383458400 - tz.transition 2014, 3, :o2, 1394348400 - tz.transition 2014, 11, :o1, 1414908000 - tz.transition 2015, 3, :o2, 1425798000 - tz.transition 2015, 11, :o1, 1446357600 - tz.transition 2016, 3, :o2, 1457852400 - tz.transition 2016, 11, :o1, 1478412000 - tz.transition 2017, 3, :o2, 1489302000 - tz.transition 2017, 11, :o1, 1509861600 - tz.transition 2018, 3, :o2, 1520751600 - tz.transition 2018, 11, :o1, 1541311200 - tz.transition 2019, 3, :o2, 1552201200 - tz.transition 2019, 11, :o1, 1572760800 - tz.transition 2020, 3, :o2, 1583650800 - tz.transition 2020, 11, :o1, 1604210400 - tz.transition 2021, 3, :o2, 1615705200 - tz.transition 2021, 11, :o1, 1636264800 - tz.transition 2022, 3, :o2, 1647154800 - tz.transition 2022, 11, :o1, 1667714400 - tz.transition 2023, 3, :o2, 1678604400 - tz.transition 2023, 11, :o1, 1699164000 - tz.transition 2024, 3, :o2, 1710054000 - tz.transition 2024, 11, :o1, 1730613600 - tz.transition 2025, 3, :o2, 1741503600 - tz.transition 2025, 11, :o1, 1762063200 - tz.transition 2026, 3, :o2, 1772953200 - tz.transition 2026, 11, :o1, 1793512800 - tz.transition 2027, 3, :o2, 1805007600 - tz.transition 2027, 11, :o1, 1825567200 - tz.transition 2028, 3, :o2, 1836457200 - tz.transition 2028, 11, :o1, 1857016800 - tz.transition 2029, 3, :o2, 1867906800 - tz.transition 2029, 11, :o1, 1888466400 - tz.transition 2030, 3, :o2, 1899356400 - tz.transition 2030, 11, :o1, 1919916000 - tz.transition 2031, 3, :o2, 1930806000 - tz.transition 2031, 11, :o1, 1951365600 - tz.transition 2032, 3, :o2, 1962860400 - tz.transition 2032, 11, :o1, 1983420000 - tz.transition 2033, 3, :o2, 1994310000 - tz.transition 2033, 11, :o1, 2014869600 - tz.transition 2034, 3, :o2, 2025759600 - tz.transition 2034, 11, :o1, 2046319200 - tz.transition 2035, 3, :o2, 2057209200 - tz.transition 2035, 11, :o1, 2077768800 - tz.transition 2036, 3, :o2, 2088658800 - tz.transition 2036, 11, :o1, 2109218400 - tz.transition 2037, 3, :o2, 2120108400 - tz.transition 2037, 11, :o1, 2140668000 - tz.transition 2038, 3, :o2, 2152162800, 59171923, 24 - tz.transition 2038, 11, :o1, 2172722400, 9862939, 4 - tz.transition 2039, 3, :o2, 2183612400, 59180659, 24 - tz.transition 2039, 11, :o1, 2204172000, 9864395, 4 - tz.transition 2040, 3, :o2, 2215062000, 59189395, 24 - tz.transition 2040, 11, :o1, 2235621600, 9865851, 4 - tz.transition 2041, 3, :o2, 2246511600, 59198131, 24 - tz.transition 2041, 11, :o1, 2267071200, 9867307, 4 - tz.transition 2042, 3, :o2, 2277961200, 59206867, 24 - tz.transition 2042, 11, :o1, 2298520800, 9868763, 4 - tz.transition 2043, 3, :o2, 2309410800, 59215603, 24 - tz.transition 2043, 11, :o1, 2329970400, 9870219, 4 - tz.transition 2044, 3, :o2, 2341465200, 59224507, 24 - tz.transition 2044, 11, :o1, 2362024800, 9871703, 4 - tz.transition 2045, 3, :o2, 2372914800, 59233243, 24 - tz.transition 2045, 11, :o1, 2393474400, 9873159, 4 - tz.transition 2046, 3, :o2, 2404364400, 59241979, 24 - tz.transition 2046, 11, :o1, 2424924000, 9874615, 4 - tz.transition 2047, 3, :o2, 2435814000, 59250715, 24 - tz.transition 2047, 11, :o1, 2456373600, 9876071, 4 - tz.transition 2048, 3, :o2, 2467263600, 59259451, 24 - tz.transition 2048, 11, :o1, 2487823200, 9877527, 4 - tz.transition 2049, 3, :o2, 2499318000, 59268355, 24 - tz.transition 2049, 11, :o1, 2519877600, 9879011, 4 - tz.transition 2050, 3, :o2, 2530767600, 59277091, 24 - tz.transition 2050, 11, :o1, 2551327200, 9880467, 4 - tz.transition 2051, 3, :o2, 2562217200, 59285827, 24 - tz.transition 2051, 11, :o1, 2582776800, 9881923, 4 - tz.transition 2052, 3, :o2, 2593666800, 59294563, 24 - tz.transition 2052, 11, :o1, 2614226400, 9883379, 4 - tz.transition 2053, 3, :o2, 2625116400, 59303299, 24 - tz.transition 2053, 11, :o1, 2645676000, 9884835, 4 - tz.transition 2054, 3, :o2, 2656566000, 59312035, 24 - tz.transition 2054, 11, :o1, 2677125600, 9886291, 4 - tz.transition 2055, 3, :o2, 2688620400, 59320939, 24 - tz.transition 2055, 11, :o1, 2709180000, 9887775, 4 - tz.transition 2056, 3, :o2, 2720070000, 59329675, 24 - tz.transition 2056, 11, :o1, 2740629600, 9889231, 4 - tz.transition 2057, 3, :o2, 2751519600, 59338411, 24 - tz.transition 2057, 11, :o1, 2772079200, 9890687, 4 - tz.transition 2058, 3, :o2, 2782969200, 59347147, 24 - tz.transition 2058, 11, :o1, 2803528800, 9892143, 4 - tz.transition 2059, 3, :o2, 2814418800, 59355883, 24 - tz.transition 2059, 11, :o1, 2834978400, 9893599, 4 - tz.transition 2060, 3, :o2, 2846473200, 59364787, 24 - tz.transition 2060, 11, :o1, 2867032800, 9895083, 4 - tz.transition 2061, 3, :o2, 2877922800, 59373523, 24 - tz.transition 2061, 11, :o1, 2898482400, 9896539, 4 - tz.transition 2062, 3, :o2, 2909372400, 59382259, 24 - tz.transition 2062, 11, :o1, 2929932000, 9897995, 4 - tz.transition 2063, 3, :o2, 2940822000, 59390995, 24 - tz.transition 2063, 11, :o1, 2961381600, 9899451, 4 - tz.transition 2064, 3, :o2, 2972271600, 59399731, 24 - tz.transition 2064, 11, :o1, 2992831200, 9900907, 4 - end - end - end - end - end -end diff -Nru ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/definitions/Australia/Melbourne.rb ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/definitions/Australia/Melbourne.rb --- ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/definitions/Australia/Melbourne.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/definitions/Australia/Melbourne.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,218 +0,0 @@ -# encoding: UTF-8 - -# This file contains data derived from the IANA Time Zone Database -# (http://www.iana.org/time-zones). - -module TZInfo - module Data - module Definitions - module Australia - module Melbourne - include TimezoneDefinition - - timezone 'Australia/Melbourne' do |tz| - tz.offset :o0, 34792, 0, :LMT - tz.offset :o1, 36000, 0, :AEST - tz.offset :o2, 36000, 3600, :AEDT - - tz.transition 1895, 1, :o1, -2364111592, 26062831051, 10800 - tz.transition 1916, 12, :o2, -1672567140, 3486569881, 1440 - tz.transition 1917, 3, :o1, -1665392400, 19370497, 8 - tz.transition 1941, 12, :o2, -883641600, 14582161, 6 - tz.transition 1942, 3, :o1, -876128400, 19443577, 8 - tz.transition 1942, 9, :o2, -860400000, 14583775, 6 - tz.transition 1943, 3, :o1, -844678800, 19446489, 8 - tz.transition 1943, 10, :o2, -828345600, 14586001, 6 - tz.transition 1944, 3, :o1, -813229200, 19449401, 8 - tz.transition 1971, 10, :o2, 57686400 - tz.transition 1972, 2, :o1, 67968000 - tz.transition 1972, 10, :o2, 89136000 - tz.transition 1973, 3, :o1, 100022400 - tz.transition 1973, 10, :o2, 120585600 - tz.transition 1974, 3, :o1, 131472000 - tz.transition 1974, 10, :o2, 152035200 - tz.transition 1975, 3, :o1, 162921600 - tz.transition 1975, 10, :o2, 183484800 - tz.transition 1976, 3, :o1, 194976000 - tz.transition 1976, 10, :o2, 215539200 - tz.transition 1977, 3, :o1, 226425600 - tz.transition 1977, 10, :o2, 246988800 - tz.transition 1978, 3, :o1, 257875200 - tz.transition 1978, 10, :o2, 278438400 - tz.transition 1979, 3, :o1, 289324800 - tz.transition 1979, 10, :o2, 309888000 - tz.transition 1980, 3, :o1, 320774400 - tz.transition 1980, 10, :o2, 341337600 - tz.transition 1981, 2, :o1, 352224000 - tz.transition 1981, 10, :o2, 372787200 - tz.transition 1982, 3, :o1, 384278400 - tz.transition 1982, 10, :o2, 404841600 - tz.transition 1983, 3, :o1, 415728000 - tz.transition 1983, 10, :o2, 436291200 - tz.transition 1984, 3, :o1, 447177600 - tz.transition 1984, 10, :o2, 467740800 - tz.transition 1985, 3, :o1, 478627200 - tz.transition 1985, 10, :o2, 499190400 - tz.transition 1986, 3, :o1, 511286400 - tz.transition 1986, 10, :o2, 530035200 - tz.transition 1987, 3, :o1, 542736000 - tz.transition 1987, 10, :o2, 561484800 - tz.transition 1988, 3, :o1, 574790400 - tz.transition 1988, 10, :o2, 594144000 - tz.transition 1989, 3, :o1, 606240000 - tz.transition 1989, 10, :o2, 625593600 - tz.transition 1990, 3, :o1, 637689600 - tz.transition 1990, 10, :o2, 657043200 - tz.transition 1991, 3, :o1, 667929600 - tz.transition 1991, 10, :o2, 688492800 - tz.transition 1992, 2, :o1, 699379200 - tz.transition 1992, 10, :o2, 719942400 - tz.transition 1993, 3, :o1, 731433600 - tz.transition 1993, 10, :o2, 751996800 - tz.transition 1994, 3, :o1, 762883200 - tz.transition 1994, 10, :o2, 783446400 - tz.transition 1995, 3, :o1, 796147200 - tz.transition 1995, 10, :o2, 814896000 - tz.transition 1996, 3, :o1, 828201600 - tz.transition 1996, 10, :o2, 846345600 - tz.transition 1997, 3, :o1, 859651200 - tz.transition 1997, 10, :o2, 877795200 - tz.transition 1998, 3, :o1, 891100800 - tz.transition 1998, 10, :o2, 909244800 - tz.transition 1999, 3, :o1, 922550400 - tz.transition 1999, 10, :o2, 941299200 - tz.transition 2000, 3, :o1, 954000000 - tz.transition 2000, 8, :o2, 967305600 - tz.transition 2001, 3, :o1, 985449600 - tz.transition 2001, 10, :o2, 1004198400 - tz.transition 2002, 3, :o1, 1017504000 - tz.transition 2002, 10, :o2, 1035648000 - tz.transition 2003, 3, :o1, 1048953600 - tz.transition 2003, 10, :o2, 1067097600 - tz.transition 2004, 3, :o1, 1080403200 - tz.transition 2004, 10, :o2, 1099152000 - tz.transition 2005, 3, :o1, 1111852800 - tz.transition 2005, 10, :o2, 1130601600 - tz.transition 2006, 4, :o1, 1143907200 - tz.transition 2006, 10, :o2, 1162051200 - tz.transition 2007, 3, :o1, 1174752000 - tz.transition 2007, 10, :o2, 1193500800 - tz.transition 2008, 4, :o1, 1207411200 - tz.transition 2008, 10, :o2, 1223136000 - tz.transition 2009, 4, :o1, 1238860800 - tz.transition 2009, 10, :o2, 1254585600 - tz.transition 2010, 4, :o1, 1270310400 - tz.transition 2010, 10, :o2, 1286035200 - tz.transition 2011, 4, :o1, 1301760000 - tz.transition 2011, 10, :o2, 1317484800 - tz.transition 2012, 3, :o1, 1333209600 - tz.transition 2012, 10, :o2, 1349539200 - tz.transition 2013, 4, :o1, 1365264000 - tz.transition 2013, 10, :o2, 1380988800 - tz.transition 2014, 4, :o1, 1396713600 - tz.transition 2014, 10, :o2, 1412438400 - tz.transition 2015, 4, :o1, 1428163200 - tz.transition 2015, 10, :o2, 1443888000 - tz.transition 2016, 4, :o1, 1459612800 - tz.transition 2016, 10, :o2, 1475337600 - tz.transition 2017, 4, :o1, 1491062400 - tz.transition 2017, 9, :o2, 1506787200 - tz.transition 2018, 3, :o1, 1522512000 - tz.transition 2018, 10, :o2, 1538841600 - tz.transition 2019, 4, :o1, 1554566400 - tz.transition 2019, 10, :o2, 1570291200 - tz.transition 2020, 4, :o1, 1586016000 - tz.transition 2020, 10, :o2, 1601740800 - tz.transition 2021, 4, :o1, 1617465600 - tz.transition 2021, 10, :o2, 1633190400 - tz.transition 2022, 4, :o1, 1648915200 - tz.transition 2022, 10, :o2, 1664640000 - tz.transition 2023, 4, :o1, 1680364800 - tz.transition 2023, 9, :o2, 1696089600 - tz.transition 2024, 4, :o1, 1712419200 - tz.transition 2024, 10, :o2, 1728144000 - tz.transition 2025, 4, :o1, 1743868800 - tz.transition 2025, 10, :o2, 1759593600 - tz.transition 2026, 4, :o1, 1775318400 - tz.transition 2026, 10, :o2, 1791043200 - tz.transition 2027, 4, :o1, 1806768000 - tz.transition 2027, 10, :o2, 1822492800 - tz.transition 2028, 4, :o1, 1838217600 - tz.transition 2028, 9, :o2, 1853942400 - tz.transition 2029, 3, :o1, 1869667200 - tz.transition 2029, 10, :o2, 1885996800 - tz.transition 2030, 4, :o1, 1901721600 - tz.transition 2030, 10, :o2, 1917446400 - tz.transition 2031, 4, :o1, 1933171200 - tz.transition 2031, 10, :o2, 1948896000 - tz.transition 2032, 4, :o1, 1964620800 - tz.transition 2032, 10, :o2, 1980345600 - tz.transition 2033, 4, :o1, 1996070400 - tz.transition 2033, 10, :o2, 2011795200 - tz.transition 2034, 4, :o1, 2027520000 - tz.transition 2034, 9, :o2, 2043244800 - tz.transition 2035, 3, :o1, 2058969600 - tz.transition 2035, 10, :o2, 2075299200 - tz.transition 2036, 4, :o1, 2091024000 - tz.transition 2036, 10, :o2, 2106748800 - tz.transition 2037, 4, :o1, 2122473600 - tz.transition 2037, 10, :o2, 2138198400 - tz.transition 2038, 4, :o1, 2153923200, 14793103, 6 - tz.transition 2038, 10, :o2, 2169648000, 14794195, 6 - tz.transition 2039, 4, :o1, 2185372800, 14795287, 6 - tz.transition 2039, 10, :o2, 2201097600, 14796379, 6 - tz.transition 2040, 3, :o1, 2216822400, 14797471, 6 - tz.transition 2040, 10, :o2, 2233152000, 14798605, 6 - tz.transition 2041, 4, :o1, 2248876800, 14799697, 6 - tz.transition 2041, 10, :o2, 2264601600, 14800789, 6 - tz.transition 2042, 4, :o1, 2280326400, 14801881, 6 - tz.transition 2042, 10, :o2, 2296051200, 14802973, 6 - tz.transition 2043, 4, :o1, 2311776000, 14804065, 6 - tz.transition 2043, 10, :o2, 2327500800, 14805157, 6 - tz.transition 2044, 4, :o1, 2343225600, 14806249, 6 - tz.transition 2044, 10, :o2, 2358950400, 14807341, 6 - tz.transition 2045, 4, :o1, 2374675200, 14808433, 6 - tz.transition 2045, 9, :o2, 2390400000, 14809525, 6 - tz.transition 2046, 3, :o1, 2406124800, 14810617, 6 - tz.transition 2046, 10, :o2, 2422454400, 14811751, 6 - tz.transition 2047, 4, :o1, 2438179200, 14812843, 6 - tz.transition 2047, 10, :o2, 2453904000, 14813935, 6 - tz.transition 2048, 4, :o1, 2469628800, 14815027, 6 - tz.transition 2048, 10, :o2, 2485353600, 14816119, 6 - tz.transition 2049, 4, :o1, 2501078400, 14817211, 6 - tz.transition 2049, 10, :o2, 2516803200, 14818303, 6 - tz.transition 2050, 4, :o1, 2532528000, 14819395, 6 - tz.transition 2050, 10, :o2, 2548252800, 14820487, 6 - tz.transition 2051, 4, :o1, 2563977600, 14821579, 6 - tz.transition 2051, 9, :o2, 2579702400, 14822671, 6 - tz.transition 2052, 4, :o1, 2596032000, 14823805, 6 - tz.transition 2052, 10, :o2, 2611756800, 14824897, 6 - tz.transition 2053, 4, :o1, 2627481600, 14825989, 6 - tz.transition 2053, 10, :o2, 2643206400, 14827081, 6 - tz.transition 2054, 4, :o1, 2658931200, 14828173, 6 - tz.transition 2054, 10, :o2, 2674656000, 14829265, 6 - tz.transition 2055, 4, :o1, 2690380800, 14830357, 6 - tz.transition 2055, 10, :o2, 2706105600, 14831449, 6 - tz.transition 2056, 4, :o1, 2721830400, 14832541, 6 - tz.transition 2056, 9, :o2, 2737555200, 14833633, 6 - tz.transition 2057, 3, :o1, 2753280000, 14834725, 6 - tz.transition 2057, 10, :o2, 2769609600, 14835859, 6 - tz.transition 2058, 4, :o1, 2785334400, 14836951, 6 - tz.transition 2058, 10, :o2, 2801059200, 14838043, 6 - tz.transition 2059, 4, :o1, 2816784000, 14839135, 6 - tz.transition 2059, 10, :o2, 2832508800, 14840227, 6 - tz.transition 2060, 4, :o1, 2848233600, 14841319, 6 - tz.transition 2060, 10, :o2, 2863958400, 14842411, 6 - tz.transition 2061, 4, :o1, 2879683200, 14843503, 6 - tz.transition 2061, 10, :o2, 2895408000, 14844595, 6 - tz.transition 2062, 4, :o1, 2911132800, 14845687, 6 - tz.transition 2062, 9, :o2, 2926857600, 14846779, 6 - tz.transition 2063, 3, :o1, 2942582400, 14847871, 6 - tz.transition 2063, 10, :o2, 2958912000, 14849005, 6 - tz.transition 2064, 4, :o1, 2974636800, 14850097, 6 - end - end - end - end - end -end diff -Nru ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/definitions/EST.rb ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/definitions/EST.rb --- ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/definitions/EST.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/definitions/EST.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -# encoding: UTF-8 - -# This file contains data derived from the IANA Time Zone Database -# (http://www.iana.org/time-zones). - -module TZInfo - module Data - module Definitions - module EST - include TimezoneDefinition - - timezone 'EST' do |tz| - tz.offset :o0, -18000, 0, :EST - - end - end - end - end -end diff -Nru ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/definitions/Etc/GMT__m__1.rb ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/definitions/Etc/GMT__m__1.rb --- ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/definitions/Etc/GMT__m__1.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/definitions/Etc/GMT__m__1.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -# encoding: UTF-8 - -# This file contains data derived from the IANA Time Zone Database -# (http://www.iana.org/time-zones). - -module TZInfo - module Data - module Definitions - module Etc - module GMT__m__1 - include TimezoneDefinition - - timezone 'Etc/GMT-1' do |tz| - tz.offset :o0, 3600, 0, :'GMT-1' - - end - end - end - end - end -end diff -Nru ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/definitions/Etc/GMT__p__1.rb ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/definitions/Etc/GMT__p__1.rb --- ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/definitions/Etc/GMT__p__1.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/definitions/Etc/GMT__p__1.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -# encoding: UTF-8 - -# This file contains data derived from the IANA Time Zone Database -# (http://www.iana.org/time-zones). - -module TZInfo - module Data - module Definitions - module Etc - module GMT__p__1 - include TimezoneDefinition - - timezone 'Etc/GMT+1' do |tz| - tz.offset :o0, -3600, 0, :'GMT+1' - - end - end - end - end - end -end diff -Nru ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/definitions/Etc/UTC.rb ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/definitions/Etc/UTC.rb --- ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/definitions/Etc/UTC.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/definitions/Etc/UTC.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -# encoding: UTF-8 - -# This file contains data derived from the IANA Time Zone Database -# (http://www.iana.org/time-zones). - -module TZInfo - module Data - module Definitions - module Etc - module UTC - include TimezoneDefinition - - timezone 'Etc/UTC' do |tz| - tz.offset :o0, 0, 0, :UTC - - end - end - end - end - end -end diff -Nru ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/definitions/Europe/Amsterdam.rb ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/definitions/Europe/Amsterdam.rb --- ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/definitions/Europe/Amsterdam.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/definitions/Europe/Amsterdam.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,261 +0,0 @@ -# encoding: UTF-8 - -# This file contains data derived from the IANA Time Zone Database -# (http://www.iana.org/time-zones). - -module TZInfo - module Data - module Definitions - module Europe - module Amsterdam - include TimezoneDefinition - - timezone 'Europe/Amsterdam' do |tz| - tz.offset :o0, 1172, 0, :LMT - tz.offset :o1, 1172, 0, :AMT - tz.offset :o2, 1172, 3600, :NST - tz.offset :o3, 1200, 3600, :NEST - tz.offset :o4, 1200, 0, :NET - tz.offset :o5, 3600, 3600, :CEST - tz.offset :o6, 3600, 0, :CET - - tz.transition 1834, 12, :o1, -4260212372, 51651636907, 21600 - tz.transition 1916, 4, :o2, -1693700372, 52293264907, 21600 - tz.transition 1916, 9, :o1, -1680484772, 52296568807, 21600 - tz.transition 1917, 4, :o2, -1663453172, 52300826707, 21600 - tz.transition 1917, 9, :o1, -1650147572, 52304153107, 21600 - tz.transition 1918, 4, :o2, -1633213172, 52308386707, 21600 - tz.transition 1918, 9, :o1, -1617488372, 52312317907, 21600 - tz.transition 1919, 4, :o2, -1601158772, 52316400307, 21600 - tz.transition 1919, 9, :o1, -1586038772, 52320180307, 21600 - tz.transition 1920, 4, :o2, -1569709172, 52324262707, 21600 - tz.transition 1920, 9, :o1, -1554589172, 52328042707, 21600 - tz.transition 1921, 4, :o2, -1538259572, 52332125107, 21600 - tz.transition 1921, 9, :o1, -1523139572, 52335905107, 21600 - tz.transition 1922, 3, :o2, -1507501172, 52339814707, 21600 - tz.transition 1922, 10, :o1, -1490566772, 52344048307, 21600 - tz.transition 1923, 6, :o2, -1470176372, 52349145907, 21600 - tz.transition 1923, 10, :o1, -1459117172, 52351910707, 21600 - tz.transition 1924, 3, :o2, -1443997172, 52355690707, 21600 - tz.transition 1924, 10, :o1, -1427667572, 52359773107, 21600 - tz.transition 1925, 6, :o2, -1406672372, 52365021907, 21600 - tz.transition 1925, 10, :o1, -1396217972, 52367635507, 21600 - tz.transition 1926, 5, :o2, -1376950772, 52372452307, 21600 - tz.transition 1926, 10, :o1, -1364768372, 52375497907, 21600 - tz.transition 1927, 5, :o2, -1345414772, 52380336307, 21600 - tz.transition 1927, 10, :o1, -1333318772, 52383360307, 21600 - tz.transition 1928, 5, :o2, -1313792372, 52388241907, 21600 - tz.transition 1928, 10, :o1, -1301264372, 52391373907, 21600 - tz.transition 1929, 5, :o2, -1282256372, 52396125907, 21600 - tz.transition 1929, 10, :o1, -1269814772, 52399236307, 21600 - tz.transition 1930, 5, :o2, -1250720372, 52404009907, 21600 - tz.transition 1930, 10, :o1, -1238365172, 52407098707, 21600 - tz.transition 1931, 5, :o2, -1219184372, 52411893907, 21600 - tz.transition 1931, 10, :o1, -1206915572, 52414961107, 21600 - tz.transition 1932, 5, :o2, -1186957172, 52419950707, 21600 - tz.transition 1932, 10, :o1, -1175465972, 52422823507, 21600 - tz.transition 1933, 5, :o2, -1156025972, 52427683507, 21600 - tz.transition 1933, 10, :o1, -1143411572, 52430837107, 21600 - tz.transition 1934, 5, :o2, -1124489972, 52435567507, 21600 - tz.transition 1934, 10, :o1, -1111961972, 52438699507, 21600 - tz.transition 1935, 5, :o2, -1092953972, 52443451507, 21600 - tz.transition 1935, 10, :o1, -1080512372, 52446561907, 21600 - tz.transition 1936, 5, :o2, -1061331572, 52451357107, 21600 - tz.transition 1936, 10, :o1, -1049062772, 52454424307, 21600 - tz.transition 1937, 5, :o2, -1029190772, 52459392307, 21600 - tz.transition 1937, 6, :o3, -1025745572, 52460253607, 21600 - tz.transition 1937, 10, :o4, -1017613200, 174874289, 72 - tz.transition 1938, 5, :o3, -998259600, 174890417, 72 - tz.transition 1938, 10, :o4, -986163600, 174900497, 72 - tz.transition 1939, 5, :o3, -966723600, 174916697, 72 - tz.transition 1939, 10, :o4, -954109200, 174927209, 72 - tz.transition 1940, 5, :o5, -935022000, 174943115, 72 - tz.transition 1942, 11, :o6, -857257200, 58335973, 24 - tz.transition 1943, 3, :o5, -844556400, 58339501, 24 - tz.transition 1943, 10, :o6, -828226800, 58344037, 24 - tz.transition 1944, 4, :o5, -812502000, 58348405, 24 - tz.transition 1944, 10, :o6, -796777200, 58352773, 24 - tz.transition 1945, 4, :o5, -781052400, 58357141, 24 - tz.transition 1945, 9, :o6, -766623600, 58361149, 24 - tz.transition 1977, 4, :o5, 228877200 - tz.transition 1977, 9, :o6, 243997200 - tz.transition 1978, 4, :o5, 260326800 - tz.transition 1978, 10, :o6, 276051600 - tz.transition 1979, 4, :o5, 291776400 - tz.transition 1979, 9, :o6, 307501200 - tz.transition 1980, 4, :o5, 323830800 - tz.transition 1980, 9, :o6, 338950800 - tz.transition 1981, 3, :o5, 354675600 - tz.transition 1981, 9, :o6, 370400400 - tz.transition 1982, 3, :o5, 386125200 - tz.transition 1982, 9, :o6, 401850000 - tz.transition 1983, 3, :o5, 417574800 - tz.transition 1983, 9, :o6, 433299600 - tz.transition 1984, 3, :o5, 449024400 - tz.transition 1984, 9, :o6, 465354000 - tz.transition 1985, 3, :o5, 481078800 - tz.transition 1985, 9, :o6, 496803600 - tz.transition 1986, 3, :o5, 512528400 - tz.transition 1986, 9, :o6, 528253200 - tz.transition 1987, 3, :o5, 543978000 - tz.transition 1987, 9, :o6, 559702800 - tz.transition 1988, 3, :o5, 575427600 - tz.transition 1988, 9, :o6, 591152400 - tz.transition 1989, 3, :o5, 606877200 - tz.transition 1989, 9, :o6, 622602000 - tz.transition 1990, 3, :o5, 638326800 - tz.transition 1990, 9, :o6, 654656400 - tz.transition 1991, 3, :o5, 670381200 - tz.transition 1991, 9, :o6, 686106000 - tz.transition 1992, 3, :o5, 701830800 - tz.transition 1992, 9, :o6, 717555600 - tz.transition 1993, 3, :o5, 733280400 - tz.transition 1993, 9, :o6, 749005200 - tz.transition 1994, 3, :o5, 764730000 - tz.transition 1994, 9, :o6, 780454800 - tz.transition 1995, 3, :o5, 796179600 - tz.transition 1995, 9, :o6, 811904400 - tz.transition 1996, 3, :o5, 828234000 - tz.transition 1996, 10, :o6, 846378000 - tz.transition 1997, 3, :o5, 859683600 - tz.transition 1997, 10, :o6, 877827600 - tz.transition 1998, 3, :o5, 891133200 - tz.transition 1998, 10, :o6, 909277200 - tz.transition 1999, 3, :o5, 922582800 - tz.transition 1999, 10, :o6, 941331600 - tz.transition 2000, 3, :o5, 954032400 - tz.transition 2000, 10, :o6, 972781200 - tz.transition 2001, 3, :o5, 985482000 - tz.transition 2001, 10, :o6, 1004230800 - tz.transition 2002, 3, :o5, 1017536400 - tz.transition 2002, 10, :o6, 1035680400 - tz.transition 2003, 3, :o5, 1048986000 - tz.transition 2003, 10, :o6, 1067130000 - tz.transition 2004, 3, :o5, 1080435600 - tz.transition 2004, 10, :o6, 1099184400 - tz.transition 2005, 3, :o5, 1111885200 - tz.transition 2005, 10, :o6, 1130634000 - tz.transition 2006, 3, :o5, 1143334800 - tz.transition 2006, 10, :o6, 1162083600 - tz.transition 2007, 3, :o5, 1174784400 - tz.transition 2007, 10, :o6, 1193533200 - tz.transition 2008, 3, :o5, 1206838800 - tz.transition 2008, 10, :o6, 1224982800 - tz.transition 2009, 3, :o5, 1238288400 - tz.transition 2009, 10, :o6, 1256432400 - tz.transition 2010, 3, :o5, 1269738000 - tz.transition 2010, 10, :o6, 1288486800 - tz.transition 2011, 3, :o5, 1301187600 - tz.transition 2011, 10, :o6, 1319936400 - tz.transition 2012, 3, :o5, 1332637200 - tz.transition 2012, 10, :o6, 1351386000 - tz.transition 2013, 3, :o5, 1364691600 - tz.transition 2013, 10, :o6, 1382835600 - tz.transition 2014, 3, :o5, 1396141200 - tz.transition 2014, 10, :o6, 1414285200 - tz.transition 2015, 3, :o5, 1427590800 - tz.transition 2015, 10, :o6, 1445734800 - tz.transition 2016, 3, :o5, 1459040400 - tz.transition 2016, 10, :o6, 1477789200 - tz.transition 2017, 3, :o5, 1490490000 - tz.transition 2017, 10, :o6, 1509238800 - tz.transition 2018, 3, :o5, 1521939600 - tz.transition 2018, 10, :o6, 1540688400 - tz.transition 2019, 3, :o5, 1553994000 - tz.transition 2019, 10, :o6, 1572138000 - tz.transition 2020, 3, :o5, 1585443600 - tz.transition 2020, 10, :o6, 1603587600 - tz.transition 2021, 3, :o5, 1616893200 - tz.transition 2021, 10, :o6, 1635642000 - tz.transition 2022, 3, :o5, 1648342800 - tz.transition 2022, 10, :o6, 1667091600 - tz.transition 2023, 3, :o5, 1679792400 - tz.transition 2023, 10, :o6, 1698541200 - tz.transition 2024, 3, :o5, 1711846800 - tz.transition 2024, 10, :o6, 1729990800 - tz.transition 2025, 3, :o5, 1743296400 - tz.transition 2025, 10, :o6, 1761440400 - tz.transition 2026, 3, :o5, 1774746000 - tz.transition 2026, 10, :o6, 1792890000 - tz.transition 2027, 3, :o5, 1806195600 - tz.transition 2027, 10, :o6, 1824944400 - tz.transition 2028, 3, :o5, 1837645200 - tz.transition 2028, 10, :o6, 1856394000 - tz.transition 2029, 3, :o5, 1869094800 - tz.transition 2029, 10, :o6, 1887843600 - tz.transition 2030, 3, :o5, 1901149200 - tz.transition 2030, 10, :o6, 1919293200 - tz.transition 2031, 3, :o5, 1932598800 - tz.transition 2031, 10, :o6, 1950742800 - tz.transition 2032, 3, :o5, 1964048400 - tz.transition 2032, 10, :o6, 1982797200 - tz.transition 2033, 3, :o5, 1995498000 - tz.transition 2033, 10, :o6, 2014246800 - tz.transition 2034, 3, :o5, 2026947600 - tz.transition 2034, 10, :o6, 2045696400 - tz.transition 2035, 3, :o5, 2058397200 - tz.transition 2035, 10, :o6, 2077146000 - tz.transition 2036, 3, :o5, 2090451600 - tz.transition 2036, 10, :o6, 2108595600 - tz.transition 2037, 3, :o5, 2121901200 - tz.transition 2037, 10, :o6, 2140045200 - tz.transition 2038, 3, :o5, 2153350800, 59172253, 24 - tz.transition 2038, 10, :o6, 2172099600, 59177461, 24 - tz.transition 2039, 3, :o5, 2184800400, 59180989, 24 - tz.transition 2039, 10, :o6, 2203549200, 59186197, 24 - tz.transition 2040, 3, :o5, 2216250000, 59189725, 24 - tz.transition 2040, 10, :o6, 2234998800, 59194933, 24 - tz.transition 2041, 3, :o5, 2248304400, 59198629, 24 - tz.transition 2041, 10, :o6, 2266448400, 59203669, 24 - tz.transition 2042, 3, :o5, 2279754000, 59207365, 24 - tz.transition 2042, 10, :o6, 2297898000, 59212405, 24 - tz.transition 2043, 3, :o5, 2311203600, 59216101, 24 - tz.transition 2043, 10, :o6, 2329347600, 59221141, 24 - tz.transition 2044, 3, :o5, 2342653200, 59224837, 24 - tz.transition 2044, 10, :o6, 2361402000, 59230045, 24 - tz.transition 2045, 3, :o5, 2374102800, 59233573, 24 - tz.transition 2045, 10, :o6, 2392851600, 59238781, 24 - tz.transition 2046, 3, :o5, 2405552400, 59242309, 24 - tz.transition 2046, 10, :o6, 2424301200, 59247517, 24 - tz.transition 2047, 3, :o5, 2437606800, 59251213, 24 - tz.transition 2047, 10, :o6, 2455750800, 59256253, 24 - tz.transition 2048, 3, :o5, 2469056400, 59259949, 24 - tz.transition 2048, 10, :o6, 2487200400, 59264989, 24 - tz.transition 2049, 3, :o5, 2500506000, 59268685, 24 - tz.transition 2049, 10, :o6, 2519254800, 59273893, 24 - tz.transition 2050, 3, :o5, 2531955600, 59277421, 24 - tz.transition 2050, 10, :o6, 2550704400, 59282629, 24 - tz.transition 2051, 3, :o5, 2563405200, 59286157, 24 - tz.transition 2051, 10, :o6, 2582154000, 59291365, 24 - tz.transition 2052, 3, :o5, 2595459600, 59295061, 24 - tz.transition 2052, 10, :o6, 2613603600, 59300101, 24 - tz.transition 2053, 3, :o5, 2626909200, 59303797, 24 - tz.transition 2053, 10, :o6, 2645053200, 59308837, 24 - tz.transition 2054, 3, :o5, 2658358800, 59312533, 24 - tz.transition 2054, 10, :o6, 2676502800, 59317573, 24 - tz.transition 2055, 3, :o5, 2689808400, 59321269, 24 - tz.transition 2055, 10, :o6, 2708557200, 59326477, 24 - tz.transition 2056, 3, :o5, 2721258000, 59330005, 24 - tz.transition 2056, 10, :o6, 2740006800, 59335213, 24 - tz.transition 2057, 3, :o5, 2752707600, 59338741, 24 - tz.transition 2057, 10, :o6, 2771456400, 59343949, 24 - tz.transition 2058, 3, :o5, 2784762000, 59347645, 24 - tz.transition 2058, 10, :o6, 2802906000, 59352685, 24 - tz.transition 2059, 3, :o5, 2816211600, 59356381, 24 - tz.transition 2059, 10, :o6, 2834355600, 59361421, 24 - tz.transition 2060, 3, :o5, 2847661200, 59365117, 24 - tz.transition 2060, 10, :o6, 2866410000, 59370325, 24 - tz.transition 2061, 3, :o5, 2879110800, 59373853, 24 - tz.transition 2061, 10, :o6, 2897859600, 59379061, 24 - tz.transition 2062, 3, :o5, 2910560400, 59382589, 24 - tz.transition 2062, 10, :o6, 2929309200, 59387797, 24 - tz.transition 2063, 3, :o5, 2942010000, 59391325, 24 - tz.transition 2063, 10, :o6, 2960758800, 59396533, 24 - tz.transition 2064, 3, :o5, 2974064400, 59400229, 24 - tz.transition 2064, 10, :o6, 2992208400, 59405269, 24 - end - end - end - end - end -end diff -Nru ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/definitions/Europe/Andorra.rb ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/definitions/Europe/Andorra.rb --- ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/definitions/Europe/Andorra.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/definitions/Europe/Andorra.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,186 +0,0 @@ -# encoding: UTF-8 - -# This file contains data derived from the IANA Time Zone Database -# (http://www.iana.org/time-zones). - -module TZInfo - module Data - module Definitions - module Europe - module Andorra - include TimezoneDefinition - - timezone 'Europe/Andorra' do |tz| - tz.offset :o0, 364, 0, :LMT - tz.offset :o1, 0, 0, :WET - tz.offset :o2, 3600, 0, :CET - tz.offset :o3, 3600, 3600, :CEST - - tz.transition 1900, 12, :o1, -2177453164, 52172326709, 21600 - tz.transition 1946, 9, :o2, -733881600, 4864187, 2 - tz.transition 1985, 3, :o3, 481078800 - tz.transition 1985, 9, :o2, 496803600 - tz.transition 1986, 3, :o3, 512528400 - tz.transition 1986, 9, :o2, 528253200 - tz.transition 1987, 3, :o3, 543978000 - tz.transition 1987, 9, :o2, 559702800 - tz.transition 1988, 3, :o3, 575427600 - tz.transition 1988, 9, :o2, 591152400 - tz.transition 1989, 3, :o3, 606877200 - tz.transition 1989, 9, :o2, 622602000 - tz.transition 1990, 3, :o3, 638326800 - tz.transition 1990, 9, :o2, 654656400 - tz.transition 1991, 3, :o3, 670381200 - tz.transition 1991, 9, :o2, 686106000 - tz.transition 1992, 3, :o3, 701830800 - tz.transition 1992, 9, :o2, 717555600 - tz.transition 1993, 3, :o3, 733280400 - tz.transition 1993, 9, :o2, 749005200 - tz.transition 1994, 3, :o3, 764730000 - tz.transition 1994, 9, :o2, 780454800 - tz.transition 1995, 3, :o3, 796179600 - tz.transition 1995, 9, :o2, 811904400 - tz.transition 1996, 3, :o3, 828234000 - tz.transition 1996, 10, :o2, 846378000 - tz.transition 1997, 3, :o3, 859683600 - tz.transition 1997, 10, :o2, 877827600 - tz.transition 1998, 3, :o3, 891133200 - tz.transition 1998, 10, :o2, 909277200 - tz.transition 1999, 3, :o3, 922582800 - tz.transition 1999, 10, :o2, 941331600 - tz.transition 2000, 3, :o3, 954032400 - tz.transition 2000, 10, :o2, 972781200 - tz.transition 2001, 3, :o3, 985482000 - tz.transition 2001, 10, :o2, 1004230800 - tz.transition 2002, 3, :o3, 1017536400 - tz.transition 2002, 10, :o2, 1035680400 - tz.transition 2003, 3, :o3, 1048986000 - tz.transition 2003, 10, :o2, 1067130000 - tz.transition 2004, 3, :o3, 1080435600 - tz.transition 2004, 10, :o2, 1099184400 - tz.transition 2005, 3, :o3, 1111885200 - tz.transition 2005, 10, :o2, 1130634000 - tz.transition 2006, 3, :o3, 1143334800 - tz.transition 2006, 10, :o2, 1162083600 - tz.transition 2007, 3, :o3, 1174784400 - tz.transition 2007, 10, :o2, 1193533200 - tz.transition 2008, 3, :o3, 1206838800 - tz.transition 2008, 10, :o2, 1224982800 - tz.transition 2009, 3, :o3, 1238288400 - tz.transition 2009, 10, :o2, 1256432400 - tz.transition 2010, 3, :o3, 1269738000 - tz.transition 2010, 10, :o2, 1288486800 - tz.transition 2011, 3, :o3, 1301187600 - tz.transition 2011, 10, :o2, 1319936400 - tz.transition 2012, 3, :o3, 1332637200 - tz.transition 2012, 10, :o2, 1351386000 - tz.transition 2013, 3, :o3, 1364691600 - tz.transition 2013, 10, :o2, 1382835600 - tz.transition 2014, 3, :o3, 1396141200 - tz.transition 2014, 10, :o2, 1414285200 - tz.transition 2015, 3, :o3, 1427590800 - tz.transition 2015, 10, :o2, 1445734800 - tz.transition 2016, 3, :o3, 1459040400 - tz.transition 2016, 10, :o2, 1477789200 - tz.transition 2017, 3, :o3, 1490490000 - tz.transition 2017, 10, :o2, 1509238800 - tz.transition 2018, 3, :o3, 1521939600 - tz.transition 2018, 10, :o2, 1540688400 - tz.transition 2019, 3, :o3, 1553994000 - tz.transition 2019, 10, :o2, 1572138000 - tz.transition 2020, 3, :o3, 1585443600 - tz.transition 2020, 10, :o2, 1603587600 - tz.transition 2021, 3, :o3, 1616893200 - tz.transition 2021, 10, :o2, 1635642000 - tz.transition 2022, 3, :o3, 1648342800 - tz.transition 2022, 10, :o2, 1667091600 - tz.transition 2023, 3, :o3, 1679792400 - tz.transition 2023, 10, :o2, 1698541200 - tz.transition 2024, 3, :o3, 1711846800 - tz.transition 2024, 10, :o2, 1729990800 - tz.transition 2025, 3, :o3, 1743296400 - tz.transition 2025, 10, :o2, 1761440400 - tz.transition 2026, 3, :o3, 1774746000 - tz.transition 2026, 10, :o2, 1792890000 - tz.transition 2027, 3, :o3, 1806195600 - tz.transition 2027, 10, :o2, 1824944400 - tz.transition 2028, 3, :o3, 1837645200 - tz.transition 2028, 10, :o2, 1856394000 - tz.transition 2029, 3, :o3, 1869094800 - tz.transition 2029, 10, :o2, 1887843600 - tz.transition 2030, 3, :o3, 1901149200 - tz.transition 2030, 10, :o2, 1919293200 - tz.transition 2031, 3, :o3, 1932598800 - tz.transition 2031, 10, :o2, 1950742800 - tz.transition 2032, 3, :o3, 1964048400 - tz.transition 2032, 10, :o2, 1982797200 - tz.transition 2033, 3, :o3, 1995498000 - tz.transition 2033, 10, :o2, 2014246800 - tz.transition 2034, 3, :o3, 2026947600 - tz.transition 2034, 10, :o2, 2045696400 - tz.transition 2035, 3, :o3, 2058397200 - tz.transition 2035, 10, :o2, 2077146000 - tz.transition 2036, 3, :o3, 2090451600 - tz.transition 2036, 10, :o2, 2108595600 - tz.transition 2037, 3, :o3, 2121901200 - tz.transition 2037, 10, :o2, 2140045200 - tz.transition 2038, 3, :o3, 2153350800, 59172253, 24 - tz.transition 2038, 10, :o2, 2172099600, 59177461, 24 - tz.transition 2039, 3, :o3, 2184800400, 59180989, 24 - tz.transition 2039, 10, :o2, 2203549200, 59186197, 24 - tz.transition 2040, 3, :o3, 2216250000, 59189725, 24 - tz.transition 2040, 10, :o2, 2234998800, 59194933, 24 - tz.transition 2041, 3, :o3, 2248304400, 59198629, 24 - tz.transition 2041, 10, :o2, 2266448400, 59203669, 24 - tz.transition 2042, 3, :o3, 2279754000, 59207365, 24 - tz.transition 2042, 10, :o2, 2297898000, 59212405, 24 - tz.transition 2043, 3, :o3, 2311203600, 59216101, 24 - tz.transition 2043, 10, :o2, 2329347600, 59221141, 24 - tz.transition 2044, 3, :o3, 2342653200, 59224837, 24 - tz.transition 2044, 10, :o2, 2361402000, 59230045, 24 - tz.transition 2045, 3, :o3, 2374102800, 59233573, 24 - tz.transition 2045, 10, :o2, 2392851600, 59238781, 24 - tz.transition 2046, 3, :o3, 2405552400, 59242309, 24 - tz.transition 2046, 10, :o2, 2424301200, 59247517, 24 - tz.transition 2047, 3, :o3, 2437606800, 59251213, 24 - tz.transition 2047, 10, :o2, 2455750800, 59256253, 24 - tz.transition 2048, 3, :o3, 2469056400, 59259949, 24 - tz.transition 2048, 10, :o2, 2487200400, 59264989, 24 - tz.transition 2049, 3, :o3, 2500506000, 59268685, 24 - tz.transition 2049, 10, :o2, 2519254800, 59273893, 24 - tz.transition 2050, 3, :o3, 2531955600, 59277421, 24 - tz.transition 2050, 10, :o2, 2550704400, 59282629, 24 - tz.transition 2051, 3, :o3, 2563405200, 59286157, 24 - tz.transition 2051, 10, :o2, 2582154000, 59291365, 24 - tz.transition 2052, 3, :o3, 2595459600, 59295061, 24 - tz.transition 2052, 10, :o2, 2613603600, 59300101, 24 - tz.transition 2053, 3, :o3, 2626909200, 59303797, 24 - tz.transition 2053, 10, :o2, 2645053200, 59308837, 24 - tz.transition 2054, 3, :o3, 2658358800, 59312533, 24 - tz.transition 2054, 10, :o2, 2676502800, 59317573, 24 - tz.transition 2055, 3, :o3, 2689808400, 59321269, 24 - tz.transition 2055, 10, :o2, 2708557200, 59326477, 24 - tz.transition 2056, 3, :o3, 2721258000, 59330005, 24 - tz.transition 2056, 10, :o2, 2740006800, 59335213, 24 - tz.transition 2057, 3, :o3, 2752707600, 59338741, 24 - tz.transition 2057, 10, :o2, 2771456400, 59343949, 24 - tz.transition 2058, 3, :o3, 2784762000, 59347645, 24 - tz.transition 2058, 10, :o2, 2802906000, 59352685, 24 - tz.transition 2059, 3, :o3, 2816211600, 59356381, 24 - tz.transition 2059, 10, :o2, 2834355600, 59361421, 24 - tz.transition 2060, 3, :o3, 2847661200, 59365117, 24 - tz.transition 2060, 10, :o2, 2866410000, 59370325, 24 - tz.transition 2061, 3, :o3, 2879110800, 59373853, 24 - tz.transition 2061, 10, :o2, 2897859600, 59379061, 24 - tz.transition 2062, 3, :o3, 2910560400, 59382589, 24 - tz.transition 2062, 10, :o2, 2929309200, 59387797, 24 - tz.transition 2063, 3, :o3, 2942010000, 59391325, 24 - tz.transition 2063, 10, :o2, 2960758800, 59396533, 24 - tz.transition 2064, 3, :o3, 2974064400, 59400229, 24 - tz.transition 2064, 10, :o2, 2992208400, 59405269, 24 - end - end - end - end - end -end diff -Nru ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/definitions/Europe/London.rb ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/definitions/Europe/London.rb --- ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/definitions/Europe/London.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/definitions/Europe/London.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,321 +0,0 @@ -# encoding: UTF-8 - -# This file contains data derived from the IANA Time Zone Database -# (http://www.iana.org/time-zones). - -module TZInfo - module Data - module Definitions - module Europe - module London - include TimezoneDefinition - - timezone 'Europe/London' do |tz| - tz.offset :o0, -75, 0, :LMT - tz.offset :o1, 0, 0, :GMT - tz.offset :o2, 0, 3600, :BST - tz.offset :o3, 0, 7200, :BDST - tz.offset :o4, 3600, 0, :BST - - tz.transition 1847, 12, :o1, -3852662325, 2760187969, 1152 - tz.transition 1916, 5, :o2, -1691964000, 29052055, 12 - tz.transition 1916, 10, :o1, -1680472800, 29053651, 12 - tz.transition 1917, 4, :o2, -1664143200, 29055919, 12 - tz.transition 1917, 9, :o1, -1650146400, 29057863, 12 - tz.transition 1918, 3, :o2, -1633903200, 29060119, 12 - tz.transition 1918, 9, :o1, -1617487200, 29062399, 12 - tz.transition 1919, 3, :o2, -1601848800, 29064571, 12 - tz.transition 1919, 9, :o1, -1586037600, 29066767, 12 - tz.transition 1920, 3, :o2, -1570399200, 29068939, 12 - tz.transition 1920, 10, :o1, -1552168800, 29071471, 12 - tz.transition 1921, 4, :o2, -1538344800, 29073391, 12 - tz.transition 1921, 10, :o1, -1522533600, 29075587, 12 - tz.transition 1922, 3, :o2, -1507500000, 29077675, 12 - tz.transition 1922, 10, :o1, -1490565600, 29080027, 12 - tz.transition 1923, 4, :o2, -1473631200, 29082379, 12 - tz.transition 1923, 9, :o1, -1460930400, 29084143, 12 - tz.transition 1924, 4, :o2, -1442786400, 29086663, 12 - tz.transition 1924, 9, :o1, -1428876000, 29088595, 12 - tz.transition 1925, 4, :o2, -1410732000, 29091115, 12 - tz.transition 1925, 10, :o1, -1396216800, 29093131, 12 - tz.transition 1926, 4, :o2, -1379282400, 29095483, 12 - tz.transition 1926, 10, :o1, -1364767200, 29097499, 12 - tz.transition 1927, 4, :o2, -1348437600, 29099767, 12 - tz.transition 1927, 10, :o1, -1333317600, 29101867, 12 - tz.transition 1928, 4, :o2, -1315778400, 29104303, 12 - tz.transition 1928, 10, :o1, -1301263200, 29106319, 12 - tz.transition 1929, 4, :o2, -1284328800, 29108671, 12 - tz.transition 1929, 10, :o1, -1269813600, 29110687, 12 - tz.transition 1930, 4, :o2, -1253484000, 29112955, 12 - tz.transition 1930, 10, :o1, -1238364000, 29115055, 12 - tz.transition 1931, 4, :o2, -1221429600, 29117407, 12 - tz.transition 1931, 10, :o1, -1206914400, 29119423, 12 - tz.transition 1932, 4, :o2, -1189980000, 29121775, 12 - tz.transition 1932, 10, :o1, -1175464800, 29123791, 12 - tz.transition 1933, 4, :o2, -1159135200, 29126059, 12 - tz.transition 1933, 10, :o1, -1143410400, 29128243, 12 - tz.transition 1934, 4, :o2, -1126476000, 29130595, 12 - tz.transition 1934, 10, :o1, -1111960800, 29132611, 12 - tz.transition 1935, 4, :o2, -1095631200, 29134879, 12 - tz.transition 1935, 10, :o1, -1080511200, 29136979, 12 - tz.transition 1936, 4, :o2, -1063576800, 29139331, 12 - tz.transition 1936, 10, :o1, -1049061600, 29141347, 12 - tz.transition 1937, 4, :o2, -1032127200, 29143699, 12 - tz.transition 1937, 10, :o1, -1017612000, 29145715, 12 - tz.transition 1938, 4, :o2, -1001282400, 29147983, 12 - tz.transition 1938, 10, :o1, -986162400, 29150083, 12 - tz.transition 1939, 4, :o2, -969228000, 29152435, 12 - tz.transition 1939, 11, :o1, -950479200, 29155039, 12 - tz.transition 1940, 2, :o2, -942012000, 29156215, 12 - tz.transition 1941, 5, :o3, -904518000, 58322845, 24 - tz.transition 1941, 8, :o2, -896050800, 58325197, 24 - tz.transition 1942, 4, :o3, -875487600, 58330909, 24 - tz.transition 1942, 8, :o2, -864601200, 58333933, 24 - tz.transition 1943, 4, :o3, -844038000, 58339645, 24 - tz.transition 1943, 8, :o2, -832546800, 58342837, 24 - tz.transition 1944, 4, :o3, -812588400, 58348381, 24 - tz.transition 1944, 9, :o2, -798073200, 58352413, 24 - tz.transition 1945, 4, :o3, -781052400, 58357141, 24 - tz.transition 1945, 7, :o2, -772066800, 58359637, 24 - tz.transition 1945, 10, :o1, -764805600, 29180827, 12 - tz.transition 1946, 4, :o2, -748476000, 29183095, 12 - tz.transition 1946, 10, :o1, -733356000, 29185195, 12 - tz.transition 1947, 3, :o2, -719445600, 29187127, 12 - tz.transition 1947, 4, :o3, -717030000, 58374925, 24 - tz.transition 1947, 8, :o2, -706748400, 58377781, 24 - tz.transition 1947, 11, :o1, -699487200, 29189899, 12 - tz.transition 1948, 3, :o2, -687996000, 29191495, 12 - tz.transition 1948, 10, :o1, -668037600, 29194267, 12 - tz.transition 1949, 4, :o2, -654732000, 29196115, 12 - tz.transition 1949, 10, :o1, -636588000, 29198635, 12 - tz.transition 1950, 4, :o2, -622072800, 29200651, 12 - tz.transition 1950, 10, :o1, -605743200, 29202919, 12 - tz.transition 1951, 4, :o2, -590623200, 29205019, 12 - tz.transition 1951, 10, :o1, -574293600, 29207287, 12 - tz.transition 1952, 4, :o2, -558568800, 29209471, 12 - tz.transition 1952, 10, :o1, -542239200, 29211739, 12 - tz.transition 1953, 4, :o2, -527119200, 29213839, 12 - tz.transition 1953, 10, :o1, -512604000, 29215855, 12 - tz.transition 1954, 4, :o2, -496274400, 29218123, 12 - tz.transition 1954, 10, :o1, -481154400, 29220223, 12 - tz.transition 1955, 4, :o2, -464220000, 29222575, 12 - tz.transition 1955, 10, :o1, -449704800, 29224591, 12 - tz.transition 1956, 4, :o2, -432165600, 29227027, 12 - tz.transition 1956, 10, :o1, -417650400, 29229043, 12 - tz.transition 1957, 4, :o2, -401320800, 29231311, 12 - tz.transition 1957, 10, :o1, -386200800, 29233411, 12 - tz.transition 1958, 4, :o2, -369266400, 29235763, 12 - tz.transition 1958, 10, :o1, -354751200, 29237779, 12 - tz.transition 1959, 4, :o2, -337816800, 29240131, 12 - tz.transition 1959, 10, :o1, -323301600, 29242147, 12 - tz.transition 1960, 4, :o2, -306972000, 29244415, 12 - tz.transition 1960, 10, :o1, -291852000, 29246515, 12 - tz.transition 1961, 3, :o2, -276732000, 29248615, 12 - tz.transition 1961, 10, :o1, -257983200, 29251219, 12 - tz.transition 1962, 3, :o2, -245282400, 29252983, 12 - tz.transition 1962, 10, :o1, -226533600, 29255587, 12 - tz.transition 1963, 3, :o2, -213228000, 29257435, 12 - tz.transition 1963, 10, :o1, -195084000, 29259955, 12 - tz.transition 1964, 3, :o2, -182383200, 29261719, 12 - tz.transition 1964, 10, :o1, -163634400, 29264323, 12 - tz.transition 1965, 3, :o2, -150933600, 29266087, 12 - tz.transition 1965, 10, :o1, -132184800, 29268691, 12 - tz.transition 1966, 3, :o2, -119484000, 29270455, 12 - tz.transition 1966, 10, :o1, -100735200, 29273059, 12 - tz.transition 1967, 3, :o2, -88034400, 29274823, 12 - tz.transition 1967, 10, :o1, -68680800, 29277511, 12 - tz.transition 1968, 2, :o2, -59004000, 29278855, 12 - tz.transition 1968, 10, :o4, -37242000, 58563755, 24 - tz.transition 1971, 10, :o1, 57722400 - tz.transition 1972, 3, :o2, 69818400 - tz.transition 1972, 10, :o1, 89172000 - tz.transition 1973, 3, :o2, 101268000 - tz.transition 1973, 10, :o1, 120621600 - tz.transition 1974, 3, :o2, 132717600 - tz.transition 1974, 10, :o1, 152071200 - tz.transition 1975, 3, :o2, 164167200 - tz.transition 1975, 10, :o1, 183520800 - tz.transition 1976, 3, :o2, 196221600 - tz.transition 1976, 10, :o1, 214970400 - tz.transition 1977, 3, :o2, 227671200 - tz.transition 1977, 10, :o1, 246420000 - tz.transition 1978, 3, :o2, 259120800 - tz.transition 1978, 10, :o1, 278474400 - tz.transition 1979, 3, :o2, 290570400 - tz.transition 1979, 10, :o1, 309924000 - tz.transition 1980, 3, :o2, 322020000 - tz.transition 1980, 10, :o1, 341373600 - tz.transition 1981, 3, :o2, 354675600 - tz.transition 1981, 10, :o1, 372819600 - tz.transition 1982, 3, :o2, 386125200 - tz.transition 1982, 10, :o1, 404269200 - tz.transition 1983, 3, :o2, 417574800 - tz.transition 1983, 10, :o1, 435718800 - tz.transition 1984, 3, :o2, 449024400 - tz.transition 1984, 10, :o1, 467773200 - tz.transition 1985, 3, :o2, 481078800 - tz.transition 1985, 10, :o1, 499222800 - tz.transition 1986, 3, :o2, 512528400 - tz.transition 1986, 10, :o1, 530672400 - tz.transition 1987, 3, :o2, 543978000 - tz.transition 1987, 10, :o1, 562122000 - tz.transition 1988, 3, :o2, 575427600 - tz.transition 1988, 10, :o1, 593571600 - tz.transition 1989, 3, :o2, 606877200 - tz.transition 1989, 10, :o1, 625626000 - tz.transition 1990, 3, :o2, 638326800 - tz.transition 1990, 10, :o1, 657075600 - tz.transition 1991, 3, :o2, 670381200 - tz.transition 1991, 10, :o1, 688525200 - tz.transition 1992, 3, :o2, 701830800 - tz.transition 1992, 10, :o1, 719974800 - tz.transition 1993, 3, :o2, 733280400 - tz.transition 1993, 10, :o1, 751424400 - tz.transition 1994, 3, :o2, 764730000 - tz.transition 1994, 10, :o1, 782874000 - tz.transition 1995, 3, :o2, 796179600 - tz.transition 1995, 10, :o1, 814323600 - tz.transition 1996, 3, :o2, 828234000 - tz.transition 1996, 10, :o1, 846378000 - tz.transition 1997, 3, :o2, 859683600 - tz.transition 1997, 10, :o1, 877827600 - tz.transition 1998, 3, :o2, 891133200 - tz.transition 1998, 10, :o1, 909277200 - tz.transition 1999, 3, :o2, 922582800 - tz.transition 1999, 10, :o1, 941331600 - tz.transition 2000, 3, :o2, 954032400 - tz.transition 2000, 10, :o1, 972781200 - tz.transition 2001, 3, :o2, 985482000 - tz.transition 2001, 10, :o1, 1004230800 - tz.transition 2002, 3, :o2, 1017536400 - tz.transition 2002, 10, :o1, 1035680400 - tz.transition 2003, 3, :o2, 1048986000 - tz.transition 2003, 10, :o1, 1067130000 - tz.transition 2004, 3, :o2, 1080435600 - tz.transition 2004, 10, :o1, 1099184400 - tz.transition 2005, 3, :o2, 1111885200 - tz.transition 2005, 10, :o1, 1130634000 - tz.transition 2006, 3, :o2, 1143334800 - tz.transition 2006, 10, :o1, 1162083600 - tz.transition 2007, 3, :o2, 1174784400 - tz.transition 2007, 10, :o1, 1193533200 - tz.transition 2008, 3, :o2, 1206838800 - tz.transition 2008, 10, :o1, 1224982800 - tz.transition 2009, 3, :o2, 1238288400 - tz.transition 2009, 10, :o1, 1256432400 - tz.transition 2010, 3, :o2, 1269738000 - tz.transition 2010, 10, :o1, 1288486800 - tz.transition 2011, 3, :o2, 1301187600 - tz.transition 2011, 10, :o1, 1319936400 - tz.transition 2012, 3, :o2, 1332637200 - tz.transition 2012, 10, :o1, 1351386000 - tz.transition 2013, 3, :o2, 1364691600 - tz.transition 2013, 10, :o1, 1382835600 - tz.transition 2014, 3, :o2, 1396141200 - tz.transition 2014, 10, :o1, 1414285200 - tz.transition 2015, 3, :o2, 1427590800 - tz.transition 2015, 10, :o1, 1445734800 - tz.transition 2016, 3, :o2, 1459040400 - tz.transition 2016, 10, :o1, 1477789200 - tz.transition 2017, 3, :o2, 1490490000 - tz.transition 2017, 10, :o1, 1509238800 - tz.transition 2018, 3, :o2, 1521939600 - tz.transition 2018, 10, :o1, 1540688400 - tz.transition 2019, 3, :o2, 1553994000 - tz.transition 2019, 10, :o1, 1572138000 - tz.transition 2020, 3, :o2, 1585443600 - tz.transition 2020, 10, :o1, 1603587600 - tz.transition 2021, 3, :o2, 1616893200 - tz.transition 2021, 10, :o1, 1635642000 - tz.transition 2022, 3, :o2, 1648342800 - tz.transition 2022, 10, :o1, 1667091600 - tz.transition 2023, 3, :o2, 1679792400 - tz.transition 2023, 10, :o1, 1698541200 - tz.transition 2024, 3, :o2, 1711846800 - tz.transition 2024, 10, :o1, 1729990800 - tz.transition 2025, 3, :o2, 1743296400 - tz.transition 2025, 10, :o1, 1761440400 - tz.transition 2026, 3, :o2, 1774746000 - tz.transition 2026, 10, :o1, 1792890000 - tz.transition 2027, 3, :o2, 1806195600 - tz.transition 2027, 10, :o1, 1824944400 - tz.transition 2028, 3, :o2, 1837645200 - tz.transition 2028, 10, :o1, 1856394000 - tz.transition 2029, 3, :o2, 1869094800 - tz.transition 2029, 10, :o1, 1887843600 - tz.transition 2030, 3, :o2, 1901149200 - tz.transition 2030, 10, :o1, 1919293200 - tz.transition 2031, 3, :o2, 1932598800 - tz.transition 2031, 10, :o1, 1950742800 - tz.transition 2032, 3, :o2, 1964048400 - tz.transition 2032, 10, :o1, 1982797200 - tz.transition 2033, 3, :o2, 1995498000 - tz.transition 2033, 10, :o1, 2014246800 - tz.transition 2034, 3, :o2, 2026947600 - tz.transition 2034, 10, :o1, 2045696400 - tz.transition 2035, 3, :o2, 2058397200 - tz.transition 2035, 10, :o1, 2077146000 - tz.transition 2036, 3, :o2, 2090451600 - tz.transition 2036, 10, :o1, 2108595600 - tz.transition 2037, 3, :o2, 2121901200 - tz.transition 2037, 10, :o1, 2140045200 - tz.transition 2038, 3, :o2, 2153350800, 59172253, 24 - tz.transition 2038, 10, :o1, 2172099600, 59177461, 24 - tz.transition 2039, 3, :o2, 2184800400, 59180989, 24 - tz.transition 2039, 10, :o1, 2203549200, 59186197, 24 - tz.transition 2040, 3, :o2, 2216250000, 59189725, 24 - tz.transition 2040, 10, :o1, 2234998800, 59194933, 24 - tz.transition 2041, 3, :o2, 2248304400, 59198629, 24 - tz.transition 2041, 10, :o1, 2266448400, 59203669, 24 - tz.transition 2042, 3, :o2, 2279754000, 59207365, 24 - tz.transition 2042, 10, :o1, 2297898000, 59212405, 24 - tz.transition 2043, 3, :o2, 2311203600, 59216101, 24 - tz.transition 2043, 10, :o1, 2329347600, 59221141, 24 - tz.transition 2044, 3, :o2, 2342653200, 59224837, 24 - tz.transition 2044, 10, :o1, 2361402000, 59230045, 24 - tz.transition 2045, 3, :o2, 2374102800, 59233573, 24 - tz.transition 2045, 10, :o1, 2392851600, 59238781, 24 - tz.transition 2046, 3, :o2, 2405552400, 59242309, 24 - tz.transition 2046, 10, :o1, 2424301200, 59247517, 24 - tz.transition 2047, 3, :o2, 2437606800, 59251213, 24 - tz.transition 2047, 10, :o1, 2455750800, 59256253, 24 - tz.transition 2048, 3, :o2, 2469056400, 59259949, 24 - tz.transition 2048, 10, :o1, 2487200400, 59264989, 24 - tz.transition 2049, 3, :o2, 2500506000, 59268685, 24 - tz.transition 2049, 10, :o1, 2519254800, 59273893, 24 - tz.transition 2050, 3, :o2, 2531955600, 59277421, 24 - tz.transition 2050, 10, :o1, 2550704400, 59282629, 24 - tz.transition 2051, 3, :o2, 2563405200, 59286157, 24 - tz.transition 2051, 10, :o1, 2582154000, 59291365, 24 - tz.transition 2052, 3, :o2, 2595459600, 59295061, 24 - tz.transition 2052, 10, :o1, 2613603600, 59300101, 24 - tz.transition 2053, 3, :o2, 2626909200, 59303797, 24 - tz.transition 2053, 10, :o1, 2645053200, 59308837, 24 - tz.transition 2054, 3, :o2, 2658358800, 59312533, 24 - tz.transition 2054, 10, :o1, 2676502800, 59317573, 24 - tz.transition 2055, 3, :o2, 2689808400, 59321269, 24 - tz.transition 2055, 10, :o1, 2708557200, 59326477, 24 - tz.transition 2056, 3, :o2, 2721258000, 59330005, 24 - tz.transition 2056, 10, :o1, 2740006800, 59335213, 24 - tz.transition 2057, 3, :o2, 2752707600, 59338741, 24 - tz.transition 2057, 10, :o1, 2771456400, 59343949, 24 - tz.transition 2058, 3, :o2, 2784762000, 59347645, 24 - tz.transition 2058, 10, :o1, 2802906000, 59352685, 24 - tz.transition 2059, 3, :o2, 2816211600, 59356381, 24 - tz.transition 2059, 10, :o1, 2834355600, 59361421, 24 - tz.transition 2060, 3, :o2, 2847661200, 59365117, 24 - tz.transition 2060, 10, :o1, 2866410000, 59370325, 24 - tz.transition 2061, 3, :o2, 2879110800, 59373853, 24 - tz.transition 2061, 10, :o1, 2897859600, 59379061, 24 - tz.transition 2062, 3, :o2, 2910560400, 59382589, 24 - tz.transition 2062, 10, :o1, 2929309200, 59387797, 24 - tz.transition 2063, 3, :o2, 2942010000, 59391325, 24 - tz.transition 2063, 10, :o1, 2960758800, 59396533, 24 - tz.transition 2064, 3, :o2, 2974064400, 59400229, 24 - tz.transition 2064, 10, :o1, 2992208400, 59405269, 24 - end - end - end - end - end -end diff -Nru ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/definitions/Europe/Paris.rb ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/definitions/Europe/Paris.rb --- ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/definitions/Europe/Paris.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/definitions/Europe/Paris.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,265 +0,0 @@ -# encoding: UTF-8 - -# This file contains data derived from the IANA Time Zone Database -# (http://www.iana.org/time-zones). - -module TZInfo - module Data - module Definitions - module Europe - module Paris - include TimezoneDefinition - - timezone 'Europe/Paris' do |tz| - tz.offset :o0, 561, 0, :LMT - tz.offset :o1, 561, 0, :PMT - tz.offset :o2, 0, 0, :WET - tz.offset :o3, 0, 3600, :WEST - tz.offset :o4, 3600, 3600, :CEST - tz.offset :o5, 3600, 0, :CET - tz.offset :o6, 0, 7200, :WEMT - - tz.transition 1891, 3, :o1, -2486678901, 69460027033, 28800 - tz.transition 1911, 3, :o2, -1855958901, 69670267033, 28800 - tz.transition 1916, 6, :o3, -1689814800, 58104707, 24 - tz.transition 1916, 10, :o2, -1680397200, 58107323, 24 - tz.transition 1917, 3, :o3, -1665363600, 58111499, 24 - tz.transition 1917, 10, :o2, -1648342800, 58116227, 24 - tz.transition 1918, 3, :o3, -1635123600, 58119899, 24 - tz.transition 1918, 10, :o2, -1616893200, 58124963, 24 - tz.transition 1919, 3, :o3, -1604278800, 58128467, 24 - tz.transition 1919, 10, :o2, -1585443600, 58133699, 24 - tz.transition 1920, 2, :o3, -1574038800, 58136867, 24 - tz.transition 1920, 10, :o2, -1552266000, 58142915, 24 - tz.transition 1921, 3, :o3, -1539997200, 58146323, 24 - tz.transition 1921, 10, :o2, -1520557200, 58151723, 24 - tz.transition 1922, 3, :o3, -1507510800, 58155347, 24 - tz.transition 1922, 10, :o2, -1490576400, 58160051, 24 - tz.transition 1923, 5, :o3, -1470618000, 58165595, 24 - tz.transition 1923, 10, :o2, -1459126800, 58168787, 24 - tz.transition 1924, 3, :o3, -1444006800, 58172987, 24 - tz.transition 1924, 10, :o2, -1427677200, 58177523, 24 - tz.transition 1925, 4, :o3, -1411952400, 58181891, 24 - tz.transition 1925, 10, :o2, -1396227600, 58186259, 24 - tz.transition 1926, 4, :o3, -1379293200, 58190963, 24 - tz.transition 1926, 10, :o2, -1364778000, 58194995, 24 - tz.transition 1927, 4, :o3, -1348448400, 58199531, 24 - tz.transition 1927, 10, :o2, -1333328400, 58203731, 24 - tz.transition 1928, 4, :o3, -1316394000, 58208435, 24 - tz.transition 1928, 10, :o2, -1301274000, 58212635, 24 - tz.transition 1929, 4, :o3, -1284339600, 58217339, 24 - tz.transition 1929, 10, :o2, -1269824400, 58221371, 24 - tz.transition 1930, 4, :o3, -1253494800, 58225907, 24 - tz.transition 1930, 10, :o2, -1238374800, 58230107, 24 - tz.transition 1931, 4, :o3, -1221440400, 58234811, 24 - tz.transition 1931, 10, :o2, -1206925200, 58238843, 24 - tz.transition 1932, 4, :o3, -1191200400, 58243211, 24 - tz.transition 1932, 10, :o2, -1175475600, 58247579, 24 - tz.transition 1933, 3, :o3, -1160355600, 58251779, 24 - tz.transition 1933, 10, :o2, -1143421200, 58256483, 24 - tz.transition 1934, 4, :o3, -1127696400, 58260851, 24 - tz.transition 1934, 10, :o2, -1111971600, 58265219, 24 - tz.transition 1935, 3, :o3, -1096851600, 58269419, 24 - tz.transition 1935, 10, :o2, -1080522000, 58273955, 24 - tz.transition 1936, 4, :o3, -1063587600, 58278659, 24 - tz.transition 1936, 10, :o2, -1049072400, 58282691, 24 - tz.transition 1937, 4, :o3, -1033347600, 58287059, 24 - tz.transition 1937, 10, :o2, -1017622800, 58291427, 24 - tz.transition 1938, 3, :o3, -1002502800, 58295627, 24 - tz.transition 1938, 10, :o2, -986173200, 58300163, 24 - tz.transition 1939, 4, :o3, -969238800, 58304867, 24 - tz.transition 1939, 11, :o2, -950490000, 58310075, 24 - tz.transition 1940, 2, :o3, -942012000, 29156215, 12 - tz.transition 1940, 6, :o4, -932436000, 29157545, 12 - tz.transition 1942, 11, :o5, -857257200, 58335973, 24 - tz.transition 1943, 3, :o4, -844556400, 58339501, 24 - tz.transition 1943, 10, :o5, -828226800, 58344037, 24 - tz.transition 1944, 4, :o4, -812502000, 58348405, 24 - tz.transition 1944, 8, :o6, -800071200, 29175929, 12 - tz.transition 1944, 10, :o3, -796266000, 58352915, 24 - tz.transition 1945, 4, :o6, -781052400, 58357141, 24 - tz.transition 1945, 9, :o5, -766623600, 58361149, 24 - tz.transition 1976, 3, :o4, 196819200 - tz.transition 1976, 9, :o5, 212540400 - tz.transition 1977, 4, :o4, 228877200 - tz.transition 1977, 9, :o5, 243997200 - tz.transition 1978, 4, :o4, 260326800 - tz.transition 1978, 10, :o5, 276051600 - tz.transition 1979, 4, :o4, 291776400 - tz.transition 1979, 9, :o5, 307501200 - tz.transition 1980, 4, :o4, 323830800 - tz.transition 1980, 9, :o5, 338950800 - tz.transition 1981, 3, :o4, 354675600 - tz.transition 1981, 9, :o5, 370400400 - tz.transition 1982, 3, :o4, 386125200 - tz.transition 1982, 9, :o5, 401850000 - tz.transition 1983, 3, :o4, 417574800 - tz.transition 1983, 9, :o5, 433299600 - tz.transition 1984, 3, :o4, 449024400 - tz.transition 1984, 9, :o5, 465354000 - tz.transition 1985, 3, :o4, 481078800 - tz.transition 1985, 9, :o5, 496803600 - tz.transition 1986, 3, :o4, 512528400 - tz.transition 1986, 9, :o5, 528253200 - tz.transition 1987, 3, :o4, 543978000 - tz.transition 1987, 9, :o5, 559702800 - tz.transition 1988, 3, :o4, 575427600 - tz.transition 1988, 9, :o5, 591152400 - tz.transition 1989, 3, :o4, 606877200 - tz.transition 1989, 9, :o5, 622602000 - tz.transition 1990, 3, :o4, 638326800 - tz.transition 1990, 9, :o5, 654656400 - tz.transition 1991, 3, :o4, 670381200 - tz.transition 1991, 9, :o5, 686106000 - tz.transition 1992, 3, :o4, 701830800 - tz.transition 1992, 9, :o5, 717555600 - tz.transition 1993, 3, :o4, 733280400 - tz.transition 1993, 9, :o5, 749005200 - tz.transition 1994, 3, :o4, 764730000 - tz.transition 1994, 9, :o5, 780454800 - tz.transition 1995, 3, :o4, 796179600 - tz.transition 1995, 9, :o5, 811904400 - tz.transition 1996, 3, :o4, 828234000 - tz.transition 1996, 10, :o5, 846378000 - tz.transition 1997, 3, :o4, 859683600 - tz.transition 1997, 10, :o5, 877827600 - tz.transition 1998, 3, :o4, 891133200 - tz.transition 1998, 10, :o5, 909277200 - tz.transition 1999, 3, :o4, 922582800 - tz.transition 1999, 10, :o5, 941331600 - tz.transition 2000, 3, :o4, 954032400 - tz.transition 2000, 10, :o5, 972781200 - tz.transition 2001, 3, :o4, 985482000 - tz.transition 2001, 10, :o5, 1004230800 - tz.transition 2002, 3, :o4, 1017536400 - tz.transition 2002, 10, :o5, 1035680400 - tz.transition 2003, 3, :o4, 1048986000 - tz.transition 2003, 10, :o5, 1067130000 - tz.transition 2004, 3, :o4, 1080435600 - tz.transition 2004, 10, :o5, 1099184400 - tz.transition 2005, 3, :o4, 1111885200 - tz.transition 2005, 10, :o5, 1130634000 - tz.transition 2006, 3, :o4, 1143334800 - tz.transition 2006, 10, :o5, 1162083600 - tz.transition 2007, 3, :o4, 1174784400 - tz.transition 2007, 10, :o5, 1193533200 - tz.transition 2008, 3, :o4, 1206838800 - tz.transition 2008, 10, :o5, 1224982800 - tz.transition 2009, 3, :o4, 1238288400 - tz.transition 2009, 10, :o5, 1256432400 - tz.transition 2010, 3, :o4, 1269738000 - tz.transition 2010, 10, :o5, 1288486800 - tz.transition 2011, 3, :o4, 1301187600 - tz.transition 2011, 10, :o5, 1319936400 - tz.transition 2012, 3, :o4, 1332637200 - tz.transition 2012, 10, :o5, 1351386000 - tz.transition 2013, 3, :o4, 1364691600 - tz.transition 2013, 10, :o5, 1382835600 - tz.transition 2014, 3, :o4, 1396141200 - tz.transition 2014, 10, :o5, 1414285200 - tz.transition 2015, 3, :o4, 1427590800 - tz.transition 2015, 10, :o5, 1445734800 - tz.transition 2016, 3, :o4, 1459040400 - tz.transition 2016, 10, :o5, 1477789200 - tz.transition 2017, 3, :o4, 1490490000 - tz.transition 2017, 10, :o5, 1509238800 - tz.transition 2018, 3, :o4, 1521939600 - tz.transition 2018, 10, :o5, 1540688400 - tz.transition 2019, 3, :o4, 1553994000 - tz.transition 2019, 10, :o5, 1572138000 - tz.transition 2020, 3, :o4, 1585443600 - tz.transition 2020, 10, :o5, 1603587600 - tz.transition 2021, 3, :o4, 1616893200 - tz.transition 2021, 10, :o5, 1635642000 - tz.transition 2022, 3, :o4, 1648342800 - tz.transition 2022, 10, :o5, 1667091600 - tz.transition 2023, 3, :o4, 1679792400 - tz.transition 2023, 10, :o5, 1698541200 - tz.transition 2024, 3, :o4, 1711846800 - tz.transition 2024, 10, :o5, 1729990800 - tz.transition 2025, 3, :o4, 1743296400 - tz.transition 2025, 10, :o5, 1761440400 - tz.transition 2026, 3, :o4, 1774746000 - tz.transition 2026, 10, :o5, 1792890000 - tz.transition 2027, 3, :o4, 1806195600 - tz.transition 2027, 10, :o5, 1824944400 - tz.transition 2028, 3, :o4, 1837645200 - tz.transition 2028, 10, :o5, 1856394000 - tz.transition 2029, 3, :o4, 1869094800 - tz.transition 2029, 10, :o5, 1887843600 - tz.transition 2030, 3, :o4, 1901149200 - tz.transition 2030, 10, :o5, 1919293200 - tz.transition 2031, 3, :o4, 1932598800 - tz.transition 2031, 10, :o5, 1950742800 - tz.transition 2032, 3, :o4, 1964048400 - tz.transition 2032, 10, :o5, 1982797200 - tz.transition 2033, 3, :o4, 1995498000 - tz.transition 2033, 10, :o5, 2014246800 - tz.transition 2034, 3, :o4, 2026947600 - tz.transition 2034, 10, :o5, 2045696400 - tz.transition 2035, 3, :o4, 2058397200 - tz.transition 2035, 10, :o5, 2077146000 - tz.transition 2036, 3, :o4, 2090451600 - tz.transition 2036, 10, :o5, 2108595600 - tz.transition 2037, 3, :o4, 2121901200 - tz.transition 2037, 10, :o5, 2140045200 - tz.transition 2038, 3, :o4, 2153350800, 59172253, 24 - tz.transition 2038, 10, :o5, 2172099600, 59177461, 24 - tz.transition 2039, 3, :o4, 2184800400, 59180989, 24 - tz.transition 2039, 10, :o5, 2203549200, 59186197, 24 - tz.transition 2040, 3, :o4, 2216250000, 59189725, 24 - tz.transition 2040, 10, :o5, 2234998800, 59194933, 24 - tz.transition 2041, 3, :o4, 2248304400, 59198629, 24 - tz.transition 2041, 10, :o5, 2266448400, 59203669, 24 - tz.transition 2042, 3, :o4, 2279754000, 59207365, 24 - tz.transition 2042, 10, :o5, 2297898000, 59212405, 24 - tz.transition 2043, 3, :o4, 2311203600, 59216101, 24 - tz.transition 2043, 10, :o5, 2329347600, 59221141, 24 - tz.transition 2044, 3, :o4, 2342653200, 59224837, 24 - tz.transition 2044, 10, :o5, 2361402000, 59230045, 24 - tz.transition 2045, 3, :o4, 2374102800, 59233573, 24 - tz.transition 2045, 10, :o5, 2392851600, 59238781, 24 - tz.transition 2046, 3, :o4, 2405552400, 59242309, 24 - tz.transition 2046, 10, :o5, 2424301200, 59247517, 24 - tz.transition 2047, 3, :o4, 2437606800, 59251213, 24 - tz.transition 2047, 10, :o5, 2455750800, 59256253, 24 - tz.transition 2048, 3, :o4, 2469056400, 59259949, 24 - tz.transition 2048, 10, :o5, 2487200400, 59264989, 24 - tz.transition 2049, 3, :o4, 2500506000, 59268685, 24 - tz.transition 2049, 10, :o5, 2519254800, 59273893, 24 - tz.transition 2050, 3, :o4, 2531955600, 59277421, 24 - tz.transition 2050, 10, :o5, 2550704400, 59282629, 24 - tz.transition 2051, 3, :o4, 2563405200, 59286157, 24 - tz.transition 2051, 10, :o5, 2582154000, 59291365, 24 - tz.transition 2052, 3, :o4, 2595459600, 59295061, 24 - tz.transition 2052, 10, :o5, 2613603600, 59300101, 24 - tz.transition 2053, 3, :o4, 2626909200, 59303797, 24 - tz.transition 2053, 10, :o5, 2645053200, 59308837, 24 - tz.transition 2054, 3, :o4, 2658358800, 59312533, 24 - tz.transition 2054, 10, :o5, 2676502800, 59317573, 24 - tz.transition 2055, 3, :o4, 2689808400, 59321269, 24 - tz.transition 2055, 10, :o5, 2708557200, 59326477, 24 - tz.transition 2056, 3, :o4, 2721258000, 59330005, 24 - tz.transition 2056, 10, :o5, 2740006800, 59335213, 24 - tz.transition 2057, 3, :o4, 2752707600, 59338741, 24 - tz.transition 2057, 10, :o5, 2771456400, 59343949, 24 - tz.transition 2058, 3, :o4, 2784762000, 59347645, 24 - tz.transition 2058, 10, :o5, 2802906000, 59352685, 24 - tz.transition 2059, 3, :o4, 2816211600, 59356381, 24 - tz.transition 2059, 10, :o5, 2834355600, 59361421, 24 - tz.transition 2060, 3, :o4, 2847661200, 59365117, 24 - tz.transition 2060, 10, :o5, 2866410000, 59370325, 24 - tz.transition 2061, 3, :o4, 2879110800, 59373853, 24 - tz.transition 2061, 10, :o5, 2897859600, 59379061, 24 - tz.transition 2062, 3, :o4, 2910560400, 59382589, 24 - tz.transition 2062, 10, :o5, 2929309200, 59387797, 24 - tz.transition 2063, 3, :o4, 2942010000, 59391325, 24 - tz.transition 2063, 10, :o5, 2960758800, 59396533, 24 - tz.transition 2064, 3, :o4, 2974064400, 59400229, 24 - tz.transition 2064, 10, :o5, 2992208400, 59405269, 24 - end - end - end - end - end -end diff -Nru ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/definitions/Europe/Prague.rb ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/definitions/Europe/Prague.rb --- ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/definitions/Europe/Prague.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/definitions/Europe/Prague.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,220 +0,0 @@ -# encoding: UTF-8 - -# This file contains data derived from the IANA Time Zone Database -# (http://www.iana.org/time-zones). - -module TZInfo - module Data - module Definitions - module Europe - module Prague - include TimezoneDefinition - - timezone 'Europe/Prague' do |tz| - tz.offset :o0, 3464, 0, :LMT - tz.offset :o1, 3464, 0, :PMT - tz.offset :o2, 3600, 0, :CET - tz.offset :o3, 3600, 3600, :CEST - - tz.transition 1849, 12, :o1, -3786829064, 25884991367, 10800 - tz.transition 1891, 9, :o2, -2469401864, 26049669767, 10800 - tz.transition 1916, 4, :o3, -1693706400, 29051813, 12 - tz.transition 1916, 9, :o2, -1680483600, 58107299, 24 - tz.transition 1917, 4, :o3, -1663455600, 58112029, 24 - tz.transition 1917, 9, :o2, -1650150000, 58115725, 24 - tz.transition 1918, 4, :o3, -1632006000, 58120765, 24 - tz.transition 1918, 9, :o2, -1618700400, 58124461, 24 - tz.transition 1940, 4, :o3, -938905200, 58313293, 24 - tz.transition 1942, 11, :o2, -857257200, 58335973, 24 - tz.transition 1943, 3, :o3, -844556400, 58339501, 24 - tz.transition 1943, 10, :o2, -828226800, 58344037, 24 - tz.transition 1944, 4, :o3, -812502000, 58348405, 24 - tz.transition 1944, 9, :o2, -798073200, 58352413, 24 - tz.transition 1945, 4, :o3, -780534000, 58357285, 24 - tz.transition 1945, 11, :o2, -761180400, 58362661, 24 - tz.transition 1946, 5, :o3, -746578800, 58366717, 24 - tz.transition 1946, 10, :o2, -733359600, 58370389, 24 - tz.transition 1947, 4, :o3, -716425200, 58375093, 24 - tz.transition 1947, 10, :o2, -701910000, 58379125, 24 - tz.transition 1948, 4, :o3, -684975600, 58383829, 24 - tz.transition 1948, 10, :o2, -670460400, 58387861, 24 - tz.transition 1949, 4, :o3, -654217200, 58392373, 24 - tz.transition 1949, 10, :o2, -639010800, 58396597, 24 - tz.transition 1979, 4, :o3, 291776400 - tz.transition 1979, 9, :o2, 307501200 - tz.transition 1980, 4, :o3, 323830800 - tz.transition 1980, 9, :o2, 338950800 - tz.transition 1981, 3, :o3, 354675600 - tz.transition 1981, 9, :o2, 370400400 - tz.transition 1982, 3, :o3, 386125200 - tz.transition 1982, 9, :o2, 401850000 - tz.transition 1983, 3, :o3, 417574800 - tz.transition 1983, 9, :o2, 433299600 - tz.transition 1984, 3, :o3, 449024400 - tz.transition 1984, 9, :o2, 465354000 - tz.transition 1985, 3, :o3, 481078800 - tz.transition 1985, 9, :o2, 496803600 - tz.transition 1986, 3, :o3, 512528400 - tz.transition 1986, 9, :o2, 528253200 - tz.transition 1987, 3, :o3, 543978000 - tz.transition 1987, 9, :o2, 559702800 - tz.transition 1988, 3, :o3, 575427600 - tz.transition 1988, 9, :o2, 591152400 - tz.transition 1989, 3, :o3, 606877200 - tz.transition 1989, 9, :o2, 622602000 - tz.transition 1990, 3, :o3, 638326800 - tz.transition 1990, 9, :o2, 654656400 - tz.transition 1991, 3, :o3, 670381200 - tz.transition 1991, 9, :o2, 686106000 - tz.transition 1992, 3, :o3, 701830800 - tz.transition 1992, 9, :o2, 717555600 - tz.transition 1993, 3, :o3, 733280400 - tz.transition 1993, 9, :o2, 749005200 - tz.transition 1994, 3, :o3, 764730000 - tz.transition 1994, 9, :o2, 780454800 - tz.transition 1995, 3, :o3, 796179600 - tz.transition 1995, 9, :o2, 811904400 - tz.transition 1996, 3, :o3, 828234000 - tz.transition 1996, 10, :o2, 846378000 - tz.transition 1997, 3, :o3, 859683600 - tz.transition 1997, 10, :o2, 877827600 - tz.transition 1998, 3, :o3, 891133200 - tz.transition 1998, 10, :o2, 909277200 - tz.transition 1999, 3, :o3, 922582800 - tz.transition 1999, 10, :o2, 941331600 - tz.transition 2000, 3, :o3, 954032400 - tz.transition 2000, 10, :o2, 972781200 - tz.transition 2001, 3, :o3, 985482000 - tz.transition 2001, 10, :o2, 1004230800 - tz.transition 2002, 3, :o3, 1017536400 - tz.transition 2002, 10, :o2, 1035680400 - tz.transition 2003, 3, :o3, 1048986000 - tz.transition 2003, 10, :o2, 1067130000 - tz.transition 2004, 3, :o3, 1080435600 - tz.transition 2004, 10, :o2, 1099184400 - tz.transition 2005, 3, :o3, 1111885200 - tz.transition 2005, 10, :o2, 1130634000 - tz.transition 2006, 3, :o3, 1143334800 - tz.transition 2006, 10, :o2, 1162083600 - tz.transition 2007, 3, :o3, 1174784400 - tz.transition 2007, 10, :o2, 1193533200 - tz.transition 2008, 3, :o3, 1206838800 - tz.transition 2008, 10, :o2, 1224982800 - tz.transition 2009, 3, :o3, 1238288400 - tz.transition 2009, 10, :o2, 1256432400 - tz.transition 2010, 3, :o3, 1269738000 - tz.transition 2010, 10, :o2, 1288486800 - tz.transition 2011, 3, :o3, 1301187600 - tz.transition 2011, 10, :o2, 1319936400 - tz.transition 2012, 3, :o3, 1332637200 - tz.transition 2012, 10, :o2, 1351386000 - tz.transition 2013, 3, :o3, 1364691600 - tz.transition 2013, 10, :o2, 1382835600 - tz.transition 2014, 3, :o3, 1396141200 - tz.transition 2014, 10, :o2, 1414285200 - tz.transition 2015, 3, :o3, 1427590800 - tz.transition 2015, 10, :o2, 1445734800 - tz.transition 2016, 3, :o3, 1459040400 - tz.transition 2016, 10, :o2, 1477789200 - tz.transition 2017, 3, :o3, 1490490000 - tz.transition 2017, 10, :o2, 1509238800 - tz.transition 2018, 3, :o3, 1521939600 - tz.transition 2018, 10, :o2, 1540688400 - tz.transition 2019, 3, :o3, 1553994000 - tz.transition 2019, 10, :o2, 1572138000 - tz.transition 2020, 3, :o3, 1585443600 - tz.transition 2020, 10, :o2, 1603587600 - tz.transition 2021, 3, :o3, 1616893200 - tz.transition 2021, 10, :o2, 1635642000 - tz.transition 2022, 3, :o3, 1648342800 - tz.transition 2022, 10, :o2, 1667091600 - tz.transition 2023, 3, :o3, 1679792400 - tz.transition 2023, 10, :o2, 1698541200 - tz.transition 2024, 3, :o3, 1711846800 - tz.transition 2024, 10, :o2, 1729990800 - tz.transition 2025, 3, :o3, 1743296400 - tz.transition 2025, 10, :o2, 1761440400 - tz.transition 2026, 3, :o3, 1774746000 - tz.transition 2026, 10, :o2, 1792890000 - tz.transition 2027, 3, :o3, 1806195600 - tz.transition 2027, 10, :o2, 1824944400 - tz.transition 2028, 3, :o3, 1837645200 - tz.transition 2028, 10, :o2, 1856394000 - tz.transition 2029, 3, :o3, 1869094800 - tz.transition 2029, 10, :o2, 1887843600 - tz.transition 2030, 3, :o3, 1901149200 - tz.transition 2030, 10, :o2, 1919293200 - tz.transition 2031, 3, :o3, 1932598800 - tz.transition 2031, 10, :o2, 1950742800 - tz.transition 2032, 3, :o3, 1964048400 - tz.transition 2032, 10, :o2, 1982797200 - tz.transition 2033, 3, :o3, 1995498000 - tz.transition 2033, 10, :o2, 2014246800 - tz.transition 2034, 3, :o3, 2026947600 - tz.transition 2034, 10, :o2, 2045696400 - tz.transition 2035, 3, :o3, 2058397200 - tz.transition 2035, 10, :o2, 2077146000 - tz.transition 2036, 3, :o3, 2090451600 - tz.transition 2036, 10, :o2, 2108595600 - tz.transition 2037, 3, :o3, 2121901200 - tz.transition 2037, 10, :o2, 2140045200 - tz.transition 2038, 3, :o3, 2153350800, 59172253, 24 - tz.transition 2038, 10, :o2, 2172099600, 59177461, 24 - tz.transition 2039, 3, :o3, 2184800400, 59180989, 24 - tz.transition 2039, 10, :o2, 2203549200, 59186197, 24 - tz.transition 2040, 3, :o3, 2216250000, 59189725, 24 - tz.transition 2040, 10, :o2, 2234998800, 59194933, 24 - tz.transition 2041, 3, :o3, 2248304400, 59198629, 24 - tz.transition 2041, 10, :o2, 2266448400, 59203669, 24 - tz.transition 2042, 3, :o3, 2279754000, 59207365, 24 - tz.transition 2042, 10, :o2, 2297898000, 59212405, 24 - tz.transition 2043, 3, :o3, 2311203600, 59216101, 24 - tz.transition 2043, 10, :o2, 2329347600, 59221141, 24 - tz.transition 2044, 3, :o3, 2342653200, 59224837, 24 - tz.transition 2044, 10, :o2, 2361402000, 59230045, 24 - tz.transition 2045, 3, :o3, 2374102800, 59233573, 24 - tz.transition 2045, 10, :o2, 2392851600, 59238781, 24 - tz.transition 2046, 3, :o3, 2405552400, 59242309, 24 - tz.transition 2046, 10, :o2, 2424301200, 59247517, 24 - tz.transition 2047, 3, :o3, 2437606800, 59251213, 24 - tz.transition 2047, 10, :o2, 2455750800, 59256253, 24 - tz.transition 2048, 3, :o3, 2469056400, 59259949, 24 - tz.transition 2048, 10, :o2, 2487200400, 59264989, 24 - tz.transition 2049, 3, :o3, 2500506000, 59268685, 24 - tz.transition 2049, 10, :o2, 2519254800, 59273893, 24 - tz.transition 2050, 3, :o3, 2531955600, 59277421, 24 - tz.transition 2050, 10, :o2, 2550704400, 59282629, 24 - tz.transition 2051, 3, :o3, 2563405200, 59286157, 24 - tz.transition 2051, 10, :o2, 2582154000, 59291365, 24 - tz.transition 2052, 3, :o3, 2595459600, 59295061, 24 - tz.transition 2052, 10, :o2, 2613603600, 59300101, 24 - tz.transition 2053, 3, :o3, 2626909200, 59303797, 24 - tz.transition 2053, 10, :o2, 2645053200, 59308837, 24 - tz.transition 2054, 3, :o3, 2658358800, 59312533, 24 - tz.transition 2054, 10, :o2, 2676502800, 59317573, 24 - tz.transition 2055, 3, :o3, 2689808400, 59321269, 24 - tz.transition 2055, 10, :o2, 2708557200, 59326477, 24 - tz.transition 2056, 3, :o3, 2721258000, 59330005, 24 - tz.transition 2056, 10, :o2, 2740006800, 59335213, 24 - tz.transition 2057, 3, :o3, 2752707600, 59338741, 24 - tz.transition 2057, 10, :o2, 2771456400, 59343949, 24 - tz.transition 2058, 3, :o3, 2784762000, 59347645, 24 - tz.transition 2058, 10, :o2, 2802906000, 59352685, 24 - tz.transition 2059, 3, :o3, 2816211600, 59356381, 24 - tz.transition 2059, 10, :o2, 2834355600, 59361421, 24 - tz.transition 2060, 3, :o3, 2847661200, 59365117, 24 - tz.transition 2060, 10, :o2, 2866410000, 59370325, 24 - tz.transition 2061, 3, :o3, 2879110800, 59373853, 24 - tz.transition 2061, 10, :o2, 2897859600, 59379061, 24 - tz.transition 2062, 3, :o3, 2910560400, 59382589, 24 - tz.transition 2062, 10, :o2, 2929309200, 59387797, 24 - tz.transition 2063, 3, :o3, 2942010000, 59391325, 24 - tz.transition 2063, 10, :o2, 2960758800, 59396533, 24 - tz.transition 2064, 3, :o3, 2974064400, 59400229, 24 - tz.transition 2064, 10, :o2, 2992208400, 59405269, 24 - end - end - end - end - end -end diff -Nru ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/definitions/UTC.rb ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/definitions/UTC.rb --- ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/definitions/UTC.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/definitions/UTC.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -# encoding: UTF-8 - -# This file contains data derived from the IANA Time Zone Database -# (http://www.iana.org/time-zones). - -module TZInfo - module Data - module Definitions - module UTC - include TimezoneDefinition - - linked_timezone 'UTC', 'Etc/UTC' - end - end - end -end diff -Nru ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/indexes/countries.rb ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/indexes/countries.rb --- ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/indexes/countries.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/indexes/countries.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,927 +0,0 @@ -# encoding: UTF-8 - -# This file contains data derived from the IANA Time Zone Database -# (http://www.iana.org/time-zones). - -module TZInfo - module Data - module Indexes - module Countries - include CountryIndexDefinition - - country 'AD', 'Andorra' do |c| - c.timezone 'Europe/Andorra', 85, 2, 91, 60 - end - country 'AE', 'United Arab Emirates' do |c| - c.timezone 'Asia/Dubai', 253, 10, 553, 10 - end - country 'AF', 'Afghanistan' do |c| - c.timezone 'Asia/Kabul', 2071, 60, 346, 5 - end - country 'AG', 'Antigua & Barbuda' do |c| - c.timezone 'America/Port_of_Spain', 213, 20, -3691, 60 - end - country 'AI', 'Anguilla' do |c| - c.timezone 'America/Port_of_Spain', 213, 20, -3691, 60 - end - country 'AL', 'Albania' do |c| - c.timezone 'Europe/Tirane', 124, 3, 119, 6 - end - country 'AM', 'Armenia' do |c| - c.timezone 'Asia/Yerevan', 2411, 60, 89, 2 - end - country 'AO', 'Angola' do |c| - c.timezone 'Africa/Lagos', 129, 20, 17, 5, 'West Africa Time (UTC+1)' - end - country 'AQ', 'Antarctica' do |c| - c.timezone 'Antarctica/Rothera', -2027, 30, -1022, 15, 'Rothera Station, Adelaide Island' - c.timezone 'Antarctica/Palmer', -324, 5, -641, 10, 'Palmer Station, Anvers Island' - c.timezone 'Antarctica/Mawson', -338, 5, 3773, 60, 'Mawson Station, Holme Bay' - c.timezone 'Antarctica/Davis', -823, 12, 2339, 30, 'Davis Station, Vestfold Hills' - c.timezone 'Antarctica/Casey', -3977, 60, 6631, 60, 'Casey Station, Bailey Peninsula' - c.timezone 'Antarctica/Vostok', -392, 5, 1069, 10, 'Vostok Station, Lake Vostok' - c.timezone 'Antarctica/DumontDUrville', -200, 3, 8401, 60, 'Dumont-d\'Urville Station, Terre Adelie' - c.timezone 'Antarctica/Syowa', -124211, 1800, 3959, 100, 'Syowa Station, E Ongul I' - c.timezone 'Antarctica/Troll', -259241, 3600, 507, 200, 'Troll Station, Queen Maud Land' - c.timezone 'Pacific/Auckland', -553, 15, 5243, 30, 'New Zealand time' - end - country 'AR', 'Argentina' do |c| - c.timezone 'America/Argentina/Buenos_Aires', -173, 5, -1169, 20, 'Buenos Aires (BA, CF)' - c.timezone 'America/Argentina/Cordoba', -157, 5, -3851, 60, 'most locations (CB, CC, CN, ER, FM, MN, SE, SF)' - c.timezone 'America/Argentina/Salta', -1487, 60, -785, 12, '(SA, LP, NQ, RN)' - c.timezone 'America/Argentina/Jujuy', -1451, 60, -653, 10, 'Jujuy (JY)' - c.timezone 'America/Argentina/Tucuman', -1609, 60, -3913, 60, 'Tucumán (TM)' - c.timezone 'America/Argentina/Catamarca', -427, 15, -3947, 60, 'Catamarca (CT), Chubut (CH)' - c.timezone 'America/Argentina/La_Rioja', -883, 30, -1337, 20, 'La Rioja (LR)' - c.timezone 'America/Argentina/San_Juan', -473, 15, -4111, 60, 'San Juan (SJ)' - c.timezone 'America/Argentina/Mendoza', -1973, 60, -4129, 60, 'Mendoza (MZ)' - c.timezone 'America/Argentina/San_Luis', -1999, 60, -1327, 20, 'San Luis (SL)' - c.timezone 'America/Argentina/Rio_Gallegos', -1549, 30, -4153, 60, 'Santa Cruz (SC)' - c.timezone 'America/Argentina/Ushuaia', -274, 5, -683, 10, 'Tierra del Fuego (TF)' - end - country 'AS', 'Samoa (American)' do |c| - c.timezone 'Pacific/Pago_Pago', -214, 15, -1707, 10, 'Samoa, Midway' - end - country 'AT', 'Austria' do |c| - c.timezone 'Europe/Vienna', 2893, 60, 49, 3 - end - country 'AU', 'Australia' do |c| - c.timezone 'Australia/Lord_Howe', -631, 20, 1909, 12, 'Lord Howe Island' - c.timezone 'Antarctica/Macquarie', -109, 2, 3179, 20, 'Macquarie Island' - c.timezone 'Australia/Hobart', -2573, 60, 8839, 60, 'Tasmania - most locations' - c.timezone 'Australia/Currie', -599, 15, 2158, 15, 'Tasmania - King Island' - c.timezone 'Australia/Melbourne', -2269, 60, 4349, 30, 'Victoria' - c.timezone 'Australia/Sydney', -508, 15, 9073, 60, 'New South Wales - most locations' - c.timezone 'Australia/Broken_Hill', -639, 20, 2829, 20, 'New South Wales - Yancowinna' - c.timezone 'Australia/Brisbane', -412, 15, 4591, 30, 'Queensland - most locations' - c.timezone 'Australia/Lindeman', -304, 15, 149, 1, 'Queensland - Holiday Islands' - c.timezone 'Australia/Adelaide', -419, 12, 1663, 12, 'South Australia' - c.timezone 'Australia/Darwin', -187, 15, 785, 6, 'Northern Territory' - c.timezone 'Australia/Perth', -639, 20, 2317, 20, 'Western Australia - most locations' - c.timezone 'Australia/Eucla', -1903, 60, 1933, 15, 'Western Australia - Eucla area' - end - country 'AW', 'Aruba' do |c| - c.timezone 'America/Curacao', 731, 60, -69, 1 - end - country 'AX', 'Aaland Islands' do |c| - c.timezone 'Europe/Helsinki', 361, 6, 749, 30 - end - country 'AZ', 'Azerbaijan' do |c| - c.timezone 'Asia/Baku', 2423, 60, 997, 20 - end - country 'BA', 'Bosnia & Herzegovina' do |c| - c.timezone 'Europe/Belgrade', 269, 6, 41, 2 - end - country 'BB', 'Barbados' do |c| - c.timezone 'America/Barbados', 131, 10, -3577, 60 - end - country 'BD', 'Bangladesh' do |c| - c.timezone 'Asia/Dhaka', 1423, 60, 1085, 12 - end - country 'BE', 'Belgium' do |c| - c.timezone 'Europe/Brussels', 305, 6, 13, 3 - end - country 'BF', 'Burkina Faso' do |c| - c.timezone 'Africa/Abidjan', 319, 60, -121, 30 - end - country 'BG', 'Bulgaria' do |c| - c.timezone 'Europe/Sofia', 2561, 60, 1399, 60 - end - country 'BH', 'Bahrain' do |c| - c.timezone 'Asia/Qatar', 1517, 60, 773, 15 - end - country 'BI', 'Burundi' do |c| - c.timezone 'Africa/Maputo', -779, 30, 391, 12, 'Central Africa Time (UTC+2)' - end - country 'BJ', 'Benin' do |c| - c.timezone 'Africa/Lagos', 129, 20, 17, 5, 'West Africa Time (UTC+1)' - end - country 'BL', 'St Barthelemy' do |c| - c.timezone 'America/Port_of_Spain', 213, 20, -3691, 60 - end - country 'BM', 'Bermuda' do |c| - c.timezone 'Atlantic/Bermuda', 1937, 60, -1943, 30 - end - country 'BN', 'Brunei' do |c| - c.timezone 'Asia/Brunei', 74, 15, 1379, 12 - end - country 'BO', 'Bolivia' do |c| - c.timezone 'America/La_Paz', -33, 2, -1363, 20 - end - country 'BQ', 'Caribbean Netherlands' do |c| - c.timezone 'America/Curacao', 731, 60, -69, 1 - end - country 'BR', 'Brazil' do |c| - c.timezone 'America/Noronha', -77, 20, -389, 12, 'Atlantic islands' - c.timezone 'America/Belem', -29, 20, -2909, 60, 'Amapá, E Pará' - c.timezone 'America/Fortaleza', -223, 60, -77, 2, 'NE Brazil (MA, PI, CE, RN, PB)' - c.timezone 'America/Recife', -161, 20, -349, 10, 'Pernambuco' - c.timezone 'America/Araguaina', -36, 5, -241, 5, 'Tocantins' - c.timezone 'America/Maceio', -29, 3, -2143, 60, 'Alagoas, Sergipe' - c.timezone 'America/Bahia', -779, 60, -2311, 60, 'Bahia' - c.timezone 'America/Sao_Paulo', -353, 15, -2797, 60, 'S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)' - c.timezone 'America/Campo_Grande', -409, 20, -3277, 60, 'Mato Grosso do Sul' - c.timezone 'America/Cuiaba', -187, 12, -673, 12, 'Mato Grosso' - c.timezone 'America/Santarem', -73, 30, -823, 15, 'W Pará' - c.timezone 'America/Porto_Velho', -263, 30, -639, 10, 'Rondônia' - c.timezone 'America/Boa_Vista', 169, 60, -182, 3, 'Roraima' - c.timezone 'America/Manaus', -47, 15, -3601, 60, 'E Amazonas' - c.timezone 'America/Eirunepe', -20, 3, -1048, 15, 'W Amazonas' - c.timezone 'America/Rio_Branco', -299, 30, -339, 5, 'Acre' - end - country 'BS', 'Bahamas' do |c| - c.timezone 'America/Nassau', 301, 12, -1547, 20 - end - country 'BT', 'Bhutan' do |c| - c.timezone 'Asia/Thimphu', 412, 15, 1793, 20 - end - country 'BV', 'Bouvet Island' - country 'BW', 'Botswana' do |c| - c.timezone 'Africa/Maputo', -779, 30, 391, 12, 'Central Africa Time (UTC+2)' - end - country 'BY', 'Belarus' do |c| - c.timezone 'Europe/Minsk', 539, 10, 827, 30 - end - country 'BZ', 'Belize' do |c| - c.timezone 'America/Belize', 35, 2, -441, 5 - end - country 'CA', 'Canada' do |c| - c.timezone 'America/St_Johns', 1427, 30, -3163, 60, 'Newfoundland Time, including SE Labrador' - c.timezone 'America/Halifax', 893, 20, -318, 5, 'Atlantic Time - Nova Scotia (most places), PEI' - c.timezone 'America/Glace_Bay', 231, 5, -1199, 20, 'Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971' - c.timezone 'America/Moncton', 461, 10, -3887, 60, 'Atlantic Time - New Brunswick' - c.timezone 'America/Goose_Bay', 160, 3, -725, 12, 'Atlantic Time - Labrador - most locations' - c.timezone 'America/Blanc-Sablon', 617, 12, -3427, 60, 'Atlantic Standard Time - Quebec - Lower North Shore' - c.timezone 'America/Toronto', 873, 20, -4763, 60, 'Eastern Time - Ontario & Quebec - most locations' - c.timezone 'America/Nipigon', 2941, 60, -1324, 15, 'Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973' - c.timezone 'America/Thunder_Bay', 2903, 60, -357, 4, 'Eastern Time - Thunder Bay, Ontario' - c.timezone 'America/Iqaluit', 956, 15, -1027, 15, 'Eastern Time - east Nunavut - most locations' - c.timezone 'America/Pangnirtung', 992, 15, -986, 15, 'Eastern Time - Pangnirtung, Nunavut' - c.timezone 'America/Resolute', 33613, 450, -22759, 240, 'Central Time - Resolute, Nunavut' - c.timezone 'America/Atikokan', 175531, 3600, -54973, 600, 'Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut' - c.timezone 'America/Rankin_Inlet', 3769, 60, -331499, 3600, 'Central Time - central Nunavut' - c.timezone 'America/Winnipeg', 2993, 60, -1943, 20, 'Central Time - Manitoba & west Ontario' - c.timezone 'America/Rainy_River', 2923, 60, -2837, 30, 'Central Time - Rainy River & Fort Frances, Ontario' - c.timezone 'America/Regina', 252, 5, -2093, 20, 'Central Standard Time - Saskatchewan - most locations' - c.timezone 'America/Swift_Current', 3017, 60, -647, 6, 'Central Standard Time - Saskatchewan - midwest' - c.timezone 'America/Edmonton', 1071, 20, -1702, 15, 'Mountain Time - Alberta, east British Columbia & west Saskatchewan' - c.timezone 'America/Cambridge_Bay', 24881, 360, -37819, 360, 'Mountain Time - west Nunavut' - c.timezone 'America/Yellowknife', 1249, 20, -2287, 20, 'Mountain Time - central Northwest Territories' - c.timezone 'America/Inuvik', 246059, 3600, -8023, 60, 'Mountain Time - west Northwest Territories' - c.timezone 'America/Creston', 491, 10, -6991, 60, 'Mountain Standard Time - Creston, British Columbia' - c.timezone 'America/Dawson_Creek', 1793, 30, -3607, 30, 'Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia' - c.timezone 'America/Vancouver', 739, 15, -7387, 60, 'Pacific Time - west British Columbia' - c.timezone 'America/Whitehorse', 3643, 60, -2701, 20, 'Pacific Time - south Yukon' - c.timezone 'America/Dawson', 961, 15, -1673, 12, 'Pacific Time - north Yukon' - end - country 'CC', 'Cocos (Keeling) Islands' do |c| - c.timezone 'Indian/Cocos', -73, 6, 1163, 12 - end - country 'CD', 'Congo (Dem. Rep.)' do |c| - c.timezone 'Africa/Maputo', -779, 30, 391, 12, 'Central Africa Time (UTC+2)' - c.timezone 'Africa/Lagos', 129, 20, 17, 5, 'West Africa Time (UTC+1)' - end - country 'CF', 'Central African Rep.' do |c| - c.timezone 'Africa/Lagos', 129, 20, 17, 5, 'West Africa Time (UTC+1)' - end - country 'CG', 'Congo (Rep.)' do |c| - c.timezone 'Africa/Lagos', 129, 20, 17, 5, 'West Africa Time (UTC+1)' - end - country 'CH', 'Switzerland' do |c| - c.timezone 'Europe/Zurich', 2843, 60, 128, 15, 'Swiss time' - end - country 'CI', 'Cote d\'Ivoire' do |c| - c.timezone 'Africa/Abidjan', 319, 60, -121, 30 - end - country 'CK', 'Cook Islands' do |c| - c.timezone 'Pacific/Rarotonga', -637, 30, -4793, 30 - end - country 'CL', 'Chile' do |c| - c.timezone 'America/Santiago', -669, 20, -212, 3, 'most locations' - c.timezone 'Pacific/Easter', -543, 20, -3283, 30, 'Easter Island' - end - country 'CM', 'Cameroon' do |c| - c.timezone 'Africa/Lagos', 129, 20, 17, 5, 'West Africa Time (UTC+1)' - end - country 'CN', 'China' do |c| - c.timezone 'Asia/Shanghai', 937, 30, 1822, 15, 'Beijing Time' - c.timezone 'Asia/Urumqi', 219, 5, 1051, 12, 'Xinjiang Time' - end - country 'CO', 'Colombia' do |c| - c.timezone 'America/Bogota', 23, 5, -889, 12 - end - country 'CR', 'Costa Rica' do |c| - c.timezone 'America/Costa_Rica', 149, 15, -1009, 12 - end - country 'CU', 'Cuba' do |c| - c.timezone 'America/Havana', 347, 15, -2471, 30 - end - country 'CV', 'Cape Verde' do |c| - c.timezone 'Atlantic/Cape_Verde', 179, 12, -1411, 60 - end - country 'CW', 'Curacao' do |c| - c.timezone 'America/Curacao', 731, 60, -69, 1 - end - country 'CX', 'Christmas Island' do |c| - c.timezone 'Indian/Christmas', -125, 12, 6343, 60 - end - country 'CY', 'Cyprus' do |c| - c.timezone 'Asia/Nicosia', 211, 6, 1001, 30 - end - country 'CZ', 'Czech Republic' do |c| - c.timezone 'Europe/Prague', 601, 12, 433, 30 - end - country 'DE', 'Germany' do |c| - c.timezone 'Europe/Berlin', 105, 2, 401, 30, 'Berlin time' - c.timezone 'Europe/Zurich', 2843, 60, 128, 15, 'Swiss time' - end - country 'DJ', 'Djibouti' do |c| - c.timezone 'Africa/Nairobi', -77, 60, 2209, 60 - end - country 'DK', 'Denmark' do |c| - c.timezone 'Europe/Copenhagen', 167, 3, 151, 12 - end - country 'DM', 'Dominica' do |c| - c.timezone 'America/Port_of_Spain', 213, 20, -3691, 60 - end - country 'DO', 'Dominican Republic' do |c| - c.timezone 'America/Santo_Domingo', 277, 15, -699, 10 - end - country 'DZ', 'Algeria' do |c| - c.timezone 'Africa/Algiers', 2207, 60, 61, 20 - end - country 'EC', 'Ecuador' do |c| - c.timezone 'America/Guayaquil', -13, 6, -479, 6, 'mainland' - c.timezone 'Pacific/Galapagos', -9, 10, -448, 5, 'Galápagos Islands' - end - country 'EE', 'Estonia' do |c| - c.timezone 'Europe/Tallinn', 713, 12, 99, 4 - end - country 'EG', 'Egypt' do |c| - c.timezone 'Africa/Cairo', 601, 20, 125, 4 - end - country 'EH', 'Western Sahara' do |c| - c.timezone 'Africa/El_Aaiun', 543, 20, -66, 5 - end - country 'ER', 'Eritrea' do |c| - c.timezone 'Africa/Nairobi', -77, 60, 2209, 60 - end - country 'ES', 'Spain' do |c| - c.timezone 'Europe/Madrid', 202, 5, -221, 60, 'mainland' - c.timezone 'Africa/Ceuta', 2153, 60, -319, 60, 'Ceuta & Melilla' - c.timezone 'Atlantic/Canary', 281, 10, -77, 5, 'Canary Islands' - end - country 'ET', 'Ethiopia' do |c| - c.timezone 'Africa/Nairobi', -77, 60, 2209, 60 - end - country 'FI', 'Finland' do |c| - c.timezone 'Europe/Helsinki', 361, 6, 749, 30 - end - country 'FJ', 'Fiji' do |c| - c.timezone 'Pacific/Fiji', -272, 15, 2141, 12 - end - country 'FK', 'Falkland Islands' do |c| - c.timezone 'Atlantic/Stanley', -517, 10, -1157, 20 - end - country 'FM', 'Micronesia' do |c| - c.timezone 'Pacific/Chuuk', 89, 12, 9107, 60, 'Chuuk (Truk) and Yap' - c.timezone 'Pacific/Pohnpei', 209, 30, 9493, 60, 'Pohnpei (Ponape)' - c.timezone 'Pacific/Kosrae', 319, 60, 9779, 60, 'Kosrae' - end - country 'FO', 'Faroe Islands' do |c| - c.timezone 'Atlantic/Faroe', 3721, 60, -203, 30 - end - country 'FR', 'France' do |c| - c.timezone 'Europe/Paris', 733, 15, 7, 3 - end - country 'GA', 'Gabon' do |c| - c.timezone 'Africa/Lagos', 129, 20, 17, 5, 'West Africa Time (UTC+1)' - end - country 'GB', 'Britain (UK)' do |c| - c.timezone 'Europe/London', 6181, 120, -451, 3600 - end - country 'GD', 'Grenada' do |c| - c.timezone 'America/Port_of_Spain', 213, 20, -3691, 60 - end - country 'GE', 'Georgia' do |c| - c.timezone 'Asia/Tbilisi', 2503, 60, 2689, 60 - end - country 'GF', 'French Guiana' do |c| - c.timezone 'America/Cayenne', 74, 15, -157, 3 - end - country 'GG', 'Guernsey' do |c| - c.timezone 'Europe/London', 6181, 120, -451, 3600 - end - country 'GH', 'Ghana' do |c| - c.timezone 'Africa/Accra', 111, 20, -13, 60 - end - country 'GI', 'Gibraltar' do |c| - c.timezone 'Europe/Gibraltar', 542, 15, -107, 20 - end - country 'GL', 'Greenland' do |c| - c.timezone 'America/Godthab', 3851, 60, -776, 15, 'most locations' - c.timezone 'America/Danmarkshavn', 2303, 30, -56, 3, 'east coast, north of Scoresbysund' - c.timezone 'America/Scoresbysund', 4229, 60, -659, 30, 'Scoresbysund / Ittoqqortoormiit' - c.timezone 'America/Thule', 2297, 30, -4127, 60, 'Thule / Pituffik' - end - country 'GM', 'Gambia' do |c| - c.timezone 'Africa/Abidjan', 319, 60, -121, 30 - end - country 'GN', 'Guinea' do |c| - c.timezone 'Africa/Abidjan', 319, 60, -121, 30 - end - country 'GP', 'Guadeloupe' do |c| - c.timezone 'America/Port_of_Spain', 213, 20, -3691, 60 - end - country 'GQ', 'Equatorial Guinea' do |c| - c.timezone 'Africa/Lagos', 129, 20, 17, 5, 'West Africa Time (UTC+1)' - end - country 'GR', 'Greece' do |c| - c.timezone 'Europe/Athens', 1139, 30, 1423, 60 - end - country 'GS', 'South Georgia & the South Sandwich Islands' do |c| - c.timezone 'Atlantic/South_Georgia', -814, 15, -548, 15 - end - country 'GT', 'Guatemala' do |c| - c.timezone 'America/Guatemala', 439, 30, -5431, 60 - end - country 'GU', 'Guam' do |c| - c.timezone 'Pacific/Guam', 202, 15, 579, 4 - end - country 'GW', 'Guinea-Bissau' do |c| - c.timezone 'Africa/Bissau', 237, 20, -187, 12 - end - country 'GY', 'Guyana' do |c| - c.timezone 'America/Guyana', 34, 5, -349, 6 - end - country 'HK', 'Hong Kong' do |c| - c.timezone 'Asia/Hong_Kong', 1337, 60, 2283, 20 - end - country 'HM', 'Heard Island & McDonald Islands' - country 'HN', 'Honduras' do |c| - c.timezone 'America/Tegucigalpa', 141, 10, -5233, 60 - end - country 'HR', 'Croatia' do |c| - c.timezone 'Europe/Belgrade', 269, 6, 41, 2 - end - country 'HT', 'Haiti' do |c| - c.timezone 'America/Port-au-Prince', 278, 15, -217, 3 - end - country 'HU', 'Hungary' do |c| - c.timezone 'Europe/Budapest', 95, 2, 229, 12 - end - country 'ID', 'Indonesia' do |c| - c.timezone 'Asia/Jakarta', -37, 6, 534, 5, 'Java & Sumatra' - c.timezone 'Asia/Pontianak', -1, 30, 328, 3, 'west & central Borneo' - c.timezone 'Asia/Makassar', -307, 60, 597, 5, 'east & south Borneo, Sulawesi (Celebes), Bali, Nusa Tengarra, west Timor' - c.timezone 'Asia/Jayapura', -38, 15, 1407, 10, 'west New Guinea (Irian Jaya) & Malukus (Moluccas)' - end - country 'IE', 'Ireland' do |c| - c.timezone 'Europe/Dublin', 160, 3, -25, 4 - end - country 'IL', 'Israel' do |c| - c.timezone 'Asia/Jerusalem', 11441, 360, 63403, 1800 - end - country 'IM', 'Isle of Man' do |c| - c.timezone 'Europe/London', 6181, 120, -451, 3600 - end - country 'IN', 'India' do |c| - c.timezone 'Asia/Kolkata', 338, 15, 2651, 30 - end - country 'IO', 'British Indian Ocean Territory' do |c| - c.timezone 'Indian/Chagos', -22, 3, 869, 12 - end - country 'IQ', 'Iraq' do |c| - c.timezone 'Asia/Baghdad', 667, 20, 533, 12 - end - country 'IR', 'Iran' do |c| - c.timezone 'Asia/Tehran', 107, 3, 1543, 30 - end - country 'IS', 'Iceland' do |c| - c.timezone 'Atlantic/Reykjavik', 1283, 20, -437, 20 - end - country 'IT', 'Italy' do |c| - c.timezone 'Europe/Rome', 419, 10, 749, 60 - end - country 'JE', 'Jersey' do |c| - c.timezone 'Europe/London', 6181, 120, -451, 3600 - end - country 'JM', 'Jamaica' do |c| - c.timezone 'America/Jamaica', 12937, 720, -11519, 150 - end - country 'JO', 'Jordan' do |c| - c.timezone 'Asia/Amman', 639, 20, 539, 15 - end - country 'JP', 'Japan' do |c| - c.timezone 'Asia/Tokyo', 32089, 900, 503081, 3600 - end - country 'KE', 'Kenya' do |c| - c.timezone 'Africa/Nairobi', -77, 60, 2209, 60 - end - country 'KG', 'Kyrgyzstan' do |c| - c.timezone 'Asia/Bishkek', 429, 10, 373, 5 - end - country 'KH', 'Cambodia' do |c| - c.timezone 'Asia/Bangkok', 55, 4, 6031, 60 - end - country 'KI', 'Kiribati' do |c| - c.timezone 'Pacific/Tarawa', 17, 12, 173, 1, 'Gilbert Islands' - c.timezone 'Pacific/Enderbury', -47, 15, -2053, 12, 'Phoenix Islands' - c.timezone 'Pacific/Kiritimati', 28, 15, -472, 3, 'Line Islands' - end - country 'KM', 'Comoros' do |c| - c.timezone 'Africa/Nairobi', -77, 60, 2209, 60 - end - country 'KN', 'St Kitts & Nevis' do |c| - c.timezone 'America/Port_of_Spain', 213, 20, -3691, 60 - end - country 'KP', 'Korea (North)' do |c| - c.timezone 'Asia/Pyongyang', 2341, 60, 503, 4 - end - country 'KR', 'Korea (South)' do |c| - c.timezone 'Asia/Seoul', 751, 20, 3809, 30 - end - country 'KW', 'Kuwait' do |c| - c.timezone 'Asia/Riyadh', 739, 30, 2803, 60 - end - country 'KY', 'Cayman Islands' do |c| - c.timezone 'America/Panama', 269, 30, -1193, 15 - end - country 'KZ', 'Kazakhstan' do |c| - c.timezone 'Asia/Almaty', 173, 4, 1539, 20, 'most locations' - c.timezone 'Asia/Qyzylorda', 224, 5, 982, 15, 'Qyzylorda (Kyzylorda, Kzyl-Orda)' - c.timezone 'Asia/Aqtobe', 3017, 60, 343, 6, 'Aqtobe (Aktobe)' - c.timezone 'Asia/Aqtau', 2671, 60, 754, 15, 'Atyrau (Atirau, Gur\'yev), Mangghystau (Mankistau)' - c.timezone 'Asia/Oral', 3073, 60, 1027, 20, 'West Kazakhstan' - end - country 'LA', 'Laos' do |c| - c.timezone 'Asia/Bangkok', 55, 4, 6031, 60 - end - country 'LB', 'Lebanon' do |c| - c.timezone 'Asia/Beirut', 2033, 60, 71, 2 - end - country 'LC', 'St Lucia' do |c| - c.timezone 'America/Port_of_Spain', 213, 20, -3691, 60 - end - country 'LI', 'Liechtenstein' do |c| - c.timezone 'Europe/Zurich', 2843, 60, 128, 15, 'Swiss time' - end - country 'LK', 'Sri Lanka' do |c| - c.timezone 'Asia/Colombo', 104, 15, 1597, 20 - end - country 'LR', 'Liberia' do |c| - c.timezone 'Africa/Monrovia', 63, 10, -647, 60 - end - country 'LS', 'Lesotho' do |c| - c.timezone 'Africa/Johannesburg', -105, 4, 28, 1 - end - country 'LT', 'Lithuania' do |c| - c.timezone 'Europe/Vilnius', 3281, 60, 1519, 60 - end - country 'LU', 'Luxembourg' do |c| - c.timezone 'Europe/Luxembourg', 248, 5, 123, 20 - end - country 'LV', 'Latvia' do |c| - c.timezone 'Europe/Riga', 1139, 20, 241, 10 - end - country 'LY', 'Libya' do |c| - c.timezone 'Africa/Tripoli', 329, 10, 791, 60 - end - country 'MA', 'Morocco' do |c| - c.timezone 'Africa/Casablanca', 673, 20, -91, 12 - end - country 'MC', 'Monaco' do |c| - c.timezone 'Europe/Monaco', 437, 10, 443, 60 - end - country 'MD', 'Moldova' do |c| - c.timezone 'Europe/Chisinau', 47, 1, 173, 6 - end - country 'ME', 'Montenegro' do |c| - c.timezone 'Europe/Belgrade', 269, 6, 41, 2 - end - country 'MF', 'St Martin (French part)' do |c| - c.timezone 'America/Port_of_Spain', 213, 20, -3691, 60 - end - country 'MG', 'Madagascar' do |c| - c.timezone 'Africa/Nairobi', -77, 60, 2209, 60 - end - country 'MH', 'Marshall Islands' do |c| - c.timezone 'Pacific/Majuro', 143, 20, 856, 5, 'most locations' - c.timezone 'Pacific/Kwajalein', 109, 12, 502, 3, 'Kwajalein' - end - country 'MK', 'Macedonia' do |c| - c.timezone 'Europe/Belgrade', 269, 6, 41, 2 - end - country 'ML', 'Mali' do |c| - c.timezone 'Africa/Abidjan', 319, 60, -121, 30 - end - country 'MM', 'Myanmar (Burma)' do |c| - c.timezone 'Asia/Rangoon', 1007, 60, 577, 6 - end - country 'MN', 'Mongolia' do |c| - c.timezone 'Asia/Ulaanbaatar', 575, 12, 6413, 60, 'most locations' - c.timezone 'Asia/Hovd', 2881, 60, 1833, 20, 'Bayan-Ölgii, Govi-Altai, Hovd, Uvs, Zavkhan' - c.timezone 'Asia/Choibalsan', 721, 15, 229, 2, 'Dornod, Sükhbaatar' - end - country 'MO', 'Macau' do |c| - c.timezone 'Asia/Macau', 667, 30, 1363, 12 - end - country 'MP', 'Northern Mariana Islands' do |c| - c.timezone 'Pacific/Guam', 202, 15, 579, 4 - end - country 'MQ', 'Martinique' do |c| - c.timezone 'America/Martinique', 73, 5, -733, 12 - end - country 'MR', 'Mauritania' do |c| - c.timezone 'Africa/Abidjan', 319, 60, -121, 30 - end - country 'MS', 'Montserrat' do |c| - c.timezone 'America/Port_of_Spain', 213, 20, -3691, 60 - end - country 'MT', 'Malta' do |c| - c.timezone 'Europe/Malta', 359, 10, 871, 60 - end - country 'MU', 'Mauritius' do |c| - c.timezone 'Indian/Mauritius', -121, 6, 115, 2 - end - country 'MV', 'Maldives' do |c| - c.timezone 'Indian/Maldives', 25, 6, 147, 2 - end - country 'MW', 'Malawi' do |c| - c.timezone 'Africa/Maputo', -779, 30, 391, 12, 'Central Africa Time (UTC+2)' - end - country 'MX', 'Mexico' do |c| - c.timezone 'America/Mexico_City', 97, 5, -1983, 20, 'Central Time - most locations' - c.timezone 'America/Cancun', 253, 12, -2603, 30, 'Central Time - Quintana Roo' - c.timezone 'America/Merida', 629, 30, -5377, 60, 'Central Time - Campeche, Yucatán' - c.timezone 'America/Monterrey', 77, 3, -6019, 60, 'Mexican Central Time - Coahuila, Durango, Nuevo León, Tamaulipas away from US border' - c.timezone 'America/Matamoros', 155, 6, -195, 2, 'US Central Time - Coahuila, Durango, Nuevo León, Tamaulipas near US border' - c.timezone 'America/Mazatlan', 1393, 60, -1277, 12, 'Mountain Time - S Baja, Nayarit, Sinaloa' - c.timezone 'America/Chihuahua', 859, 30, -1273, 12, 'Mexican Mountain Time - Chihuahua away from US border' - c.timezone 'America/Ojinaga', 887, 30, -1253, 12, 'US Mountain Time - Chihuahua near US border' - c.timezone 'America/Hermosillo', 436, 15, -3329, 30, 'Mountain Standard Time - Sonora' - c.timezone 'America/Tijuana', 488, 15, -7021, 60, 'US Pacific Time - Baja California near US border' - c.timezone 'America/Santa_Isabel', 303, 10, -1723, 15, 'Mexican Pacific Time - Baja California away from US border' - c.timezone 'America/Bahia_Banderas', 104, 5, -421, 4, 'Mexican Central Time - Bahía de Banderas' - end - country 'MY', 'Malaysia' do |c| - c.timezone 'Asia/Kuala_Lumpur', 19, 6, 1017, 10, 'peninsular Malaysia' - c.timezone 'Asia/Kuching', 31, 20, 331, 3, 'Sabah & Sarawak' - end - country 'MZ', 'Mozambique' do |c| - c.timezone 'Africa/Maputo', -779, 30, 391, 12, 'Central Africa Time (UTC+2)' - end - country 'NA', 'Namibia' do |c| - c.timezone 'Africa/Windhoek', -677, 30, 171, 10 - end - country 'NC', 'New Caledonia' do |c| - c.timezone 'Pacific/Noumea', -334, 15, 3329, 20 - end - country 'NE', 'Niger' do |c| - c.timezone 'Africa/Lagos', 129, 20, 17, 5, 'West Africa Time (UTC+1)' - end - country 'NF', 'Norfolk Island' do |c| - c.timezone 'Pacific/Norfolk', -581, 20, 5039, 30 - end - country 'NG', 'Nigeria' do |c| - c.timezone 'Africa/Lagos', 129, 20, 17, 5, 'West Africa Time (UTC+1)' - end - country 'NI', 'Nicaragua' do |c| - c.timezone 'America/Managua', 243, 20, -5177, 60 - end - country 'NL', 'Netherlands' do |c| - c.timezone 'Europe/Amsterdam', 1571, 30, 49, 10 - end - country 'NO', 'Norway' do |c| - c.timezone 'Europe/Oslo', 719, 12, 43, 4 - end - country 'NP', 'Nepal' do |c| - c.timezone 'Asia/Kathmandu', 1663, 60, 5119, 60 - end - country 'NR', 'Nauru' do |c| - c.timezone 'Pacific/Nauru', -31, 60, 2003, 12 - end - country 'NU', 'Niue' do |c| - c.timezone 'Pacific/Niue', -1141, 60, -2039, 12 - end - country 'NZ', 'New Zealand' do |c| - c.timezone 'Pacific/Auckland', -553, 15, 5243, 30, 'New Zealand time' - c.timezone 'Pacific/Chatham', -879, 20, -3531, 20, 'Chatham Islands' - end - country 'OM', 'Oman' do |c| - c.timezone 'Asia/Dubai', 253, 10, 553, 10 - end - country 'PA', 'Panama' do |c| - c.timezone 'America/Panama', 269, 30, -1193, 15 - end - country 'PE', 'Peru' do |c| - c.timezone 'America/Lima', -241, 20, -1541, 20 - end - country 'PF', 'French Polynesia' do |c| - c.timezone 'Pacific/Tahiti', -263, 15, -4487, 30, 'Society Islands' - c.timezone 'Pacific/Marquesas', -9, 1, -279, 2, 'Marquesas Islands' - c.timezone 'Pacific/Gambier', -347, 15, -2699, 20, 'Gambier Islands' - end - country 'PG', 'Papua New Guinea' do |c| - c.timezone 'Pacific/Port_Moresby', -19, 2, 883, 6 - end - country 'PH', 'Philippines' do |c| - c.timezone 'Asia/Manila', 175, 12, 121, 1 - end - country 'PK', 'Pakistan' do |c| - c.timezone 'Asia/Karachi', 373, 15, 1341, 20 - end - country 'PL', 'Poland' do |c| - c.timezone 'Europe/Warsaw', 209, 4, 21, 1 - end - country 'PM', 'St Pierre & Miquelon' do |c| - c.timezone 'America/Miquelon', 941, 20, -169, 3 - end - country 'PN', 'Pitcairn' do |c| - c.timezone 'Pacific/Pitcairn', -376, 15, -1561, 12 - end - country 'PR', 'Puerto Rico' do |c| - c.timezone 'America/Puerto_Rico', 11081, 600, -118991, 1800 - end - country 'PS', 'Palestine' do |c| - c.timezone 'Asia/Gaza', 63, 2, 517, 15, 'Gaza Strip' - c.timezone 'Asia/Hebron', 473, 15, 7019, 200, 'West Bank' - end - country 'PT', 'Portugal' do |c| - c.timezone 'Europe/Lisbon', 2323, 60, -137, 15, 'mainland' - c.timezone 'Atlantic/Madeira', 979, 30, -169, 10, 'Madeira Islands' - c.timezone 'Atlantic/Azores', 566, 15, -77, 3, 'Azores' - end - country 'PW', 'Palau' do |c| - c.timezone 'Pacific/Palau', 22, 3, 8069, 60 - end - country 'PY', 'Paraguay' do |c| - c.timezone 'America/Asuncion', -379, 15, -173, 3 - end - country 'QA', 'Qatar' do |c| - c.timezone 'Asia/Qatar', 1517, 60, 773, 15 - end - country 'RE', 'Reunion' do |c| - c.timezone 'Indian/Reunion', -313, 15, 832, 15, 'Réunion, Crozet Is, Scattered Is' - end - country 'RO', 'Romania' do |c| - c.timezone 'Europe/Bucharest', 1333, 30, 261, 10 - end - country 'RS', 'Serbia' do |c| - c.timezone 'Europe/Belgrade', 269, 6, 41, 2 - end - country 'RU', 'Russia' do |c| - c.timezone 'Europe/Kaliningrad', 3283, 60, 41, 2, 'Moscow-01 - Kaliningrad' - c.timezone 'Europe/Moscow', 66907, 1200, 8464, 225, 'Moscow+00 - west Russia' - c.timezone 'Europe/Simferopol', 899, 20, 341, 10, 'Moscow+00 - Crimea' - c.timezone 'Europe/Volgograd', 731, 15, 533, 12, 'Moscow+00 - Caspian Sea' - c.timezone 'Europe/Samara', 266, 5, 1003, 20, 'Moscow+00 (Moscow+01 after 2014-10-26) - Samara, Udmurtia' - c.timezone 'Asia/Yekaterinburg', 1137, 20, 303, 5, 'Moscow+02 - Urals' - c.timezone 'Asia/Omsk', 55, 1, 367, 5, 'Moscow+03 - west Siberia' - c.timezone 'Asia/Novosibirsk', 1651, 30, 995, 12, 'Moscow+03 - Novosibirsk' - c.timezone 'Asia/Novokuznetsk', 215, 4, 5227, 60, 'Moscow+03 (Moscow+04 after 2014-10-26) - Kemerovo' - c.timezone 'Asia/Krasnoyarsk', 3361, 60, 557, 6, 'Moscow+04 - Yenisei River' - c.timezone 'Asia/Irkutsk', 784, 15, 313, 3, 'Moscow+05 - Lake Baikal' - c.timezone 'Asia/Chita', 1041, 20, 1702, 15, 'Moscow+06 (Moscow+05 after 2014-10-26) - Zabaykalsky' - c.timezone 'Asia/Yakutsk', 62, 1, 389, 3, 'Moscow+06 - Lena River' - c.timezone 'Asia/Khandyga', 225563, 3600, 243997, 1800, 'Moscow+06 - Tomponsky, Ust-Maysky' - c.timezone 'Asia/Vladivostok', 259, 6, 1979, 15, 'Moscow+07 - Amur River' - c.timezone 'Asia/Sakhalin', 1409, 30, 1427, 10, 'Moscow+07 - Sakhalin Island' - c.timezone 'Asia/Ust-Nera', 232417, 3600, 10742, 75, 'Moscow+07 - Oymyakonsky' - c.timezone 'Asia/Magadan', 1787, 30, 754, 5, 'Moscow+08 (Moscow+07 after 2014-10-26) - Magadan' - c.timezone 'Asia/Srednekolymsk', 1012, 15, 9223, 60, 'Moscow+08 - E Sakha, N Kuril Is' - c.timezone 'Asia/Kamchatka', 3181, 60, 3173, 20, 'Moscow+08 (Moscow+09 after 2014-10-26) - Kamchatka' - c.timezone 'Asia/Anadyr', 259, 4, 10649, 60, 'Moscow+08 (Moscow+09 after 2014-10-26) - Bering Sea' - end - country 'RW', 'Rwanda' do |c| - c.timezone 'Africa/Maputo', -779, 30, 391, 12, 'Central Africa Time (UTC+2)' - end - country 'SA', 'Saudi Arabia' do |c| - c.timezone 'Asia/Riyadh', 739, 30, 2803, 60 - end - country 'SB', 'Solomon Islands' do |c| - c.timezone 'Pacific/Guadalcanal', -143, 15, 801, 5 - end - country 'SC', 'Seychelles' do |c| - c.timezone 'Indian/Mahe', -14, 3, 832, 15 - end - country 'SD', 'Sudan' do |c| - c.timezone 'Africa/Khartoum', 78, 5, 488, 15 - end - country 'SE', 'Sweden' do |c| - c.timezone 'Europe/Stockholm', 178, 3, 361, 20 - end - country 'SG', 'Singapore' do |c| - c.timezone 'Asia/Singapore', 77, 60, 2077, 20 - end - country 'SH', 'St Helena' do |c| - c.timezone 'Africa/Abidjan', 319, 60, -121, 30 - end - country 'SI', 'Slovenia' do |c| - c.timezone 'Europe/Belgrade', 269, 6, 41, 2 - end - country 'SJ', 'Svalbard & Jan Mayen' do |c| - c.timezone 'Europe/Oslo', 719, 12, 43, 4 - end - country 'SK', 'Slovakia' do |c| - c.timezone 'Europe/Prague', 601, 12, 433, 30 - end - country 'SL', 'Sierra Leone' do |c| - c.timezone 'Africa/Abidjan', 319, 60, -121, 30 - end - country 'SM', 'San Marino' do |c| - c.timezone 'Europe/Rome', 419, 10, 749, 60 - end - country 'SN', 'Senegal' do |c| - c.timezone 'Africa/Abidjan', 319, 60, -121, 30 - end - country 'SO', 'Somalia' do |c| - c.timezone 'Africa/Nairobi', -77, 60, 2209, 60 - end - country 'SR', 'Suriname' do |c| - c.timezone 'America/Paramaribo', 35, 6, -331, 6 - end - country 'SS', 'South Sudan' do |c| - c.timezone 'Africa/Khartoum', 78, 5, 488, 15 - end - country 'ST', 'Sao Tome & Principe' do |c| - c.timezone 'Africa/Abidjan', 319, 60, -121, 30 - end - country 'SV', 'El Salvador' do |c| - c.timezone 'America/El_Salvador', 137, 10, -446, 5 - end - country 'SX', 'St Maarten (Dutch part)' do |c| - c.timezone 'America/Curacao', 731, 60, -69, 1 - end - country 'SY', 'Syria' do |c| - c.timezone 'Asia/Damascus', 67, 2, 363, 10 - end - country 'SZ', 'Swaziland' do |c| - c.timezone 'Africa/Johannesburg', -105, 4, 28, 1 - end - country 'TC', 'Turks & Caicos Is' do |c| - c.timezone 'America/Grand_Turk', 322, 15, -1067, 15 - end - country 'TD', 'Chad' do |c| - c.timezone 'Africa/Ndjamena', 727, 60, 301, 20 - end - country 'TF', 'French Southern & Antarctic Lands' do |c| - c.timezone 'Indian/Kerguelen', -17767, 360, 28087, 400, 'Kerguelen, St Paul I, Amsterdam I' - c.timezone 'Indian/Reunion', -313, 15, 832, 15, 'Réunion, Crozet Is, Scattered Is' - end - country 'TG', 'Togo' do |c| - c.timezone 'Africa/Abidjan', 319, 60, -121, 30 - end - country 'TH', 'Thailand' do |c| - c.timezone 'Asia/Bangkok', 55, 4, 6031, 60 - end - country 'TJ', 'Tajikistan' do |c| - c.timezone 'Asia/Dushanbe', 463, 12, 344, 5 - end - country 'TK', 'Tokelau' do |c| - c.timezone 'Pacific/Fakaofo', -281, 30, -5137, 30 - end - country 'TL', 'East Timor' do |c| - c.timezone 'Asia/Dili', -171, 20, 1507, 12 - end - country 'TM', 'Turkmenistan' do |c| - c.timezone 'Asia/Ashgabat', 759, 20, 3503, 60 - end - country 'TN', 'Tunisia' do |c| - c.timezone 'Africa/Tunis', 184, 5, 611, 60 - end - country 'TO', 'Tonga' do |c| - c.timezone 'Pacific/Tongatapu', -127, 6, -1051, 6 - end - country 'TR', 'Turkey' do |c| - c.timezone 'Europe/Istanbul', 2461, 60, 869, 30 - end - country 'TT', 'Trinidad & Tobago' do |c| - c.timezone 'America/Port_of_Spain', 213, 20, -3691, 60 - end - country 'TV', 'Tuvalu' do |c| - c.timezone 'Pacific/Funafuti', -511, 60, 10753, 60 - end - country 'TW', 'Taiwan' do |c| - c.timezone 'Asia/Taipei', 501, 20, 243, 2 - end - country 'TZ', 'Tanzania' do |c| - c.timezone 'Africa/Nairobi', -77, 60, 2209, 60 - end - country 'UA', 'Ukraine' do |c| - c.timezone 'Europe/Kiev', 1513, 30, 1831, 60, 'most locations' - c.timezone 'Europe/Uzhgorod', 2917, 60, 223, 10, 'Ruthenia' - c.timezone 'Europe/Zaporozhye', 287, 6, 211, 6, 'Zaporozh\'ye, E Lugansk / Zaporizhia, E Luhansk' - end - country 'UG', 'Uganda' do |c| - c.timezone 'Africa/Nairobi', -77, 60, 2209, 60 - end - country 'UM', 'US minor outlying islands' do |c| - c.timezone 'Pacific/Wake', 1157, 60, 9997, 60, 'Wake Island' - c.timezone 'Pacific/Pago_Pago', -214, 15, -1707, 10, 'Samoa, Midway' - c.timezone 'Pacific/Honolulu', 15341, 720, -18943, 120, 'Hawaii time' - end - country 'US', 'United States' do |c| - c.timezone 'America/New_York', 48857, 1200, -266423, 3600, 'Eastern Time' - c.timezone 'America/Detroit', 152393, 3600, -19931, 240, 'Eastern Time - Michigan - most locations' - c.timezone 'America/Kentucky/Louisville', 9181, 240, -154367, 1800, 'Eastern Time - Kentucky - Louisville area' - c.timezone 'America/Kentucky/Monticello', 132587, 3600, -101819, 1200, 'Eastern Time - Kentucky - Wayne County' - c.timezone 'America/Indiana/Indianapolis', 23861, 600, -310169, 3600, 'Eastern Time - Indiana - most locations' - c.timezone 'America/Indiana/Vincennes', 69619, 1800, -315103, 3600, 'Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties' - c.timezone 'America/Indiana/Winamac', 29557, 720, -311771, 3600, 'Eastern Time - Indiana - Pulaski County' - c.timezone 'America/Indiana/Marengo', 17269, 450, -310841, 3600, 'Eastern Time - Indiana - Crawford County' - c.timezone 'America/Indiana/Petersburg', 138571, 3600, -314203, 3600, 'Eastern Time - Indiana - Pike County' - c.timezone 'America/Indiana/Vevay', 34873, 900, -153121, 1800, 'Eastern Time - Indiana - Switzerland County' - c.timezone 'America/Chicago', 837, 20, -1753, 20, 'Central Time' - c.timezone 'America/Indiana/Tell_City', 136631, 3600, -312341, 3600, 'Central Time - Indiana - Perry County' - c.timezone 'America/Indiana/Knox', 9911, 240, -693, 8, 'Central Time - Indiana - Starke County' - c.timezone 'America/Menominee', 40597, 900, -105137, 1200, 'Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties' - c.timezone 'America/North_Dakota/Center', 169619, 3600, -121559, 1200, 'Central Time - North Dakota - Oliver County' - c.timezone 'America/North_Dakota/New_Salem', 9369, 200, -121693, 1200, 'Central Time - North Dakota - Morton County (except Mandan area)' - c.timezone 'America/North_Dakota/Beulah', 56717, 1200, -916, 9, 'Central Time - North Dakota - Mercer County' - c.timezone 'America/Denver', 47687, 1200, -125981, 1200, 'Mountain Time' - c.timezone 'America/Boise', 157009, 3600, -46481, 400, 'Mountain Time - south Idaho & east Oregon' - c.timezone 'America/Phoenix', 20069, 600, -16811, 150, 'Mountain Standard Time - Arizona (except Navajo)' - c.timezone 'America/Los_Angeles', 30647, 900, -212837, 1800, 'Pacific Time' - c.timezone 'America/Metlakatla', 198457, 3600, -18947, 144, 'Pacific Standard Time - Annette Island, Alaska' - c.timezone 'America/Anchorage', 44077, 720, -539641, 3600, 'Alaska Time' - c.timezone 'America/Juneau', 209887, 3600, -483911, 3600, 'Alaska Time - Alaska panhandle' - c.timezone 'America/Sitka', 41167, 720, -487087, 3600, 'Alaska Time - southeast Alaska panhandle' - c.timezone 'America/Yakutat', 214369, 3600, -251509, 1800, 'Alaska Time - Alaska panhandle neck' - c.timezone 'America/Nome', 58051, 900, -595463, 3600, 'Alaska Time - west Alaska' - c.timezone 'America/Adak', 1297, 25, -635969, 3600, 'Aleutian Islands' - c.timezone 'Pacific/Honolulu', 15341, 720, -18943, 120, 'Hawaii time' - end - country 'UY', 'Uruguay' do |c| - c.timezone 'America/Montevideo', -2093, 60, -3371, 60 - end - country 'UZ', 'Uzbekistan' do |c| - c.timezone 'Asia/Samarkand', 119, 3, 334, 5, 'west Uzbekistan' - c.timezone 'Asia/Tashkent', 124, 3, 693, 10, 'east Uzbekistan' - end - country 'VA', 'Vatican City' do |c| - c.timezone 'Europe/Rome', 419, 10, 749, 60 - end - country 'VC', 'St Vincent' do |c| - c.timezone 'America/Port_of_Spain', 213, 20, -3691, 60 - end - country 'VE', 'Venezuela' do |c| - c.timezone 'America/Caracas', 21, 2, -1004, 15 - end - country 'VG', 'Virgin Islands (UK)' do |c| - c.timezone 'America/Port_of_Spain', 213, 20, -3691, 60 - end - country 'VI', 'Virgin Islands (US)' do |c| - c.timezone 'America/Port_of_Spain', 213, 20, -3691, 60 - end - country 'VN', 'Vietnam' do |c| - c.timezone 'Asia/Bangkok', 55, 4, 6031, 60 - end - country 'VU', 'Vanuatu' do |c| - c.timezone 'Pacific/Efate', -53, 3, 2021, 12 - end - country 'WF', 'Wallis & Futuna' do |c| - c.timezone 'Pacific/Wallis', -133, 10, -1057, 6 - end - country 'WS', 'Samoa (western)' do |c| - c.timezone 'Pacific/Apia', -83, 6, -2576, 15 - end - country 'YE', 'Yemen' do |c| - c.timezone 'Asia/Riyadh', 739, 30, 2803, 60 - end - country 'YT', 'Mayotte' do |c| - c.timezone 'Africa/Nairobi', -77, 60, 2209, 60 - end - country 'ZA', 'South Africa' do |c| - c.timezone 'Africa/Johannesburg', -105, 4, 28, 1 - end - country 'ZM', 'Zambia' do |c| - c.timezone 'Africa/Maputo', -779, 30, 391, 12, 'Central Africa Time (UTC+2)' - end - country 'ZW', 'Zimbabwe' do |c| - c.timezone 'Africa/Maputo', -779, 30, 391, 12, 'Central Africa Time (UTC+2)' - end - end - end - end -end diff -Nru ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/indexes/timezones.rb ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/indexes/timezones.rb --- ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/indexes/timezones.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/indexes/timezones.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,596 +0,0 @@ -# encoding: UTF-8 - -# This file contains data derived from the IANA Time Zone Database -# (http://www.iana.org/time-zones). - -module TZInfo - module Data - module Indexes - module Timezones - include TimezoneIndexDefinition - - timezone 'Africa/Abidjan' - timezone 'Africa/Accra' - timezone 'Africa/Addis_Ababa' - timezone 'Africa/Algiers' - timezone 'Africa/Asmara' - linked_timezone 'Africa/Asmera' - linked_timezone 'Africa/Bamako' - timezone 'Africa/Bangui' - linked_timezone 'Africa/Banjul' - timezone 'Africa/Bissau' - timezone 'Africa/Blantyre' - timezone 'Africa/Brazzaville' - timezone 'Africa/Bujumbura' - timezone 'Africa/Cairo' - timezone 'Africa/Casablanca' - timezone 'Africa/Ceuta' - linked_timezone 'Africa/Conakry' - linked_timezone 'Africa/Dakar' - timezone 'Africa/Dar_es_Salaam' - timezone 'Africa/Djibouti' - timezone 'Africa/Douala' - timezone 'Africa/El_Aaiun' - linked_timezone 'Africa/Freetown' - timezone 'Africa/Gaborone' - timezone 'Africa/Harare' - timezone 'Africa/Johannesburg' - linked_timezone 'Africa/Juba' - timezone 'Africa/Kampala' - timezone 'Africa/Khartoum' - timezone 'Africa/Kigali' - timezone 'Africa/Kinshasa' - timezone 'Africa/Lagos' - timezone 'Africa/Libreville' - linked_timezone 'Africa/Lome' - timezone 'Africa/Luanda' - timezone 'Africa/Lubumbashi' - timezone 'Africa/Lusaka' - timezone 'Africa/Malabo' - timezone 'Africa/Maputo' - timezone 'Africa/Maseru' - timezone 'Africa/Mbabane' - timezone 'Africa/Mogadishu' - timezone 'Africa/Monrovia' - timezone 'Africa/Nairobi' - timezone 'Africa/Ndjamena' - timezone 'Africa/Niamey' - linked_timezone 'Africa/Nouakchott' - linked_timezone 'Africa/Ouagadougou' - timezone 'Africa/Porto-Novo' - linked_timezone 'Africa/Sao_Tome' - linked_timezone 'Africa/Timbuktu' - timezone 'Africa/Tripoli' - timezone 'Africa/Tunis' - timezone 'Africa/Windhoek' - timezone 'America/Adak' - timezone 'America/Anchorage' - linked_timezone 'America/Anguilla' - timezone 'America/Antigua' - timezone 'America/Araguaina' - timezone 'America/Argentina/Buenos_Aires' - timezone 'America/Argentina/Catamarca' - linked_timezone 'America/Argentina/ComodRivadavia' - timezone 'America/Argentina/Cordoba' - timezone 'America/Argentina/Jujuy' - timezone 'America/Argentina/La_Rioja' - timezone 'America/Argentina/Mendoza' - timezone 'America/Argentina/Rio_Gallegos' - timezone 'America/Argentina/Salta' - timezone 'America/Argentina/San_Juan' - timezone 'America/Argentina/San_Luis' - timezone 'America/Argentina/Tucuman' - timezone 'America/Argentina/Ushuaia' - linked_timezone 'America/Aruba' - timezone 'America/Asuncion' - timezone 'America/Atikokan' - linked_timezone 'America/Atka' - timezone 'America/Bahia' - timezone 'America/Bahia_Banderas' - timezone 'America/Barbados' - timezone 'America/Belem' - timezone 'America/Belize' - timezone 'America/Blanc-Sablon' - timezone 'America/Boa_Vista' - timezone 'America/Bogota' - timezone 'America/Boise' - linked_timezone 'America/Buenos_Aires' - timezone 'America/Cambridge_Bay' - timezone 'America/Campo_Grande' - timezone 'America/Cancun' - timezone 'America/Caracas' - linked_timezone 'America/Catamarca' - timezone 'America/Cayenne' - timezone 'America/Cayman' - timezone 'America/Chicago' - timezone 'America/Chihuahua' - linked_timezone 'America/Coral_Harbour' - linked_timezone 'America/Cordoba' - timezone 'America/Costa_Rica' - timezone 'America/Creston' - timezone 'America/Cuiaba' - timezone 'America/Curacao' - timezone 'America/Danmarkshavn' - timezone 'America/Dawson' - timezone 'America/Dawson_Creek' - timezone 'America/Denver' - timezone 'America/Detroit' - linked_timezone 'America/Dominica' - timezone 'America/Edmonton' - timezone 'America/Eirunepe' - timezone 'America/El_Salvador' - linked_timezone 'America/Ensenada' - linked_timezone 'America/Fort_Wayne' - timezone 'America/Fortaleza' - timezone 'America/Glace_Bay' - timezone 'America/Godthab' - timezone 'America/Goose_Bay' - timezone 'America/Grand_Turk' - linked_timezone 'America/Grenada' - linked_timezone 'America/Guadeloupe' - timezone 'America/Guatemala' - timezone 'America/Guayaquil' - timezone 'America/Guyana' - timezone 'America/Halifax' - timezone 'America/Havana' - timezone 'America/Hermosillo' - timezone 'America/Indiana/Indianapolis' - timezone 'America/Indiana/Knox' - timezone 'America/Indiana/Marengo' - timezone 'America/Indiana/Petersburg' - timezone 'America/Indiana/Tell_City' - timezone 'America/Indiana/Vevay' - timezone 'America/Indiana/Vincennes' - timezone 'America/Indiana/Winamac' - linked_timezone 'America/Indianapolis' - timezone 'America/Inuvik' - timezone 'America/Iqaluit' - timezone 'America/Jamaica' - linked_timezone 'America/Jujuy' - timezone 'America/Juneau' - timezone 'America/Kentucky/Louisville' - timezone 'America/Kentucky/Monticello' - linked_timezone 'America/Knox_IN' - linked_timezone 'America/Kralendijk' - timezone 'America/La_Paz' - timezone 'America/Lima' - timezone 'America/Los_Angeles' - linked_timezone 'America/Louisville' - linked_timezone 'America/Lower_Princes' - timezone 'America/Maceio' - timezone 'America/Managua' - timezone 'America/Manaus' - linked_timezone 'America/Marigot' - timezone 'America/Martinique' - timezone 'America/Matamoros' - timezone 'America/Mazatlan' - linked_timezone 'America/Mendoza' - timezone 'America/Menominee' - timezone 'America/Merida' - timezone 'America/Metlakatla' - timezone 'America/Mexico_City' - timezone 'America/Miquelon' - timezone 'America/Moncton' - timezone 'America/Monterrey' - timezone 'America/Montevideo' - timezone 'America/Montreal' - linked_timezone 'America/Montserrat' - timezone 'America/Nassau' - timezone 'America/New_York' - timezone 'America/Nipigon' - timezone 'America/Nome' - timezone 'America/Noronha' - timezone 'America/North_Dakota/Beulah' - timezone 'America/North_Dakota/Center' - timezone 'America/North_Dakota/New_Salem' - timezone 'America/Ojinaga' - timezone 'America/Panama' - timezone 'America/Pangnirtung' - timezone 'America/Paramaribo' - timezone 'America/Phoenix' - timezone 'America/Port-au-Prince' - timezone 'America/Port_of_Spain' - linked_timezone 'America/Porto_Acre' - timezone 'America/Porto_Velho' - timezone 'America/Puerto_Rico' - timezone 'America/Rainy_River' - timezone 'America/Rankin_Inlet' - timezone 'America/Recife' - timezone 'America/Regina' - timezone 'America/Resolute' - timezone 'America/Rio_Branco' - linked_timezone 'America/Rosario' - timezone 'America/Santa_Isabel' - timezone 'America/Santarem' - timezone 'America/Santiago' - timezone 'America/Santo_Domingo' - timezone 'America/Sao_Paulo' - timezone 'America/Scoresbysund' - linked_timezone 'America/Shiprock' - timezone 'America/Sitka' - linked_timezone 'America/St_Barthelemy' - timezone 'America/St_Johns' - linked_timezone 'America/St_Kitts' - linked_timezone 'America/St_Lucia' - linked_timezone 'America/St_Thomas' - linked_timezone 'America/St_Vincent' - timezone 'America/Swift_Current' - timezone 'America/Tegucigalpa' - timezone 'America/Thule' - timezone 'America/Thunder_Bay' - timezone 'America/Tijuana' - timezone 'America/Toronto' - linked_timezone 'America/Tortola' - timezone 'America/Vancouver' - linked_timezone 'America/Virgin' - timezone 'America/Whitehorse' - timezone 'America/Winnipeg' - timezone 'America/Yakutat' - timezone 'America/Yellowknife' - timezone 'Antarctica/Casey' - timezone 'Antarctica/Davis' - timezone 'Antarctica/DumontDUrville' - timezone 'Antarctica/Macquarie' - timezone 'Antarctica/Mawson' - linked_timezone 'Antarctica/McMurdo' - timezone 'Antarctica/Palmer' - timezone 'Antarctica/Rothera' - linked_timezone 'Antarctica/South_Pole' - timezone 'Antarctica/Syowa' - timezone 'Antarctica/Troll' - timezone 'Antarctica/Vostok' - linked_timezone 'Arctic/Longyearbyen' - timezone 'Asia/Aden' - timezone 'Asia/Almaty' - timezone 'Asia/Amman' - timezone 'Asia/Anadyr' - timezone 'Asia/Aqtau' - timezone 'Asia/Aqtobe' - timezone 'Asia/Ashgabat' - linked_timezone 'Asia/Ashkhabad' - timezone 'Asia/Baghdad' - timezone 'Asia/Bahrain' - timezone 'Asia/Baku' - timezone 'Asia/Bangkok' - timezone 'Asia/Beirut' - timezone 'Asia/Bishkek' - timezone 'Asia/Brunei' - linked_timezone 'Asia/Calcutta' - timezone 'Asia/Chita' - timezone 'Asia/Choibalsan' - linked_timezone 'Asia/Chongqing' - linked_timezone 'Asia/Chungking' - timezone 'Asia/Colombo' - linked_timezone 'Asia/Dacca' - timezone 'Asia/Damascus' - timezone 'Asia/Dhaka' - timezone 'Asia/Dili' - timezone 'Asia/Dubai' - timezone 'Asia/Dushanbe' - timezone 'Asia/Gaza' - linked_timezone 'Asia/Harbin' - timezone 'Asia/Hebron' - timezone 'Asia/Ho_Chi_Minh' - timezone 'Asia/Hong_Kong' - timezone 'Asia/Hovd' - timezone 'Asia/Irkutsk' - linked_timezone 'Asia/Istanbul' - timezone 'Asia/Jakarta' - timezone 'Asia/Jayapura' - timezone 'Asia/Jerusalem' - timezone 'Asia/Kabul' - timezone 'Asia/Kamchatka' - timezone 'Asia/Karachi' - linked_timezone 'Asia/Kashgar' - timezone 'Asia/Kathmandu' - linked_timezone 'Asia/Katmandu' - timezone 'Asia/Khandyga' - timezone 'Asia/Kolkata' - timezone 'Asia/Krasnoyarsk' - timezone 'Asia/Kuala_Lumpur' - timezone 'Asia/Kuching' - timezone 'Asia/Kuwait' - linked_timezone 'Asia/Macao' - timezone 'Asia/Macau' - timezone 'Asia/Magadan' - timezone 'Asia/Makassar' - timezone 'Asia/Manila' - timezone 'Asia/Muscat' - timezone 'Asia/Nicosia' - timezone 'Asia/Novokuznetsk' - timezone 'Asia/Novosibirsk' - timezone 'Asia/Omsk' - timezone 'Asia/Oral' - timezone 'Asia/Phnom_Penh' - timezone 'Asia/Pontianak' - timezone 'Asia/Pyongyang' - timezone 'Asia/Qatar' - timezone 'Asia/Qyzylorda' - timezone 'Asia/Rangoon' - timezone 'Asia/Riyadh' - linked_timezone 'Asia/Saigon' - timezone 'Asia/Sakhalin' - timezone 'Asia/Samarkand' - timezone 'Asia/Seoul' - timezone 'Asia/Shanghai' - timezone 'Asia/Singapore' - timezone 'Asia/Srednekolymsk' - timezone 'Asia/Taipei' - timezone 'Asia/Tashkent' - timezone 'Asia/Tbilisi' - timezone 'Asia/Tehran' - linked_timezone 'Asia/Tel_Aviv' - linked_timezone 'Asia/Thimbu' - timezone 'Asia/Thimphu' - timezone 'Asia/Tokyo' - linked_timezone 'Asia/Ujung_Pandang' - timezone 'Asia/Ulaanbaatar' - linked_timezone 'Asia/Ulan_Bator' - timezone 'Asia/Urumqi' - timezone 'Asia/Ust-Nera' - timezone 'Asia/Vientiane' - timezone 'Asia/Vladivostok' - timezone 'Asia/Yakutsk' - timezone 'Asia/Yekaterinburg' - timezone 'Asia/Yerevan' - timezone 'Atlantic/Azores' - timezone 'Atlantic/Bermuda' - timezone 'Atlantic/Canary' - timezone 'Atlantic/Cape_Verde' - linked_timezone 'Atlantic/Faeroe' - timezone 'Atlantic/Faroe' - linked_timezone 'Atlantic/Jan_Mayen' - timezone 'Atlantic/Madeira' - timezone 'Atlantic/Reykjavik' - timezone 'Atlantic/South_Georgia' - linked_timezone 'Atlantic/St_Helena' - timezone 'Atlantic/Stanley' - linked_timezone 'Australia/ACT' - timezone 'Australia/Adelaide' - timezone 'Australia/Brisbane' - timezone 'Australia/Broken_Hill' - linked_timezone 'Australia/Canberra' - timezone 'Australia/Currie' - timezone 'Australia/Darwin' - timezone 'Australia/Eucla' - timezone 'Australia/Hobart' - linked_timezone 'Australia/LHI' - timezone 'Australia/Lindeman' - timezone 'Australia/Lord_Howe' - timezone 'Australia/Melbourne' - linked_timezone 'Australia/NSW' - linked_timezone 'Australia/North' - timezone 'Australia/Perth' - linked_timezone 'Australia/Queensland' - linked_timezone 'Australia/South' - timezone 'Australia/Sydney' - linked_timezone 'Australia/Tasmania' - linked_timezone 'Australia/Victoria' - linked_timezone 'Australia/West' - linked_timezone 'Australia/Yancowinna' - linked_timezone 'Brazil/Acre' - linked_timezone 'Brazil/DeNoronha' - linked_timezone 'Brazil/East' - linked_timezone 'Brazil/West' - timezone 'CET' - timezone 'CST6CDT' - linked_timezone 'Canada/Atlantic' - linked_timezone 'Canada/Central' - linked_timezone 'Canada/East-Saskatchewan' - linked_timezone 'Canada/Eastern' - linked_timezone 'Canada/Mountain' - linked_timezone 'Canada/Newfoundland' - linked_timezone 'Canada/Pacific' - linked_timezone 'Canada/Saskatchewan' - linked_timezone 'Canada/Yukon' - linked_timezone 'Chile/Continental' - linked_timezone 'Chile/EasterIsland' - linked_timezone 'Cuba' - timezone 'EET' - timezone 'EST' - timezone 'EST5EDT' - linked_timezone 'Egypt' - linked_timezone 'Eire' - timezone 'Etc/GMT' - linked_timezone 'Etc/GMT+0' - timezone 'Etc/GMT+1' - timezone 'Etc/GMT+10' - timezone 'Etc/GMT+11' - timezone 'Etc/GMT+12' - timezone 'Etc/GMT+2' - timezone 'Etc/GMT+3' - timezone 'Etc/GMT+4' - timezone 'Etc/GMT+5' - timezone 'Etc/GMT+6' - timezone 'Etc/GMT+7' - timezone 'Etc/GMT+8' - timezone 'Etc/GMT+9' - linked_timezone 'Etc/GMT-0' - timezone 'Etc/GMT-1' - timezone 'Etc/GMT-10' - timezone 'Etc/GMT-11' - timezone 'Etc/GMT-12' - timezone 'Etc/GMT-13' - timezone 'Etc/GMT-14' - timezone 'Etc/GMT-2' - timezone 'Etc/GMT-3' - timezone 'Etc/GMT-4' - timezone 'Etc/GMT-5' - timezone 'Etc/GMT-6' - timezone 'Etc/GMT-7' - timezone 'Etc/GMT-8' - timezone 'Etc/GMT-9' - linked_timezone 'Etc/GMT0' - linked_timezone 'Etc/Greenwich' - timezone 'Etc/UCT' - timezone 'Etc/UTC' - linked_timezone 'Etc/Universal' - linked_timezone 'Etc/Zulu' - timezone 'Europe/Amsterdam' - timezone 'Europe/Andorra' - timezone 'Europe/Athens' - linked_timezone 'Europe/Belfast' - timezone 'Europe/Belgrade' - timezone 'Europe/Berlin' - linked_timezone 'Europe/Bratislava' - timezone 'Europe/Brussels' - timezone 'Europe/Bucharest' - timezone 'Europe/Budapest' - linked_timezone 'Europe/Busingen' - timezone 'Europe/Chisinau' - timezone 'Europe/Copenhagen' - timezone 'Europe/Dublin' - timezone 'Europe/Gibraltar' - linked_timezone 'Europe/Guernsey' - timezone 'Europe/Helsinki' - linked_timezone 'Europe/Isle_of_Man' - timezone 'Europe/Istanbul' - linked_timezone 'Europe/Jersey' - timezone 'Europe/Kaliningrad' - timezone 'Europe/Kiev' - timezone 'Europe/Lisbon' - linked_timezone 'Europe/Ljubljana' - timezone 'Europe/London' - timezone 'Europe/Luxembourg' - timezone 'Europe/Madrid' - timezone 'Europe/Malta' - linked_timezone 'Europe/Mariehamn' - timezone 'Europe/Minsk' - timezone 'Europe/Monaco' - timezone 'Europe/Moscow' - linked_timezone 'Europe/Nicosia' - timezone 'Europe/Oslo' - timezone 'Europe/Paris' - linked_timezone 'Europe/Podgorica' - timezone 'Europe/Prague' - timezone 'Europe/Riga' - timezone 'Europe/Rome' - timezone 'Europe/Samara' - linked_timezone 'Europe/San_Marino' - linked_timezone 'Europe/Sarajevo' - timezone 'Europe/Simferopol' - linked_timezone 'Europe/Skopje' - timezone 'Europe/Sofia' - timezone 'Europe/Stockholm' - timezone 'Europe/Tallinn' - timezone 'Europe/Tirane' - linked_timezone 'Europe/Tiraspol' - timezone 'Europe/Uzhgorod' - linked_timezone 'Europe/Vaduz' - linked_timezone 'Europe/Vatican' - timezone 'Europe/Vienna' - timezone 'Europe/Vilnius' - timezone 'Europe/Volgograd' - timezone 'Europe/Warsaw' - linked_timezone 'Europe/Zagreb' - timezone 'Europe/Zaporozhye' - timezone 'Europe/Zurich' - linked_timezone 'GB' - linked_timezone 'GB-Eire' - linked_timezone 'GMT' - linked_timezone 'GMT+0' - linked_timezone 'GMT-0' - linked_timezone 'GMT0' - linked_timezone 'Greenwich' - timezone 'HST' - linked_timezone 'Hongkong' - linked_timezone 'Iceland' - timezone 'Indian/Antananarivo' - timezone 'Indian/Chagos' - timezone 'Indian/Christmas' - timezone 'Indian/Cocos' - timezone 'Indian/Comoro' - timezone 'Indian/Kerguelen' - timezone 'Indian/Mahe' - timezone 'Indian/Maldives' - timezone 'Indian/Mauritius' - timezone 'Indian/Mayotte' - timezone 'Indian/Reunion' - linked_timezone 'Iran' - linked_timezone 'Israel' - linked_timezone 'Jamaica' - linked_timezone 'Japan' - linked_timezone 'Kwajalein' - linked_timezone 'Libya' - timezone 'MET' - timezone 'MST' - timezone 'MST7MDT' - linked_timezone 'Mexico/BajaNorte' - linked_timezone 'Mexico/BajaSur' - linked_timezone 'Mexico/General' - linked_timezone 'NZ' - linked_timezone 'NZ-CHAT' - linked_timezone 'Navajo' - linked_timezone 'PRC' - timezone 'PST8PDT' - timezone 'Pacific/Apia' - timezone 'Pacific/Auckland' - timezone 'Pacific/Chatham' - timezone 'Pacific/Chuuk' - timezone 'Pacific/Easter' - timezone 'Pacific/Efate' - timezone 'Pacific/Enderbury' - timezone 'Pacific/Fakaofo' - timezone 'Pacific/Fiji' - timezone 'Pacific/Funafuti' - timezone 'Pacific/Galapagos' - timezone 'Pacific/Gambier' - timezone 'Pacific/Guadalcanal' - timezone 'Pacific/Guam' - timezone 'Pacific/Honolulu' - linked_timezone 'Pacific/Johnston' - timezone 'Pacific/Kiritimati' - timezone 'Pacific/Kosrae' - timezone 'Pacific/Kwajalein' - timezone 'Pacific/Majuro' - timezone 'Pacific/Marquesas' - timezone 'Pacific/Midway' - timezone 'Pacific/Nauru' - timezone 'Pacific/Niue' - timezone 'Pacific/Norfolk' - timezone 'Pacific/Noumea' - timezone 'Pacific/Pago_Pago' - timezone 'Pacific/Palau' - timezone 'Pacific/Pitcairn' - timezone 'Pacific/Pohnpei' - linked_timezone 'Pacific/Ponape' - timezone 'Pacific/Port_Moresby' - timezone 'Pacific/Rarotonga' - timezone 'Pacific/Saipan' - linked_timezone 'Pacific/Samoa' - timezone 'Pacific/Tahiti' - timezone 'Pacific/Tarawa' - timezone 'Pacific/Tongatapu' - linked_timezone 'Pacific/Truk' - timezone 'Pacific/Wake' - timezone 'Pacific/Wallis' - linked_timezone 'Pacific/Yap' - linked_timezone 'Poland' - linked_timezone 'Portugal' - linked_timezone 'ROC' - linked_timezone 'ROK' - linked_timezone 'Singapore' - linked_timezone 'Turkey' - linked_timezone 'UCT' - linked_timezone 'US/Alaska' - linked_timezone 'US/Aleutian' - linked_timezone 'US/Arizona' - linked_timezone 'US/Central' - linked_timezone 'US/East-Indiana' - linked_timezone 'US/Eastern' - linked_timezone 'US/Hawaii' - linked_timezone 'US/Indiana-Starke' - linked_timezone 'US/Michigan' - linked_timezone 'US/Mountain' - linked_timezone 'US/Pacific' - linked_timezone 'US/Pacific-New' - linked_timezone 'US/Samoa' - linked_timezone 'UTC' - linked_timezone 'Universal' - linked_timezone 'W-SU' - timezone 'WET' - linked_timezone 'Zulu' - end - end - end -end diff -Nru ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/version.rb ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/version.rb --- ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data/version.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data/version.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -module TZInfo - module Data - # TZInfo::Data version information. - module Version - # The format of the Ruby modules. The only format currently supported by - # TZInfo is version 1. - FORMAT = 1 - - # The version of the {IANA Time Zone Database}[http://www.iana.org/time-zones] - # used to generate this version of TZInfo::Data. - TZDATA = '2014f' - end - end -end diff -Nru ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data.rb ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data.rb --- ruby-tzinfo-1.2.6/test/tzinfo-data/tzinfo/data.rb 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/tzinfo-data/tzinfo/data.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -# Top level module for TZInfo. -module TZInfo - # Top level module for TZInfo::Data. - module Data - end -end - -require 'tzinfo/data/version' Binary files /tmp/tmp1__nrbj3/6KS5sjn70P/ruby-tzinfo-1.2.6/test/zoneinfo/America/Argentina/Buenos_Aires and /tmp/tmp1__nrbj3/8QcohKxo2Z/ruby-tzinfo-2.0.4/test/zoneinfo/America/Argentina/Buenos_Aires differ Binary files /tmp/tmp1__nrbj3/6KS5sjn70P/ruby-tzinfo-1.2.6/test/zoneinfo/America/New_York and /tmp/tmp1__nrbj3/8QcohKxo2Z/ruby-tzinfo-2.0.4/test/zoneinfo/America/New_York differ Binary files /tmp/tmp1__nrbj3/6KS5sjn70P/ruby-tzinfo-1.2.6/test/zoneinfo/Australia/Melbourne and /tmp/tmp1__nrbj3/8QcohKxo2Z/ruby-tzinfo-2.0.4/test/zoneinfo/Australia/Melbourne differ Binary files /tmp/tmp1__nrbj3/6KS5sjn70P/ruby-tzinfo-1.2.6/test/zoneinfo/EST and /tmp/tmp1__nrbj3/8QcohKxo2Z/ruby-tzinfo-2.0.4/test/zoneinfo/EST differ Binary files /tmp/tmp1__nrbj3/6KS5sjn70P/ruby-tzinfo-1.2.6/test/zoneinfo/Etc/UTC and /tmp/tmp1__nrbj3/8QcohKxo2Z/ruby-tzinfo-2.0.4/test/zoneinfo/Etc/UTC differ Binary files /tmp/tmp1__nrbj3/6KS5sjn70P/ruby-tzinfo-1.2.6/test/zoneinfo/Europe/Amsterdam and /tmp/tmp1__nrbj3/8QcohKxo2Z/ruby-tzinfo-2.0.4/test/zoneinfo/Europe/Amsterdam differ Binary files /tmp/tmp1__nrbj3/6KS5sjn70P/ruby-tzinfo-1.2.6/test/zoneinfo/Europe/Andorra and /tmp/tmp1__nrbj3/8QcohKxo2Z/ruby-tzinfo-2.0.4/test/zoneinfo/Europe/Andorra differ Binary files /tmp/tmp1__nrbj3/6KS5sjn70P/ruby-tzinfo-1.2.6/test/zoneinfo/Europe/London and /tmp/tmp1__nrbj3/8QcohKxo2Z/ruby-tzinfo-2.0.4/test/zoneinfo/Europe/London differ Binary files /tmp/tmp1__nrbj3/6KS5sjn70P/ruby-tzinfo-1.2.6/test/zoneinfo/Europe/Paris and /tmp/tmp1__nrbj3/8QcohKxo2Z/ruby-tzinfo-2.0.4/test/zoneinfo/Europe/Paris differ Binary files /tmp/tmp1__nrbj3/6KS5sjn70P/ruby-tzinfo-1.2.6/test/zoneinfo/Europe/Prague and /tmp/tmp1__nrbj3/8QcohKxo2Z/ruby-tzinfo-2.0.4/test/zoneinfo/Europe/Prague differ Binary files /tmp/tmp1__nrbj3/6KS5sjn70P/ruby-tzinfo-1.2.6/test/zoneinfo/Factory and /tmp/tmp1__nrbj3/8QcohKxo2Z/ruby-tzinfo-2.0.4/test/zoneinfo/Factory differ diff -Nru ruby-tzinfo-1.2.6/test/zoneinfo/.gitignore ruby-tzinfo-2.0.4/test/zoneinfo/.gitignore --- ruby-tzinfo-1.2.6/test/zoneinfo/.gitignore 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/zoneinfo/.gitignore 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -UTC -localtime diff -Nru ruby-tzinfo-1.2.6/test/zoneinfo/iso3166.tab ruby-tzinfo-2.0.4/test/zoneinfo/iso3166.tab --- ruby-tzinfo-1.2.6/test/zoneinfo/iso3166.tab 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/zoneinfo/iso3166.tab 1970-01-01 00:00:00.000000000 +0000 @@ -1,275 +0,0 @@ -# ISO 3166 alpha-2 country codes -# -# This file is in the public domain, so clarified as of -# 2009-05-17 by Arthur David Olson. -# -# From Paul Eggert (2014-07-18): -# This file contains a table of two-letter country codes. Columns are -# separated by a single tab. Lines beginning with '#' are comments. -# Although all text currently uses ASCII encoding, this is planned to -# change to UTF-8 soon. The columns of the table are as follows: -# -# 1. ISO 3166-1 alpha-2 country code, current as of -# ISO 3166-1 Newsletter VI-16 (2013-07-11). See: Updates on ISO 3166 -# http://www.iso.org/iso/home/standards/country_codes/updates_on_iso_3166.htm -# 2. The usual English name for the coded region, -# chosen so that alphabetic sorting of subsets produces helpful lists. -# This is not the same as the English name in the ISO 3166 tables. -# -# The table is sorted by country code. -# -# This table is intended as an aid for users, to help them select time -# zone data appropriate for their practical needs. It is not intended -# to take or endorse any position on legal or territorial claims. -# -#country- -#code name of country, territory, area, or subdivision -AD Andorra -AE United Arab Emirates -AF Afghanistan -AG Antigua & Barbuda -AI Anguilla -AL Albania -AM Armenia -AO Angola -AQ Antarctica -AR Argentina -AS Samoa (American) -AT Austria -AU Australia -AW Aruba -AX Aaland Islands -AZ Azerbaijan -BA Bosnia & Herzegovina -BB Barbados -BD Bangladesh -BE Belgium -BF Burkina Faso -BG Bulgaria -BH Bahrain -BI Burundi -BJ Benin -BL St Barthelemy -BM Bermuda -BN Brunei -BO Bolivia -BQ Caribbean Netherlands -BR Brazil -BS Bahamas -BT Bhutan -BV Bouvet Island -BW Botswana -BY Belarus -BZ Belize -CA Canada -CC Cocos (Keeling) Islands -CD Congo (Dem. Rep.) -CF Central African Rep. -CG Congo (Rep.) -CH Switzerland -CI Cote d'Ivoire -CK Cook Islands -CL Chile -CM Cameroon -CN China -CO Colombia -CR Costa Rica -CU Cuba -CV Cape Verde -CW Curacao -CX Christmas Island -CY Cyprus -CZ Czech Republic -DE Germany -DJ Djibouti -DK Denmark -DM Dominica -DO Dominican Republic -DZ Algeria -EC Ecuador -EE Estonia -EG Egypt -EH Western Sahara -ER Eritrea -ES Spain -ET Ethiopia -FI Finland -FJ Fiji -FK Falkland Islands -FM Micronesia -FO Faroe Islands -FR France -GA Gabon -GB Britain (UK) -GD Grenada -GE Georgia -GF French Guiana -GG Guernsey -GH Ghana -GI Gibraltar -GL Greenland -GM Gambia -GN Guinea -GP Guadeloupe -GQ Equatorial Guinea -GR Greece -GS South Georgia & the South Sandwich Islands -GT Guatemala -GU Guam -GW Guinea-Bissau -GY Guyana -HK Hong Kong -HM Heard Island & McDonald Islands -HN Honduras -HR Croatia -HT Haiti -HU Hungary -ID Indonesia -IE Ireland -IL Israel -IM Isle of Man -IN India -IO British Indian Ocean Territory -IQ Iraq -IR Iran -IS Iceland -IT Italy -JE Jersey -JM Jamaica -JO Jordan -JP Japan -KE Kenya -KG Kyrgyzstan -KH Cambodia -KI Kiribati -KM Comoros -KN St Kitts & Nevis -KP Korea (North) -KR Korea (South) -KW Kuwait -KY Cayman Islands -KZ Kazakhstan -LA Laos -LB Lebanon -LC St Lucia -LI Liechtenstein -LK Sri Lanka -LR Liberia -LS Lesotho -LT Lithuania -LU Luxembourg -LV Latvia -LY Libya -MA Morocco -MC Monaco -MD Moldova -ME Montenegro -MF St Martin (French part) -MG Madagascar -MH Marshall Islands -MK Macedonia -ML Mali -MM Myanmar (Burma) -MN Mongolia -MO Macau -MP Northern Mariana Islands -MQ Martinique -MR Mauritania -MS Montserrat -MT Malta -MU Mauritius -MV Maldives -MW Malawi -MX Mexico -MY Malaysia -MZ Mozambique -NA Namibia -NC New Caledonia -NE Niger -NF Norfolk Island -NG Nigeria -NI Nicaragua -NL Netherlands -NO Norway -NP Nepal -NR Nauru -NU Niue -NZ New Zealand -OM Oman -PA Panama -PE Peru -PF French Polynesia -PG Papua New Guinea -PH Philippines -PK Pakistan -PL Poland -PM St Pierre & Miquelon -PN Pitcairn -PR Puerto Rico -PS Palestine -PT Portugal -PW Palau -PY Paraguay -QA Qatar -RE Reunion -RO Romania -RS Serbia -RU Russia -RW Rwanda -SA Saudi Arabia -SB Solomon Islands -SC Seychelles -SD Sudan -SE Sweden -SG Singapore -SH St Helena -SI Slovenia -SJ Svalbard & Jan Mayen -SK Slovakia -SL Sierra Leone -SM San Marino -SN Senegal -SO Somalia -SR Suriname -SS South Sudan -ST Sao Tome & Principe -SV El Salvador -SX St Maarten (Dutch part) -SY Syria -SZ Swaziland -TC Turks & Caicos Is -TD Chad -TF French Southern & Antarctic Lands -TG Togo -TH Thailand -TJ Tajikistan -TK Tokelau -TL East Timor -TM Turkmenistan -TN Tunisia -TO Tonga -TR Turkey -TT Trinidad & Tobago -TV Tuvalu -TW Taiwan -TZ Tanzania -UA Ukraine -UG Uganda -UM US minor outlying islands -US United States -UY Uruguay -UZ Uzbekistan -VA Vatican City -VC St Vincent -VE Venezuela -VG Virgin Islands (UK) -VI Virgin Islands (US) -VN Vietnam -VU Vanuatu -WF Wallis & Futuna -WS Samoa (western) -YE Yemen -YT Mayotte -ZA South Africa -ZM Zambia -ZW Zimbabwe diff -Nru ruby-tzinfo-1.2.6/test/zoneinfo/leapseconds ruby-tzinfo-2.0.4/test/zoneinfo/leapseconds --- ruby-tzinfo-1.2.6/test/zoneinfo/leapseconds 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/zoneinfo/leapseconds 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -# Allowance for leap seconds added to each time zone file. - -# This file is in the public domain. - -# This file is generated automatically from the data in the public-domain -# leap-seconds.list file, which is copied from: -# ftp://ftp.nist.gov/pub/time/leap-seconds.list -# For more about leap-seconds.list, please see -# The NTP Timescale and Leap Seconds -# https://www.eecis.udel.edu/~mills/leap.html - -# The International Earth Rotation and Reference Systems Service -# periodically uses leap seconds to keep UTC to within 0.9 s of UT1 -# (which measures the true angular orientation of the earth in space); see -# Levine J. Coordinated Universal Time and the leap second. -# URSI Radio Sci Bull. 2016;89(4):30-6. doi:10.23919/URSIRSB.2016.7909995 -# http://ieeexplore.ieee.org/document/7909995/ -# There were no leap seconds before 1972, because the official mechanism -# accounting for the discrepancy between atomic time and the earth's rotation -# did not exist until the early 1970s. - -# The correction (+ or -) is made at the given time, so lines -# will typically look like: -# Leap YEAR MON DAY 23:59:60 + R/S -# or -# Leap YEAR MON DAY 23:59:59 - R/S - -# If the leapsecond is Rolling (R) the given time is local time. -# If the leapsecond is Stationary (S) the given time is UTC. - -# Leap YEAR MONTH DAY HH:MM:SS CORR R/S -Leap 1972 Jun 30 23:59:60 + S -Leap 1972 Dec 31 23:59:60 + S -Leap 1973 Dec 31 23:59:60 + S -Leap 1974 Dec 31 23:59:60 + S -Leap 1975 Dec 31 23:59:60 + S -Leap 1976 Dec 31 23:59:60 + S -Leap 1977 Dec 31 23:59:60 + S -Leap 1978 Dec 31 23:59:60 + S -Leap 1979 Dec 31 23:59:60 + S -Leap 1981 Jun 30 23:59:60 + S -Leap 1982 Jun 30 23:59:60 + S -Leap 1983 Jun 30 23:59:60 + S -Leap 1985 Jun 30 23:59:60 + S -Leap 1987 Dec 31 23:59:60 + S -Leap 1989 Dec 31 23:59:60 + S -Leap 1990 Dec 31 23:59:60 + S -Leap 1992 Jun 30 23:59:60 + S -Leap 1993 Jun 30 23:59:60 + S -Leap 1994 Jun 30 23:59:60 + S -Leap 1995 Dec 31 23:59:60 + S -Leap 1997 Jun 30 23:59:60 + S -Leap 1998 Dec 31 23:59:60 + S -Leap 2005 Dec 31 23:59:60 + S -Leap 2008 Dec 31 23:59:60 + S -Leap 2012 Jun 30 23:59:60 + S -Leap 2015 Jun 30 23:59:60 + S -Leap 2016 Dec 31 23:59:60 + S - -# Updated through IERS Bulletin C54 -# File expires on: 28 June 2018 Binary files /tmp/tmp1__nrbj3/6KS5sjn70P/ruby-tzinfo-1.2.6/test/zoneinfo/posix/Europe/London and /tmp/tmp1__nrbj3/8QcohKxo2Z/ruby-tzinfo-2.0.4/test/zoneinfo/posix/Europe/London differ Binary files /tmp/tmp1__nrbj3/6KS5sjn70P/ruby-tzinfo-1.2.6/test/zoneinfo/posixrules and /tmp/tmp1__nrbj3/8QcohKxo2Z/ruby-tzinfo-2.0.4/test/zoneinfo/posixrules differ Binary files /tmp/tmp1__nrbj3/6KS5sjn70P/ruby-tzinfo-1.2.6/test/zoneinfo/right/Europe/London and /tmp/tmp1__nrbj3/8QcohKxo2Z/ruby-tzinfo-2.0.4/test/zoneinfo/right/Europe/London differ diff -Nru ruby-tzinfo-1.2.6/test/zoneinfo/zone1970.tab ruby-tzinfo-2.0.4/test/zoneinfo/zone1970.tab --- ruby-tzinfo-1.2.6/test/zoneinfo/zone1970.tab 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/zoneinfo/zone1970.tab 1970-01-01 00:00:00.000000000 +0000 @@ -1,369 +0,0 @@ -# tz zone descriptions -# -# This file is in the public domain. -# -# From Paul Eggert (2014-07-31): -# This file contains a table where each row stands for a zone where -# civil time stamps have agreed since 1970. Columns are separated by -# a single tab. Lines beginning with '#' are comments. All text uses -# UTF-8 encoding. The columns of the table are as follows: -# -# 1. The countries that overlap the zone, as a comma-separated list -# of ISO 3166 2-character country codes. See the file 'iso3166.tab'. -# 2. Latitude and longitude of the zone's principal location -# in ISO 6709 sign-degrees-minutes-seconds format, -# either +-DDMM+-DDDMM or +-DDMMSS+-DDDMMSS, -# first latitude (+ is north), then longitude (+ is east). -# 3. Zone name used in value of TZ environment variable. -# Please see the 'Theory' file for how zone names are chosen. -# If multiple zones overlap a country, each has a row in the -# table, with each column 1 containing the country code. -# 4. Comments; present if and only if a country has multiple zones. -# -# If a zone covers multiple countries, the most-populous city is used, -# and that country is listed first in column 1; any other countries -# are listed alphabetically by country code. The table is sorted -# first by country code, then (if possible) by an order within the -# country that (1) makes some geographical sense, and (2) puts the -# most populous zones first, where that does not contradict (1). -# -# This table is intended as an aid for users, to help them select time -# zone data appropriate for their practical needs. It is not intended -# to take or endorse any position on legal or territorial claims. -# -#country- -#codes coordinates TZ comments -AD +4230+00131 Europe/Andorra -AE,OM +2518+05518 Asia/Dubai -AF +3431+06912 Asia/Kabul -AL +4120+01950 Europe/Tirane -AM +4011+04430 Asia/Yerevan -AQ -6734-06808 Antarctica/Rothera Rothera Station, Adelaide Island -AQ -6448-06406 Antarctica/Palmer Palmer Station, Anvers Island -AQ -6736+06253 Antarctica/Mawson Mawson Station, Holme Bay -AQ -6835+07758 Antarctica/Davis Davis Station, Vestfold Hills -AQ -6617+11031 Antarctica/Casey Casey Station, Bailey Peninsula -AQ -7824+10654 Antarctica/Vostok Vostok Station, Lake Vostok -AQ -6640+14001 Antarctica/DumontDUrville Dumont-d'Urville Station, Terre Adelie -AQ -690022+0393524 Antarctica/Syowa Syowa Station, E Ongul I -AQ -720041+0023206 Antarctica/Troll Troll Station, Queen Maud Land -AR -3436-05827 America/Argentina/Buenos_Aires Buenos Aires (BA, CF) -AR -3124-06411 America/Argentina/Cordoba most locations (CB, CC, CN, ER, FM, MN, SE, SF) -AR -2447-06525 America/Argentina/Salta (SA, LP, NQ, RN) -AR -2411-06518 America/Argentina/Jujuy Jujuy (JY) -AR -2649-06513 America/Argentina/Tucuman Tucumán (TM) -AR -2828-06547 America/Argentina/Catamarca Catamarca (CT), Chubut (CH) -AR -2926-06651 America/Argentina/La_Rioja La Rioja (LR) -AR -3132-06831 America/Argentina/San_Juan San Juan (SJ) -AR -3253-06849 America/Argentina/Mendoza Mendoza (MZ) -AR -3319-06621 America/Argentina/San_Luis San Luis (SL) -AR -5138-06913 America/Argentina/Rio_Gallegos Santa Cruz (SC) -AR -5448-06818 America/Argentina/Ushuaia Tierra del Fuego (TF) -AS,UM -1416-17042 Pacific/Pago_Pago Samoa, Midway -AT +4813+01620 Europe/Vienna -AU -3133+15905 Australia/Lord_Howe Lord Howe Island -AU -5430+15857 Antarctica/Macquarie Macquarie Island -AU -4253+14719 Australia/Hobart Tasmania - most locations -AU -3956+14352 Australia/Currie Tasmania - King Island -AU -3749+14458 Australia/Melbourne Victoria -AU -3352+15113 Australia/Sydney New South Wales - most locations -AU -3157+14127 Australia/Broken_Hill New South Wales - Yancowinna -AU -2728+15302 Australia/Brisbane Queensland - most locations -AU -2016+14900 Australia/Lindeman Queensland - Holiday Islands -AU -3455+13835 Australia/Adelaide South Australia -AU -1228+13050 Australia/Darwin Northern Territory -AU -3157+11551 Australia/Perth Western Australia - most locations -AU -3143+12852 Australia/Eucla Western Australia - Eucla area -AZ +4023+04951 Asia/Baku -BB +1306-05937 America/Barbados -BD +2343+09025 Asia/Dhaka -BE +5050+00420 Europe/Brussels -BG +4241+02319 Europe/Sofia -BM +3217-06446 Atlantic/Bermuda -BN +0456+11455 Asia/Brunei -BO -1630-06809 America/La_Paz -BR -0351-03225 America/Noronha Atlantic islands -BR -0127-04829 America/Belem Amapá, E Pará -BR -0343-03830 America/Fortaleza NE Brazil (MA, PI, CE, RN, PB) -BR -0803-03454 America/Recife Pernambuco -BR -0712-04812 America/Araguaina Tocantins -BR -0940-03543 America/Maceio Alagoas, Sergipe -BR -1259-03831 America/Bahia Bahia -BR -2332-04637 America/Sao_Paulo S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS) -BR -2027-05437 America/Campo_Grande Mato Grosso do Sul -BR -1535-05605 America/Cuiaba Mato Grosso -BR -0226-05452 America/Santarem W Pará -BR -0846-06354 America/Porto_Velho Rondônia -BR +0249-06040 America/Boa_Vista Roraima -BR -0308-06001 America/Manaus E Amazonas -BR -0640-06952 America/Eirunepe W Amazonas -BR -0958-06748 America/Rio_Branco Acre -BS +2505-07721 America/Nassau -BT +2728+08939 Asia/Thimphu -BY +5354+02734 Europe/Minsk -BZ +1730-08812 America/Belize -CA +4734-05243 America/St_Johns Newfoundland Time, including SE Labrador -CA +4439-06336 America/Halifax Atlantic Time - Nova Scotia (most places), PEI -CA +4612-05957 America/Glace_Bay Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971 -CA +4606-06447 America/Moncton Atlantic Time - New Brunswick -CA +5320-06025 America/Goose_Bay Atlantic Time - Labrador - most locations -CA +5125-05707 America/Blanc-Sablon Atlantic Standard Time - Quebec - Lower North Shore -CA +4339-07923 America/Toronto Eastern Time - Ontario & Quebec - most locations -CA +4901-08816 America/Nipigon Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973 -CA +4823-08915 America/Thunder_Bay Eastern Time - Thunder Bay, Ontario -CA +6344-06828 America/Iqaluit Eastern Time - east Nunavut - most locations -CA +6608-06544 America/Pangnirtung Eastern Time - Pangnirtung, Nunavut -CA +744144-0944945 America/Resolute Central Time - Resolute, Nunavut -CA +484531-0913718 America/Atikokan Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut -CA +624900-0920459 America/Rankin_Inlet Central Time - central Nunavut -CA +4953-09709 America/Winnipeg Central Time - Manitoba & west Ontario -CA +4843-09434 America/Rainy_River Central Time - Rainy River & Fort Frances, Ontario -CA +5024-10439 America/Regina Central Standard Time - Saskatchewan - most locations -CA +5017-10750 America/Swift_Current Central Standard Time - Saskatchewan - midwest -CA +5333-11328 America/Edmonton Mountain Time - Alberta, east British Columbia & west Saskatchewan -CA +690650-1050310 America/Cambridge_Bay Mountain Time - west Nunavut -CA +6227-11421 America/Yellowknife Mountain Time - central Northwest Territories -CA +682059-1334300 America/Inuvik Mountain Time - west Northwest Territories -CA +4906-11631 America/Creston Mountain Standard Time - Creston, British Columbia -CA +5946-12014 America/Dawson_Creek Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia -CA +4916-12307 America/Vancouver Pacific Time - west British Columbia -CA +6043-13503 America/Whitehorse Pacific Time - south Yukon -CA +6404-13925 America/Dawson Pacific Time - north Yukon -CC -1210+09655 Indian/Cocos -CH,DE,LI +4723+00832 Europe/Zurich Swiss time -CI,BF,GM,GN,ML,MR,SH,SL,SN,ST,TG +0519-00402 Africa/Abidjan -CK -2114-15946 Pacific/Rarotonga -CL -3327-07040 America/Santiago most locations -CL -2709-10926 Pacific/Easter Easter Island -CN +3114+12128 Asia/Shanghai Beijing Time -CN +4348+08735 Asia/Urumqi Xinjiang Time -CO +0436-07405 America/Bogota -CR +0956-08405 America/Costa_Rica -CU +2308-08222 America/Havana -CV +1455-02331 Atlantic/Cape_Verde -CW,AW,BQ,SX +1211-06900 America/Curacao -CX -1025+10543 Indian/Christmas -CY +3510+03322 Asia/Nicosia -CZ,SK +5005+01426 Europe/Prague -DE +5230+01322 Europe/Berlin Berlin time -DK +5540+01235 Europe/Copenhagen -DO +1828-06954 America/Santo_Domingo -DZ +3647+00303 Africa/Algiers -EC -0210-07950 America/Guayaquil mainland -EC -0054-08936 Pacific/Galapagos Galápagos Islands -EE +5925+02445 Europe/Tallinn -EG +3003+03115 Africa/Cairo -EH +2709-01312 Africa/El_Aaiun -ES +4024-00341 Europe/Madrid mainland -ES +3553-00519 Africa/Ceuta Ceuta & Melilla -ES +2806-01524 Atlantic/Canary Canary Islands -FI,AX +6010+02458 Europe/Helsinki -FJ -1808+17825 Pacific/Fiji -FK -5142-05751 Atlantic/Stanley -FM +0725+15147 Pacific/Chuuk Chuuk (Truk) and Yap -FM +0658+15813 Pacific/Pohnpei Pohnpei (Ponape) -FM +0519+16259 Pacific/Kosrae Kosrae -FO +6201-00646 Atlantic/Faroe -FR +4852+00220 Europe/Paris -GB,GG,IM,JE +513030-0000731 Europe/London -GE +4143+04449 Asia/Tbilisi -GF +0456-05220 America/Cayenne -GH +0533-00013 Africa/Accra -GI +3608-00521 Europe/Gibraltar -GL +6411-05144 America/Godthab most locations -GL +7646-01840 America/Danmarkshavn east coast, north of Scoresbysund -GL +7029-02158 America/Scoresbysund Scoresbysund / Ittoqqortoormiit -GL +7634-06847 America/Thule Thule / Pituffik -GR +3758+02343 Europe/Athens -GS -5416-03632 Atlantic/South_Georgia -GT +1438-09031 America/Guatemala -GU,MP +1328+14445 Pacific/Guam -GW +1151-01535 Africa/Bissau -GY +0648-05810 America/Guyana -HK +2217+11409 Asia/Hong_Kong -HN +1406-08713 America/Tegucigalpa -HT +1832-07220 America/Port-au-Prince -HU +4730+01905 Europe/Budapest -ID -0610+10648 Asia/Jakarta Java & Sumatra -ID -0002+10920 Asia/Pontianak west & central Borneo -ID -0507+11924 Asia/Makassar east & south Borneo, Sulawesi (Celebes), Bali, Nusa Tengarra, west Timor -ID -0232+14042 Asia/Jayapura west New Guinea (Irian Jaya) & Malukus (Moluccas) -IE +5320-00615 Europe/Dublin -IL +314650+0351326 Asia/Jerusalem -IN +2232+08822 Asia/Kolkata -IO -0720+07225 Indian/Chagos -IQ +3321+04425 Asia/Baghdad -IR +3540+05126 Asia/Tehran -IS +6409-02151 Atlantic/Reykjavik -IT,SM,VA +4154+01229 Europe/Rome -JM +175805-0764736 America/Jamaica -JO +3157+03556 Asia/Amman -JP +353916+1394441 Asia/Tokyo -KE,DJ,ER,ET,KM,MG,SO,TZ,UG,YT -0117+03649 Africa/Nairobi -KG +4254+07436 Asia/Bishkek -KI +0125+17300 Pacific/Tarawa Gilbert Islands -KI -0308-17105 Pacific/Enderbury Phoenix Islands -KI +0152-15720 Pacific/Kiritimati Line Islands -KP +3901+12545 Asia/Pyongyang -KR +3733+12658 Asia/Seoul -KZ +4315+07657 Asia/Almaty most locations -KZ +4448+06528 Asia/Qyzylorda Qyzylorda (Kyzylorda, Kzyl-Orda) -KZ +5017+05710 Asia/Aqtobe Aqtobe (Aktobe) -KZ +4431+05016 Asia/Aqtau Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau) -KZ +5113+05121 Asia/Oral West Kazakhstan -LB +3353+03530 Asia/Beirut -LK +0656+07951 Asia/Colombo -LR +0618-01047 Africa/Monrovia -LT +5441+02519 Europe/Vilnius -LU +4936+00609 Europe/Luxembourg -LV +5657+02406 Europe/Riga -LY +3254+01311 Africa/Tripoli -MA +3339-00735 Africa/Casablanca -MC +4342+00723 Europe/Monaco -MD +4700+02850 Europe/Chisinau -MH +0709+17112 Pacific/Majuro most locations -MH +0905+16720 Pacific/Kwajalein Kwajalein -MM +1647+09610 Asia/Rangoon -MN +4755+10653 Asia/Ulaanbaatar most locations -MN +4801+09139 Asia/Hovd Bayan-Ölgii, Govi-Altai, Hovd, Uvs, Zavkhan -MN +4804+11430 Asia/Choibalsan Dornod, Sükhbaatar -MO +2214+11335 Asia/Macau -MQ +1436-06105 America/Martinique -MT +3554+01431 Europe/Malta -MU -2010+05730 Indian/Mauritius -MV +0410+07330 Indian/Maldives -MX +1924-09909 America/Mexico_City Central Time - most locations -MX +2105-08646 America/Cancun Central Time - Quintana Roo -MX +2058-08937 America/Merida Central Time - Campeche, Yucatán -MX +2540-10019 America/Monterrey Mexican Central Time - Coahuila, Durango, Nuevo León, Tamaulipas away from US border -MX +2550-09730 America/Matamoros US Central Time - Coahuila, Durango, Nuevo León, Tamaulipas near US border -MX +2313-10625 America/Mazatlan Mountain Time - S Baja, Nayarit, Sinaloa -MX +2838-10605 America/Chihuahua Mexican Mountain Time - Chihuahua away from US border -MX +2934-10425 America/Ojinaga US Mountain Time - Chihuahua near US border -MX +2904-11058 America/Hermosillo Mountain Standard Time - Sonora -MX +3232-11701 America/Tijuana US Pacific Time - Baja California near US border -MX +3018-11452 America/Santa_Isabel Mexican Pacific Time - Baja California away from US border -MX +2048-10515 America/Bahia_Banderas Mexican Central Time - Bahía de Banderas -MY +0310+10142 Asia/Kuala_Lumpur peninsular Malaysia -MY +0133+11020 Asia/Kuching Sabah & Sarawak -MZ,BI,BW,CD,MW,RW,ZM,ZW -2558+03235 Africa/Maputo Central Africa Time (UTC+2) -NA -2234+01706 Africa/Windhoek -NC -2216+16627 Pacific/Noumea -NF -2903+16758 Pacific/Norfolk -NG,AO,BJ,CD,CF,CG,CM,GA,GQ,NE +0627+00324 Africa/Lagos West Africa Time (UTC+1) -NI +1209-08617 America/Managua -NL +5222+00454 Europe/Amsterdam -NO,SJ +5955+01045 Europe/Oslo -NP +2743+08519 Asia/Kathmandu -NR -0031+16655 Pacific/Nauru -NU -1901-16955 Pacific/Niue -NZ,AQ -3652+17446 Pacific/Auckland New Zealand time -NZ -4357-17633 Pacific/Chatham Chatham Islands -PA,KY +0858-07932 America/Panama -PE -1203-07703 America/Lima -PF -1732-14934 Pacific/Tahiti Society Islands -PF -0900-13930 Pacific/Marquesas Marquesas Islands -PF -2308-13457 Pacific/Gambier Gambier Islands -PG -0930+14710 Pacific/Port_Moresby -PH +1435+12100 Asia/Manila -PK +2452+06703 Asia/Karachi -PL +5215+02100 Europe/Warsaw -PM +4703-05620 America/Miquelon -PN -2504-13005 Pacific/Pitcairn -PR +182806-0660622 America/Puerto_Rico -PS +3130+03428 Asia/Gaza Gaza Strip -PS +313200+0350542 Asia/Hebron West Bank -PT +3843-00908 Europe/Lisbon mainland -PT +3238-01654 Atlantic/Madeira Madeira Islands -PT +3744-02540 Atlantic/Azores Azores -PW +0720+13429 Pacific/Palau -PY -2516-05740 America/Asuncion -QA,BH +2517+05132 Asia/Qatar -RE,TF -2052+05528 Indian/Reunion Réunion, Crozet Is, Scattered Is -RO +4426+02606 Europe/Bucharest -RS,BA,HR,ME,MK,SI +4450+02030 Europe/Belgrade -RU +5443+02030 Europe/Kaliningrad Moscow-01 - Kaliningrad -RU +554521+0373704 Europe/Moscow Moscow+00 - west Russia -RU +4457+03406 Europe/Simferopol Moscow+00 - Crimea -RU +4844+04425 Europe/Volgograd Moscow+00 - Caspian Sea -RU +5312+05009 Europe/Samara Moscow+00 (Moscow+01 after 2014-10-26) - Samara, Udmurtia -RU +5651+06036 Asia/Yekaterinburg Moscow+02 - Urals -RU +5500+07324 Asia/Omsk Moscow+03 - west Siberia -RU +5502+08255 Asia/Novosibirsk Moscow+03 - Novosibirsk -RU +5345+08707 Asia/Novokuznetsk Moscow+03 (Moscow+04 after 2014-10-26) - Kemerovo -RU +5601+09250 Asia/Krasnoyarsk Moscow+04 - Yenisei River -RU +5216+10420 Asia/Irkutsk Moscow+05 - Lake Baikal -RU +5203+11328 Asia/Chita Moscow+06 (Moscow+05 after 2014-10-26) - Zabaykalsky -RU +6200+12940 Asia/Yakutsk Moscow+06 - Lena River -RU +623923+1353314 Asia/Khandyga Moscow+06 - Tomponsky, Ust-Maysky -RU +4310+13156 Asia/Vladivostok Moscow+07 - Amur River -RU +4658+14242 Asia/Sakhalin Moscow+07 - Sakhalin Island -RU +643337+1431336 Asia/Ust-Nera Moscow+07 - Oymyakonsky -RU +5934+15048 Asia/Magadan Moscow+08 (Moscow+07 after 2014-10-26) - Magadan -RU +6728+15343 Asia/Srednekolymsk Moscow+08 - E Sakha, N Kuril Is -RU +5301+15839 Asia/Kamchatka Moscow+08 (Moscow+09 after 2014-10-26) - Kamchatka -RU +6445+17729 Asia/Anadyr Moscow+08 (Moscow+09 after 2014-10-26) - Bering Sea -SA,KW,YE +2438+04643 Asia/Riyadh -SB -0932+16012 Pacific/Guadalcanal -SC -0440+05528 Indian/Mahe -SD,SS +1536+03232 Africa/Khartoum -SE +5920+01803 Europe/Stockholm -SG +0117+10351 Asia/Singapore -SR +0550-05510 America/Paramaribo -SV +1342-08912 America/El_Salvador -SY +3330+03618 Asia/Damascus -TC +2128-07108 America/Grand_Turk -TD +1207+01503 Africa/Ndjamena -TF -492110+0701303 Indian/Kerguelen Kerguelen, St Paul I, Amsterdam I -TH,KH,LA,VN +1345+10031 Asia/Bangkok -TJ +3835+06848 Asia/Dushanbe -TK -0922-17114 Pacific/Fakaofo -TL -0833+12535 Asia/Dili -TM +3757+05823 Asia/Ashgabat -TN +3648+01011 Africa/Tunis -TO -2110-17510 Pacific/Tongatapu -TR +4101+02858 Europe/Istanbul -TT,AG,AI,BL,DM,GD,GP,MF,LC,KN,MS,VC,VG,VI +1039-06131 America/Port_of_Spain -TV -0831+17913 Pacific/Funafuti -TW +2503+12130 Asia/Taipei -UA +5026+03031 Europe/Kiev most locations -UA +4837+02218 Europe/Uzhgorod Ruthenia -UA +4750+03510 Europe/Zaporozhye Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk -UM +1917+16637 Pacific/Wake Wake Island -US +404251-0740023 America/New_York Eastern Time -US +421953-0830245 America/Detroit Eastern Time - Michigan - most locations -US +381515-0854534 America/Kentucky/Louisville Eastern Time - Kentucky - Louisville area -US +364947-0845057 America/Kentucky/Monticello Eastern Time - Kentucky - Wayne County -US +394606-0860929 America/Indiana/Indianapolis Eastern Time - Indiana - most locations -US +384038-0873143 America/Indiana/Vincennes Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties -US +410305-0863611 America/Indiana/Winamac Eastern Time - Indiana - Pulaski County -US +382232-0862041 America/Indiana/Marengo Eastern Time - Indiana - Crawford County -US +382931-0871643 America/Indiana/Petersburg Eastern Time - Indiana - Pike County -US +384452-0850402 America/Indiana/Vevay Eastern Time - Indiana - Switzerland County -US +415100-0873900 America/Chicago Central Time -US +375711-0864541 America/Indiana/Tell_City Central Time - Indiana - Perry County -US +411745-0863730 America/Indiana/Knox Central Time - Indiana - Starke County -US +450628-0873651 America/Menominee Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties -US +470659-1011757 America/North_Dakota/Center Central Time - North Dakota - Oliver County -US +465042-1012439 America/North_Dakota/New_Salem Central Time - North Dakota - Morton County (except Mandan area) -US +471551-1014640 America/North_Dakota/Beulah Central Time - North Dakota - Mercer County -US +394421-1045903 America/Denver Mountain Time -US +433649-1161209 America/Boise Mountain Time - south Idaho & east Oregon -US +332654-1120424 America/Phoenix Mountain Standard Time - Arizona (except Navajo) -US +340308-1181434 America/Los_Angeles Pacific Time -US +550737-1313435 America/Metlakatla Pacific Standard Time - Annette Island, Alaska -US +611305-1495401 America/Anchorage Alaska Time -US +581807-1342511 America/Juneau Alaska Time - Alaska panhandle -US +571035-1351807 America/Sitka Alaska Time - southeast Alaska panhandle -US +593249-1394338 America/Yakutat Alaska Time - Alaska panhandle neck -US +643004-1652423 America/Nome Alaska Time - west Alaska -US +515248-1763929 America/Adak Aleutian Islands -US,UM +211825-1575130 Pacific/Honolulu Hawaii time -UY -3453-05611 America/Montevideo -UZ +3940+06648 Asia/Samarkand west Uzbekistan -UZ +4120+06918 Asia/Tashkent east Uzbekistan -VE +1030-06656 America/Caracas -VU -1740+16825 Pacific/Efate -WF -1318-17610 Pacific/Wallis -WS -1350-17144 Pacific/Apia -ZA,LS,SZ -2615+02800 Africa/Johannesburg diff -Nru ruby-tzinfo-1.2.6/test/zoneinfo/zone.tab ruby-tzinfo-2.0.4/test/zoneinfo/zone.tab --- ruby-tzinfo-1.2.6/test/zoneinfo/zone.tab 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/test/zoneinfo/zone.tab 1970-01-01 00:00:00.000000000 +0000 @@ -1,439 +0,0 @@ -# tz zone descriptions (deprecated version) -# -# This file is in the public domain, so clarified as of -# 2009-05-17 by Arthur David Olson. -# -# From Paul Eggert (2014-07-31): -# This file is intended as a backward-compatibility aid for older programs. -# New programs should use zone1970.tab. This file is like zone1970.tab (see -# zone1970.tab's comments), but with the following additional restrictions: -# -# 1. This file contains only ASCII characters. -# 2. The first data column contains exactly one country code. -# -# Because of (2), each row stands for an area that is the intersection -# of a region identified by a country code and of a zone where civil -# clocks have agreed since 1970; this is a narrower definition than -# that of zone1970.tab. -# -# This table is intended as an aid for users, to help them select time -# zone data appropriate for their practical needs. It is not intended -# to take or endorse any position on legal or territorial claims. -# -#country- -#code coordinates TZ comments -AD +4230+00131 Europe/Andorra -AE +2518+05518 Asia/Dubai -AF +3431+06912 Asia/Kabul -AG +1703-06148 America/Antigua -AI +1812-06304 America/Anguilla -AL +4120+01950 Europe/Tirane -AM +4011+04430 Asia/Yerevan -AO -0848+01314 Africa/Luanda -AQ -7750+16636 Antarctica/McMurdo McMurdo, South Pole, Scott (New Zealand time) -AQ -6734-06808 Antarctica/Rothera Rothera Station, Adelaide Island -AQ -6448-06406 Antarctica/Palmer Palmer Station, Anvers Island -AQ -6736+06253 Antarctica/Mawson Mawson Station, Holme Bay -AQ -6835+07758 Antarctica/Davis Davis Station, Vestfold Hills -AQ -6617+11031 Antarctica/Casey Casey Station, Bailey Peninsula -AQ -7824+10654 Antarctica/Vostok Vostok Station, Lake Vostok -AQ -6640+14001 Antarctica/DumontDUrville Dumont-d'Urville Station, Terre Adelie -AQ -690022+0393524 Antarctica/Syowa Syowa Station, E Ongul I -AQ -720041+0023206 Antarctica/Troll Troll Station, Queen Maud Land -AR -3436-05827 America/Argentina/Buenos_Aires Buenos Aires (BA, CF) -AR -3124-06411 America/Argentina/Cordoba most locations (CB, CC, CN, ER, FM, MN, SE, SF) -AR -2447-06525 America/Argentina/Salta (SA, LP, NQ, RN) -AR -2411-06518 America/Argentina/Jujuy Jujuy (JY) -AR -2649-06513 America/Argentina/Tucuman Tucuman (TM) -AR -2828-06547 America/Argentina/Catamarca Catamarca (CT), Chubut (CH) -AR -2926-06651 America/Argentina/La_Rioja La Rioja (LR) -AR -3132-06831 America/Argentina/San_Juan San Juan (SJ) -AR -3253-06849 America/Argentina/Mendoza Mendoza (MZ) -AR -3319-06621 America/Argentina/San_Luis San Luis (SL) -AR -5138-06913 America/Argentina/Rio_Gallegos Santa Cruz (SC) -AR -5448-06818 America/Argentina/Ushuaia Tierra del Fuego (TF) -AS -1416-17042 Pacific/Pago_Pago -AT +4813+01620 Europe/Vienna -AU -3133+15905 Australia/Lord_Howe Lord Howe Island -AU -5430+15857 Antarctica/Macquarie Macquarie Island -AU -4253+14719 Australia/Hobart Tasmania - most locations -AU -3956+14352 Australia/Currie Tasmania - King Island -AU -3749+14458 Australia/Melbourne Victoria -AU -3352+15113 Australia/Sydney New South Wales - most locations -AU -3157+14127 Australia/Broken_Hill New South Wales - Yancowinna -AU -2728+15302 Australia/Brisbane Queensland - most locations -AU -2016+14900 Australia/Lindeman Queensland - Holiday Islands -AU -3455+13835 Australia/Adelaide South Australia -AU -1228+13050 Australia/Darwin Northern Territory -AU -3157+11551 Australia/Perth Western Australia - most locations -AU -3143+12852 Australia/Eucla Western Australia - Eucla area -AW +1230-06958 America/Aruba -AX +6006+01957 Europe/Mariehamn -AZ +4023+04951 Asia/Baku -BA +4352+01825 Europe/Sarajevo -BB +1306-05937 America/Barbados -BD +2343+09025 Asia/Dhaka -BE +5050+00420 Europe/Brussels -BF +1222-00131 Africa/Ouagadougou -BG +4241+02319 Europe/Sofia -BH +2623+05035 Asia/Bahrain -BI -0323+02922 Africa/Bujumbura -BJ +0629+00237 Africa/Porto-Novo -BL +1753-06251 America/St_Barthelemy -BM +3217-06446 Atlantic/Bermuda -BN +0456+11455 Asia/Brunei -BO -1630-06809 America/La_Paz -BQ +120903-0681636 America/Kralendijk -BR -0351-03225 America/Noronha Atlantic islands -BR -0127-04829 America/Belem Amapa, E Para -BR -0343-03830 America/Fortaleza NE Brazil (MA, PI, CE, RN, PB) -BR -0803-03454 America/Recife Pernambuco -BR -0712-04812 America/Araguaina Tocantins -BR -0940-03543 America/Maceio Alagoas, Sergipe -BR -1259-03831 America/Bahia Bahia -BR -2332-04637 America/Sao_Paulo S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS) -BR -2027-05437 America/Campo_Grande Mato Grosso do Sul -BR -1535-05605 America/Cuiaba Mato Grosso -BR -0226-05452 America/Santarem W Para -BR -0846-06354 America/Porto_Velho Rondonia -BR +0249-06040 America/Boa_Vista Roraima -BR -0308-06001 America/Manaus E Amazonas -BR -0640-06952 America/Eirunepe W Amazonas -BR -0958-06748 America/Rio_Branco Acre -BS +2505-07721 America/Nassau -BT +2728+08939 Asia/Thimphu -BW -2439+02555 Africa/Gaborone -BY +5354+02734 Europe/Minsk -BZ +1730-08812 America/Belize -CA +4734-05243 America/St_Johns Newfoundland Time, including SE Labrador -CA +4439-06336 America/Halifax Atlantic Time - Nova Scotia (most places), PEI -CA +4612-05957 America/Glace_Bay Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971 -CA +4606-06447 America/Moncton Atlantic Time - New Brunswick -CA +5320-06025 America/Goose_Bay Atlantic Time - Labrador - most locations -CA +5125-05707 America/Blanc-Sablon Atlantic Standard Time - Quebec - Lower North Shore -CA +4339-07923 America/Toronto Eastern Time - Ontario & Quebec - most locations -CA +4901-08816 America/Nipigon Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973 -CA +4823-08915 America/Thunder_Bay Eastern Time - Thunder Bay, Ontario -CA +6344-06828 America/Iqaluit Eastern Time - east Nunavut - most locations -CA +6608-06544 America/Pangnirtung Eastern Time - Pangnirtung, Nunavut -CA +744144-0944945 America/Resolute Central Time - Resolute, Nunavut -CA +484531-0913718 America/Atikokan Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut -CA +624900-0920459 America/Rankin_Inlet Central Time - central Nunavut -CA +4953-09709 America/Winnipeg Central Time - Manitoba & west Ontario -CA +4843-09434 America/Rainy_River Central Time - Rainy River & Fort Frances, Ontario -CA +5024-10439 America/Regina Central Standard Time - Saskatchewan - most locations -CA +5017-10750 America/Swift_Current Central Standard Time - Saskatchewan - midwest -CA +5333-11328 America/Edmonton Mountain Time - Alberta, east British Columbia & west Saskatchewan -CA +690650-1050310 America/Cambridge_Bay Mountain Time - west Nunavut -CA +6227-11421 America/Yellowknife Mountain Time - central Northwest Territories -CA +682059-1334300 America/Inuvik Mountain Time - west Northwest Territories -CA +4906-11631 America/Creston Mountain Standard Time - Creston, British Columbia -CA +5946-12014 America/Dawson_Creek Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia -CA +4916-12307 America/Vancouver Pacific Time - west British Columbia -CA +6043-13503 America/Whitehorse Pacific Time - south Yukon -CA +6404-13925 America/Dawson Pacific Time - north Yukon -CC -1210+09655 Indian/Cocos -CD -0418+01518 Africa/Kinshasa west Dem. Rep. of Congo -CD -1140+02728 Africa/Lubumbashi east Dem. Rep. of Congo -CF +0422+01835 Africa/Bangui -CG -0416+01517 Africa/Brazzaville -CH +4723+00832 Europe/Zurich -CI +0519-00402 Africa/Abidjan -CK -2114-15946 Pacific/Rarotonga -CL -3327-07040 America/Santiago most locations -CL -2709-10926 Pacific/Easter Easter Island -CM +0403+00942 Africa/Douala -CN +3114+12128 Asia/Shanghai Beijing Time -CN +4348+08735 Asia/Urumqi Xinjiang Time -CO +0436-07405 America/Bogota -CR +0956-08405 America/Costa_Rica -CU +2308-08222 America/Havana -CV +1455-02331 Atlantic/Cape_Verde -CW +1211-06900 America/Curacao -CX -1025+10543 Indian/Christmas -CY +3510+03322 Asia/Nicosia -CZ +5005+01426 Europe/Prague -DE +5230+01322 Europe/Berlin most locations -DE +4742+00841 Europe/Busingen Busingen -DJ +1136+04309 Africa/Djibouti -DK +5540+01235 Europe/Copenhagen -DM +1518-06124 America/Dominica -DO +1828-06954 America/Santo_Domingo -DZ +3647+00303 Africa/Algiers -EC -0210-07950 America/Guayaquil mainland -EC -0054-08936 Pacific/Galapagos Galapagos Islands -EE +5925+02445 Europe/Tallinn -EG +3003+03115 Africa/Cairo -EH +2709-01312 Africa/El_Aaiun -ER +1520+03853 Africa/Asmara -ES +4024-00341 Europe/Madrid mainland -ES +3553-00519 Africa/Ceuta Ceuta & Melilla -ES +2806-01524 Atlantic/Canary Canary Islands -ET +0902+03842 Africa/Addis_Ababa -FI +6010+02458 Europe/Helsinki -FJ -1808+17825 Pacific/Fiji -FK -5142-05751 Atlantic/Stanley -FM +0725+15147 Pacific/Chuuk Chuuk (Truk) and Yap -FM +0658+15813 Pacific/Pohnpei Pohnpei (Ponape) -FM +0519+16259 Pacific/Kosrae Kosrae -FO +6201-00646 Atlantic/Faroe -FR +4852+00220 Europe/Paris -GA +0023+00927 Africa/Libreville -GB +513030-0000731 Europe/London -GD +1203-06145 America/Grenada -GE +4143+04449 Asia/Tbilisi -GF +0456-05220 America/Cayenne -GG +4927-00232 Europe/Guernsey -GH +0533-00013 Africa/Accra -GI +3608-00521 Europe/Gibraltar -GL +6411-05144 America/Godthab most locations -GL +7646-01840 America/Danmarkshavn east coast, north of Scoresbysund -GL +7029-02158 America/Scoresbysund Scoresbysund / Ittoqqortoormiit -GL +7634-06847 America/Thule Thule / Pituffik -GM +1328-01639 Africa/Banjul -GN +0931-01343 Africa/Conakry -GP +1614-06132 America/Guadeloupe -GQ +0345+00847 Africa/Malabo -GR +3758+02343 Europe/Athens -GS -5416-03632 Atlantic/South_Georgia -GT +1438-09031 America/Guatemala -GU +1328+14445 Pacific/Guam -GW +1151-01535 Africa/Bissau -GY +0648-05810 America/Guyana -HK +2217+11409 Asia/Hong_Kong -HN +1406-08713 America/Tegucigalpa -HR +4548+01558 Europe/Zagreb -HT +1832-07220 America/Port-au-Prince -HU +4730+01905 Europe/Budapest -ID -0610+10648 Asia/Jakarta Java & Sumatra -ID -0002+10920 Asia/Pontianak west & central Borneo -ID -0507+11924 Asia/Makassar east & south Borneo, Sulawesi (Celebes), Bali, Nusa Tengarra, west Timor -ID -0232+14042 Asia/Jayapura west New Guinea (Irian Jaya) & Malukus (Moluccas) -IE +5320-00615 Europe/Dublin -IL +314650+0351326 Asia/Jerusalem -IM +5409-00428 Europe/Isle_of_Man -IN +2232+08822 Asia/Kolkata -IO -0720+07225 Indian/Chagos -IQ +3321+04425 Asia/Baghdad -IR +3540+05126 Asia/Tehran -IS +6409-02151 Atlantic/Reykjavik -IT +4154+01229 Europe/Rome -JE +4912-00207 Europe/Jersey -JM +175805-0764736 America/Jamaica -JO +3157+03556 Asia/Amman -JP +353916+1394441 Asia/Tokyo -KE -0117+03649 Africa/Nairobi -KG +4254+07436 Asia/Bishkek -KH +1133+10455 Asia/Phnom_Penh -KI +0125+17300 Pacific/Tarawa Gilbert Islands -KI -0308-17105 Pacific/Enderbury Phoenix Islands -KI +0152-15720 Pacific/Kiritimati Line Islands -KM -1141+04316 Indian/Comoro -KN +1718-06243 America/St_Kitts -KP +3901+12545 Asia/Pyongyang -KR +3733+12658 Asia/Seoul -KW +2920+04759 Asia/Kuwait -KY +1918-08123 America/Cayman -KZ +4315+07657 Asia/Almaty most locations -KZ +4448+06528 Asia/Qyzylorda Qyzylorda (Kyzylorda, Kzyl-Orda) -KZ +5017+05710 Asia/Aqtobe Aqtobe (Aktobe) -KZ +4431+05016 Asia/Aqtau Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau) -KZ +5113+05121 Asia/Oral West Kazakhstan -LA +1758+10236 Asia/Vientiane -LB +3353+03530 Asia/Beirut -LC +1401-06100 America/St_Lucia -LI +4709+00931 Europe/Vaduz -LK +0656+07951 Asia/Colombo -LR +0618-01047 Africa/Monrovia -LS -2928+02730 Africa/Maseru -LT +5441+02519 Europe/Vilnius -LU +4936+00609 Europe/Luxembourg -LV +5657+02406 Europe/Riga -LY +3254+01311 Africa/Tripoli -MA +3339-00735 Africa/Casablanca -MC +4342+00723 Europe/Monaco -MD +4700+02850 Europe/Chisinau -ME +4226+01916 Europe/Podgorica -MF +1804-06305 America/Marigot -MG -1855+04731 Indian/Antananarivo -MH +0709+17112 Pacific/Majuro most locations -MH +0905+16720 Pacific/Kwajalein Kwajalein -MK +4159+02126 Europe/Skopje -ML +1239-00800 Africa/Bamako -MM +1647+09610 Asia/Rangoon -MN +4755+10653 Asia/Ulaanbaatar most locations -MN +4801+09139 Asia/Hovd Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan -MN +4804+11430 Asia/Choibalsan Dornod, Sukhbaatar -MO +2214+11335 Asia/Macau -MP +1512+14545 Pacific/Saipan -MQ +1436-06105 America/Martinique -MR +1806-01557 Africa/Nouakchott -MS +1643-06213 America/Montserrat -MT +3554+01431 Europe/Malta -MU -2010+05730 Indian/Mauritius -MV +0410+07330 Indian/Maldives -MW -1547+03500 Africa/Blantyre -MX +1924-09909 America/Mexico_City Central Time - most locations -MX +2105-08646 America/Cancun Central Time - Quintana Roo -MX +2058-08937 America/Merida Central Time - Campeche, Yucatan -MX +2540-10019 America/Monterrey Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from US border -MX +2550-09730 America/Matamoros US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border -MX +2313-10625 America/Mazatlan Mountain Time - S Baja, Nayarit, Sinaloa -MX +2838-10605 America/Chihuahua Mexican Mountain Time - Chihuahua away from US border -MX +2934-10425 America/Ojinaga US Mountain Time - Chihuahua near US border -MX +2904-11058 America/Hermosillo Mountain Standard Time - Sonora -MX +3232-11701 America/Tijuana US Pacific Time - Baja California near US border -MX +3018-11452 America/Santa_Isabel Mexican Pacific Time - Baja California away from US border -MX +2048-10515 America/Bahia_Banderas Mexican Central Time - Bahia de Banderas -MY +0310+10142 Asia/Kuala_Lumpur peninsular Malaysia -MY +0133+11020 Asia/Kuching Sabah & Sarawak -MZ -2558+03235 Africa/Maputo -NA -2234+01706 Africa/Windhoek -NC -2216+16627 Pacific/Noumea -NE +1331+00207 Africa/Niamey -NF -2903+16758 Pacific/Norfolk -NG +0627+00324 Africa/Lagos -NI +1209-08617 America/Managua -NL +5222+00454 Europe/Amsterdam -NO +5955+01045 Europe/Oslo -NP +2743+08519 Asia/Kathmandu -NR -0031+16655 Pacific/Nauru -NU -1901-16955 Pacific/Niue -NZ -3652+17446 Pacific/Auckland most locations -NZ -4357-17633 Pacific/Chatham Chatham Islands -OM +2336+05835 Asia/Muscat -PA +0858-07932 America/Panama -PE -1203-07703 America/Lima -PF -1732-14934 Pacific/Tahiti Society Islands -PF -0900-13930 Pacific/Marquesas Marquesas Islands -PF -2308-13457 Pacific/Gambier Gambier Islands -PG -0930+14710 Pacific/Port_Moresby -PH +1435+12100 Asia/Manila -PK +2452+06703 Asia/Karachi -PL +5215+02100 Europe/Warsaw -PM +4703-05620 America/Miquelon -PN -2504-13005 Pacific/Pitcairn -PR +182806-0660622 America/Puerto_Rico -PS +3130+03428 Asia/Gaza Gaza Strip -PS +313200+0350542 Asia/Hebron West Bank -PT +3843-00908 Europe/Lisbon mainland -PT +3238-01654 Atlantic/Madeira Madeira Islands -PT +3744-02540 Atlantic/Azores Azores -PW +0720+13429 Pacific/Palau -PY -2516-05740 America/Asuncion -QA +2517+05132 Asia/Qatar -RE -2052+05528 Indian/Reunion -RO +4426+02606 Europe/Bucharest -RS +4450+02030 Europe/Belgrade -RU +5443+02030 Europe/Kaliningrad Moscow-01 - Kaliningrad -RU +554521+0373704 Europe/Moscow Moscow+00 - west Russia -RU +4457+03406 Europe/Simferopol Moscow+00 - Crimea -RU +4844+04425 Europe/Volgograd Moscow+00 - Caspian Sea -RU +5312+05009 Europe/Samara Moscow+00 (Moscow+01 after 2014-10-26) - Samara, Udmurtia -RU +5651+06036 Asia/Yekaterinburg Moscow+02 - Urals -RU +5500+07324 Asia/Omsk Moscow+03 - west Siberia -RU +5502+08255 Asia/Novosibirsk Moscow+03 - Novosibirsk -RU +5345+08707 Asia/Novokuznetsk Moscow+03 (Moscow+04 after 2014-10-26) - Kemerovo -RU +5601+09250 Asia/Krasnoyarsk Moscow+04 - Yenisei River -RU +5216+10420 Asia/Irkutsk Moscow+05 - Lake Baikal -RU +5203+11328 Asia/Chita Moscow+06 (Moscow+05 after 2014-10-26) - Zabaykalsky -RU +6200+12940 Asia/Yakutsk Moscow+06 - Lena River -RU +623923+1353314 Asia/Khandyga Moscow+06 - Tomponsky, Ust-Maysky -RU +4310+13156 Asia/Vladivostok Moscow+07 - Amur River -RU +4658+14242 Asia/Sakhalin Moscow+07 - Sakhalin Island -RU +643337+1431336 Asia/Ust-Nera Moscow+07 - Oymyakonsky -RU +5934+15048 Asia/Magadan Moscow+08 (Moscow+07 after 2014-10-26) - Magadan -RU +6728+15343 Asia/Srednekolymsk Moscow+08 - E Sakha, N Kuril Is -RU +5301+15839 Asia/Kamchatka Moscow+08 (Moscow+09 after 2014-10-26) - Kamchatka -RU +6445+17729 Asia/Anadyr Moscow+08 (Moscow+09 after 2014-10-26) - Bering Sea -RW -0157+03004 Africa/Kigali -SA +2438+04643 Asia/Riyadh -SB -0932+16012 Pacific/Guadalcanal -SC -0440+05528 Indian/Mahe -SD +1536+03232 Africa/Khartoum -SE +5920+01803 Europe/Stockholm -SG +0117+10351 Asia/Singapore -SH -1555-00542 Atlantic/St_Helena -SI +4603+01431 Europe/Ljubljana -SJ +7800+01600 Arctic/Longyearbyen -SK +4809+01707 Europe/Bratislava -SL +0830-01315 Africa/Freetown -SM +4355+01228 Europe/San_Marino -SN +1440-01726 Africa/Dakar -SO +0204+04522 Africa/Mogadishu -SR +0550-05510 America/Paramaribo -SS +0451+03136 Africa/Juba -ST +0020+00644 Africa/Sao_Tome -SV +1342-08912 America/El_Salvador -SX +180305-0630250 America/Lower_Princes -SY +3330+03618 Asia/Damascus -SZ -2618+03106 Africa/Mbabane -TC +2128-07108 America/Grand_Turk -TD +1207+01503 Africa/Ndjamena -TF -492110+0701303 Indian/Kerguelen -TG +0608+00113 Africa/Lome -TH +1345+10031 Asia/Bangkok -TJ +3835+06848 Asia/Dushanbe -TK -0922-17114 Pacific/Fakaofo -TL -0833+12535 Asia/Dili -TM +3757+05823 Asia/Ashgabat -TN +3648+01011 Africa/Tunis -TO -2110-17510 Pacific/Tongatapu -TR +4101+02858 Europe/Istanbul -TT +1039-06131 America/Port_of_Spain -TV -0831+17913 Pacific/Funafuti -TW +2503+12130 Asia/Taipei -TZ -0648+03917 Africa/Dar_es_Salaam -UA +5026+03031 Europe/Kiev most locations -UA +4837+02218 Europe/Uzhgorod Ruthenia -UA +4750+03510 Europe/Zaporozhye Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk -UG +0019+03225 Africa/Kampala -UM +1645-16931 Pacific/Johnston Johnston Atoll -UM +2813-17722 Pacific/Midway Midway Islands -UM +1917+16637 Pacific/Wake Wake Island -US +404251-0740023 America/New_York Eastern Time -US +421953-0830245 America/Detroit Eastern Time - Michigan - most locations -US +381515-0854534 America/Kentucky/Louisville Eastern Time - Kentucky - Louisville area -US +364947-0845057 America/Kentucky/Monticello Eastern Time - Kentucky - Wayne County -US +394606-0860929 America/Indiana/Indianapolis Eastern Time - Indiana - most locations -US +384038-0873143 America/Indiana/Vincennes Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties -US +410305-0863611 America/Indiana/Winamac Eastern Time - Indiana - Pulaski County -US +382232-0862041 America/Indiana/Marengo Eastern Time - Indiana - Crawford County -US +382931-0871643 America/Indiana/Petersburg Eastern Time - Indiana - Pike County -US +384452-0850402 America/Indiana/Vevay Eastern Time - Indiana - Switzerland County -US +415100-0873900 America/Chicago Central Time -US +375711-0864541 America/Indiana/Tell_City Central Time - Indiana - Perry County -US +411745-0863730 America/Indiana/Knox Central Time - Indiana - Starke County -US +450628-0873651 America/Menominee Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties -US +470659-1011757 America/North_Dakota/Center Central Time - North Dakota - Oliver County -US +465042-1012439 America/North_Dakota/New_Salem Central Time - North Dakota - Morton County (except Mandan area) -US +471551-1014640 America/North_Dakota/Beulah Central Time - North Dakota - Mercer County -US +394421-1045903 America/Denver Mountain Time -US +433649-1161209 America/Boise Mountain Time - south Idaho & east Oregon -US +332654-1120424 America/Phoenix Mountain Standard Time - Arizona (except Navajo) -US +340308-1181434 America/Los_Angeles Pacific Time -US +550737-1313435 America/Metlakatla Pacific Standard Time - Annette Island, Alaska -US +611305-1495401 America/Anchorage Alaska Time -US +581807-1342511 America/Juneau Alaska Time - Alaska panhandle -US +571035-1351807 America/Sitka Alaska Time - southeast Alaska panhandle -US +593249-1394338 America/Yakutat Alaska Time - Alaska panhandle neck -US +643004-1652423 America/Nome Alaska Time - west Alaska -US +515248-1763929 America/Adak Aleutian Islands -US +211825-1575130 Pacific/Honolulu Hawaii -UY -3453-05611 America/Montevideo -UZ +3940+06648 Asia/Samarkand west Uzbekistan -UZ +4120+06918 Asia/Tashkent east Uzbekistan -VA +415408+0122711 Europe/Vatican -VC +1309-06114 America/St_Vincent -VE +1030-06656 America/Caracas -VG +1827-06437 America/Tortola -VI +1821-06456 America/St_Thomas -VN +1045+10640 Asia/Ho_Chi_Minh -VU -1740+16825 Pacific/Efate -WF -1318-17610 Pacific/Wallis -WS -1350-17144 Pacific/Apia -YE +1245+04512 Asia/Aden -YT -1247+04514 Indian/Mayotte -ZA -2615+02800 Africa/Johannesburg -ZM -1525+02817 Africa/Lusaka -ZW -1750+03103 Africa/Harare diff -Nru ruby-tzinfo-1.2.6/.travis.yml ruby-tzinfo-2.0.4/.travis.yml --- ruby-tzinfo-1.2.6/.travis.yml 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/.travis.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -language: ruby -dist: trusty -sudo: false -before_install: - - if [[ $TRAVIS_RUBY_VERSION =~ ^((1|2\.[012]|jruby-1)\.|ree$) ]]; then gem install rubygems-update --version '~> 2.7' --no-document && update_rubygems; else gem update --system; fi - - gem --version - - if [[ $TRAVIS_RUBY_VERSION =~ ^((1|2\.[012]|jruby-1)\.|ree$) ]]; then gem install bundler --version '~> 1.17'; else gem install bundler; fi - - bundle --version -before_script: - - bundle update -cache: bundler -env: - global: - - TESTOPTS=--verbose -rvm: - - 1.8.7-head - - 1.9.2-p330 - - 1.9.3-p551 - - 2.0.0-p648 - - 2.1.10 - - 2.2.10 - - 2.3.8 - - 2.4.9 - - 2.5.7 - - 2.6.5 - - 2.7.0-rc2 - - ruby-head - - jruby-18mode - - jruby-1.7.27 - - jruby-9.1.17.0 - - jruby-9.2.9.0 - - jruby-head - - rbx-2.71828182 - - rbx-3.107 - - ree -matrix: - allow_failures: - - rvm: ruby-head - - rvm: jruby-head - - rvm: rbx-2.71828182 diff -Nru ruby-tzinfo-1.2.6/tzinfo.gemspec ruby-tzinfo-2.0.4/tzinfo.gemspec --- ruby-tzinfo-1.2.6/tzinfo.gemspec 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/tzinfo.gemspec 2020-12-30 06:49:15.000000000 +0000 @@ -1,21 +1,39 @@ +######################################################### +# This file has been automatically generated by gem2tgz # +######################################################### +# -*- encoding: utf-8 -*- +# stub: tzinfo 2.0.4 ruby lib + Gem::Specification.new do |s| - s.name = 'tzinfo' - s.version = '1.2.6' - s.summary = 'Daylight savings aware timezone library' - s.description = 'TZInfo provides daylight savings aware transformations between times in different time zones.' - s.author = 'Philip Ross' - s.email = 'phil.ross@gmail.com' - s.homepage = 'http://tzinfo.github.io' - s.license = 'MIT' - s.files = %w(CHANGES.md LICENSE Rakefile README.md tzinfo.gemspec .yardopts) + - Dir['lib/**/*.rb'].delete_if {|f| f.include?('.svn')} + - Dir['test/**/*.rb'].delete_if {|f| f.include?('.svn')} + - Dir['test/zoneinfo/**/*'].delete_if {|f| f.include?('.svn') || File.symlink?(f)} - s.platform = Gem::Platform::RUBY - s.require_path = 'lib' - s.rdoc_options << '--title' << 'TZInfo' << - '--main' << 'README.md' - s.extra_rdoc_files = ['README.md', 'CHANGES.md', 'LICENSE'] - s.required_ruby_version = '>= 1.8.7' - s.add_dependency 'thread_safe', '~> 0.1' + s.name = "tzinfo".freeze + s.version = "2.0.4" + + s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= + s.metadata = { "bug_tracker_uri" => "https://github.com/tzinfo/tzinfo/issues", "changelog_uri" => "https://github.com/tzinfo/tzinfo/blob/master/CHANGES.md", "documentation_uri" => "https://rubydoc.info/gems/tzinfo/2.0.4", "homepage_uri" => "https://tzinfo.github.io", "source_code_uri" => "https://github.com/tzinfo/tzinfo/tree/v2.0.4" } if s.respond_to? :metadata= + s.require_paths = ["lib".freeze] + s.authors = ["Philip Ross".freeze] + s.cert_chain = ["-----BEGIN CERTIFICATE-----\nMIIDPDCCAiSgAwIBAgIBATANBgkqhkiG9w0BAQsFADAkMSIwIAYDVQQDDBlwaGls\nLnJvc3MvREM9Z21haWwvREM9Y29tMB4XDTE5MTIyNDE0NTU0N1oXDTM5MTIyNDE0\nNTU0N1owJDEiMCAGA1UEAwwZcGhpbC5yb3NzL0RDPWdtYWlsL0RDPWNvbTCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJGcwfqn4ZsmPl0b1Lt9dCzExrE5\nEeP/CRQjBdGHkF+mSpi69XysxdwLdfg5SPr9LfxthUug4nNFd5fDCiXM8hYe9jQD\nTmkIQKNBh4fFpGngn9gyy+SumCXi6b5L6d/aMc59NAOM6LJ88TOdH1648dh5rq3C\nULq82n3gg4+u0HHGjRPuR/pnCFQCZbANYdX+UBWd0qkOJn/EreNKROmEeHr/xKuh\n2/GlKFKt9KLcW3hwBB4fHHVYUzRau7D1m9KbEERdg//qNDC4B7fD2BFJuPbM5S7J\n41VwDAh1O8B/Qpg0f+S83K4Kodw4MiPGsug55UkNtd3mGR/zZJ9WM03DSwkCAwEA\nAaN5MHcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFA+Z8zvfzBuA\nesoHIfz7+jxfUOcfMB4GA1UdEQQXMBWBE3BoaWwucm9zc0BnbWFpbC5jb20wHgYD\nVR0SBBcwFYETcGhpbC5yb3NzQGdtYWlsLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEA\nJ80xgZ3gGdQVA8N+8NJANU5HLuZIU9jOaAlziU9ImoTgPiOHKGZC4as1TwT4kBt1\nQcnu7YSANYRrxP5tpOHsWPF/MQYgerAFCZS5+PzOTudwZ+7OsMW4/EMHy6aCVHEd\nc7HzQRC4mSrDRpWxzyBnZ5nX5OAmIkKA8NgeKybT/4Ku6iFPPUQwlyxQaO+Wlxdo\nFqHwpjRyoiVSpe4RUTNK3d3qesWPYi7Lxn6k6ZZeEdvG6ya33AXktE3jmmF+jPR1\nJ3Zn/kSTjTekiaspyGbczC3PUaeJNxr+yCvR4sk71Xmk/GaKKGOHedJ1uj/LAXrA\nMR0mpl7b8zCg0PFC1J73uw==\n-----END CERTIFICATE-----\n".freeze] + s.date = "2020-12-16" + s.description = "TZInfo provides access to time zone data and allows times to be converted using time zone rules.".freeze + s.email = "phil.ross@gmail.com".freeze + s.extra_rdoc_files = ["CHANGES.md".freeze, "LICENSE".freeze, "README.md".freeze] + s.files = [".yardopts".freeze, "CHANGES.md".freeze, "LICENSE".freeze, "README.md".freeze, "lib/tzinfo.rb".freeze, "lib/tzinfo/annual_rules.rb".freeze, "lib/tzinfo/country.rb".freeze, "lib/tzinfo/country_timezone.rb".freeze, "lib/tzinfo/data_source.rb".freeze, "lib/tzinfo/data_sources.rb".freeze, "lib/tzinfo/data_sources/constant_offset_data_timezone_info.rb".freeze, "lib/tzinfo/data_sources/country_info.rb".freeze, "lib/tzinfo/data_sources/data_timezone_info.rb".freeze, "lib/tzinfo/data_sources/linked_timezone_info.rb".freeze, "lib/tzinfo/data_sources/posix_time_zone_parser.rb".freeze, "lib/tzinfo/data_sources/ruby_data_source.rb".freeze, "lib/tzinfo/data_sources/timezone_info.rb".freeze, "lib/tzinfo/data_sources/transitions_data_timezone_info.rb".freeze, "lib/tzinfo/data_sources/zoneinfo_data_source.rb".freeze, "lib/tzinfo/data_sources/zoneinfo_reader.rb".freeze, "lib/tzinfo/data_timezone.rb".freeze, "lib/tzinfo/datetime_with_offset.rb".freeze, "lib/tzinfo/format1.rb".freeze, "lib/tzinfo/format1/country_definer.rb".freeze, "lib/tzinfo/format1/country_index_definition.rb".freeze, "lib/tzinfo/format1/timezone_definer.rb".freeze, "lib/tzinfo/format1/timezone_definition.rb".freeze, "lib/tzinfo/format1/timezone_index_definition.rb".freeze, "lib/tzinfo/format2.rb".freeze, "lib/tzinfo/format2/country_definer.rb".freeze, "lib/tzinfo/format2/country_index_definer.rb".freeze, "lib/tzinfo/format2/country_index_definition.rb".freeze, "lib/tzinfo/format2/timezone_definer.rb".freeze, "lib/tzinfo/format2/timezone_definition.rb".freeze, "lib/tzinfo/format2/timezone_index_definer.rb".freeze, "lib/tzinfo/format2/timezone_index_definition.rb".freeze, "lib/tzinfo/info_timezone.rb".freeze, "lib/tzinfo/linked_timezone.rb".freeze, "lib/tzinfo/offset_timezone_period.rb".freeze, "lib/tzinfo/string_deduper.rb".freeze, "lib/tzinfo/time_with_offset.rb".freeze, "lib/tzinfo/timestamp.rb".freeze, "lib/tzinfo/timestamp_with_offset.rb".freeze, "lib/tzinfo/timezone.rb".freeze, "lib/tzinfo/timezone_offset.rb".freeze, "lib/tzinfo/timezone_period.rb".freeze, "lib/tzinfo/timezone_proxy.rb".freeze, "lib/tzinfo/timezone_transition.rb".freeze, "lib/tzinfo/transition_rule.rb".freeze, "lib/tzinfo/transitions_timezone_period.rb".freeze, "lib/tzinfo/untaint_ext.rb".freeze, "lib/tzinfo/version.rb".freeze, "lib/tzinfo/with_offset.rb".freeze] + s.homepage = "https://tzinfo.github.io".freeze + s.licenses = ["MIT".freeze] + s.rdoc_options = ["--title".freeze, "TZInfo".freeze, "--main".freeze, "README.md".freeze] + s.required_ruby_version = Gem::Requirement.new(">= 1.9.3".freeze) + s.rubygems_version = "2.5.2.1".freeze + s.summary = "Time Zone Library".freeze + + if s.respond_to? :specification_version then + s.specification_version = 4 + + if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q.freeze, ["~> 1.0"]) + else + s.add_dependency(%q.freeze, ["~> 1.0"]) + end + else + s.add_dependency(%q.freeze, ["~> 1.0"]) + end end diff -Nru ruby-tzinfo-1.2.6/.yardopts ruby-tzinfo-2.0.4/.yardopts --- ruby-tzinfo-1.2.6/.yardopts 2020-02-07 12:49:25.000000000 +0000 +++ ruby-tzinfo-2.0.4/.yardopts 2020-12-30 06:49:15.000000000 +0000 @@ -1,4 +1,7 @@ +--markup markdown --no-private +--protected +--readme README.md lib/**/*.rb - CHANGES.md