Hello community, here is the log from the commit of package rubygem-tzinfo for openSUSE:Factory checked in at 2017-04-11 09:33:14 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/rubygem-tzinfo (Old) and /work/SRC/openSUSE:Factory/.rubygem-tzinfo.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "rubygem-tzinfo" Tue Apr 11 09:33:14 2017 rev:18 rq:482693 version:1.2.3 Changes: -------- --- /work/SRC/openSUSE:Factory/rubygem-tzinfo/rubygem-tzinfo.changes 2014-10-18 09:10:14.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.rubygem-tzinfo.new/rubygem-tzinfo.changes 2017-04-11 09:33:19.889363911 +0200 @@ -1,0 +2,26 @@ +Sun Mar 26 04:36:44 UTC 2017 - co...@suse.com + +- updated to version 1.2.3 + see installed CHANGES.md + + Version 1.2.3 - 25-Mar-2017 + --------------------------- + + * 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 + 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. + * 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. + +------------------------------------------------------------------- Old: ---- tzinfo-1.2.2.gem New: ---- tzinfo-1.2.3.gem ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ rubygem-tzinfo.spec ++++++ --- /var/tmp/diff_new_pack.Ul8goM/_old 2017-04-11 09:33:20.833230578 +0200 +++ /var/tmp/diff_new_pack.Ul8goM/_new 2017-04-11 09:33:20.833230578 +0200 @@ -1,7 +1,7 @@ # # spec file for package rubygem-tzinfo # -# Copyright (c) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -16,8 +16,15 @@ # +# +# This file was generated with a gem2rpm.yml and not just plain gem2rpm. +# All sections marked as MANUAL, license headers, summaries and descriptions +# can be maintained in that file. Please consult this file before editing any +# of those fields +# + Name: rubygem-tzinfo -Version: 1.2.2 +Version: 1.2.3 Release: 0 %define mod_name tzinfo %define mod_full_name %{mod_name}-%{version} ++++++ tzinfo-1.2.2.gem -> tzinfo-1.2.3.gem ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/CHANGES.md new/CHANGES.md --- old/CHANGES.md 2014-08-08 19:46:45.000000000 +0200 +++ new/CHANGES.md 2017-03-25 19:37:26.000000000 +0100 @@ -1,3 +1,24 @@ +Version 1.2.3 - 25-Mar-2017 +--------------------------- + +* 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 + 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. +* 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. + + Version 1.2.2 - 8-Aug-2014 -------------------------- @@ -92,6 +113,106 @@ use other TimezonePeriod instance methods instead (issue #7655). +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 +-------------------------------------------- + +* 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 +------------------------------------------- + +* 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 +-------------------------------------------- + +* 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 +-------------------------------------------- + +* 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 +-------------------------------------------- + +* 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 +-------------------------------------------- + +* 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 +------------------------------------------- + +* From version 2015e, the IANA time zone database uses non-ASCII characters in + country names. Backport the encoding handling from TZInfo::Data to allow + TZInfo 0.3.x to support Ruby 1.9 (which would otherwise fail with an invalid + byte sequence error when loading the countries index). Resolves #41. + + +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 +-------------------------------------------- + +* 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 +-------------------------------------------- + +* 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 +-------------------------------------------- + +* 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 +------------------------------------------- + +* 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 +-------------------------------------------- + +* 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 ------------------------------------------- @@ -177,7 +298,7 @@ Version 0.3.28 (tzdata v2011g) - 13-Jun-2011 ---------------------------------------------= +--------------------------------------------- * 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. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/LICENSE new/LICENSE --- old/LICENSE 2014-08-08 19:46:45.000000000 +0200 +++ new/LICENSE 2017-03-25 19:37:26.000000000 +0100 @@ -1,4 +1,4 @@ -Copyright (c) 2005-2014 Philip Ross +Copyright (c) 2005-2017 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 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Rakefile new/Rakefile --- old/Rakefile 2014-08-08 19:46:45.000000000 +0200 +++ new/Rakefile 2017-03-25 19:37:26.000000000 +0100 @@ -21,7 +21,10 @@ private :orig_sh def sh(*cmd, &block) - if cmd.first =~ /\A__tar_with_owner__ -?([zjcvf]+)(.*)\z/ + 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}" Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ Binary files old/checksums.yaml.gz.sig and new/checksums.yaml.gz.sig differ Binary files old/data.tar.gz.sig and new/data.tar.gz.sig differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/tzinfo/timezone.rb new/lib/tzinfo/timezone.rb --- old/lib/tzinfo/timezone.rb 2014-08-08 19:46:45.000000000 +0200 +++ new/lib/tzinfo/timezone.rb 2017-03-25 19:37:26.000000000 +0100 @@ -236,13 +236,9 @@ elsif parts.length == 1 parts[0] else - if skip_first_part - result = '' - else - result = parts[0] + ' - ' - end - - parts[1, parts.length - 1].reverse_each {|part| + prefix = skip_first_part ? nil : "#{parts[0]} - " + + parts = parts.drop(1).map do |part| part.gsub!(/_/, ' ') if part.index(/[a-z]/) @@ -254,13 +250,11 @@ # Missing an apostrophe if two consecutive upper case characters. part.gsub!(/([A-Z])([A-Z])/, '\1\'\2') end - - result << part - result << ', ' - } - - result.slice!(result.length - 2, 2) - result + + part + end + + "#{prefix}#{parts.reverse.join(', ')}" end end @@ -559,22 +553,60 @@ 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 is replaced with the - # timezone abbreviation for the specified time (for example, EST or EDT). + # 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) period = period_for_utc(utc) local = period.to_local(utc) local = Time.at(local).utc unless local.kind_of?(Time) || local.kind_of?(DateTime) abbreviation = period.abbreviation.to_s.gsub(/%/, '%%') - format = format.gsub(/(.?)%Z/) do - if $1 == '%' - # return %%Z so the real strftime treats it as a literal %Z too - '%%Z' - else + format = format.gsub(/%(%*)(Z|:*z)/) do + if $1.length.odd? + # Escaped literal percent or series of percents. Pass on to strftime. + "#$1%#$2" + 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 end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/tzinfo/timezone_offset.rb new/lib/tzinfo/timezone_offset.rb --- old/lib/tzinfo/timezone_offset.rb 2014-08-08 19:46:45.000000000 +0200 +++ new/lib/tzinfo/timezone_offset.rb 2017-03-25 19:37:26.000000000 +0100 @@ -34,6 +34,8 @@ # 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 @@ -42,6 +44,8 @@ # 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 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/tzinfo/timezone_period.rb new/lib/tzinfo/timezone_period.rb --- old/lib/tzinfo/timezone_period.rb 2014-08-08 19:46:45.000000000 +0200 +++ new/lib/tzinfo/timezone_period.rb 2017-03-25 19:37:26.000000000 +0100 @@ -126,45 +126,62 @@ 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. + # 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 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/tzinfo/timezone_proxy.rb new/lib/tzinfo/timezone_proxy.rb --- old/lib/tzinfo/timezone_proxy.rb 2014-08-08 19:46:45.000000000 +0200 +++ new/lib/tzinfo/timezone_proxy.rb 2017-03-25 19:37:26.000000000 +0100 @@ -38,6 +38,35 @@ 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. + def transitions_up_to(to, from = nil) + real_timezone.transitions_up_to(to, from) + end + # Returns the canonical zone for this Timezone. def canonical_zone real_timezone.canonical_zone diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/tzinfo/zoneinfo_data_source.rb new/lib/tzinfo/zoneinfo_data_source.rb --- old/lib/tzinfo/zoneinfo_data_source.rb 2014-08-08 19:46:45.000000000 +0200 +++ new/lib/tzinfo/zoneinfo_data_source.rb 2017-03-25 19:37:26.000000000 +0100 @@ -349,9 +349,9 @@ # localtime 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. - # Factory is the compiled in default timezone. + # timeconfig is a symlink included on Slackware. - enum_timezones(nil, ['+VERSION', 'localtime', 'posix', 'posixrules', 'right', 'src', 'Factory']) do |identifier| + enum_timezones(nil, ['+VERSION', 'localtime', 'posix', 'posixrules', 'right', 'src', 'timeconfig']) do |identifier| index << identifier end @@ -432,7 +432,7 @@ file_is_5_column = true if column5 - zone_tab << [codes.split(','), zone_identifier, latitude, longitude, column4, column5] + zone_tab << [codes.split(','.freeze), zone_identifier, latitude, longitude, column4, column5] end end end @@ -480,7 +480,7 @@ 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 == '-' + result = -result if sign == '-'.freeze result end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/tzinfo/zoneinfo_timezone_info.rb new/lib/tzinfo/zoneinfo_timezone_info.rb --- old/lib/tzinfo/zoneinfo_timezone_info.rb 2014-08-08 19:46:45.000000000 +0200 +++ new/lib/tzinfo/zoneinfo_timezone_info.rb 2017-03-25 19:37:26.000000000 +0100 @@ -56,39 +56,109 @@ result end - # Zoneinfo doesn't include the offset from standard time (std_offset). - # Derive the missing offsets by looking at changes in the total UTC - # offset. + # 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. # - # This will be run through forwards and then backwards by the parse - # method. - def derive_offsets(transitions, offsets) - previous_offset = nil + # 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 - transitions.each do |t| - offset = offsets[t[:offset]] + 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) + difference_to_next = utc_total_offset - (utc_offset_from_next || utc_total_offset) + + utc_offset = if 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 # difference_to_previous <= 0 && difference_to_next <= 0 + # DST, but the either the offset has stayed the same or decreased + # relative to both the previous and next used base utc offset, or + # there are no non-DST offsets. Assume a 1 hour offset from base. + utc_total_offset - 3600 + end - if !offset[:std_offset] && offset[:is_dst] && previous_offset - difference = offset[:utc_total_offset] - previous_offset[:utc_total_offset] - - if previous_offset[:is_dst] - if previous_offset[:std_offset] - std_offset = previous_offset[:std_offset] + difference - else - std_offset = nil + 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 - else - std_offset = difference - end - - if std_offset && std_offset > 0 - offset[:std_offset] = std_offset - offset[:utc_offset] = offset[:utc_total_offset] - std_offset + + transition[:offset] = offset_index end + else + utc_offset_from_previous = utc_total_offset end - - previous_offset = offset 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. @@ -127,27 +197,27 @@ transitions = [] if using_64bit - (0...timecnt).each do |i| - high, low = check_read(file, 8).unpack('NN') + 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 - (0...timecnt).each do |i| - transition_time = make_signed_int32(check_read(file, 4).unpack('N')[0]) + timecnt.times do |i| + transition_time = make_signed_int32(check_read(file, 4).unpack('N'.freeze)[0]) transitions << {:at => transition_time} end end - (0...timecnt).each do |i| - localtime_type = check_read(file, 1).unpack('C')[0] + timecnt.times do |i| + localtime_type = check_read(file, 1).unpack('C'.freeze)[0] transitions[i][:offset] = localtime_type end offsets = [] - (0...typecnt).each do |i| - gmtoff, isdst, abbrind = check_read(file, 6).unpack('NCC') + 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} @@ -179,33 +249,12 @@ end # Derive the offsets from standard time (std_offset). - derive_offsets(transitions, offsets) - derive_offsets(transitions.reverse, offsets) - - # Assign anything left a standard offset of one hour - offsets.each do |o| - if !o[:std_offset] && o[:is_dst] - o[:std_offset] = 3600 - o[:utc_offset] = o[:utc_total_offset] - 3600 - end - end - - # Find the first non-dst offset. This is used as the offset for the time - # before the first transition. - first = nil - offsets.each_with_index do |o, i| - if !o[:is_dst] - first = i - break - end - end + first_offset_index = derive_offsets(transitions, offsets) - if first - offset first, offsets[first][:utc_offset], offsets[first][:std_offset], offsets[first][:abbr].untaint.to_sym - end + define_offset(first_offset_index, offsets[first_offset_index]) offsets.each_with_index do |o, i| - offset i, o[:utc_offset], o[:std_offset], o[:abbr].untaint.to_sym unless i == first + define_offset(i, o) unless i == first_offset_index end if !using_64bit && !RubyCoreSupport.time_supports_negative diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metadata new/metadata --- old/metadata 2014-08-08 19:46:45.000000000 +0200 +++ new/metadata 2017-03-25 19:37:26.000000000 +0100 @@ -1,7 +1,7 @@ --- !ruby/object:Gem::Specification name: tzinfo version: !ruby/object:Gem::Version - version: 1.2.2 + version: 1.2.3 platform: ruby authors: - Philip Ross @@ -12,7 +12,7 @@ -----BEGIN CERTIFICATE----- MIIDdDCCAlygAwIBAgIBATANBgkqhkiG9w0BAQUFADBAMRIwEAYDVQQDDAlwaGls LnJvc3MxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2Nv - bTAeFw0xMzA5MjUyMTA0NTNaFw0xNDA5MjUyMTA0NTNaMEAxEjAQBgNVBAMMCXBo + bTAeFw0xNjEwMjAxOTMyMDZaFw0xNzEwMjAxOTMyMDZaMEAxEjAQBgNVBAMMCXBo aWwucm9zczEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYD Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkZzB+qfhmyY+XRvU u310LMTGsTkR4/8JFCMF0YeQX6ZKmLr1fKzF3At1+DlI+v0t/G2FS6Dic0V3l8MK @@ -23,14 +23,14 @@ TcNLCQIDAQABo3kwdzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQU D5nzO9/MG4B6ygch/Pv6PF9Q5x8wHgYDVR0RBBcwFYETcGhpbC5yb3NzQGdtYWls LmNvbTAeBgNVHRIEFzAVgRNwaGlsLnJvc3NAZ21haWwuY29tMA0GCSqGSIb3DQEB - BQUAA4IBAQAKZJXA++aLjISMKZea4PmXuH93YbMxoyBby3SRfwvLh7cBMEiCy5fu - xYR46qa9ixC6JyVuxAWA2AGHLOqabKkq6AxntqIk1OAnZGBNRuCnLYzSx+6YDjaY - ZcAmqPdS0Adj+1lNc+MgHiMrMLimNO4Cur4w4zYNZFvQan78WtLnwiaYPM2Tke1B - UVjGvQVkM6gVIVH3937au2iHpJAehbhkEbgM02knNemiNwi58j7pMS9MhelxJxdz - fs7XSYlwQp0zY7PFSMwJeBpQFDBnShcweRQ+0QdUUS4FHrwfXex0QsXp9UROUX+4 - 6BVw9ZDNFnDH4PQjZGbdwanB7kzm+TEi + BQUAA4IBAQBM+pMz41DnLx/Edg6cZe7JYFeXXQmVeltwDEefCa4cXxfLTsR6m7vW + aBxCCJ62qrfe2dF1d8lp5X94nAmG8FyzSH4Gt8Ul69zOLw31E5XkT2bDcBTzWwcf + OmYp+4rBeXWVwf76baYDNrJyFBp42cuj3vQBOQ2mJcwjeBldyUFVxElq93ISpN+2 + xSO5T8UfFZWHwv9H9cGhQnInu/hpl/vFcz5LM/l1CODRITfEbNUlr6Lb4JLxm58y + sB3eS05Xw5lTvyhTICdMJIRk5jPPk3Sv/H1G7urfugkdEqT66FO+pgBnC9o7HvXN + E2bpXUbNbgEUfOfgi7vQ9NLDfb+3Brxl -----END CERTIFICATE----- -date: 2014-08-08 00:00:00.000000000 Z +date: 2017-03-25 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: thread_safe @@ -185,7 +185,7 @@ version: '0' requirements: [] rubyforge_project: -rubygems_version: 2.2.2 +rubygems_version: 2.6.11 signing_key: specification_version: 4 summary: Daylight savings aware timezone library Binary files old/metadata.gz.sig and new/metadata.gz.sig differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/test/tc_country.rb new/test/tc_country.rb --- old/test/tc_country.rb 2014-08-08 19:46:45.000000000 +0200 +++ new/test/tc_country.rb 2017-03-25 19:37:26.000000000 +0100 @@ -47,7 +47,7 @@ Country.get('GB') safe_test do - code = 'GB'.taint + code = 'GB'.dup.taint assert(code.tainted?) country = Country.get(code) assert_equal('GB', country.code) @@ -59,14 +59,14 @@ Country.get('GB') safe_test do - country = Country.get('GB'.taint.freeze) + country = Country.get('GB'.dup.taint.freeze) assert_equal('GB', country.code) end end def test_get_tainted_not_previously_loaded safe_test do - code = 'GB'.taint + code = 'GB'.dup.taint assert(code.tainted?) country = Country.get(code) assert_equal('GB', country.code) @@ -76,7 +76,7 @@ def test_get_tainted_and_frozen_not_previously_loaded safe_test do - country = Country.get('GB'.taint.freeze) + country = Country.get('GB'.dup.taint.freeze) assert_equal('GB', country.code) end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/test/tc_ruby_data_source.rb new/test/tc_ruby_data_source.rb --- old/test/tc_ruby_data_source.rb 2014-08-08 19:46:45.000000000 +0200 +++ new/test/tc_ruby_data_source.rb 2017-03-25 19:37:26.000000000 +0100 @@ -56,7 +56,7 @@ def test_load_timezone_info_tainted safe_test do - identifier = 'Europe/Amsterdam'.taint + identifier = 'Europe/Amsterdam'.dup.taint assert(identifier.tainted?) info = @data_source.load_timezone_info(identifier) assert_equal('Europe/Amsterdam', info.identifier) @@ -66,7 +66,7 @@ def test_load_timezone_info_tainted_and_frozen safe_test do - info = @data_source.load_timezone_info('Europe/Amsterdam'.taint.freeze) + info = @data_source.load_timezone_info('Europe/Amsterdam'.dup.taint.freeze) assert_equal('Europe/Amsterdam', info.identifier) end end @@ -120,7 +120,7 @@ def test_load_country_info_tainted safe_test do - code = 'NL'.taint + code = 'NL'.dup.taint assert(code.tainted?) info = @data_source.load_country_info(code) assert_equal('NL', info.code) @@ -130,7 +130,7 @@ def test_load_country_info_tainted_and_frozen safe_test do - info = @data_source.load_country_info('NL'.taint.freeze) + info = @data_source.load_country_info('NL'.dup.taint.freeze) assert_equal('NL', info.code) end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/test/tc_timezone.rb new/test/tc_timezone.rb --- old/test/tc_timezone.rb 2014-08-08 19:46:45.000000000 +0200 +++ new/test/tc_timezone.rb 2017-03-25 19:37:26.000000000 +0100 @@ -243,7 +243,7 @@ Timezone.get('Europe/Andorra') safe_test do - identifier = 'Europe/Andorra'.taint + identifier = 'Europe/Andorra'.dup.taint assert(identifier.tainted?) tz = Timezone.get(identifier) assert_equal('Europe/Andorra', tz.identifier) @@ -255,14 +255,14 @@ Timezone.get('Europe/Andorra') safe_test do - tz = Timezone.get('Europe/Andorra'.taint.freeze) + tz = Timezone.get('Europe/Andorra'.dup.taint.freeze) assert_equal('Europe/Andorra', tz.identifier) end end def test_get_tainted_not_previously_loaded safe_test do - identifier = 'Europe/Andorra'.taint + identifier = 'Europe/Andorra'.dup.taint assert(identifier.tainted?) tz = Timezone.get(identifier) assert_equal('Europe/Andorra', tz.identifier) @@ -272,7 +272,7 @@ def test_get_tainted_and_frozen_not_previously_loaded safe_test do - tz = Timezone.get('Europe/Amsterdam'.taint.freeze) + tz = Timezone.get('Europe/Amsterdam'.dup.taint.freeze) assert_equal('Europe/Amsterdam', tz.identifier) end end @@ -436,6 +436,13 @@ 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) @@ -1246,26 +1253,35 @@ def test_strftime_datetime tz = Timezone.get('Europe/London') - assert_equal('23:12:02 BST', tz.strftime('%H:%M:%S %Z', DateTime.new(2006, 7, 15, 22, 12, 2))) - assert_equal('BST', tz.strftime('%Z', DateTime.new(2006, 7, 15, 22, 12, 2))) - assert_equal('%ZBST', tz.strftime('%%Z%Z', DateTime.new(2006, 7, 15, 22, 12, 2))) - assert_equal('BST BST', tz.strftime('%Z %Z', DateTime.new(2006, 7, 15, 22, 12, 2))) + 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)) end def test_strftime_time tz = Timezone.get('Europe/London') - assert_equal('23:12:02 BST', tz.strftime('%H:%M:%S %Z', Time.utc(2006, 7, 15, 22, 12, 2))) - assert_equal('BST', tz.strftime('%Z', Time.utc(2006, 7, 15, 22, 12, 2))) - assert_equal('%ZBST', tz.strftime('%%Z%Z', Time.utc(2006, 7, 15, 22, 12, 2))) - assert_equal('BST BST', tz.strftime('%Z %Z', Time.utc(2006, 7, 15, 22, 12, 2))) + 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)) end def test_strftime_int tz = Timezone.get('Europe/London') - assert_equal('23:12:02 BST', tz.strftime('%H:%M:%S %Z', Time.utc(2006, 7, 15, 22, 12, 2).to_i)) - assert_equal('BST', tz.strftime('%Z', Time.utc(2006, 7, 15, 22, 12, 2).to_i)) - assert_equal('%ZBST', tz.strftime('%%Z%Z', Time.utc(2006, 7, 15, 22, 12, 2).to_i)) - assert_equal('BST BST', tz.strftime('%Z %Z', Time.utc(2006, 7, 15, 22, 12, 2).to_i)) + 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)) end def test_get_missing_data_source diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/test/tc_timezone_proxy.rb new/test/tc_timezone_proxy.rb --- old/test/tc_timezone_proxy.rb 2014-08-08 19:46:45.000000000 +0200 +++ new/test/tc_timezone_proxy.rb 2017-03-25 19:37:26.000000000 +0100 @@ -5,45 +5,59 @@ 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_raises(InvalidTimezoneIdentifier) { proxy.now } + 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.utc_to_local(DateTime.new(2006,1,1,0,0,0)) } - assert_raises(InvalidTimezoneIdentifier) { proxy.local_to_utc(DateTime.new(2006,1,1,0,0,0)) } - assert_raises(InvalidTimezoneIdentifier) { proxy.period_for_utc(DateTime.new(2006,1,1,0,0,0)) } - assert_raises(InvalidTimezoneIdentifier) { proxy.period_for_local(DateTime.new(2006,1,1,0,0,0)) } - assert_raises(InvalidTimezoneIdentifier) { proxy.canonical_identifier } - assert_raises(InvalidTimezoneIdentifier) { proxy.canonical_zone } + 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') - assert_equal('Europe/London', proxy.identifier) - - assert_nothing_raised { proxy.now } + 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 } - - real = Timezone.get('Europe/London') - - assert_equal(real.utc_to_local(DateTime.new(2005,8,1,0,0,0)), proxy.utc_to_local(DateTime.new(2005,8,1,0,0,0))) - assert_equal(real.local_to_utc(DateTime.new(2005,8,1,0,0,0)), proxy.local_to_utc(DateTime.new(2005,8,1,0,0,0))) - assert_equal(real.period_for_utc(DateTime.new(2005,8,1,0,0,0)), proxy.period_for_utc(DateTime.new(2005,8,1,0,0,0))) - assert_equal(real.period_for_local(DateTime.new(2005,8,1,0,0,0)), proxy.period_for_local(DateTime.new(2005,8,1,0,0,0))) - assert_equal(real.identifier, proxy.identifier) - assert_equal(real.name, proxy.name) - assert_equal(real.to_s, proxy.to_s) 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.canonical_identifier, proxy.canonical_identifier) - assert_same(real.canonical_zone, proxy.canonical_zone) - - assert_equal('Europe/London', proxy.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) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/test/tc_zoneinfo_data_source.rb new/test/tc_zoneinfo_data_source.rb --- old/test/tc_zoneinfo_data_source.rb 2014-08-08 19:46:45.000000000 +0200 +++ new/test/tc_zoneinfo_data_source.rb 2017-03-25 19:37:26.000000000 +0100 @@ -395,6 +395,41 @@ 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) @@ -453,8 +488,9 @@ begin FileUtils.ln_s(outside_file, file) - rescue NotImplementedError - # Symlinks not supported on this platform - skip test + rescue NotImplementedError, Errno::EACCES + # Symlinks not supported on this platform, or permission denied + # (administrative rights are required on Windows). Skip test. return end @@ -478,8 +514,9 @@ begin FileUtils.ln_s(File.join(File.expand_path(dir), 'EST'), link) - rescue NotImplementedError - # Symlinks not supported on this platform - skip test + rescue NotImplementedError, Errno::EACCES + # Symlinks not supported on this platform, or permission denied + # (administrative rights are required on Windows). Skip test. return end @@ -505,8 +542,9 @@ begin FileUtils.ln_s('../outside', link) - rescue NotImplementedError - # Symlinks not supported on this platform - skip test + rescue NotImplementedError, Errno::EACCES + # Symlinks not supported on this platform, or permission denied + # (administrative rights are required on Windows). Skip test. return end @@ -541,8 +579,9 @@ subdir_link = File.join(subdir, 'Link') begin FileUtils.ln_s('../Subdir/EST', subdir_link) - rescue NotImplementedError - # Symlinks not supported on this platform - skip test + rescue NotImplementedError, Errno::EACCES + # Symlinks not supported on this platform, or permission denied + # (administrative rights are required on Windows). Skip test. return end @@ -613,7 +652,7 @@ def test_load_timezone_info_tainted safe_test do - identifier = 'Europe/Amsterdam'.taint + identifier = 'Europe/Amsterdam'.dup.taint assert(identifier.tainted?) info = @data_source.load_timezone_info(identifier) assert_equal('Europe/Amsterdam', info.identifier) @@ -623,7 +662,7 @@ def test_load_timezone_info_tainted_and_frozen safe_test do - info = @data_source.load_timezone_info('Europe/Amsterdam'.taint.freeze) + info = @data_source.load_timezone_info('Europe/Amsterdam'.dup.taint.freeze) assert_equal('Europe/Amsterdam', info.identifier) end end @@ -653,11 +692,11 @@ 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; localtime, posixrules and Factory zones + # Exclude right (with leapseconds) and posix (copy) directories; .tab files; localtime and posixrules files. entries = entries.select do |file| file !~ /\A(posix|right)\// && file !~ /\.tab\z/ && - !%w(localtime posixrules Factory).include?(file) + !%w(localtime posixrules).include?(file) end entries.sort @@ -714,6 +753,38 @@ 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. @@ -768,7 +839,7 @@ def test_load_country_info_tainted safe_test do - code = 'NL'.taint + code = 'NL'.dup.taint assert(code.tainted?) info = @data_source.load_country_info(code) assert_equal('NL', info.code) @@ -778,7 +849,7 @@ def test_load_country_info_tainted_and_frozen safe_test do - info = @data_source.load_country_info('NL'.taint.freeze) + info = @data_source.load_country_info('NL'.dup.taint.freeze) assert_equal('NL', info.code) end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/test/tc_zoneinfo_timezone_info.rb new/test/tc_zoneinfo_timezone_info.rb --- old/test/tc_zoneinfo_timezone_info.rb 2014-08-08 19:46:45.000000000 +0200 +++ new/test/tc_zoneinfo_timezone_info.rb 2017-03-25 19:37:26.000000000 +0100 @@ -286,6 +286,17 @@ 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}] @@ -707,27 +718,39 @@ end end - def test_load_starts_all_same_dst_offset + 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. - # - # If there are no changes in the UTC offset (ignoring the first offset, - # which is usually local mean time), then a value of 1 hour is used as the - # standard time offset. - + offsets = [ {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'}, - {:gmtoff => 7200, :isdst => true, :abbrev => 'XDDT'}] - - transitions = [ - {:at => Time.utc(2000, 1, 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, 3600, true, Time.utc(2000, 1, 1), nil, info) + {: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 @@ -756,6 +779,297 @@ 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_load_in_safe_mode offsets = [{:gmtoff => -12094, :isdst => false, :abbrev => 'LT'}] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/test/test_utils.rb new/test/test_utils.rb --- old/test/test_utils.rb 2014-08-08 19:46:45.000000000 +0200 +++ new/test/test_utils.rb 2017-03-25 19:37:26.000000000 +0100 @@ -28,7 +28,9 @@ begin FileUtils.ln_s(target, path) - rescue NotImplementedError + 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 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tzinfo.gemspec new/tzinfo.gemspec --- old/tzinfo.gemspec 2014-08-08 19:46:45.000000000 +0200 +++ new/tzinfo.gemspec 2017-03-25 19:37:26.000000000 +0100 @@ -1,6 +1,6 @@ Gem::Specification.new do |s| s.name = 'tzinfo' - s.version = '1.2.2' + s.version = '1.2.3' 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'