Support both tzinfo v1 and v2 alongwith non-half hour offsets. (#8880)

Merge pull request 8880
This commit is contained in:
Phil Ross 2021-12-08 11:35:42 +00:00 committed by GitHub
parent 956701f96c
commit 9c9cf3e82b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 91 additions and 63 deletions

View File

@ -86,7 +86,7 @@ group :jekyll_optional_dependencies do
# 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", ENV["TZINFO_VERSION"] if ENV["TZINFO_VERSION"]
gem "tzinfo-data"
end
end

View File

@ -13,6 +13,12 @@ build: off
environment:
BUNDLE_WITHOUT: "benchmark:development"
matrix:
- RUBY_FOLDER_VER: "26"
TZINFO_VERSION: "~> 1.2"
TEST_SUITE: "test"
- RUBY_FOLDER_VER: "26"
TZINFO_VERSION: "~> 2.0"
TEST_SUITE: "test"
- RUBY_FOLDER_VER: "26"
TEST_SUITE: "test"
- RUBY_FOLDER_VER: "26"
@ -21,6 +27,12 @@ environment:
TEST_SUITE: "profile-docs"
- RUBY_FOLDER_VER: "26"
TEST_SUITE: "memprof"
- RUBY_FOLDER_VER: "26"
TZINFO_VERSION: "~> 1.2"
TEST_SUITE: "cucumber"
- RUBY_FOLDER_VER: "26"
TZINFO_VERSION: "~> 2.0"
TEST_SUITE: "cucumber"
- RUBY_FOLDER_VER: "26"
TEST_SUITE: "cucumber"

View File

@ -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
```
<div class="note warning">
<h5>TZInfo 2.0 incompatibility</h5>
<p>
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.
</p>
<p>
We therefore recommend that you lock the Timezone library to version 1.2 and above by listing
<code>gem 'tzinfo', '~> 1.2'</code> in your <code>Gemfile</code>.
</p>
</div>
## Auto Regeneration
Jekyll uses the `listen` gem to watch for changes when the `--watch` switch is specified during a build or serve.

View File

@ -291,6 +291,28 @@ Feature: Site configuration
And I should see "Post Layout: <p>content for entry1.</p>\n built at 2013-04-09T09:22:00-10:00" in "_site/2013/04/09/entry1.html"
And I should see "Post Layout: <p>content for entry2.</p>\n built at 2013-04-09T13:14:00-10:00" in "_site/2013/04/09/entry2.html"
Scenario: Generate proper dates with explicitly set timezone (using non-half hour offset )
Given I have a _layouts directory
And I have a page layout that contains "Page Layout: {{ site.posts.size }}"
And I have a post layout that contains "Post Layout: {{ content }} built at {{ page.date | date_to_xmlschema }}"
And I have an "index.html" page with layout "page" that contains "site index page"
And I have a configuration file with:
| key | value |
| timezone | Australia/Eucla |
And I have a _posts directory
And I have the following posts:
| title | date | layout | content |
| entry1 | 2013-04-09 23:22 +0400 | post | content for entry1. |
| entry2 | 2013-04-10 03:14 +0400 | post | content for entry2. |
When I run jekyll build
Then I should get a zero exit status
And the _site directory should exist
And I should see "Page Layout: 2" in "_site/index.html"
And the "_site/2013/04/10/entry1.html" file should exist
And the "_site/2013/04/10/entry2.html" file should exist
And I should see "Post Layout: <p>content for entry1.</p>\n built at 2013-04-10T04:07:00\+08:45" in "_site/2013/04/10/entry1.html"
And I should see "Post Layout: <p>content for entry2.</p>\n built at 2013-04-10T07:59:00\+08:45" in "_site/2013/04/10/entry2.html"
Scenario: Limit the number of posts generated by most recent date
Given I have a _posts directory
And I have a configuration file with:

View File

@ -92,7 +92,7 @@ module Jekyll
# 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

View File

@ -11,64 +11,35 @@ module Jekyll
# 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))
#
# Format the hour as a two-digit number.
# Establish the minutes based on modulo expression.
hh = format("%<hour>02d", :hour => absolute_hour(difference).ceil)
mm = modulo.zero? ? "00" : "30"
sign = offset.positive? ? "-" : "+"
Jekyll.logger.debug "Timezone:", "#{timezone} #{offset}#{hh}:#{mm}"
rational_hours = offset.abs.to_r / 3600
hours = rational_hours.to_i
minutes = ((rational_hours - hours) * 60).to_i
#
# Format the hours and minutes as two-digit numbers.
time = format("%<hours>02d:%<minutes>02d", :hours => hours, :minutes => minutes)
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

31
test/test_win_tz.rb Normal file
View File

@ -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 |tz, expected|
should "use base offset in winter for #{tz}" do
result = Jekyll::Utils::WinTZ.calculate(tz, Time.utc(2021, 1, 1))
assert_equal expected, result
end
end
[["America/New_York", "WTZ+04:00"], ["Europe/Paris", "WTZ-02:00"]].each do |tz, expected|
should "apply DST in summer for #{tz}" do
result = Jekyll::Utils::WinTZ.calculate(tz, Time.utc(2021, 7, 1))
assert_equal expected, result
end
end
[["Australia/Eucla", "WTZ-08:45"], ["Pacific/Marquesas", "WTZ+09:30"]].each do |tz, expected|
should "handle non zero minutes for #{tz}" do
result = Jekyll::Utils::WinTZ.calculate(tz, 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