time 0.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of time might be problematic. Click here for more details.

@@ -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: []