Reputation: 2752
As I understand, UTC means a time is given in timezone +00:00. But Ruby thinks different in Time#utc?
. I've observed this in Ruby 2.5.1:
a = Time.new(2018,6,13, 9,0,0, '+00:00')
# => 2018-06-13 09:00:00 +0000
b = Time.utc(2018,6,13, 9,0,0)
# => 2018-06-13 09:00:00 UTC
a == b
# => true
a.utc?
# => false (WHY???)
b.utc?
# => true
IMHO, a.utc?
should return true. Is there any explanation?
Addition: From the Ruby docs for Time#utc?
Returns true if time represents a time in UTC (GMT).
What exactly means "representing a time in UTC/GMT"? An offset of 0 is not enough, obviously.
Upvotes: 5
Views: 153
Reputation: 114188
Implementation-wise, Ruby's (i.e. MRI) internal time structure has a gmt
field which specifies the time's type:
PACKED_STRUCT_UNALIGNED(struct time_object {
wideval_t timew; /* time_t value * TIME_SCALE. possibly Rational. */
struct vtm vtm;
uint8_t gmt:3; /* 0:localtime 1:utc 2:fixoff 3:init */
uint8_t tm_got:1;
});
The utc?
method merely checks whether gmt
is 1
.
Therefore, a time instance in local time or a time instance with explicit offset will never be utc?
, even if your system's timezone offset is UTC+0:
Time.local(2018) #=> 2018-01-01 00:00:00 +0000
Time.local(2018).utc? #=> false
Time.new(2018) #=> 2018-01-01 00:00:00 +0000
Time.new(2018).utc? #=> false
as opposed to a time instance created via utc
: (note that the offset is shown as UTC
)
Time.utc(2018) #=> 2018-01-01 00:00:00 UTC
Time.utc(2018).utc? #=> true
You could check the utc_offset
instead:
t = Time.new(2018) #=> 2018-01-01 00:00:00 +0000
t.utc_offset #=> 0
t.utc_offset.zero? #=> true
Upvotes: 5