Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 3 commits into from
Dec 8, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 2 additions & 7 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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

#
Expand Down
20 changes: 6 additions & 14 deletions docs/_docs/installation/windows.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
22 changes: 22 additions & 0 deletions features/site_configuration.feature
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion lib/jekyll/commands/new.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
63 changes: 17 additions & 46 deletions lib/jekyll/utils/win_tz.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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("%<hour>02d", :hour => absolute_hour(difference).ceil)
mm = modulo.zero? ? "00" : "30"
# Format the hours and minutes as two-digit numbers.
time = format("%<hours>02d:%<minutes>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
Expand Down
31 changes: 31 additions & 0 deletions test/test_win_tz.rb
Original file line number Diff line number Diff line change
@@ -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