Skip to content

Commit

Permalink
Add DOSTime#absolute_time?.
Browse files Browse the repository at this point in the history
This method returns `true` if the time instance was created with accurate
timezone information. Ultimately, only those times parsed from binary
DOS format are missing accurate timezone information, but we need this
flag because ruby `Time` objects (from which `DOSTime` is decended) always
have a timezone set (usually whatever is local at the time).
  • Loading branch information
hainesr committed Apr 8, 2024
1 parent d53f046 commit 0c0003c
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 1 deletion.
12 changes: 11 additions & 1 deletion lib/zip/dos_time.rb
Expand Up @@ -16,6 +16,14 @@ class DOSTime < Time # :nodoc:all
# bits 5-8 month (1-12)
# bits 9-15 year (four digit year minus 1980)

attr_writer :absolute_time # :nodoc:

def absolute_time?
# If absolute time is not set, we can assume it is an absolute time
# because times do have timezone information by default.
@absolute_time.nil? ? true : @absolute_time
end

def to_binary_dos_time
(sec / 2) +
(min << 5) +
Expand Down Expand Up @@ -53,7 +61,9 @@ def self.parse_binary_dos_format(bin_dos_date, bin_dos_time)
month = (0b111100000 & bin_dos_date) >> 5
year = ((0b1111111000000000 & bin_dos_date) >> 9) + 1980

local(year, month, day, hour, minute, second)
time = local(year, month, day, hour, minute, second)
time.absolute_time = false
time
end

if defined? JRUBY_VERSION && Gem::Version.new(JRUBY_VERSION) < '9.2.18.0'
Expand Down
86 changes: 86 additions & 0 deletions test/dos_time_test.rb
@@ -0,0 +1,86 @@
# frozen_string_literal: true

require 'test_helper'
require 'zip/dos_time'

class DOSTimeTest < MiniTest::Test
def setup
@dos_time = Zip::DOSTime.new(2022, 1, 1, 12, 0, 0)
end

def test_new
dos_time = Zip::DOSTime.new
assert(dos_time.absolute_time?)

dos_time = Zip::DOSTime.new(2022, 1, 1, 12, 0, 0)
assert(dos_time.absolute_time?)

dos_time = Zip::DOSTime.new(2022, 1, 1, 12, 0, 0, 0)
assert(dos_time.absolute_time?)
end

def test_now
dos_time = Zip::DOSTime.now
assert(dos_time.absolute_time?)
end

def test_utc
dos_time = Zip::DOSTime.utc(2022, 1, 1, 12, 0, 0)
assert(dos_time.absolute_time?)
end

def test_gm
dos_time = Zip::DOSTime.gm(2022, 1, 1, 12, 0, 0)
assert(dos_time.absolute_time?)
end

def test_mktime
dos_time = Zip::DOSTime.mktime(2022, 1, 1, 12, 0, 0)
assert(dos_time.absolute_time?)
end

def test_from_time
time = Time.new(2022, 1, 1, 12, 0, 0)
dos_time = Zip::DOSTime.from_time(time)
assert_equal(@dos_time, dos_time)
assert(dos_time.absolute_time?)
end

def test_parse_binary_dos_format
bin_dos_date = 0b101010000100001
bin_dos_time = 0b110000000000000
dos_time = Zip::DOSTime.parse_binary_dos_format(bin_dos_date, bin_dos_time)
assert_equal(@dos_time, dos_time)
refute(dos_time.absolute_time?)
end

def test_at
time = Time.at(1_641_038_400)
dos_time = Zip::DOSTime.at(1_641_038_400)
assert_equal(time, dos_time)
assert(dos_time.absolute_time?)
end

def test_local
dos_time = Zip::DOSTime.local(2022, 1, 1, 12, 0, 0)
assert(dos_time.absolute_time?)
end

def test_comparison
time = Time.new(2022, 1, 1, 12, 0, 0)
assert_equal(0, @dos_time <=> time)
end

def test_jruby_cmp
return unless defined? JRUBY_VERSION && Gem::Version.new(JRUBY_VERSION) < '9.2.18.0'

time = Time.new(2022, 1, 1, 12, 0, 0)
assert(@dos_time == time)
assert(@dos_time <= time)
assert(@dos_time >= time)

time = Time.new(2022, 1, 1, 12, 1, 1)
assert(time > @dos_time)
assert(@dos_time < time)
end
end

0 comments on commit 0c0003c

Please sign in to comment.