Skip to content
76 changes: 76 additions & 0 deletions scripts/generate_windows_zone_names.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# This script generates the file src/crystal/system/win32/zone_names.cr
# that contains mappings for windows time zone names based on the values
# found in http://unicode.org/cldr/data/common/supplemental/windowsZones.xml

require "http/client"
require "xml"
require "../src/compiler/crystal/formatter"

WINDOWS_ZONE_NAMES_SOURCE = "http://unicode.org/cldr/data/common/supplemental/windowsZones.xml"
TARGET_FILE = File.join(__DIR__, "..", "src", "crystal", "system", "win32", "zone_names.cr")

response = HTTP::Client.get(WINDOWS_ZONE_NAMES_SOURCE)

# Simple redirection resolver
# TODO: Needs to be replaced by proper redirect handling that should be provided by `HTTP::Client`
if (300..399).includes?(response.status_code) && (location = response.headers["Location"]?)
response = HTTP::Client.get(location)
end

xml = XML.parse(response.body)

nodes = xml.xpath_nodes("/supplementalData/windowsZones/mapTimezones/mapZone[@territory=001]")

entries = [] of {key: String, zones: {String, String}, tzdata_name: String}

nodes.each do |node|
location = Time::Location.load(node["type"])
next unless location
time = Time.now(location).at_beginning_of_year
zone1 = time.zone
zone2 = (time + 6.months).zone

if zone1.offset > zone2.offset
# southern hemisphere
zones = {zone2.name, zone1.name}
else
# northern hemisphere
zones = {zone1.name, zone2.name}
end

entries << {key: node["other"], zones: zones, tzdata_name: location.name}
rescue err : Time::Location::InvalidLocationNameError
pp err
end

# sort by IANA database identifier
entries.sort_by! &.[:tzdata_name]

hash_items = String.build do |io|
entries.each do |entry|
entry[:key].inspect(io)
io << " => "
entry[:zones].inspect(io)
io << ", # " << entry[:tzdata_name] << "\n"
end
end

source = <<-CRYSTAL
# This file was automatically generated by running:
#
# scripts/generate_windows_zone_names.cr
#
# DO NOT EDIT

module Crystal::System::Time
# These mappings for windows time zone names are based on
# #{WINDOWS_ZONE_NAMES_SOURCE}
WINDOWS_ZONE_NAMES = {
#{hash_items}
}
end
CRYSTAL

source = Crystal.format(source)

File.write(TARGET_FILE, source)
Binary file added spec/std/data/zoneinfo.zip
Binary file not shown.
Binary file added spec/std/data/zoneinfo/Foo/Bar
Binary file not shown.
10 changes: 5 additions & 5 deletions spec/std/file_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -1033,8 +1033,8 @@ describe "File" do
filename = "#{__DIR__}/data/temp_write.txt"
File.write(filename, "")

atime = Time.new(2000, 1, 2)
mtime = Time.new(2000, 3, 4)
atime = Time.utc(2000, 1, 2)
mtime = Time.utc(2000, 3, 4)

File.utime(atime, mtime, filename)

Expand All @@ -1046,8 +1046,8 @@ describe "File" do
end

it "raises if file not found" do
atime = Time.new(2000, 1, 2)
mtime = Time.new(2000, 3, 4)
atime = Time.utc(2000, 1, 2)
mtime = Time.utc(2000, 3, 4)

expect_raises Errno, "Error setting time to file" do
File.utime(atime, mtime, "#{__DIR__}/nonexistent_file")
Expand All @@ -1069,7 +1069,7 @@ describe "File" do

it "sets file times to given time" do
filename = "#{__DIR__}/data/temp_touch.txt"
time = Time.new(2000, 3, 4)
time = Time.utc(2000, 3, 4)
begin
File.touch(filename, time)

Expand Down
14 changes: 3 additions & 11 deletions spec/std/http/http_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe HTTP do
it "parses and is local (#2744)" do
date = "Mon, 09 Sep 2011 23:36:00 -0300"
parsed_time = HTTP.parse_time(date).not_nil!
parsed_time.local?.should be_true
parsed_time.offset.should eq -3 * 3600
parsed_time.to_utc.to_s.should eq("2011-09-10 02:36:00 UTC")
end

Expand All @@ -44,16 +44,8 @@ describe HTTP do
end

it "with local time zone" do
tz = ENV["TZ"]?
ENV["TZ"] = "Europe/Berlin"
LibC.tzset
begin
time = Time.new(1994, 11, 6, 8, 49, 37, nanosecond: 0, kind: Time::Kind::Local)
HTTP.rfc1123_date(time).should eq(time.to_utc.to_s("%a, %d %b %Y %H:%M:%S GMT"))
ensure
ENV["TZ"] = tz
LibC.tzset
end
time = Time.new(1994, 11, 6, 8, 49, 37, nanosecond: 0, location: Time::Location.load("Europe/Berlin"))
HTTP.rfc1123_date(time).should eq(time.to_utc.to_s("%a, %d %b %Y %H:%M:%S GMT"))
end
end

Expand Down
2 changes: 1 addition & 1 deletion spec/std/json/mapping_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ describe "JSON mapping" do
it "parses json with Time::Format converter" do
json = JSONWithTime.from_json(%({"value": "2014-10-31 23:37:16"}))
json.value.should be_a(Time)
json.value.to_s.should eq("2014-10-31 23:37:16")
json.value.to_s.should eq("2014-10-31 23:37:16 UTC")
json.to_json.should eq(%({"value":"2014-10-31 23:37:16"}))
end

Expand Down
Loading