diff --git a/Gemfile b/Gemfile index be1aca20f9a..d8a150527c4 100644 --- a/Gemfile +++ b/Gemfile @@ -32,6 +32,8 @@ group :test do gem "test-theme", :path => File.expand_path("test/fixtures/test-theme", __dir__) gem "test-theme-skinny", :path => File.expand_path("test/fixtures/test-theme-skinny", __dir__) gem "test-theme-symlink", :path => File.expand_path("test/fixtures/test-theme-symlink", __dir__) + gem "tzinfo", ">= 1", "< 3" + gem "tzinfo-data" if RUBY_ENGINE == "jruby" gem "http_parser.rb", "~> 0.6.0" @@ -81,13 +83,6 @@ group :jekyll_optional_dependencies do gem "liquid-c", "~> 4.0" gem "yajl-ruby", "~> 1.4" end - - # Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem - # and associated library - platforms :jruby, :mswin, :mingw, :x64_mingw do - gem "tzinfo", "~> 1.2" - gem "tzinfo-data" - end end # diff --git a/docs/_docs/installation/windows.md b/docs/_docs/installation/windows.md index eacd92c6942..c7d77ed0fbb 100644 --- a/docs/_docs/installation/windows.md +++ b/docs/_docs/installation/windows.md @@ -121,22 +121,14 @@ While 'new' blogs created with Jekyll v3.4 and greater, will have the following sites *will* have to update their `Gemfile` (and installed gems) to enable development on Windows: ```ruby -# Windows does not include zoneinfo files, so bundle the tzinfo-data gem -gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] +# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem +# and associated library. +platforms :mingw, :x64_mingw, :mswin, :jruby do + gem "tzinfo", ">= 1", "< 3" + gem "tzinfo-data" +end ``` -
-
TZInfo 2.0 incompatibility
-

- Version 2.0 of the TZInfo library has introduced a change in how timezone offsets are calculated. - This will result in incorrect date and time for your posts when the site is built with Jekyll 3.x on Windows. -

-

- We therefore recommend that you lock the Timezone library to version 1.2 and above by listing - gem 'tzinfo', '~> 1.2' in your Gemfile. -

-
- ## Auto Regeneration Jekyll uses the `listen` gem to watch for changes when the `--watch` switch is specified during a build or serve. diff --git a/lib/jekyll/commands/new.rb b/lib/jekyll/commands/new.rb index 150b4aa7360..f85026baf56 100644 --- a/lib/jekyll/commands/new.rb +++ b/lib/jekyll/commands/new.rb @@ -92,7 +92,7 @@ def gemfile_contents # Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem # and associated library. platforms :mingw, :x64_mingw, :mswin, :jruby do - gem "tzinfo", "~> 1.2" + gem "tzinfo", ">= 1", "< 3" gem "tzinfo-data" end diff --git a/lib/jekyll/utils/win_tz.rb b/lib/jekyll/utils/win_tz.rb index 9c55c42eac4..9d25a1fd753 100644 --- a/lib/jekyll/utils/win_tz.rb +++ b/lib/jekyll/utils/win_tz.rb @@ -11,64 +11,35 @@ module WinTZ # timezone - the IANA Time Zone specified in "_config.yml" # # Returns a string that ultimately re-defines ENV["TZ"] in Windows - def calculate(timezone) + def calculate(timezone, now = Time.now) External.require_with_graceful_fail("tzinfo") unless defined?(TZInfo) tz = TZInfo::Timezone.get(timezone) - difference = Time.now.to_i - tz.now.to_i + + # + # Use period_for_utc and utc_total_offset instead of + # period_for and observed_utc_offset for compatibility with tzinfo v1. + offset = tz.period_for_utc(now.getutc).utc_total_offset + # # POSIX style definition reverses the offset sign. # e.g. Eastern Standard Time (EST) that is 5Hrs. to the 'west' of Prime Meridian # is denoted as: # EST+5 (or) EST+05:00 # Reference: http://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html - sign = difference.negative? ? "-" : "+" - offset = sign == "-" ? "+" : "-" unless difference.zero? - # - # convert the difference (in seconds) to hours, as a rational number, and perform - # a modulo operation on it. - modulo = modulo_of(rational_hour(difference)) + sign = offset.positive? ? "-" : "+" + + rational_hours = offset.abs.to_r / 3600 + hours = rational_hours.to_i + minutes = ((rational_hours - hours) * 60).to_i + # - # Format the hour as a two-digit number. - # Establish the minutes based on modulo expression. - hh = format("%02d", :hour => absolute_hour(difference).ceil) - mm = modulo.zero? ? "00" : "30" + # Format the hours and minutes as two-digit numbers. + time = format("%02d:%02d", hours: hours, minutes: minutes) - Jekyll.logger.debug "Timezone:", "#{timezone} #{offset}#{hh}:#{mm}" + Jekyll.logger.debug "Timezone:", "#{timezone} #{sign}#{time}" # # Note: The 3-letter-word below doesn't have a particular significance. - "WTZ#{sign}#{hh}:#{mm}" - end - - private - - # Private: Convert given seconds to an hour as a rational number. - # - # seconds - supplied as an integer, it is converted to a rational number. - # 3600 - no. of seconds in an hour. - # - # Returns a rational number. - def rational_hour(seconds) - seconds.to_r / 3600 - end - - # Private: Convert given seconds to an hour as an absolute number. - # - # seconds - supplied as an integer, it is converted to its absolute. - # 3600 - no. of seconds in an hour. - # - # Returns an integer. - def absolute_hour(seconds) - seconds.abs / 3600 - end - - # Private: Perform a modulo operation on a given fraction. - # - # fraction - supplied as a rational number, its numerator is divided - # by its denominator and the remainder returned. - # - # Returns an integer. - def modulo_of(fraction) - fraction.numerator % fraction.denominator + "WTZ#{sign}#{time}" end end end diff --git a/test/test_win_tz.rb b/test/test_win_tz.rb new file mode 100644 index 00000000000..e1d60908c79 --- /dev/null +++ b/test/test_win_tz.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require "helper" + +class TestWinTz < JekyllUnitTest + [["America/New_York", "WTZ+05:00"], ["Europe/Paris", "WTZ-01:00"]].each do |timezone, expected| + should "use base offset in winter for #{timezone}" do + result = Jekyll::Utils::WinTZ.calculate(timezone, Time.utc(2021, 1, 1)) + assert_equal expected, result + end + end + + [["America/New_York", "WTZ+04:00"], ["Europe/Paris", "WTZ-02:00"]].each do |timezone, expected| + should "apply DST in summer for #{timezone}" do + result = Jekyll::Utils::WinTZ.calculate(timezone, Time.utc(2021, 7, 1)) + assert_equal expected, result + end + end + + [["Australia/Eucla", "WTZ-08:45"], ["Pacific/Marquesas", "WTZ+09:30"]].each do |timezone, expected| + should "handle non zero minutes for #{timezone}" do + result = Jekyll::Utils::WinTZ.calculate(timezone, Time.utc(2021, 1, 1)) + assert_equal expected, result + end + end + + should "return zero for UTC" do + result = Jekyll::Utils::WinTZ.calculate("UTC") + assert_equal "WTZ+00:00", result + end +end \ No newline at end of file