time 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c47638cb2be498039f169a0ce7d6a27fd2b80a92bd146851ba2331a94ad275ed
4
+ data.tar.gz: 606dc87c28c5dfbedee0e6742ab5f33b2189484e1ab0109ffb16896fe6a4ddaf
5
+ SHA512:
6
+ metadata.gz: 0000daa2037422789d66429c2b6b923421df025f9ee7283bba89f7452cb929dadc3cd9b09d231ff0d61a9b2f32ce8fba814e35eeeccf2c8a669f244682012929
7
+ data.tar.gz: 6523a7756bb65cac7e1981c5632804e82fc392f1db5ae1e61ba34025f826c79477faeb2700c5b6bcd0cb1be7ad53ddaafde61dba276ad393246eb33ad6b43093
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in time.gemspec
4
+ gemspec
5
+
6
+ gem "rake", "~> 12.0"
7
+ gem "minitest", "~> 5.0"
@@ -0,0 +1,22 @@
1
+ Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions
5
+ are met:
6
+ 1. Redistributions of source code must retain the above copyright
7
+ notice, this list of conditions and the following disclaimer.
8
+ 2. Redistributions in binary form must reproduce the above copyright
9
+ notice, this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
11
+
12
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
16
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22
+ SUCH DAMAGE.
@@ -0,0 +1,54 @@
1
+ # Time
2
+
3
+ When 'time' is required, Time is extended with additional methods for parsing
4
+ and converting Times.
5
+
6
+ ## Features
7
+
8
+ This library extends the Time class with the following conversions between
9
+ date strings and Time objects:
10
+
11
+ * date-time defined by {RFC 2822}[http://www.ietf.org/rfc/rfc2822.txt]
12
+ * HTTP-date defined by {RFC 2616}[http://www.ietf.org/rfc/rfc2616.txt]
13
+ * dateTime defined by XML Schema Part 2: Datatypes ({ISO
14
+ 8601}[http://www.iso.org/iso/date_and_time_format])
15
+ * various formats handled by Date._parse
16
+ * custom formats handled by Date._strptime
17
+
18
+ ## Installation
19
+
20
+ Add this line to your application's Gemfile:
21
+
22
+ ```ruby
23
+ gem 'time'
24
+ ```
25
+
26
+ And then execute:
27
+
28
+ $ bundle install
29
+
30
+ Or install it yourself as:
31
+
32
+ $ gem install time
33
+
34
+ ## Usage
35
+
36
+ Takes a string representation of a Time and attempts to parse it
37
+ using a heuristic.
38
+
39
+ ```ruby
40
+ require 'time'
41
+
42
+ Time.parse("2010-10-31") #=> 2010-10-31 00:00:00 -0500
43
+ ```
44
+
45
+ ## Development
46
+
47
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
48
+
49
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
50
+
51
+ ## Contributing
52
+
53
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/time.
54
+
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "time"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,745 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+
5
+ # :stopdoc:
6
+
7
+ # = time.rb
8
+ #
9
+ # When 'time' is required, Time is extended with additional methods for parsing
10
+ # and converting Times.
11
+ #
12
+ # == Features
13
+ #
14
+ # This library extends the Time class with the following conversions between
15
+ # date strings and Time objects:
16
+ #
17
+ # * date-time defined by {RFC 2822}[http://www.ietf.org/rfc/rfc2822.txt]
18
+ # * HTTP-date defined by {RFC 2616}[http://www.ietf.org/rfc/rfc2616.txt]
19
+ # * dateTime defined by XML Schema Part 2: Datatypes ({ISO
20
+ # 8601}[http://www.iso.org/iso/date_and_time_format])
21
+ # * various formats handled by Date._parse
22
+ # * custom formats handled by Date._strptime
23
+
24
+ # :startdoc:
25
+
26
+ class Time
27
+ class << Time
28
+
29
+ #
30
+ # A hash of timezones mapped to hour differences from UTC. The
31
+ # set of time zones corresponds to the ones specified by RFC 2822
32
+ # and ISO 8601.
33
+ #
34
+ ZoneOffset = { # :nodoc:
35
+ 'UTC' => 0,
36
+ # ISO 8601
37
+ 'Z' => 0,
38
+ # RFC 822
39
+ 'UT' => 0, 'GMT' => 0,
40
+ 'EST' => -5, 'EDT' => -4,
41
+ 'CST' => -6, 'CDT' => -5,
42
+ 'MST' => -7, 'MDT' => -6,
43
+ 'PST' => -8, 'PDT' => -7,
44
+ # Following definition of military zones is original one.
45
+ # See RFC 1123 and RFC 2822 for the error in RFC 822.
46
+ 'A' => +1, 'B' => +2, 'C' => +3, 'D' => +4, 'E' => +5, 'F' => +6,
47
+ 'G' => +7, 'H' => +8, 'I' => +9, 'K' => +10, 'L' => +11, 'M' => +12,
48
+ 'N' => -1, 'O' => -2, 'P' => -3, 'Q' => -4, 'R' => -5, 'S' => -6,
49
+ 'T' => -7, 'U' => -8, 'V' => -9, 'W' => -10, 'X' => -11, 'Y' => -12,
50
+ }
51
+
52
+ #
53
+ # Return the number of seconds the specified time zone differs
54
+ # from UTC.
55
+ #
56
+ # Numeric time zones that include minutes, such as
57
+ # <code>-10:00</code> or <code>+1330</code> will work, as will
58
+ # simpler hour-only time zones like <code>-10</code> or
59
+ # <code>+13</code>.
60
+ #
61
+ # Textual time zones listed in ZoneOffset are also supported.
62
+ #
63
+ # If the time zone does not match any of the above, +zone_offset+
64
+ # will check if the local time zone (both with and without
65
+ # potential Daylight Saving \Time changes being in effect) matches
66
+ # +zone+. Specifying a value for +year+ will change the year used
67
+ # to find the local time zone.
68
+ #
69
+ # If +zone_offset+ is unable to determine the offset, nil will be
70
+ # returned.
71
+ #
72
+ # require 'time'
73
+ #
74
+ # Time.zone_offset("EST") #=> -18000
75
+ #
76
+ # You must require 'time' to use this method.
77
+ #
78
+ def zone_offset(zone, year=self.now.year)
79
+ off = nil
80
+ zone = zone.upcase
81
+ if /\A([+-])(\d\d)(:?)(\d\d)(?:\3(\d\d))?\z/ =~ zone
82
+ off = ($1 == '-' ? -1 : 1) * (($2.to_i * 60 + $4.to_i) * 60 + $5.to_i)
83
+ elsif zone.match?(/\A[+-]\d\d\z/)
84
+ off = zone.to_i * 3600
85
+ elsif ZoneOffset.include?(zone)
86
+ off = ZoneOffset[zone] * 3600
87
+ elsif ((t = self.local(year, 1, 1)).zone.upcase == zone rescue false)
88
+ off = t.utc_offset
89
+ elsif ((t = self.local(year, 7, 1)).zone.upcase == zone rescue false)
90
+ off = t.utc_offset
91
+ end
92
+ off
93
+ end
94
+
95
+ def zone_utc?(zone)
96
+ # * +0000
97
+ # In RFC 2822, +0000 indicate a time zone at Universal Time.
98
+ # Europe/Lisbon is "a time zone at Universal Time" in Winter.
99
+ # Atlantic/Reykjavik is "a time zone at Universal Time".
100
+ # Africa/Dakar is "a time zone at Universal Time".
101
+ # So +0000 is a local time such as Europe/London, etc.
102
+ # * GMT
103
+ # GMT is used as a time zone abbreviation in Europe/London,
104
+ # Africa/Dakar, etc.
105
+ # So it is a local time.
106
+ #
107
+ # * -0000, -00:00
108
+ # In RFC 2822, -0000 the date-time contains no information about the
109
+ # local time zone.
110
+ # In RFC 3339, -00:00 is used for the time in UTC is known,
111
+ # but the offset to local time is unknown.
112
+ # They are not appropriate for specific time zone such as
113
+ # Europe/London because time zone neutral,
114
+ # So -00:00 and -0000 are treated as UTC.
115
+ zone.match?(/\A(?:-00:00|-0000|-00|UTC|Z|UT)\z/i)
116
+ end
117
+ private :zone_utc?
118
+
119
+ def force_zone!(t, zone, offset=nil)
120
+ if zone_utc?(zone)
121
+ t.utc
122
+ elsif offset ||= zone_offset(zone)
123
+ # Prefer the local timezone over the fixed offset timezone because
124
+ # the former is a real timezone and latter is an artificial timezone.
125
+ t.localtime
126
+ if t.utc_offset != offset
127
+ # Use the fixed offset timezone only if the local timezone cannot
128
+ # represent the given offset.
129
+ t.localtime(offset)
130
+ end
131
+ else
132
+ t.localtime
133
+ end
134
+ end
135
+ private :force_zone!
136
+
137
+ LeapYearMonthDays = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] # :nodoc:
138
+ CommonYearMonthDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] # :nodoc:
139
+ def month_days(y, m)
140
+ if ((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0)
141
+ LeapYearMonthDays[m-1]
142
+ else
143
+ CommonYearMonthDays[m-1]
144
+ end
145
+ end
146
+ private :month_days
147
+
148
+ def apply_offset(year, mon, day, hour, min, sec, off)
149
+ if off < 0
150
+ off = -off
151
+ off, o = off.divmod(60)
152
+ if o != 0 then sec += o; o, sec = sec.divmod(60); off += o end
153
+ off, o = off.divmod(60)
154
+ if o != 0 then min += o; o, min = min.divmod(60); off += o end
155
+ off, o = off.divmod(24)
156
+ if o != 0 then hour += o; o, hour = hour.divmod(24); off += o end
157
+ if off != 0
158
+ day += off
159
+ days = month_days(year, mon)
160
+ if days and days < day
161
+ mon += 1
162
+ if 12 < mon
163
+ mon = 1
164
+ year += 1
165
+ end
166
+ day = 1
167
+ end
168
+ end
169
+ elsif 0 < off
170
+ off, o = off.divmod(60)
171
+ if o != 0 then sec -= o; o, sec = sec.divmod(60); off -= o end
172
+ off, o = off.divmod(60)
173
+ if o != 0 then min -= o; o, min = min.divmod(60); off -= o end
174
+ off, o = off.divmod(24)
175
+ if o != 0 then hour -= o; o, hour = hour.divmod(24); off -= o end
176
+ if off != 0 then
177
+ day -= off
178
+ if day < 1
179
+ mon -= 1
180
+ if mon < 1
181
+ year -= 1
182
+ mon = 12
183
+ end
184
+ day = month_days(year, mon)
185
+ end
186
+ end
187
+ end
188
+ return year, mon, day, hour, min, sec
189
+ end
190
+ private :apply_offset
191
+
192
+ def make_time(date, year, yday, mon, day, hour, min, sec, sec_fraction, zone, now)
193
+ if !year && !yday && !mon && !day && !hour && !min && !sec && !sec_fraction
194
+ raise ArgumentError, "no time information in #{date.inspect}"
195
+ end
196
+
197
+ off = nil
198
+ if year || now
199
+ off_year = year || now.year
200
+ off = zone_offset(zone, off_year) if zone
201
+ end
202
+
203
+ if yday
204
+ unless (1..366) === yday
205
+ raise ArgumentError, "yday #{yday} out of range"
206
+ end
207
+ mon, day = (yday-1).divmod(31)
208
+ mon += 1
209
+ day += 1
210
+ t = make_time(date, year, nil, mon, day, hour, min, sec, sec_fraction, zone, now)
211
+ diff = yday - t.yday
212
+ return t if diff.zero?
213
+ day += diff
214
+ if day > 28 and day > (mday = month_days(off_year, mon))
215
+ if (mon += 1) > 12
216
+ raise ArgumentError, "yday #{yday} out of range"
217
+ end
218
+ day -= mday
219
+ end
220
+ return make_time(date, year, nil, mon, day, hour, min, sec, sec_fraction, zone, now)
221
+ end
222
+
223
+ if now and now.respond_to?(:getlocal)
224
+ if off
225
+ now = now.getlocal(off) if now.utc_offset != off
226
+ else
227
+ now = now.getlocal
228
+ end
229
+ end
230
+
231
+ usec = nil
232
+ usec = sec_fraction * 1000000 if sec_fraction
233
+
234
+ if now
235
+ begin
236
+ break if year; year = now.year
237
+ break if mon; mon = now.mon
238
+ break if day; day = now.day
239
+ break if hour; hour = now.hour
240
+ break if min; min = now.min
241
+ break if sec; sec = now.sec
242
+ break if sec_fraction; usec = now.tv_usec
243
+ end until true
244
+ end
245
+
246
+ year ||= 1970
247
+ mon ||= 1
248
+ day ||= 1
249
+ hour ||= 0
250
+ min ||= 0
251
+ sec ||= 0
252
+ usec ||= 0
253
+
254
+ if year != off_year
255
+ off = nil
256
+ off = zone_offset(zone, year) if zone
257
+ end
258
+
259
+ if off
260
+ year, mon, day, hour, min, sec =
261
+ apply_offset(year, mon, day, hour, min, sec, off)
262
+ t = self.utc(year, mon, day, hour, min, sec, usec)
263
+ force_zone!(t, zone, off)
264
+ t
265
+ else
266
+ self.local(year, mon, day, hour, min, sec, usec)
267
+ end
268
+ end
269
+ private :make_time
270
+
271
+ #
272
+ # Takes a string representation of a Time and attempts to parse it
273
+ # using a heuristic.
274
+ #
275
+ # This method **does not** function as a validator. If the input
276
+ # string does not match valid formats strictly, you may get a
277
+ # cryptic result. Should consider to use `Time.strptime` instead
278
+ # of this method as possible.
279
+ #
280
+ # require 'time'
281
+ #
282
+ # Time.parse("2010-10-31") #=> 2010-10-31 00:00:00 -0500
283
+ #
284
+ # Any missing pieces of the date are inferred based on the current date.
285
+ #
286
+ # require 'time'
287
+ #
288
+ # # assuming the current date is "2011-10-31"
289
+ # Time.parse("12:00") #=> 2011-10-31 12:00:00 -0500
290
+ #
291
+ # We can change the date used to infer our missing elements by passing a second
292
+ # object that responds to #mon, #day and #year, such as Date, Time or DateTime.
293
+ # We can also use our own object.
294
+ #
295
+ # require 'time'
296
+ #
297
+ # class MyDate
298
+ # attr_reader :mon, :day, :year
299
+ #
300
+ # def initialize(mon, day, year)
301
+ # @mon, @day, @year = mon, day, year
302
+ # end
303
+ # end
304
+ #
305
+ # d = Date.parse("2010-10-28")
306
+ # t = Time.parse("2010-10-29")
307
+ # dt = DateTime.parse("2010-10-30")
308
+ # md = MyDate.new(10,31,2010)
309
+ #
310
+ # Time.parse("12:00", d) #=> 2010-10-28 12:00:00 -0500
311
+ # Time.parse("12:00", t) #=> 2010-10-29 12:00:00 -0500
312
+ # Time.parse("12:00", dt) #=> 2010-10-30 12:00:00 -0500
313
+ # Time.parse("12:00", md) #=> 2010-10-31 12:00:00 -0500
314
+ #
315
+ # If a block is given, the year described in +date+ is converted
316
+ # by the block. This is specifically designed for handling two
317
+ # digit years. For example, if you wanted to treat all two digit
318
+ # years prior to 70 as the year 2000+ you could write this:
319
+ #
320
+ # require 'time'
321
+ #
322
+ # Time.parse("01-10-31") {|year| year + (year < 70 ? 2000 : 1900)}
323
+ # #=> 2001-10-31 00:00:00 -0500
324
+ # Time.parse("70-10-31") {|year| year + (year < 70 ? 2000 : 1900)}
325
+ # #=> 1970-10-31 00:00:00 -0500
326
+ #
327
+ # If the upper components of the given time are broken or missing, they are
328
+ # supplied with those of +now+. For the lower components, the minimum
329
+ # values (1 or 0) are assumed if broken or missing. For example:
330
+ #
331
+ # require 'time'
332
+ #
333
+ # # Suppose it is "Thu Nov 29 14:33:20 2001" now and
334
+ # # your time zone is EST which is GMT-5.
335
+ # now = Time.parse("Thu Nov 29 14:33:20 2001")
336
+ # Time.parse("16:30", now) #=> 2001-11-29 16:30:00 -0500
337
+ # Time.parse("7/23", now) #=> 2001-07-23 00:00:00 -0500
338
+ # Time.parse("Aug 31", now) #=> 2001-08-31 00:00:00 -0500
339
+ # Time.parse("Aug 2000", now) #=> 2000-08-01 00:00:00 -0500
340
+ #
341
+ # Since there are numerous conflicts among locally defined time zone
342
+ # abbreviations all over the world, this method is not intended to
343
+ # understand all of them. For example, the abbreviation "CST" is
344
+ # used variously as:
345
+ #
346
+ # -06:00 in America/Chicago,
347
+ # -05:00 in America/Havana,
348
+ # +08:00 in Asia/Harbin,
349
+ # +09:30 in Australia/Darwin,
350
+ # +10:30 in Australia/Adelaide,
351
+ # etc.
352
+ #
353
+ # Based on this fact, this method only understands the time zone
354
+ # abbreviations described in RFC 822 and the system time zone, in the
355
+ # order named. (i.e. a definition in RFC 822 overrides the system
356
+ # time zone definition.) The system time zone is taken from
357
+ # <tt>Time.local(year, 1, 1).zone</tt> and
358
+ # <tt>Time.local(year, 7, 1).zone</tt>.
359
+ # If the extracted time zone abbreviation does not match any of them,
360
+ # it is ignored and the given time is regarded as a local time.
361
+ #
362
+ # ArgumentError is raised if Date._parse cannot extract information from
363
+ # +date+ or if the Time class cannot represent specified date.
364
+ #
365
+ # This method can be used as a fail-safe for other parsing methods as:
366
+ #
367
+ # Time.rfc2822(date) rescue Time.parse(date)
368
+ # Time.httpdate(date) rescue Time.parse(date)
369
+ # Time.xmlschema(date) rescue Time.parse(date)
370
+ #
371
+ # A failure of Time.parse should be checked, though.
372
+ #
373
+ # You must require 'time' to use this method.
374
+ #
375
+ def parse(date, now=self.now)
376
+ comp = !block_given?
377
+ d = Date._parse(date, comp)
378
+ year = d[:year]
379
+ year = yield(year) if year && !comp
380
+ make_time(date, year, d[:yday], d[:mon], d[:mday], d[:hour], d[:min], d[:sec], d[:sec_fraction], d[:zone], now)
381
+ end
382
+
383
+ #
384
+ # Works similar to +parse+ except that instead of using a
385
+ # heuristic to detect the format of the input string, you provide
386
+ # a second argument that describes the format of the string.
387
+ #
388
+ # If a block is given, the year described in +date+ is converted by the
389
+ # block. For example:
390
+ #
391
+ # Time.strptime(...) {|y| y < 100 ? (y >= 69 ? y + 1900 : y + 2000) : y}
392
+ #
393
+ # Below is a list of the formatting options:
394
+ #
395
+ # %a :: The abbreviated weekday name ("Sun")
396
+ # %A :: The full weekday name ("Sunday")
397
+ # %b :: The abbreviated month name ("Jan")
398
+ # %B :: The full month name ("January")
399
+ # %c :: The preferred local date and time representation
400
+ # %C :: Century (20 in 2009)
401
+ # %d :: Day of the month (01..31)
402
+ # %D :: Date (%m/%d/%y)
403
+ # %e :: Day of the month, blank-padded ( 1..31)
404
+ # %F :: Equivalent to %Y-%m-%d (the ISO 8601 date format)
405
+ # %g :: The last two digits of the commercial year
406
+ # %G :: The week-based year according to ISO-8601 (week 1 starts on Monday
407
+ # and includes January 4)
408
+ # %h :: Equivalent to %b
409
+ # %H :: Hour of the day, 24-hour clock (00..23)
410
+ # %I :: Hour of the day, 12-hour clock (01..12)
411
+ # %j :: Day of the year (001..366)
412
+ # %k :: hour, 24-hour clock, blank-padded ( 0..23)
413
+ # %l :: hour, 12-hour clock, blank-padded ( 0..12)
414
+ # %L :: Millisecond of the second (000..999)
415
+ # %m :: Month of the year (01..12)
416
+ # %M :: Minute of the hour (00..59)
417
+ # %n :: Newline (\n)
418
+ # %N :: Fractional seconds digits
419
+ # %p :: Meridian indicator ("AM" or "PM")
420
+ # %P :: Meridian indicator ("am" or "pm")
421
+ # %r :: time, 12-hour (same as %I:%M:%S %p)
422
+ # %R :: time, 24-hour (%H:%M)
423
+ # %s :: Number of seconds since 1970-01-01 00:00:00 UTC.
424
+ # %S :: Second of the minute (00..60)
425
+ # %t :: Tab character (\t)
426
+ # %T :: time, 24-hour (%H:%M:%S)
427
+ # %u :: Day of the week as a decimal, Monday being 1. (1..7)
428
+ # %U :: Week number of the current year, starting with the first Sunday as
429
+ # the first day of the first week (00..53)
430
+ # %v :: VMS date (%e-%b-%Y)
431
+ # %V :: Week number of year according to ISO 8601 (01..53)
432
+ # %W :: Week number of the current year, starting with the first Monday
433
+ # as the first day of the first week (00..53)
434
+ # %w :: Day of the week (Sunday is 0, 0..6)
435
+ # %x :: Preferred representation for the date alone, no time
436
+ # %X :: Preferred representation for the time alone, no date
437
+ # %y :: Year without a century (00..99)
438
+ # %Y :: Year which may include century, if provided
439
+ # %z :: Time zone as hour offset from UTC (e.g. +0900)
440
+ # %Z :: Time zone name
441
+ # %% :: Literal "%" character
442
+ # %+ :: date(1) (%a %b %e %H:%M:%S %Z %Y)
443
+ #
444
+ # require 'time'
445
+ #
446
+ # Time.strptime("2000-10-31", "%Y-%m-%d") #=> 2000-10-31 00:00:00 -0500
447
+ #
448
+ # You must require 'time' to use this method.
449
+ #
450
+ def strptime(date, format, now=self.now)
451
+ d = Date._strptime(date, format)
452
+ raise ArgumentError, "invalid date or strptime format - `#{date}' `#{format}'" unless d
453
+ if seconds = d[:seconds]
454
+ if sec_fraction = d[:sec_fraction]
455
+ usec = sec_fraction * 1000000
456
+ usec *= -1 if seconds < 0
457
+ else
458
+ usec = 0
459
+ end
460
+ t = Time.at(seconds, usec)
461
+ if zone = d[:zone]
462
+ force_zone!(t, zone)
463
+ end
464
+ else
465
+ year = d[:year]
466
+ year = yield(year) if year && block_given?
467
+ yday = d[:yday]
468
+ if (d[:cwyear] && !year) || ((d[:cwday] || d[:cweek]) && !(d[:mon] && d[:mday]))
469
+ # make_time doesn't deal with cwyear/cwday/cweek
470
+ return Date.strptime(date, format).to_time
471
+ end
472
+ if (d[:wnum0] || d[:wnum1]) && !yday && !(d[:mon] && d[:mday])
473
+ yday = Date.strptime(date, format).yday
474
+ end
475
+ t = make_time(date, year, yday, d[:mon], d[:mday], d[:hour], d[:min], d[:sec], d[:sec_fraction], d[:zone], now)
476
+ end
477
+ t
478
+ end
479
+
480
+ MonthValue = { # :nodoc:
481
+ 'JAN' => 1, 'FEB' => 2, 'MAR' => 3, 'APR' => 4, 'MAY' => 5, 'JUN' => 6,
482
+ 'JUL' => 7, 'AUG' => 8, 'SEP' => 9, 'OCT' =>10, 'NOV' =>11, 'DEC' =>12
483
+ }
484
+
485
+ #
486
+ # Parses +date+ as date-time defined by RFC 2822 and converts it to a Time
487
+ # object. The format is identical to the date format defined by RFC 822 and
488
+ # updated by RFC 1123.
489
+ #
490
+ # ArgumentError is raised if +date+ is not compliant with RFC 2822
491
+ # or if the Time class cannot represent specified date.
492
+ #
493
+ # See #rfc2822 for more information on this format.
494
+ #
495
+ # require 'time'
496
+ #
497
+ # Time.rfc2822("Wed, 05 Oct 2011 22:26:12 -0400")
498
+ # #=> 2010-10-05 22:26:12 -0400
499
+ #
500
+ # You must require 'time' to use this method.
501
+ #
502
+ def rfc2822(date)
503
+ if /\A\s*
504
+ (?:(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)\s*,\s*)?
505
+ (\d{1,2})\s+
506
+ (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+
507
+ (\d{2,})\s+
508
+ (\d{2})\s*
509
+ :\s*(\d{2})\s*
510
+ (?::\s*(\d{2}))?\s+
511
+ ([+-]\d{4}|
512
+ UT|GMT|EST|EDT|CST|CDT|MST|MDT|PST|PDT|[A-IK-Z])/ix =~ date
513
+ # Since RFC 2822 permit comments, the regexp has no right anchor.
514
+ day = $1.to_i
515
+ mon = MonthValue[$2.upcase]
516
+ year = $3.to_i
517
+ short_year_p = $3.length <= 3
518
+ hour = $4.to_i
519
+ min = $5.to_i
520
+ sec = $6 ? $6.to_i : 0
521
+ zone = $7
522
+
523
+ if short_year_p
524
+ # following year completion is compliant with RFC 2822.
525
+ year = if year < 50
526
+ 2000 + year
527
+ else
528
+ 1900 + year
529
+ end
530
+ end
531
+
532
+ off = zone_offset(zone)
533
+ year, mon, day, hour, min, sec =
534
+ apply_offset(year, mon, day, hour, min, sec, off)
535
+ t = self.utc(year, mon, day, hour, min, sec)
536
+ force_zone!(t, zone, off)
537
+ t
538
+ else
539
+ raise ArgumentError.new("not RFC 2822 compliant date: #{date.inspect}")
540
+ end
541
+ end
542
+ alias rfc822 rfc2822
543
+
544
+ #
545
+ # Parses +date+ as an HTTP-date defined by RFC 2616 and converts it to a
546
+ # Time object.
547
+ #
548
+ # ArgumentError is raised if +date+ is not compliant with RFC 2616 or if
549
+ # the Time class cannot represent specified date.
550
+ #
551
+ # See #httpdate for more information on this format.
552
+ #
553
+ # require 'time'
554
+ #
555
+ # Time.httpdate("Thu, 06 Oct 2011 02:26:12 GMT")
556
+ # #=> 2011-10-06 02:26:12 UTC
557
+ #
558
+ # You must require 'time' to use this method.
559
+ #
560
+ def httpdate(date)
561
+ if date.match?(/\A\s*
562
+ (?:Mon|Tue|Wed|Thu|Fri|Sat|Sun),\x20
563
+ (\d{2})\x20
564
+ (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\x20
565
+ (\d{4})\x20
566
+ (\d{2}):(\d{2}):(\d{2})\x20
567
+ GMT
568
+ \s*\z/ix)
569
+ self.rfc2822(date).utc
570
+ elsif /\A\s*
571
+ (?:Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday),\x20
572
+ (\d\d)-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(\d\d)\x20
573
+ (\d\d):(\d\d):(\d\d)\x20
574
+ GMT
575
+ \s*\z/ix =~ date
576
+ year = $3.to_i
577
+ if year < 50
578
+ year += 2000
579
+ else
580
+ year += 1900
581
+ end
582
+ self.utc(year, $2, $1.to_i, $4.to_i, $5.to_i, $6.to_i)
583
+ elsif /\A\s*
584
+ (?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)\x20
585
+ (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\x20
586
+ (\d\d|\x20\d)\x20
587
+ (\d\d):(\d\d):(\d\d)\x20
588
+ (\d{4})
589
+ \s*\z/ix =~ date
590
+ self.utc($6.to_i, MonthValue[$1.upcase], $2.to_i,
591
+ $3.to_i, $4.to_i, $5.to_i)
592
+ else
593
+ raise ArgumentError.new("not RFC 2616 compliant date: #{date.inspect}")
594
+ end
595
+ end
596
+
597
+ #
598
+ # Parses +time+ as a dateTime defined by the XML Schema and converts it to
599
+ # a Time object. The format is a restricted version of the format defined
600
+ # by ISO 8601.
601
+ #
602
+ # ArgumentError is raised if +time+ is not compliant with the format or if
603
+ # the Time class cannot represent the specified time.
604
+ #
605
+ # See #xmlschema for more information on this format.
606
+ #
607
+ # require 'time'
608
+ #
609
+ # Time.xmlschema("2011-10-05T22:26:12-04:00")
610
+ # #=> 2011-10-05 22:26:12-04:00
611
+ #
612
+ # You must require 'time' to use this method.
613
+ #
614
+ def xmlschema(time)
615
+ if /\A\s*
616
+ (-?\d+)-(\d\d)-(\d\d)
617
+ T
618
+ (\d\d):(\d\d):(\d\d)
619
+ (\.\d+)?
620
+ (Z|[+-]\d\d(?::?\d\d)?)?
621
+ \s*\z/ix =~ time
622
+ year = $1.to_i
623
+ mon = $2.to_i
624
+ day = $3.to_i
625
+ hour = $4.to_i
626
+ min = $5.to_i
627
+ sec = $6.to_i
628
+ usec = 0
629
+ if $7
630
+ usec = Rational($7) * 1000000
631
+ end
632
+ if $8
633
+ zone = $8
634
+ off = zone_offset(zone)
635
+ year, mon, day, hour, min, sec =
636
+ apply_offset(year, mon, day, hour, min, sec, off)
637
+ t = self.utc(year, mon, day, hour, min, sec, usec)
638
+ force_zone!(t, zone, off)
639
+ t
640
+ else
641
+ self.local(year, mon, day, hour, min, sec, usec)
642
+ end
643
+ else
644
+ raise ArgumentError.new("invalid xmlschema format: #{time.inspect}")
645
+ end
646
+ end
647
+ alias iso8601 xmlschema
648
+ end # class << self
649
+
650
+ #
651
+ # Returns a string which represents the time as date-time defined by RFC 2822:
652
+ #
653
+ # day-of-week, DD month-name CCYY hh:mm:ss zone
654
+ #
655
+ # where zone is [+-]hhmm.
656
+ #
657
+ # If +self+ is a UTC time, -0000 is used as zone.
658
+ #
659
+ # require 'time'
660
+ #
661
+ # t = Time.now
662
+ # t.rfc2822 # => "Wed, 05 Oct 2011 22:26:12 -0400"
663
+ #
664
+ # You must require 'time' to use this method.
665
+ #
666
+ def rfc2822
667
+ sprintf('%s, %02d %s %0*d %02d:%02d:%02d ',
668
+ RFC2822_DAY_NAME[wday],
669
+ day, RFC2822_MONTH_NAME[mon-1], year < 0 ? 5 : 4, year,
670
+ hour, min, sec) <<
671
+ if utc?
672
+ '-0000'
673
+ else
674
+ off = utc_offset
675
+ sign = off < 0 ? '-' : '+'
676
+ sprintf('%s%02d%02d', sign, *(off.abs / 60).divmod(60))
677
+ end
678
+ end
679
+ alias rfc822 rfc2822
680
+
681
+
682
+ RFC2822_DAY_NAME = [ # :nodoc:
683
+ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'
684
+ ]
685
+
686
+ RFC2822_MONTH_NAME = [ # :nodoc:
687
+ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
688
+ 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
689
+ ]
690
+
691
+ #
692
+ # Returns a string which represents the time as RFC 1123 date of HTTP-date
693
+ # defined by RFC 2616:
694
+ #
695
+ # day-of-week, DD month-name CCYY hh:mm:ss GMT
696
+ #
697
+ # Note that the result is always UTC (GMT).
698
+ #
699
+ # require 'time'
700
+ #
701
+ # t = Time.now
702
+ # t.httpdate # => "Thu, 06 Oct 2011 02:26:12 GMT"
703
+ #
704
+ # You must require 'time' to use this method.
705
+ #
706
+ def httpdate
707
+ t = dup.utc
708
+ sprintf('%s, %02d %s %0*d %02d:%02d:%02d GMT',
709
+ RFC2822_DAY_NAME[t.wday],
710
+ t.day, RFC2822_MONTH_NAME[t.mon-1], t.year < 0 ? 5 : 4, t.year,
711
+ t.hour, t.min, t.sec)
712
+ end
713
+
714
+ #
715
+ # Returns a string which represents the time as a dateTime defined by XML
716
+ # Schema:
717
+ #
718
+ # CCYY-MM-DDThh:mm:ssTZD
719
+ # CCYY-MM-DDThh:mm:ss.sssTZD
720
+ #
721
+ # where TZD is Z or [+-]hh:mm.
722
+ #
723
+ # If self is a UTC time, Z is used as TZD. [+-]hh:mm is used otherwise.
724
+ #
725
+ # +fractional_digits+ specifies a number of digits to use for fractional
726
+ # seconds. Its default value is 0.
727
+ #
728
+ # require 'time'
729
+ #
730
+ # t = Time.now
731
+ # t.iso8601 # => "2011-10-05T22:26:12-04:00"
732
+ #
733
+ # You must require 'time' to use this method.
734
+ #
735
+ def xmlschema(fraction_digits=0)
736
+ fraction_digits = fraction_digits.to_i
737
+ s = strftime("%FT%T")
738
+ if fraction_digits > 0
739
+ s << strftime(".%#{fraction_digits}N")
740
+ end
741
+ s << (utc? ? 'Z' : strftime("%:z"))
742
+ end
743
+ alias iso8601 xmlschema
744
+ end
745
+
@@ -0,0 +1,22 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = "time"
3
+ spec.version = "0.1.0"
4
+ spec.authors = ["Tanaka Akira"]
5
+ spec.email = ["akr@fsij.org"]
6
+
7
+ spec.summary = %q{Extends the Time class with methods for parsing and conversion.}
8
+ spec.description = %q{Extends the Time class with methods for parsing and conversion.}
9
+ spec.homepage = "https://github.com/ruby/time"
10
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
11
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
12
+
13
+ spec.metadata["homepage_uri"] = spec.homepage
14
+ spec.metadata["source_code_uri"] = spec.homepage
15
+
16
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
17
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ end
19
+ spec.bindir = "exe"
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ["lib"]
22
+ end
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: time
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Tanaka Akira
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-09-18 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Extends the Time class with methods for parsing and conversion.
14
+ email:
15
+ - akr@fsij.org
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".gitignore"
21
+ - Gemfile
22
+ - LICENSE.txt
23
+ - README.md
24
+ - Rakefile
25
+ - bin/console
26
+ - bin/setup
27
+ - lib/time.rb
28
+ - time.gemspec
29
+ homepage: https://github.com/ruby/time
30
+ licenses:
31
+ - Ruby
32
+ - BSD-2-Clause
33
+ metadata:
34
+ homepage_uri: https://github.com/ruby/time
35
+ source_code_uri: https://github.com/ruby/time
36
+ post_install_message:
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: 2.3.0
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ requirements: []
51
+ rubygems_version: 3.2.0.rc.1
52
+ signing_key:
53
+ specification_version: 4
54
+ summary: Extends the Time class with methods for parsing and conversion.
55
+ test_files: []