Class: TimeWithZone

Inherits:
Object
  • Object
show all
Defined in:
lib/time_with_zone.rb,
lib/time_with_zone/version.rb

Overview

Handle time with zone withtout ActiveSupport or ENV

require 'time_with_zone'

TimeWithZone.strptime_with_zone('2016-10-10', '%Y-%m-%d', 'Asia/Taipei')
# => '2016-10-10 00:00:00 +0800'

TimeWithZone.parse_with_zone('2016-10-10', 'Asia/Taipei')
# => '2016-10-10 00:00:00 +0800'

time = Time.parse('2016-10-10 00:00:00 +00:00')
TimeWithZone.set_zone(time, 'Asia/Taipei')
# => '2016-10-10 00:00:00 +0800'

time = Time.parse('2016-10-10 00:00:00 +00:00')
TimeWithZone.localtime_with_zone(time, 'Asia/Taipei')
# => '2016-10-10 08:00:00 +0800'

Constant Summary

NUMERIC_PATTERN =

[+-]HH:MM, [+-]HHMM, [+-]HH

%r{\A[+-]\d\d(:?\d\d)?\z}
NAME_PATTERN =

Region/Zone, Region/Zone/Zone

%r{\A[^/]+/[^/]+(/[^/]+)?\z}
ZoneOffset =

Short-abbreviation timezone which Ruby's Time class supports

(class << Time; self; end)::ZoneOffset
VERSION =
"0.3.1"

Class Method Summary (collapse)

Class Method Details

+ (Time) localtime_with_zone(time, timezone)

Time#localtime with timezone (non-destructive)

ENV['TZ'] = '+09:00' # Assume your local timezone is +09:00

require 'time'

time = Time.parse("2016-10-20 00:00:00 +00:00") 
time.dup.localtime("+08:00")
#=> 2010-10-20 08:00:00 +0800
time.dup.localtime("CDT")
#=> error
time.dup.localtime("Asia/Taipei")
#=> error

require 'time_with_zone'

time = Time.parse("2016-10-20 00:00:00 +00:00") 
TimeWithZone.localtime_with_zone(time, "+08:00")
#=> 2010-10-20 08:00:00 +0800
TimeWithZone.localtime_with_zone(time, "CDT")
#=> 2016-10-19 19:00:00 -0500
TimeWithZone.localtime_with_zone(time, "Asia/Taipei")
#=> 2010-10-20 08:00:00 +0800

This method is actually a short-hand of

require 'time_with_zone'
time = Time.parse("2016-10-20 00:00:00 +00:00")

time.dup.localtime(TimeWithZone.zone_offset("Asia/Taipei", time))
#=> 2010-10-20 08:00:00 +0800

Parameters:

Returns:

  • (Time)


69
70
71
# File 'lib/time_with_zone.rb', line 69

def self.localtime_with_zone(time, timezone)
  localtime_with_zone!(time.dup, timezone)
end

+ (Time) localtime_with_zone!(time, timezone)

Time#localtime with timezone (destructive)

Parameters:

Returns:

  • (Time)

See Also:



79
80
81
82
# File 'lib/time_with_zone.rb', line 79

def self.localtime_with_zone!(time, timezone)
  _zone_offset = zone_offset(timezone, time)
  time.localtime(_zone_offset)
end

+ (Time) parse_with_zone(date, timezone)

Time.parse with timezone

ENV['TZ'] = '+09:00' # Assume your local timezone is +09:00

require 'time'

Time.parse("2016-10-20")
#=> 2016-10-20 00:00:00 +0900
Time.parse("2016-10-20 00:00:00 +08:00")
#=> 2016-10-20 00:00:00 +0800
Time.parse("2016-10-20 00:00:00 CDT")
#=> 2016-10-20 00:00:00 -0500
Time.parse("2016-10-20 00:00:00 Asia/Taipei")
#=> 2016-10-20 00:00:00 +0900 (does not work)

require 'time_with_zone'

TimeWithZone.parse_with_zone("2016-10-20", "+08:00")
#=> 2016-10-20 00:00:00 +0800
TimeWithZone.parse_with_zone("2016-10-20", "CDT")
#=> 2016-10-20 00:00:00 -0500
TimeWithZone.parse_with_zone("2016-10-20", "Asia/Taipei")
#=> 2016-10-20 00:00:00 +0800

Parameters:

Returns:

  • (Time)


111
112
113
114
# File 'lib/time_with_zone.rb', line 111

def self.parse_with_zone(date, timezone)
  time = Time.parse(date)
  set_zone!(time, timezone)
end

+ (Time) parse_with_zone_offset(date, zone_offset)

Time.parse with zone_offset

require 'time_with_zone'

TimeWithZone.parse_with_zone_offset("2016-10-20", 28800)
#=> 2016-10-20 00:00:00 +0800

Parameters:

  • date (String)

    string to be parsed

  • zone_offset (Integer)

Returns:

  • (Time)


126
127
128
129
# File 'lib/time_with_zone.rb', line 126

def self.parse_with_zone_offset(date, zone_offset)
  time = Time.parse(date)
  set_zone_offset!(time, zone_offset)
end

+ (Time) set_zone(time, timezone)

This method changes only the zone field of Time object

require 'time_with_zone'

time = Time.parse("2016-02-02 00:00:00 +00:00")
TimeWithZone.set_zone(time, "+08:00")
#=> "2016-02-02 00:00:00 +0800"
# Note that it is not "2016-02-02 08:00:00 +0800" like Time#localtime(timezone)

Parameters:

  • time (Time)
  • timezone (String)

Returns:

  • (Time)


193
194
195
# File 'lib/time_with_zone.rb', line 193

def self.set_zone(time, timezone)
  set_zone!(time.dup, timezone)
end

+ (Time) set_zone_offset(time, zone_offset)

This method changes only the zone offset field of Time object

require 'time_with_zone'
time = Time.parse("2016-02-02 00:00:00 +00:00")

TimeWithZone.set_zone_offset(time, 28800)
#=> "2016-02-02 00:00:00 +0800"
# Note that it is not "2016-02-02 08:00:00 +0800" like Time#localtime(zone_offset)

Parameters:

  • time (Time)
  • zone_offset (Integer)

Returns:

  • (Time)


209
210
211
# File 'lib/time_with_zone.rb', line 209

def self.set_zone_offset(time, zone_offset)
  set_zone_offset!(time.dup, zone_offset)
end

+ (Time) strptime_with_zone(date, format, timezone)

Time.strptime with timezone

ENV['TZ'] = '+09:00' # Assume your local timezone is +09:00

require 'time'

Time.strptime("2016-10-20", "%Y-%m-%d")
#=> 2016-10-20 00:00:00 +0900
Time.strptime("2016-10-20 +08:00", "%Y-%m-%d %z")
#=> 2016-10-20 00:00:00 +0800
Time.strptime("2016-10-20 CDT", "%Y-%m-%d %Z")
#=> 2016-10-20 00:00:00 -0500
Time.strptime("2016-10-20 Asia/Taipei", "%Y-%m-%d %Z")
#=> 2016-10-20 00:00:00 +0900 (does not work)

require 'time_with_zone'

TimeWithZone.strptime_with_zone("2016-10-20", "%Y-%m-%d", "+08:00")
#=> 2016-10-20 00:00:00 +0800
TimeWithZone.strptime_with_zone("2016-10-20", "%Y-%m-%d", "CDT")
#=> 2016-10-20 00:00:00 -0500
TimeWithZone.strptime_with_zone("2016-10-20", "%Y-%m-%d", "Asia/Taipei")
#=> 2016-10-20 00:00:00 +0800

Parameters:

Returns:

  • (Time)


160
161
162
163
# File 'lib/time_with_zone.rb', line 160

def self.strptime_with_zone(date, format, timezone)
  time = Time.strptime(date, format)
  set_zone!(time, timezone)
end

+ (Time) strptime_with_zone_offset(date, format, zone_offset)

Time.strptime with zone_offset

require 'time_with_zone'

TimeWithZone.strptime_with_zone_offset("2016-10-20", "%Y-%m-%d", 28800)
#=> 2016-10-20 00:00:00 +0800

Parameters:

  • date (String)

    string to be parsed

  • format (String)
  • zone_offset (Integer)

Returns:

  • (Time)


176
177
178
179
# File 'lib/time_with_zone.rb', line 176

def self.strptime_with_zone_offset(date, format, zone_offset)
  time = Time.strptime(date, format)
  set_zone_offset!(time, zone_offset)
end

+ (Integer) zone_offset(timezone, time = nil)

Returns zone offset for given timezone string

require 'time_with_zone'

TimeWithZone.zone_offset("+08:00")
#=> 28800
TimeWithZone.zone_offset("Asia/Taipei")
#=> 28800
TimeWithZone.zone_offset("PST")
#=> -28800
TimeWithZone.zone_offset("America/Los_Angeles")
#=> -25200 
TimeWithZone.zone_offset("America/Los_Angeles", Time.parse("2016-07-07 00:00:00 +00:00"))
#=> -25200 # DST (Daylight Saving Time)
TimeWithZone.zone_offset("America/Los_Angeles", Time.parse("2016-01-01 00:00:00 +00:00"))
#=> -28800 # non DST

Parameters:

Returns:

  • (Integer)

    zone offset



233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/time_with_zone.rb', line 233

def self.zone_offset(timezone, time = nil)
  if NUMERIC_PATTERN === timezone
    Time.zone_offset(timezone)
  elsif NAME_PATTERN === timezone
    tz = TZInfo::Timezone.get(timezone)
    if time
      tz.period_for_utc(time).utc_total_offset
    else
      tz.current_period.utc_total_offset
    end
  elsif ZoneOffset.include?(timezone)
    ZoneOffset[timezone] * 3600
  else
    raise ArgumentError, "timezone format is invalid: #{timezone}"
  end
end