zones 0.6.2 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +44 -7
  3. data/lib/zones.rb +74 -104
  4. data/zones.gemspec +3 -5
  5. metadata +4 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5f86231105060ba0d2a2e5de9b5d5e1a12697442eab2f53e25141ae9e364c595
4
- data.tar.gz: 435fd13071ba665a0e3c8f4cca2162a804ca160ffee145ca179558a4e22f383d
3
+ metadata.gz: fcc3e314485f8294d9dfbfa29afc78ccd6cf9619cd67095bc5fe6b1f84616277
4
+ data.tar.gz: 36bea6abe134f28921a23d3a1bb9bb6e1cea7b1c9ffb6fbfc80362156e3f6895
5
5
  SHA512:
6
- metadata.gz: 10f84f521cefa6e9ef0d3933338d8c6666dde86908fb18cf8d530ffe71535e95cb8c028a1537356edba17ce5d36a6fdf71a86dfc040208a178b0ea8282adfa48
7
- data.tar.gz: 5929966234fda57b8b1fac23ace116f43369e3a68a994ad4413d56ed001c415efc22e850e27f2a2de9175bfb8bd6a363575d14d408a7618a69b246c18b6e3fc6
6
+ metadata.gz: 1c9742d8ce70f27717f435d2174c8c019529d168cf84162d0f89769f3d394eac3ddd5f150e171edd5de0d1eb2b847a997909031368f9f3038770f1ba479c1447
7
+ data.tar.gz: 48e62375f30a6bb5a45ef207a419f13731b06cc11c8e2b9df6a7a6c4df74235c1451956e3d69b5beb5c798d0ba64c98aa10b38bdb29c244d3bf1e3c58d0445f3
data/README.md CHANGED
@@ -1,17 +1,54 @@
1
1
  # zones
2
2
 
3
- `zones` is a Ruby gem that makes it easy to parse time and convert it between time zones.
3
+ A friendly Ruby gem for time parsing and time zone conversion.
4
+
5
+ ## API
6
+
7
+ ```ruby
8
+ Time.tz(str, toz=nil, asz=nil) # create a new Time object with a time zone
9
+ Time.tz!(str, asz="UTC", toz=nil) # overrides original time zone and swaps params
10
+ Time#to(zone) # converts a time to a new time zone
11
+ Time#as(zone) # keeps the time, but changes the time zone
12
+
13
+ String#to_tz # calls Time.tz
14
+ String#to_tz! # calls Time.tz!
15
+ String#to_day # calls Date.to_day
16
+ String#iso_date # parses and shows ISO date (YYYY-MM-DD)
17
+ ```
4
18
 
5
19
  ## Examples
6
20
 
21
+ Parsing strings:
22
+
7
23
  ```ruby
8
- # when parsing, the "!" means to ignore the supplied time zone / offset
9
- x = "3 August 2017 11:43 +0415".to_tz("US/Pacific") # 2017-08-03 00:28:00 -0700
10
- y = "3 August 2017 11:43 +0415".to_tz!("US/Pacific") # 2017-08-03 11:43:00 -0700
24
+ # no argument means to parse the value as is; "!" ignores the time zone and uses UTC
25
+ x = "3 August 2013 11:43 +0415".to_tz # 2013-08-03 11:43:00 +0415
26
+ y = "3 August 2013 11:43 +0415".to_tz! # 2013-08-03 11:43:00 +0000
11
27
 
12
- # when converting, the "!" means to only change the offset
13
- x.to_tz("US/Eastern") # 2017-08-03 03:28:00 -0400
14
- y.to_tz!("US/Eastern") # 2017-08-03 11:43:00 -0400
28
+ # one argument means to convert to that time zone, use "!" to ignore the original offset
29
+ x = "3 August 2013 11:43 +0415".to_tz("US/Pacific") # 2013-08-03 00:28:00 -0700
30
+ y = "3 August 2013 11:43 +0415".to_tz!("US/Pacific") # 2013-08-03 11:43:00 -0700
31
+
32
+ # use two arguments to indicate source and destination time zones, "!" swaps the order
33
+ x = "3 August 2013 11:43 +0415".to_tz("US/Pacific", "America/Caracas") # 2013-08-03 09:13:00 -0700
34
+ y = "3 August 2013 11:43 +0415".to_tz!("US/Pacific", "America/Caracas") # 2013-08-03 14:13:00 -0430
35
+ ```
36
+
37
+ Converting values:
38
+
39
+ ```ruby
40
+ # 'as' keeps the time but changes the time zone, 'to' converts to a new time zone
41
+ x = "May 29, 2023 6:15pm -06:00".to_tz # 2023-05-29 18:15:00 -0600
42
+ x.as("US/Eastern") # 2023-05-29 18:15:00 -0400
43
+ x.to("US/Eastern") # 2023-05-29 20:15:00 -0400
44
+ ```
45
+
46
+ Sample formats:
47
+
48
+ ```ruby
49
+ x = "4/13/1971 19:25 -0700".to_tz # 1971-04-13 19:25:00 -0700
50
+ x = "13 May 2022 11:20PM".to_tz # 2022-05-13 23:20:00 -0600
51
+ x = "September 24, 2008".iso_date # 2008-09-24
15
52
  ```
16
53
 
17
54
  ## License
data/lib/zones.rb CHANGED
@@ -1,49 +1,42 @@
1
1
  require "tzinfo"
2
2
 
3
- # ==[ Dart uses the folllowing ]==
4
- #
5
- # date ::= yeardate time_opt timezone_opt
6
- # yeardate ::= year colon_opt month colon_opt day
7
- # year ::= sign_opt digit{4,6}
8
- # colon_opt :: <empty> | ':'
9
- # sign ::= '+' | '-'
10
- # sign_opt ::= <empty> | sign
11
- # month ::= digit{2}
12
- # day ::= digit{2}
13
- # time_opt ::= <empty> | (' ' | 'T') hour minutes_opt
14
- # minutes_opt ::= <empty> | colon_opt digit{2} seconds_opt
15
- # seconds_opt ::= <empty> | colon_opt digit{2} millis_opt
16
- # micros_opt ::= <empty> | ('.' | ',') digit+
17
- # timezone_opt ::= <empty> | space_opt timezone
18
- # space_opt :: ' ' | <empty>
19
- # timezone ::= 'z' | 'Z' | sign digit{2} timezonemins_opt
20
- # timezonemins_opt ::= <empty> | colon_opt digit{2}
21
- #
22
- # static final RegExp _parseFormat =
23
- # RegExp(r'^([+-]?\d{4,6})-?(\d\d)-?(\d\d)' // Day part.
24
- # r'(?:[ T](\d\d)(?::?(\d\d)(?::?(\d\d)(?:[.,](\d+))?)?)?' // Time part.
25
- # r'( ?[zZ]| ?([-+])(\d\d)(?::?(\d\d))?)?)?$'); // Timezone part.
3
+ module MonthValue
4
+ def month_value(str)
5
+ (val = str.to_i).zero? ? (@month_value ||= {
6
+ "jan" => 1, "january" => 1, "jul" => 7, "july" => 7,
7
+ "feb" => 2, "february" => 2, "aug" => 8, "august" => 8,
8
+ "mar" => 3, "march" => 3, "sep" => 9, "september" => 9,
9
+ "apr" => 4, "april" => 4, "oct" => 10, "october" => 10,
10
+ "may" => 5, "nov" => 11, "november" => 11,
11
+ "jun" => 6, "june" => 6, "dec" => 12, "december" => 12,
12
+ })[str.downcase] : val or raise "bad month: #{str}"
13
+ end
14
+ end
26
15
 
27
16
  class Date
17
+ extend MonthValue
18
+
28
19
  def self.parse_str(str)
29
20
  case str
30
- when %r!^((?:19|20)\d\d)(\d\d)(\d\d)(\d\d)!
21
+ when %r!^((?:19|20)\d\d)(\d\d)(\d\d)!
31
22
  ymd = [$1.to_i, $2.to_i, $3.to_i]
32
23
  when %r!^
33
- (?:(0[1-9]|[12]\d|3[01]|[1-9][-/ ])[-/ ]? # $1: day
34
- ((?>[a-z]{3,9}))[-/ ]? # $2: month
35
- ((?>19|20)\d\d) # $3: year
24
+ (?:(0[1-9]|[12]\d|3[01]|[1-9](?=\D))[-/\s]? # $1: day
25
+ ( (?>[a-z]{3,9}))[-/\s]? # $2: month (no digits allowed here)
26
+ ((?>19|20)\d\d) # $3: year
36
27
  | # or...
37
- ((?>19|20)\d\d)[-/]? # $4: year
38
- (0[1-9]|1[012]|[1-9][-/])[-/]? # $5: month
39
- (0[1-9]|[12]\d|3[01]|[1-9][\sT]) # $6: day
28
+ ((?>19|20)\d\d)[-/\s]? # $4: year
29
+ (0[1-9]|1[012]|[1-9](?=\D)|(?>[a-z]{3,9}))[-/\s]? # $5: month
30
+ (0[1-9]|[12]\d|3[01]|[1-9]\b) # $6: day
40
31
  | # or...
41
- (0[1-9]|1[012]|[1-9][-/])[-/]? # $7: month
42
- (0[1-9]|[12]\d|3[01]|[1-9][-/])[-/]? # $8: day
43
- ((?>19|20)\d\d) # $9: year
32
+ (0[1-9]|1[012]|[1-9](?=\D)|(?>[a-z]{3,9}))[-/\s]? # $7: month
33
+ (0[1-9]|[12]\d|3[01]|[1-9](?=\D)),?[-/\s]? # $8: day
34
+ ((?>19|20)\d\d) # $9: year
44
35
  )
45
36
  !iox
46
- ymd = $1 ? [$3.to_i, month_num($2), $1.to_i] : $4 ? [$4.to_i, $5.to_i, $6.to_i] : [$9.to_i, $7.to_i, $8.to_i]
37
+ ymd = $1 ? [ $3.to_i, month_value($2), $1.to_i] : \
38
+ $4 ? [ $4.to_i, month_value($5), $6.to_i] : \
39
+ [ $9.to_i, month_value($7), $8.to_i]
47
40
  else
48
41
  raise "can't parse: #{str}"
49
42
  end
@@ -58,113 +51,90 @@ class Date
58
51
  end
59
52
 
60
53
  class Time
61
- def self.parse_str(str, ignore_offset=false)
54
+ extend MonthValue
55
+
56
+ def self.parse_str(str)
62
57
  case str
63
- when %r!^((?:19|20)\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)?\.?(\d+)?([-+]\d\d:?\d\d)?!
58
+ when %r!^
59
+ ((?:19|20)\d\d)[-/\s]?(\d\d)[-/\s]?(\d\d)\s? # $1-3: year, month, day
60
+ (\d\d):?(\d\d):?(\d\d)?\.?(\d+)? # $4-7: hour, min, sec, decimal
61
+ ([-+]\d\d:?\d\d)? # $8 : offset
62
+ !x
64
63
  ymd = [$1.to_i, $2.to_i, $3.to_i]
65
64
  hms = [$4.to_i, $5.to_i, "#{$6}.#{$7}".to_f]
66
- off = $8.sub(/(\d)(\d\d)$/,'\1:\2') if $8 && !ignore_offset
65
+ off = $8.sub(/(\d)(\d\d)$/,'\1:\2') if $8
67
66
  when %r!^
68
- (?:(0[1-9]|[12]\d|3[01]|[1-9][-/ ])[-/ ]? # $1: day
69
- ((?>[a-z]{3,9}))[-/ ]? # $2: month
70
- ((?>19|20)\d\d) # $3: year
67
+ (?:(0[1-9]|[12]\d|3[01]|[1-9](?=\D))[-/\s]? # $1: day
68
+ ( (?>[a-z]{3,9}))[-/\s]? # $2: month (no digits allowed here)
69
+ ((?>19|20)\d\d) # $3: year
71
70
  | # or...
72
- ((?>19|20)\d\d)[-/]? # $4: year
73
- (0[1-9]|1[012]|[1-9][-/])[-/]? # $5: month
74
- (0[1-9]|[12]\d|3[01]|[1-9][\sT]) # $6: day
71
+ ((?>19|20)\d\d)[-/\s]? # $4: year
72
+ (0[1-9]|1[012]|[1-9](?=\D)|(?>[a-z]{3,9}))[-/\s]? # $5: month
73
+ (0[1-9]|[12]\d|3[01]|[1-9](?=\D)) # $6: day
75
74
  | # or...
76
- (0[1-9]|1[012]|[1-9][-/])[-/]? # $7: month
77
- (0[1-9]|[12]\d|3[01]|[1-9][-/])[-/]? # $8: day
78
- ((?>19|20)\d\d) # $9: year
75
+ (0[1-9]|1[012]|[1-9](?=\D)|(?>[a-z]{3,9}))[-/\s]? # $7: month
76
+ (0[1-9]|[12]\d|3[01]|[1-9](?=\D)),?[-/\s]? # $8: day
77
+ ((?>19|20)\d\d) # $9: year
79
78
  )\s?T?\s?
80
- (\d\d?)? # $10: hour
81
- :?(\d\d)? # $11: min
82
- :?(\d\d)? # $12: sec
83
- \.?(\d+)? # $13: dec
84
- \s?(?:(a|p)?m)? # $14: am/pm
85
- \s?(([-+])?(\d\d):?(\d\d)|UTC|GMT)? # $15: offset ($16=sign, $17=hours, $18=mins)
79
+ (\d\d?)? # $10: hour
80
+ :?(\d\d)? # $11: min
81
+ :?(\d\d)? # $12: sec
82
+ \.?(\d+)? # $13: dec
83
+ \s?(?:(a|p)?m)? # $14: am/pm
84
+ \s?(([-+])?(\d\d):?(\d\d)|UTC|GMT|Z)? # $15: offset ($16=sign, $17=hours, $18=mins)
86
85
  !iox
87
- ymd = $1 ? [$3.to_i, month_num($2), $1.to_i] : $4 ? [$4.to_i, $5.to_i, $6.to_i] : [$9.to_i, $7.to_i, $8.to_i]
86
+ ymd = $1 ? [ $3.to_i, month_value($2), $1.to_i] : \
87
+ $4 ? [ $4.to_i, month_value($5), $6.to_i] : \
88
+ [ $9.to_i, month_value($7), $8.to_i]
88
89
  hms = [$14 ? ($10.to_i % 12) + (($14=="P" || $14=="p") ? 12 : 0) : $10.to_i, $11.to_i, "#{$12}.#{$13}".to_f]
89
- off = ($17 ? "#{$16||'+'}#{$17}:#{$18}" : "+00:00") if $15 && !ignore_offset
90
+ off = ($17 ? "#{$16||'+'}#{$17}:#{$18}" : "+00:00") if $15
90
91
  else
91
92
  raise "can't parse: #{str}"
92
93
  end
93
- off ? [ymd, hms, off] : [ymd, hms]
94
- end
95
-
96
- # get month number
97
- def self.month_num(str)
98
- (@month_num ||= {
99
- "jan" => 1, "january" => 1, "jul" => 7, "july" => 7,
100
- "feb" => 2, "february" => 2, "aug" => 8, "august" => 8,
101
- "mar" => 3, "march" => 3, "sep" => 9, "septmeber" => 9,
102
- "apr" => 4, "april" => 4, "oct" => 10, "october" => 10,
103
- "may" => 5, "nov" => 11, "november" => 11,
104
- "jun" => 6, "june" => 6, "dec" => 12, "december" => 12,
105
- })[str.downcase] or raise "bad month: #{str}"
94
+ [ymd, hms, off]
106
95
  end
107
96
 
108
- # parse time and honor desired timezone
109
- def self.to_tz(str, zone=nil, ignore_offset=false)
110
- ymd, hms, off = parse_str(str, ignore_offset)
111
- out = Time.new(*ymd, *hms, off)
112
- if zone
113
- if off
114
- out = out.to_tz(zone)
115
- else
116
- utc = out.utc
117
- off = TZInfo::Timezone.get(zone).utc_to_local(utc) - utc
118
- out = Time.new(*ymd, *hms, off)
119
- end
120
- else
121
- out
122
- end
97
+ def self.tz(str, toz=nil, asz=nil)
98
+ ymd, hms, off = parse_str(str)
99
+ out = Time.new(*ymd, *hms, asz ? TZInfo::Timezone.get(asz) : off)
100
+ toz ? out.to(toz) : out
123
101
  end
124
102
 
125
- # ignore supplied timezone, use local
126
- def self.to_tz!(str, zone=nil)
127
- to_tz(str, zone, true)
103
+ def self.tz!(str, asz="UTC", toz=nil)
104
+ tz(str, toz, asz)
128
105
  end
129
106
 
130
- # NOTE: We can clean this up too...
131
- # this 1-liner works, but returns a TZInfo::TimeWithOffset???
132
- # def in_tz(zone); TZInfo::Timezone.get(zone).to_local(self); end
133
-
134
- # same time moment, different time zone offset
135
- def in_tz(zone)
107
+ # same time moment, different time zone (ie - change time and zone)
108
+ def to(zone)
136
109
  cfg = TZInfo::Timezone.get(zone)
137
110
  use = cfg.to_local(self)
138
111
  ary = use.to_a[1,5].reverse.push(strftime("%S.%6N").to_f)
139
112
  Time.new(*ary, cfg)
140
113
  end
141
114
 
142
- # same time values, different time zone offset
143
- def as_tz(zone)
115
+ # same time values, different time zone (ie - change time zone only)
116
+ def as(zone)
144
117
  cfg = TZInfo::Timezone.get(zone)
145
118
  use = self
146
119
  ary = use.to_a[1,5].reverse.push(strftime("%S.%6N").to_f)
147
120
  Time.new(*ary, cfg)
148
121
  end
149
-
150
- alias_method :to_tz , :in_tz
151
- alias_method :to_tz!, :as_tz
152
122
  end
153
123
 
154
124
  class String
155
- def to_tz(*args)
156
- Time.to_tz(self, *args)
125
+ def to_day
126
+ Date.to_day(self)
157
127
  end
158
128
 
159
- def to_tz!(*args)
160
- Time.to_tz!(self, *args)
129
+ def iso_date(fmt="%Y-%m-%d")
130
+ to_day.strftime(fmt)
161
131
  end
162
132
 
163
- def to_day
164
- Date.to_day(self)
133
+ def to_tz(*args)
134
+ Time.tz(self, *args)
165
135
  end
166
136
 
167
- def to_day!(fmt="%Y-%m-%d")
168
- to_day.strftime(fmt)
137
+ def to_tz!(*args)
138
+ Time.tz!(self, *args)
169
139
  end
170
140
  end
data/zones.gemspec CHANGED
@@ -1,12 +1,10 @@
1
- # encoding: utf-8
2
-
3
1
  Gem::Specification.new do |s|
4
2
  s.name = "zones"
5
- s.version = "0.6.2"
3
+ s.version = "1.0.1"
6
4
  s.author = "Steve Shreeve"
7
5
  s.email = "steve.shreeve@gmail.com"
8
- s.summary = "Easy time parsing and conversion between time zones"
9
- s.description = "This gem makes it easy to work with time zones."
6
+ s.summary =
7
+ s.description = "A friendly Ruby gem for time parsing and time zone conversion"
10
8
  s.homepage = "https://github.com/shreeve/zones"
11
9
  s.license = "MIT"
12
10
  s.files = `git ls-files`.split("\n") - %w[.gitignore]
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zones
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Shreeve
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-06-27 00:00:00.000000000 Z
11
+ date: 2023-06-29 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: This gem makes it easy to work with time zones.
13
+ description: A friendly Ruby gem for time parsing and time zone conversion
14
14
  email: steve.shreeve@gmail.com
15
15
  executables: []
16
16
  extensions: []
@@ -43,5 +43,5 @@ requirements: []
43
43
  rubygems_version: 3.4.14
44
44
  signing_key:
45
45
  specification_version: 4
46
- summary: Easy time parsing and conversion between time zones
46
+ summary: A friendly Ruby gem for time parsing and time zone conversion
47
47
  test_files: []