motion-date 1.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 48fe60bbe3633e1c19e92ee31e4cbed921a05305
4
+ data.tar.gz: 5bcc8953e84c3f05f7628562e49516daae31d0c4
5
+ SHA512:
6
+ metadata.gz: 114e6ac4299bf9de860c723e0a92c13e1222effe40d253d8a28ec4303b39130cdd6187efbc380f47fd9f508f5ee8695d32d0e428690a6db786a02ea510dc88c8
7
+ data.tar.gz: abc018298a1f798ad00091ea6ec1b2f3df580cf3ef7761db00f24cdc817dcd39c73f87d289d752ef6538d8332101a7c8ca72d6f40b8a096cc60483eabfeb84fd
@@ -0,0 +1,40 @@
1
+ # motion-date
2
+
3
+ This is RubyMotion library which provides methods of Date/DateTime/Time which are same as CRuby Standard Library.
4
+ You can see APIs in http://ruby-doc.org/stdlib-2.2.2/libdoc/date/rdoc/index.html
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'motion-date'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install motion-date
19
+
20
+ ## Usage
21
+
22
+ ```
23
+ a = Date.new(1993, 2, 24)
24
+ b = Date.parse('1993-02-24')
25
+ b += 10
26
+
27
+ b - a #=> 10
28
+ b.year #=> 1993
29
+ b.strftime('%a') #=> "Sat"
30
+
31
+ yesterday = Date.today - 1
32
+ ```
33
+
34
+ ## Contributing
35
+
36
+ 1. Fork it
37
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
38
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
39
+ 4. Push to the branch (`git push origin my-new-feature`)
40
+ 5. Create new Pull Request
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+
3
+ unless defined?(Motion::Project::Config)
4
+ raise "This file must be required within a RubyMotion project Rakefile."
5
+ end
6
+
7
+ lib_dir_path = File.dirname(File.expand_path(__FILE__))
8
+ Motion::Project::App.setup do |app|
9
+ app.files.unshift(Dir.glob(File.join(lib_dir_path, "project/**/*.rb")))
10
+ end
@@ -0,0 +1,1845 @@
1
+ #
2
+ # date.rb - date and time library
3
+ #
4
+ # Author: Tadayoshi Funaba 1998-2011
5
+ #
6
+ # Documentation: William Webber <william@williamwebber.com>
7
+ #
8
+ #--
9
+ # $Id: date.rb,v 2.37 2008-01-17 20:16:31+09 tadf Exp $
10
+ #++
11
+ #
12
+ # == Overview
13
+ #
14
+ # This file provides two classes for working with
15
+ # dates and times.
16
+ #
17
+ # The first class, Date, represents dates.
18
+ # It works with years, months, weeks, and days.
19
+ # See the Date class documentation for more details.
20
+ #
21
+ # The second, DateTime, extends Date to include hours,
22
+ # minutes, seconds, and fractions of a second. It
23
+ # provides basic support for time zones. See the
24
+ # DateTime class documentation for more details.
25
+ #
26
+ # === Ways of calculating the date.
27
+ #
28
+ # In common usage, the date is reckoned in years since or
29
+ # before the Common Era (CE/BCE, also known as AD/BC), then
30
+ # as a month and day-of-the-month within the current year.
31
+ # This is known as the *Civil* *Date*, and abbreviated
32
+ # as +civil+ in the Date class.
33
+ #
34
+ # Instead of year, month-of-the-year, and day-of-the-month,
35
+ # the date can also be reckoned in terms of year and
36
+ # day-of-the-year. This is known as the *Ordinal* *Date*,
37
+ # and is abbreviated as +ordinal+ in the Date class. (Note
38
+ # that referring to this as the Julian date is incorrect.)
39
+ #
40
+ # The date can also be reckoned in terms of year, week-of-the-year,
41
+ # and day-of-the-week. This is known as the *Commercial*
42
+ # *Date*, and is abbreviated as +commercial+ in the
43
+ # Date class. The commercial week runs Monday (day-of-the-week
44
+ # 1) to Sunday (day-of-the-week 7), in contrast to the civil
45
+ # week which runs Sunday (day-of-the-week 0) to Saturday
46
+ # (day-of-the-week 6). The first week of the commercial year
47
+ # starts on the Monday on or before January 1, and the commercial
48
+ # year itself starts on this Monday, not January 1.
49
+ #
50
+ # For scientific purposes, it is convenient to refer to a date
51
+ # simply as a day count, counting from an arbitrary initial
52
+ # day. The date first chosen for this was January 1, 4713 BCE.
53
+ # A count of days from this date is the *Julian* *Day* *Number*
54
+ # or *Julian* *Date*, which is abbreviated as +jd+ in the
55
+ # Date class. This is in local time, and counts from midnight
56
+ # on the initial day. The stricter usage is in UTC, and counts
57
+ # from midday on the initial day. This is referred to in the
58
+ # Date class as the *Astronomical* *Julian* *Day* *Number*, and
59
+ # abbreviated as +ajd+. In the Date class, the Astronomical
60
+ # Julian Day Number includes fractional days.
61
+ #
62
+ # Another absolute day count is the *Modified* *Julian* *Day*
63
+ # *Number*, which takes November 17, 1858 as its initial day.
64
+ # This is abbreviated as +mjd+ in the Date class. There
65
+ # is also an *Astronomical* *Modified* *Julian* *Day* *Number*,
66
+ # which is in UTC and includes fractional days. This is
67
+ # abbreviated as +amjd+ in the Date class. Like the Modified
68
+ # Julian Day Number (and unlike the Astronomical Julian
69
+ # Day Number), it counts from midnight.
70
+ #
71
+ # Alternative calendars such as the Chinese Lunar Calendar,
72
+ # the Islamic Calendar, or the French Revolutionary Calendar
73
+ # are not supported by the Date class; nor are calendars that
74
+ # are based on an Era different from the Common Era, such as
75
+ # the Japanese Imperial Calendar or the Republic of China
76
+ # Calendar.
77
+ #
78
+ # === Calendar Reform
79
+ #
80
+ # The standard civil year is 365 days long. However, the
81
+ # solar year is fractionally longer than this. To account
82
+ # for this, a *leap* *year* is occasionally inserted. This
83
+ # is a year with 366 days, the extra day falling on February 29.
84
+ # In the early days of the civil calendar, every fourth
85
+ # year without exception was a leap year. This way of
86
+ # reckoning leap years is the *Julian* *Calendar*.
87
+ #
88
+ # However, the solar year is marginally shorter than 365 1/4
89
+ # days, and so the *Julian* *Calendar* gradually ran slow
90
+ # over the centuries. To correct this, every 100th year
91
+ # (but not every 400th year) was excluded as a leap year.
92
+ # This way of reckoning leap years, which we use today, is
93
+ # the *Gregorian* *Calendar*.
94
+ #
95
+ # The Gregorian Calendar was introduced at different times
96
+ # in different regions. The day on which it was introduced
97
+ # for a particular region is the *Day* *of* *Calendar*
98
+ # *Reform* for that region. This is abbreviated as +sg+
99
+ # (for Start of Gregorian calendar) in the Date class.
100
+ #
101
+ # Two such days are of particular
102
+ # significance. The first is October 15, 1582, which was
103
+ # the Day of Calendar Reform for Italy and most Catholic
104
+ # countries. The second is September 14, 1752, which was
105
+ # the Day of Calendar Reform for England and its colonies
106
+ # (including what is now the United States). These two
107
+ # dates are available as the constants Date::ITALY and
108
+ # Date::ENGLAND, respectively. (By comparison, Germany and
109
+ # Holland, less Catholic than Italy but less stubborn than
110
+ # England, changed over in 1698; Sweden in 1753; Russia not
111
+ # till 1918, after the Revolution; and Greece in 1923. Many
112
+ # Orthodox churches still use the Julian Calendar. A complete
113
+ # list of Days of Calendar Reform can be found at
114
+ # http://www.polysyllabic.com/GregConv.html.)
115
+ #
116
+ # Switching from the Julian to the Gregorian calendar
117
+ # involved skipping a number of days to make up for the
118
+ # accumulated lag, and the later the switch was (or is)
119
+ # done, the more days need to be skipped. So in 1582 in Italy,
120
+ # 4th October was followed by 15th October, skipping 10 days; in 1752
121
+ # in England, 2nd September was followed by 14th September, skipping
122
+ # 11 days; and if I decided to switch from Julian to Gregorian
123
+ # Calendar this midnight, I would go from 27th July 2003 (Julian)
124
+ # today to 10th August 2003 (Gregorian) tomorrow, skipping
125
+ # 13 days. The Date class is aware of this gap, and a supposed
126
+ # date that would fall in the middle of it is regarded as invalid.
127
+ #
128
+ # The Day of Calendar Reform is relevant to all date representations
129
+ # involving years. It is not relevant to the Julian Day Numbers,
130
+ # except for converting between them and year-based representations.
131
+ #
132
+ # In the Date and DateTime classes, the Day of Calendar Reform or
133
+ # +sg+ can be specified a number of ways. First, it can be as
134
+ # the Julian Day Number of the Day of Calendar Reform. Second,
135
+ # it can be using the constants Date::ITALY or Date::ENGLAND; these
136
+ # are in fact the Julian Day Numbers of the Day of Calendar Reform
137
+ # of the respective regions. Third, it can be as the constant
138
+ # Date::JULIAN, which means to always use the Julian Calendar.
139
+ # Finally, it can be as the constant Date::GREGORIAN, which means
140
+ # to always use the Gregorian Calendar.
141
+ #
142
+ # Note: in the Julian Calendar, New Years Day was March 25. The
143
+ # Date class does not follow this convention.
144
+ #
145
+ # === Time Zones
146
+ #
147
+ # DateTime objects support a simple representation
148
+ # of time zones. Time zones are represented as an offset
149
+ # from UTC, as a fraction of a day. This offset is the
150
+ # how much local time is later (or earlier) than UTC.
151
+ # UTC offset 0 is centred on England (also known as GMT).
152
+ # As you travel east, the offset increases until you
153
+ # reach the dateline in the middle of the Pacific Ocean;
154
+ # as you travel west, the offset decreases. This offset
155
+ # is abbreviated as +of+ in the Date class.
156
+ #
157
+ # This simple representation of time zones does not take
158
+ # into account the common practice of Daylight Savings
159
+ # Time or Summer Time.
160
+ #
161
+ # Most DateTime methods return the date and the
162
+ # time in local time. The two exceptions are
163
+ # #ajd() and #amjd(), which return the date and time
164
+ # in UTC time, including fractional days.
165
+ #
166
+ # The Date class does not support time zone offsets, in that
167
+ # there is no way to create a Date object with a time zone.
168
+ # However, methods of the Date class when used by a
169
+ # DateTime instance will use the time zone offset of this
170
+ # instance.
171
+ #
172
+ # == Examples of use
173
+ #
174
+ # === Print out the date of every Sunday between two dates.
175
+ #
176
+ # def print_sundays(d1, d2)
177
+ # d1 +=1 while (d1.wday != 0)
178
+ # d1.step(d2, 7) do |date|
179
+ # puts "#{Date::MONTHNAMES[date.mon]} #{date.day}"
180
+ # end
181
+ # end
182
+ #
183
+ # print_sundays(Date::civil(2003, 4, 8), Date::civil(2003, 5, 23))
184
+ #
185
+ # === Calculate how many seconds to go till midnight on New Year's Day.
186
+ #
187
+ # def secs_to_new_year(now = DateTime::now())
188
+ # new_year = DateTime.new(now.year + 1, 1, 1)
189
+ # dif = new_year - now
190
+ # hours, mins, secs, ignore_fractions = Date::day_fraction_to_time(dif)
191
+ # return hours * 60 * 60 + mins * 60 + secs
192
+ # end
193
+ #
194
+ # puts secs_to_new_year()
195
+
196
+ # Class representing a date.
197
+ #
198
+ # See the documentation to the file date.rb for an overview.
199
+ #
200
+ # Internally, the date is represented as an Astronomical
201
+ # Julian Day Number, +ajd+. The Day of Calendar Reform, +sg+, is
202
+ # also stored, for conversions to other date formats. (There
203
+ # is also an +of+ field for a time zone offset, but this
204
+ # is only for the use of the DateTime subclass.)
205
+ #
206
+ # A new Date object is created using one of the object creation
207
+ # class methods named after the corresponding date format, and the
208
+ # arguments appropriate to that date format; for instance,
209
+ # Date::civil() (aliased to Date::new()) with year, month,
210
+ # and day-of-month, or Date::ordinal() with year and day-of-year.
211
+ # All of these object creation class methods also take the
212
+ # Day of Calendar Reform as an optional argument.
213
+ #
214
+ # Date objects are immutable once created.
215
+ #
216
+ # Once a Date has been created, date values
217
+ # can be retrieved for the different date formats supported
218
+ # using instance methods. For instance, #mon() gives the
219
+ # Civil month, #cwday() gives the Commercial day of the week,
220
+ # and #yday() gives the Ordinal day of the year. Date values
221
+ # can be retrieved in any format, regardless of what format
222
+ # was used to create the Date instance.
223
+ #
224
+ # The Date class includes the Comparable module, allowing
225
+ # date objects to be compared and sorted, ranges of dates
226
+ # to be created, and so forth.
227
+ class Date
228
+
229
+ include Comparable
230
+
231
+ # Full month names, in English. Months count from 1 to 12; a
232
+ # month's numerical representation indexed into this array
233
+ # gives the name of that month (hence the first element is nil).
234
+ MONTHNAMES = [nil] + %w(January February March April May June July
235
+ August September October November December)
236
+
237
+ # Full names of days of the week, in English. Days of the week
238
+ # count from 0 to 6 (except in the commercial week); a day's numerical
239
+ # representation indexed into this array gives the name of that day.
240
+ DAYNAMES = %w(Sunday Monday Tuesday Wednesday Thursday Friday Saturday)
241
+
242
+ # Abbreviated month names, in English.
243
+ ABBR_MONTHNAMES = [nil] + %w(Jan Feb Mar Apr May Jun
244
+ Jul Aug Sep Oct Nov Dec)
245
+
246
+ # Abbreviated day names, in English.
247
+ ABBR_DAYNAMES = %w(Sun Mon Tue Wed Thu Fri Sat)
248
+
249
+ [MONTHNAMES, DAYNAMES, ABBR_MONTHNAMES, ABBR_DAYNAMES].each do |xs|
250
+ xs.each{|x| x.freeze unless x.nil?}.freeze
251
+ end
252
+
253
+ class Infinity < Numeric # :nodoc:
254
+
255
+ include Comparable
256
+
257
+ def initialize(d=1) @d = d <=> 0 end
258
+
259
+ def d() @d end
260
+
261
+ protected :d
262
+
263
+ def zero? () false end
264
+ def finite? () false end
265
+ def infinite? () d.nonzero? end
266
+ def nan? () d.zero? end
267
+
268
+ def abs() self.class.new end
269
+
270
+ def -@ () self.class.new(-d) end
271
+ def +@ () self.class.new(+d) end
272
+
273
+ def <=> (other)
274
+ case other
275
+ when Infinity; return d <=> other.d
276
+ when Numeric; return d
277
+ else
278
+ begin
279
+ l, r = other.coerce(self)
280
+ return l <=> r
281
+ rescue NoMethodError
282
+ end
283
+ end
284
+ nil
285
+ end
286
+
287
+ def coerce(other)
288
+ case other
289
+ when Numeric; return -d, d
290
+ else
291
+ super
292
+ end
293
+ end
294
+
295
+ end
296
+
297
+ # The Julian Day Number of the Day of Calendar Reform for Italy
298
+ # and the Catholic countries.
299
+ ITALY = 2299161 # 1582-10-15
300
+
301
+ # The Julian Day Number of the Day of Calendar Reform for England
302
+ # and her Colonies.
303
+ ENGLAND = 2361222 # 1752-09-14
304
+
305
+ # A constant used to indicate that a Date should always use the
306
+ # Julian calendar.
307
+ JULIAN = Infinity.new
308
+
309
+ # A constant used to indicate that a Date should always use the
310
+ # Gregorian calendar.
311
+ GREGORIAN = -Infinity.new
312
+
313
+ HALF_DAYS_IN_DAY = Rational(1, 2) # :nodoc:
314
+ HOURS_IN_DAY = Rational(1, 24) # :nodoc:
315
+ MINUTES_IN_DAY = Rational(1, 1440) # :nodoc:
316
+ SECONDS_IN_DAY = Rational(1, 86400) # :nodoc:
317
+ MILLISECONDS_IN_DAY = Rational(1, 86400*10**3) # :nodoc:
318
+ NANOSECONDS_IN_DAY = Rational(1, 86400*10**9) # :nodoc:
319
+ MILLISECONDS_IN_SECOND = Rational(1, 10**3) # :nodoc:
320
+ NANOSECONDS_IN_SECOND = Rational(1, 10**9) # :nodoc:
321
+
322
+ MJD_EPOCH_IN_AJD = Rational(4800001, 2) # 1858-11-17 # :nodoc:
323
+ UNIX_EPOCH_IN_AJD = Rational(4881175, 2) # 1970-01-01 # :nodoc:
324
+ MJD_EPOCH_IN_CJD = 2400001 # :nodoc:
325
+ UNIX_EPOCH_IN_CJD = 2440588 # :nodoc:
326
+ LD_EPOCH_IN_CJD = 2299160 # :nodoc:
327
+
328
+ t = Module.new do
329
+
330
+ private
331
+
332
+ def find_fdoy(y, sg) # :nodoc:
333
+ j = nil
334
+ 1.upto(31) do |d|
335
+ break if j = _valid_civil?(y, 1, d, sg)
336
+ end
337
+ j
338
+ end
339
+
340
+ def find_ldoy(y, sg) # :nodoc:
341
+ j = nil
342
+ 31.downto(1) do |d|
343
+ break if j = _valid_civil?(y, 12, d, sg)
344
+ end
345
+ j
346
+ end
347
+
348
+ def find_fdom(y, m, sg) # :nodoc:
349
+ j = nil
350
+ 1.upto(31) do |d|
351
+ break if j = _valid_civil?(y, m, d, sg)
352
+ end
353
+ j
354
+ end
355
+
356
+ def find_ldom(y, m, sg) # :nodoc:
357
+ j = nil
358
+ 31.downto(1) do |d|
359
+ break if j = _valid_civil?(y, m, d, sg)
360
+ end
361
+ j
362
+ end
363
+
364
+ # Convert an Ordinal Date to a Julian Day Number.
365
+ #
366
+ # +y+ and +d+ are the year and day-of-year to convert.
367
+ # +sg+ specifies the Day of Calendar Reform.
368
+ #
369
+ # Returns the corresponding Julian Day Number.
370
+ def ordinal_to_jd(y, d, sg=GREGORIAN) # :nodoc:
371
+ find_fdoy(y, sg) + d - 1
372
+ end
373
+
374
+ # Convert a Julian Day Number to an Ordinal Date.
375
+ #
376
+ # +jd+ is the Julian Day Number to convert.
377
+ # +sg+ specifies the Day of Calendar Reform.
378
+ #
379
+ # Returns the corresponding Ordinal Date as
380
+ # [year, day_of_year]
381
+ def jd_to_ordinal(jd, sg=GREGORIAN) # :nodoc:
382
+ y = jd_to_civil(jd, sg)[0]
383
+ j = find_fdoy(y, sg)
384
+ doy = jd - j + 1
385
+ return y, doy
386
+ end
387
+
388
+ # Convert a Civil Date to a Julian Day Number.
389
+ # +y+, +m+, and +d+ are the year, month, and day of the
390
+ # month. +sg+ specifies the Day of Calendar Reform.
391
+ #
392
+ # Returns the corresponding Julian Day Number.
393
+ def civil_to_jd(y, m, d, sg=GREGORIAN) # :nodoc:
394
+ if m <= 2
395
+ y -= 1
396
+ m += 12
397
+ end
398
+ a = (y / 100.0).floor
399
+ b = 2 - a + (a / 4.0).floor
400
+ jd = (365.25 * (y + 4716)).floor +
401
+ (30.6001 * (m + 1)).floor +
402
+ d + b - 1524
403
+ if jd < sg
404
+ jd -= b
405
+ end
406
+ jd
407
+ end
408
+
409
+ # Convert a Julian Day Number to a Civil Date. +jd+ is
410
+ # the Julian Day Number. +sg+ specifies the Day of
411
+ # Calendar Reform.
412
+ #
413
+ # Returns the corresponding [year, month, day_of_month]
414
+ # as a three-element array.
415
+ def jd_to_civil(jd, sg=GREGORIAN) # :nodoc:
416
+ if jd < sg
417
+ a = jd
418
+ else
419
+ x = ((jd - 1867216.25) / 36524.25).floor
420
+ a = jd + 1 + x - (x / 4.0).floor
421
+ end
422
+ b = a + 1524
423
+ c = ((b - 122.1) / 365.25).floor
424
+ d = (365.25 * c).floor
425
+ e = ((b - d) / 30.6001).floor
426
+ dom = b - d - (30.6001 * e).floor
427
+ if e <= 13
428
+ m = e - 1
429
+ y = c - 4716
430
+ else
431
+ m = e - 13
432
+ y = c - 4715
433
+ end
434
+ return y, m, dom
435
+ end
436
+
437
+ # Convert a Commercial Date to a Julian Day Number.
438
+ #
439
+ # +y+, +w+, and +d+ are the (commercial) year, week of the year,
440
+ # and day of the week of the Commercial Date to convert.
441
+ # +sg+ specifies the Day of Calendar Reform.
442
+ def commercial_to_jd(y, w, d, sg=GREGORIAN) # :nodoc:
443
+ j = find_fdoy(y, sg) + 3
444
+ (j - (((j - 1) + 1) % 7)) +
445
+ 7 * (w - 1) +
446
+ (d - 1)
447
+ end
448
+
449
+ # Convert a Julian Day Number to a Commercial Date
450
+ #
451
+ # +jd+ is the Julian Day Number to convert.
452
+ # +sg+ specifies the Day of Calendar Reform.
453
+ #
454
+ # Returns the corresponding Commercial Date as
455
+ # [commercial_year, week_of_year, day_of_week]
456
+ def jd_to_commercial(jd, sg=GREGORIAN) # :nodoc:
457
+ a = jd_to_civil(jd - 3, sg)[0]
458
+ y = if jd >= commercial_to_jd(a + 1, 1, 1, sg) then a + 1 else a end
459
+ w = 1 + ((jd - commercial_to_jd(y, 1, 1, sg)) / 7).floor
460
+ d = (jd + 1) % 7
461
+ d = 7 if d == 0
462
+ return y, w, d
463
+ end
464
+
465
+ def weeknum_to_jd(y, w, d, f=0, sg=GREGORIAN) # :nodoc:
466
+ a = find_fdoy(y, sg) + 6
467
+ (a - ((a - f) + 1) % 7 - 7) + 7 * w + d
468
+ end
469
+
470
+ def jd_to_weeknum(jd, f=0, sg=GREGORIAN) # :nodoc:
471
+ y, m, d = jd_to_civil(jd, sg)
472
+ a = find_fdoy(y, sg) + 6
473
+ w, d = (jd - (a - ((a - f) + 1) % 7) + 7).divmod(7)
474
+ return y, w, d
475
+ end
476
+
477
+ def nth_kday_to_jd(y, m, n, k, sg=GREGORIAN) # :nodoc:
478
+ j = if n > 0
479
+ find_fdom(y, m, sg) - 1
480
+ else
481
+ find_ldom(y, m, sg) + 7
482
+ end
483
+ (j - (((j - k) + 1) % 7)) + 7 * n
484
+ end
485
+
486
+ def jd_to_nth_kday(jd, sg=GREGORIAN) # :nodoc:
487
+ y, m, d = jd_to_civil(jd, sg)
488
+ j = find_fdom(y, m, sg)
489
+ return y, m, ((jd - j) / 7).floor + 1, jd_to_wday(jd)
490
+ end
491
+
492
+ # Convert an Astronomical Julian Day Number to a (civil) Julian
493
+ # Day Number.
494
+ #
495
+ # +ajd+ is the Astronomical Julian Day Number to convert.
496
+ # +of+ is the offset from UTC as a fraction of a day (defaults to 0).
497
+ #
498
+ # Returns the (civil) Julian Day Number as [day_number,
499
+ # fraction] where +fraction+ is always 1/2.
500
+ def ajd_to_jd(ajd, of=0) (ajd + of + HALF_DAYS_IN_DAY).divmod(1) end # :nodoc:
501
+
502
+ # Convert a (civil) Julian Day Number to an Astronomical Julian
503
+ # Day Number.
504
+ #
505
+ # +jd+ is the Julian Day Number to convert, and +fr+ is a
506
+ # fractional day.
507
+ # +of+ is the offset from UTC as a fraction of a day (defaults to 0).
508
+ #
509
+ # Returns the Astronomical Julian Day Number as a single
510
+ # numeric value.
511
+ def jd_to_ajd(jd, fr, of=0) jd + fr - of - HALF_DAYS_IN_DAY end # :nodoc:
512
+
513
+ # Convert a fractional day +fr+ to [hours, minutes, seconds,
514
+ # fraction_of_a_second]
515
+ def day_fraction_to_time(fr) # :nodoc:
516
+ ss, fr = fr.divmod(SECONDS_IN_DAY) # 4p
517
+ h, ss = ss.divmod(3600)
518
+ min, s = ss.divmod(60)
519
+ return h, min, s, fr * 86400
520
+ end
521
+
522
+ # Convert an +h+ hour, +min+ minutes, +s+ seconds period
523
+ # to a fractional day.
524
+ begin
525
+ Rational(Rational(1, 2), 2) # a challenge
526
+
527
+ def time_to_day_fraction(h, min, s)
528
+ Rational(h * 3600 + min * 60 + s, 86400) # 4p
529
+ end
530
+ rescue
531
+ def time_to_day_fraction(h, min, s)
532
+ if Integer === h && Integer === min && Integer === s
533
+ Rational(h * 3600 + min * 60 + s, 86400) # 4p
534
+ else
535
+ (h * 3600 + min * 60 + s).to_r/86400 # 4p
536
+ end
537
+ end
538
+ end
539
+
540
+ # Convert an Astronomical Modified Julian Day Number to an
541
+ # Astronomical Julian Day Number.
542
+ def amjd_to_ajd(amjd) amjd + MJD_EPOCH_IN_AJD end # :nodoc:
543
+
544
+ # Convert an Astronomical Julian Day Number to an
545
+ # Astronomical Modified Julian Day Number.
546
+ def ajd_to_amjd(ajd) ajd - MJD_EPOCH_IN_AJD end # :nodoc:
547
+
548
+ # Convert a Modified Julian Day Number to a Julian
549
+ # Day Number.
550
+ def mjd_to_jd(mjd) mjd + MJD_EPOCH_IN_CJD end # :nodoc:
551
+
552
+ # Convert a Julian Day Number to a Modified Julian Day
553
+ # Number.
554
+ def jd_to_mjd(jd) jd - MJD_EPOCH_IN_CJD end # :nodoc:
555
+
556
+ # Convert a count of the number of days since the adoption
557
+ # of the Gregorian Calendar (in Italy) to a Julian Day Number.
558
+ def ld_to_jd(ld) ld + LD_EPOCH_IN_CJD end # :nodoc:
559
+
560
+ # Convert a Julian Day Number to the number of days since
561
+ # the adoption of the Gregorian Calendar (in Italy).
562
+ def jd_to_ld(jd) jd - LD_EPOCH_IN_CJD end # :nodoc:
563
+
564
+ # Convert a Julian Day Number to the day of the week.
565
+ #
566
+ # Sunday is day-of-week 0; Saturday is day-of-week 6.
567
+ def jd_to_wday(jd) (jd + 1) % 7 end # :nodoc:
568
+
569
+ # Is +jd+ a valid Julian Day Number?
570
+ #
571
+ # If it is, returns it. In fact, any value is treated as a valid
572
+ # Julian Day Number.
573
+ def _valid_jd? (jd, sg=GREGORIAN) jd end # :nodoc:
574
+
575
+ # Do the year +y+ and day-of-year +d+ make a valid Ordinal Date?
576
+ # Returns the corresponding Julian Day Number if they do, or
577
+ # nil if they don't.
578
+ #
579
+ # +d+ can be a negative number, in which case it counts backwards
580
+ # from the end of the year (-1 being the last day of the year).
581
+ # No year wraparound is performed, however, so valid values of
582
+ # +d+ are -365 .. -1, 1 .. 365 on a non-leap-year,
583
+ # -366 .. -1, 1 .. 366 on a leap year.
584
+ # A date falling in the period skipped in the Day of Calendar Reform
585
+ # adjustment is not valid.
586
+ #
587
+ # +sg+ specifies the Day of Calendar Reform.
588
+ def _valid_ordinal? (y, d, sg=GREGORIAN) # :nodoc:
589
+ if d < 0
590
+ return unless j = find_ldoy(y, sg)
591
+ ny, nd = jd_to_ordinal(j + d + 1, sg)
592
+ return unless ny == y
593
+ d = nd
594
+ end
595
+ jd = ordinal_to_jd(y, d, sg)
596
+ return unless [y, d] == jd_to_ordinal(jd, sg)
597
+ jd
598
+ end
599
+
600
+ # Do year +y+, month +m+, and day-of-month +d+ make a
601
+ # valid Civil Date? Returns the corresponding Julian
602
+ # Day Number if they do, nil if they don't.
603
+ #
604
+ # +m+ and +d+ can be negative, in which case they count
605
+ # backwards from the end of the year and the end of the
606
+ # month respectively. No wraparound is performed, however,
607
+ # and invalid values cause an ArgumentError to be raised.
608
+ # A date falling in the period skipped in the Day of Calendar
609
+ # Reform adjustment is not valid.
610
+ #
611
+ # +sg+ specifies the Day of Calendar Reform.
612
+ def _valid_civil? (y, m, d, sg=GREGORIAN) # :nodoc:
613
+ if m < 0
614
+ m += 13
615
+ end
616
+ if d < 0
617
+ return unless j = find_ldom(y, m, sg)
618
+ ny, nm, nd = jd_to_civil(j + d + 1, sg)
619
+ return unless [ny, nm] == [y, m]
620
+ d = nd
621
+ end
622
+ jd = civil_to_jd(y, m, d, sg)
623
+ return unless [y, m, d] == jd_to_civil(jd, sg)
624
+ jd
625
+ end
626
+
627
+ # Do year +y+, week-of-year +w+, and day-of-week +d+ make a
628
+ # valid Commercial Date? Returns the corresponding Julian
629
+ # Day Number if they do, nil if they don't.
630
+ #
631
+ # Monday is day-of-week 1; Sunday is day-of-week 7.
632
+ #
633
+ # +w+ and +d+ can be negative, in which case they count
634
+ # backwards from the end of the year and the end of the
635
+ # week respectively. No wraparound is performed, however,
636
+ # and invalid values cause an ArgumentError to be raised.
637
+ # A date falling in the period skipped in the Day of Calendar
638
+ # Reform adjustment is not valid.
639
+ #
640
+ # +sg+ specifies the Day of Calendar Reform.
641
+ def _valid_commercial? (y, w, d, sg=GREGORIAN) # :nodoc:
642
+ if d < 0
643
+ d += 8
644
+ end
645
+ if w < 0
646
+ ny, nw, nd =
647
+ jd_to_commercial(commercial_to_jd(y + 1, 1, 1, sg) + w * 7, sg)
648
+ return unless ny == y
649
+ w = nw
650
+ end
651
+ jd = commercial_to_jd(y, w, d, sg)
652
+ return unless [y, w, d] == jd_to_commercial(jd, sg)
653
+ jd
654
+ end
655
+
656
+ def _valid_weeknum? (y, w, d, f, sg=GREGORIAN) # :nodoc:
657
+ if d < 0
658
+ d += 7
659
+ end
660
+ if w < 0
661
+ ny, nw, nd, nf =
662
+ jd_to_weeknum(weeknum_to_jd(y + 1, 1, f, f, sg) + w * 7, f, sg)
663
+ return unless ny == y
664
+ w = nw
665
+ end
666
+ jd = weeknum_to_jd(y, w, d, f, sg)
667
+ return unless [y, w, d] == jd_to_weeknum(jd, f, sg)
668
+ jd
669
+ end
670
+
671
+ def _valid_nth_kday? (y, m, n, k, sg=GREGORIAN) # :nodoc:
672
+ if k < 0
673
+ k += 7
674
+ end
675
+ if n < 0
676
+ ny, nm = (y * 12 + m).divmod(12)
677
+ nm, = (nm + 1) .divmod(1)
678
+ ny, nm, nn, nk =
679
+ jd_to_nth_kday(nth_kday_to_jd(ny, nm, 1, k, sg) + n * 7, sg)
680
+ return unless [ny, nm] == [y, m]
681
+ n = nn
682
+ end
683
+ jd = nth_kday_to_jd(y, m, n, k, sg)
684
+ return unless [y, m, n, k] == jd_to_nth_kday(jd, sg)
685
+ jd
686
+ end
687
+
688
+ # Do hour +h+, minute +min+, and second +s+ constitute a valid time?
689
+ #
690
+ # If they do, returns their value as a fraction of a day. If not,
691
+ # returns nil.
692
+ #
693
+ # The 24-hour clock is used. Negative values of +h+, +min+, and
694
+ # +sec+ are treating as counting backwards from the end of the
695
+ # next larger unit (e.g. a +min+ of -2 is treated as 58). No
696
+ # wraparound is performed.
697
+ def _valid_time? (h, min, s) # :nodoc:
698
+ h += 24 if h < 0
699
+ min += 60 if min < 0
700
+ s += 60 if s < 0
701
+ return unless ((0...24) === h &&
702
+ (0...60) === min &&
703
+ (0...60) === s) ||
704
+ (24 == h &&
705
+ 0 == min &&
706
+ 0 == s)
707
+ time_to_day_fraction(h, min, s)
708
+ end
709
+
710
+ end
711
+
712
+ extend t
713
+ include t
714
+
715
+ # Is a year a leap year in the Julian calendar?
716
+ #
717
+ # All years divisible by 4 are leap years in the Julian calendar.
718
+ def self.julian_leap? (y) y % 4 == 0 end
719
+
720
+ # Is a year a leap year in the Gregorian calendar?
721
+ #
722
+ # All years divisible by 4 are leap years in the Gregorian calendar,
723
+ # except for years divisible by 100 and not by 400.
724
+ def self.gregorian_leap? (y) y % 4 == 0 && y % 100 != 0 || y % 400 == 0 end
725
+
726
+ class << self; alias_method :leap?, :gregorian_leap? end
727
+ class << self; alias_method :new!, :new end
728
+
729
+ def self.valid_jd? (jd, sg=ITALY)
730
+ !!_valid_jd?(jd, sg)
731
+ end
732
+
733
+ def self.valid_ordinal? (y, d, sg=ITALY)
734
+ !!_valid_ordinal?(y, d, sg)
735
+ end
736
+
737
+ def self.valid_civil? (y, m, d, sg=ITALY)
738
+ !!_valid_civil?(y, m, d, sg)
739
+ end
740
+
741
+ class << self; alias_method :valid_date?, :valid_civil? end
742
+
743
+ def self.valid_commercial? (y, w, d, sg=ITALY)
744
+ !!_valid_commercial?(y, w, d, sg)
745
+ end
746
+
747
+ def self.valid_weeknum? (y, w, d, f, sg=ITALY) # :nodoc:
748
+ !!_valid_weeknum?(y, w, d, f, sg)
749
+ end
750
+
751
+ private_class_method :valid_weeknum?
752
+
753
+ def self.valid_nth_kday? (y, m, n, k, sg=ITALY) # :nodoc:
754
+ !!_valid_nth_kday?(y, m, n, k, sg)
755
+ end
756
+
757
+ private_class_method :valid_nth_kday?
758
+
759
+ def self.valid_time? (h, min, s) # :nodoc:
760
+ !!_valid_time?(h, min, s)
761
+ end
762
+
763
+ private_class_method :valid_time?
764
+
765
+ # Create a new Date object from a Julian Day Number.
766
+ #
767
+ # +jd+ is the Julian Day Number; if not specified, it defaults to
768
+ # 0.
769
+ # +sg+ specifies the Day of Calendar Reform.
770
+ def self.jd(jd=0, sg=ITALY)
771
+ jd = _valid_jd?(jd, sg)
772
+ new!(jd_to_ajd(jd, 0, 0), 0, sg)
773
+ end
774
+
775
+ # Create a new Date object from an Ordinal Date, specified
776
+ # by year +y+ and day-of-year +d+. +d+ can be negative,
777
+ # in which it counts backwards from the end of the year.
778
+ # No year wraparound is performed, however. An invalid
779
+ # value for +d+ results in an ArgumentError being raised.
780
+ #
781
+ # +y+ defaults to -4712, and +d+ to 1; this is Julian Day
782
+ # Number day 0.
783
+ #
784
+ # +sg+ specifies the Day of Calendar Reform.
785
+ def self.ordinal(y=-4712, d=1, sg=ITALY)
786
+ unless jd = _valid_ordinal?(y, d, sg)
787
+ raise ArgumentError, 'invalid date'
788
+ end
789
+ new!(jd_to_ajd(jd, 0, 0), 0, sg)
790
+ end
791
+
792
+ # Create a new Date object for the Civil Date specified by
793
+ # year +y+, month +m+, and day-of-month +d+.
794
+ #
795
+ # +m+ and +d+ can be negative, in which case they count
796
+ # backwards from the end of the year and the end of the
797
+ # month respectively. No wraparound is performed, however,
798
+ # and invalid values cause an ArgumentError to be raised.
799
+ # can be negative
800
+ #
801
+ # +y+ defaults to -4712, +m+ to 1, and +d+ to 1; this is
802
+ # Julian Day Number day 0.
803
+ #
804
+ # +sg+ specifies the Day of Calendar Reform.
805
+ def self.civil(y=-4712, m=1, d=1, sg=ITALY)
806
+ unless jd = _valid_civil?(y, m, d, sg)
807
+ raise ArgumentError, 'invalid date'
808
+ end
809
+ new!(jd_to_ajd(jd, 0, 0), 0, sg)
810
+ end
811
+
812
+ class << self; alias_method :new, :civil end
813
+
814
+ # Create a new Date object for the Commercial Date specified by
815
+ # year +y+, week-of-year +w+, and day-of-week +d+.
816
+ #
817
+ # Monday is day-of-week 1; Sunday is day-of-week 7.
818
+ #
819
+ # +w+ and +d+ can be negative, in which case they count
820
+ # backwards from the end of the year and the end of the
821
+ # week respectively. No wraparound is performed, however,
822
+ # and invalid values cause an ArgumentError to be raised.
823
+ #
824
+ # +y+ defaults to -4712, +w+ to 1, and +d+ to 1; this is
825
+ # Julian Day Number day 0.
826
+ #
827
+ # +sg+ specifies the Day of Calendar Reform.
828
+ def self.commercial(y=-4712, w=1, d=1, sg=ITALY)
829
+ unless jd = _valid_commercial?(y, w, d, sg)
830
+ raise ArgumentError, 'invalid date'
831
+ end
832
+ new!(jd_to_ajd(jd, 0, 0), 0, sg)
833
+ end
834
+
835
+ def self.weeknum(y=-4712, w=0, d=1, f=0, sg=ITALY)
836
+ unless jd = _valid_weeknum?(y, w, d, f, sg)
837
+ raise ArgumentError, 'invalid date'
838
+ end
839
+ new!(jd_to_ajd(jd, 0, 0), 0, sg)
840
+ end
841
+
842
+ private_class_method :weeknum
843
+
844
+ def self.nth_kday(y=-4712, m=1, n=1, k=1, sg=ITALY)
845
+ unless jd = _valid_nth_kday?(y, m, n, k, sg)
846
+ raise ArgumentError, 'invalid date'
847
+ end
848
+ new!(jd_to_ajd(jd, 0, 0), 0, sg)
849
+ end
850
+
851
+ private_class_method :nth_kday
852
+
853
+ def self.rewrite_frags(elem) # :nodoc:
854
+ elem ||= {}
855
+ if seconds = elem[:seconds]
856
+ d, fr = seconds.divmod(86400)
857
+ h, fr = fr.divmod(3600)
858
+ min, fr = fr.divmod(60)
859
+ s, fr = fr.divmod(1)
860
+ elem[:jd] = UNIX_EPOCH_IN_CJD + d
861
+ elem[:hour] = h
862
+ elem[:min] = min
863
+ elem[:sec] = s
864
+ elem[:sec_fraction] = fr
865
+ elem.delete(:seconds)
866
+ elem.delete(:offset)
867
+ end
868
+ elem
869
+ end
870
+
871
+ private_class_method :rewrite_frags
872
+
873
+ def self.complete_frags(elem) # :nodoc:
874
+ i = 0
875
+ g = [[:time, [:hour, :min, :sec]],
876
+ [nil, [:jd]],
877
+ [:ordinal, [:year, :yday, :hour, :min, :sec]],
878
+ [:civil, [:year, :mon, :mday, :hour, :min, :sec]],
879
+ [:commercial, [:cwyear, :cweek, :cwday, :hour, :min, :sec]],
880
+ [:wday, [:wday, :hour, :min, :sec]],
881
+ [:wnum0, [:year, :wnum0, :wday, :hour, :min, :sec]],
882
+ [:wnum1, [:year, :wnum1, :wday, :hour, :min, :sec]],
883
+ [nil, [:cwyear, :cweek, :wday, :hour, :min, :sec]],
884
+ [nil, [:year, :wnum0, :cwday, :hour, :min, :sec]],
885
+ [nil, [:year, :wnum1, :cwday, :hour, :min, :sec]]].
886
+ collect{|k, a| e = elem.values_at(*a).compact; [k, a, e]}.
887
+ select{|k, a, e| e.size > 0}.
888
+ sort_by{|k, a, e| [e.size, i -= 1]}.last
889
+
890
+ d = nil
891
+
892
+ if g && g[0] && (g[1].size - g[2].size) != 0
893
+ d ||= Date.today
894
+
895
+ case g[0]
896
+ when :ordinal
897
+ elem[:year] ||= d.year
898
+ elem[:yday] ||= 1
899
+ when :civil
900
+ g[1].each do |e|
901
+ break if elem[e]
902
+ elem[e] = d.__send__(e)
903
+ end
904
+ elem[:mon] ||= 1
905
+ elem[:mday] ||= 1
906
+ when :commercial
907
+ g[1].each do |e|
908
+ break if elem[e]
909
+ elem[e] = d.__send__(e)
910
+ end
911
+ elem[:cweek] ||= 1
912
+ elem[:cwday] ||= 1
913
+ when :wday
914
+ elem[:jd] ||= (d - d.wday + elem[:wday]).jd
915
+ when :wnum0
916
+ g[1].each do |e|
917
+ break if elem[e]
918
+ elem[e] = d.__send__(e)
919
+ end
920
+ elem[:wnum0] ||= 0
921
+ elem[:wday] ||= 0
922
+ when :wnum1
923
+ g[1].each do |e|
924
+ break if elem[e]
925
+ elem[e] = d.__send__(e)
926
+ end
927
+ elem[:wnum1] ||= 0
928
+ elem[:wday] ||= 1
929
+ end
930
+ end
931
+
932
+ if g && g[0] == :time
933
+ if self <= DateTime
934
+ d ||= Date.today
935
+ elem[:jd] ||= d.jd
936
+ end
937
+ end
938
+
939
+ elem[:hour] ||= 0
940
+ elem[:min] ||= 0
941
+ elem[:sec] ||= 0
942
+ elem[:sec] = [elem[:sec], 59].min
943
+
944
+ elem
945
+ end
946
+
947
+ private_class_method :complete_frags
948
+
949
+ def self.valid_date_frags?(elem, sg) # :nodoc:
950
+ catch :jd do
951
+ a = elem.values_at(:jd)
952
+ if a.all?
953
+ if jd = _valid_jd?(*(a << sg))
954
+ throw :jd, jd
955
+ end
956
+ end
957
+
958
+ a = elem.values_at(:year, :yday)
959
+ if a.all?
960
+ if jd = _valid_ordinal?(*(a << sg))
961
+ throw :jd, jd
962
+ end
963
+ end
964
+
965
+ a = elem.values_at(:year, :mon, :mday)
966
+ if a.all?
967
+ if jd = _valid_civil?(*(a << sg))
968
+ throw :jd, jd
969
+ end
970
+ end
971
+
972
+ a = elem.values_at(:cwyear, :cweek, :cwday)
973
+ if a[2].nil? && elem[:wday]
974
+ a[2] = elem[:wday].nonzero? || 7
975
+ end
976
+ if a.all?
977
+ if jd = _valid_commercial?(*(a << sg))
978
+ throw :jd, jd
979
+ end
980
+ end
981
+
982
+ a = elem.values_at(:year, :wnum0, :wday)
983
+ if a[2].nil? && elem[:cwday]
984
+ a[2] = elem[:cwday] % 7
985
+ end
986
+ if a.all?
987
+ if jd = _valid_weeknum?(*(a << 0 << sg))
988
+ throw :jd, jd
989
+ end
990
+ end
991
+
992
+ a = elem.values_at(:year, :wnum1, :wday)
993
+ if a[2]
994
+ a[2] = (a[2] - 1) % 7
995
+ end
996
+ if a[2].nil? && elem[:cwday]
997
+ a[2] = (elem[:cwday] - 1) % 7
998
+ end
999
+ if a.all?
1000
+ if jd = _valid_weeknum?(*(a << 1 << sg))
1001
+ throw :jd, jd
1002
+ end
1003
+ end
1004
+ end
1005
+ end
1006
+
1007
+ private_class_method :valid_date_frags?
1008
+
1009
+ def self.valid_time_frags? (elem) # :nodoc:
1010
+ h, min, s = elem.values_at(:hour, :min, :sec)
1011
+ _valid_time?(h, min, s)
1012
+ end
1013
+
1014
+ private_class_method :valid_time_frags?
1015
+
1016
+ def self.new_by_frags(elem, sg) # :nodoc:
1017
+ elem = rewrite_frags(elem)
1018
+ elem = complete_frags(elem)
1019
+ unless jd = valid_date_frags?(elem, sg)
1020
+ raise ArgumentError, 'invalid date'
1021
+ end
1022
+ new!(jd_to_ajd(jd, 0, 0), 0, sg)
1023
+ end
1024
+
1025
+ private_class_method :new_by_frags
1026
+
1027
+ # Create a new Date object by parsing from a String
1028
+ # according to a specified format.
1029
+ #
1030
+ # +str+ is a String holding a date representation.
1031
+ # +fmt+ is the format that the date is in. See
1032
+ # date/format.rb for details on supported formats.
1033
+ #
1034
+ # The default +str+ is '-4712-01-01', and the default
1035
+ # +fmt+ is '%F', which means Year-Month-Day_of_Month.
1036
+ # This gives Julian Day Number day 0.
1037
+ #
1038
+ # +sg+ specifies the Day of Calendar Reform.
1039
+ #
1040
+ # An ArgumentError will be raised if +str+ cannot be
1041
+ # parsed.
1042
+ def self.strptime(str='-4712-01-01', fmt='%F', sg=ITALY)
1043
+ elem = _strptime(str, fmt)
1044
+ new_by_frags(elem, sg)
1045
+ end
1046
+
1047
+ # Create a new Date object by parsing from a String,
1048
+ # without specifying the format.
1049
+ #
1050
+ # +str+ is a String holding a date representation.
1051
+ # +comp+ specifies whether to interpret 2-digit years
1052
+ # as 19XX (>= 69) or 20XX (< 69); the default is not to.
1053
+ # The method will attempt to parse a date from the String
1054
+ # using various heuristics; see #_parse in date/format.rb
1055
+ # for more details. If parsing fails, an ArgumentError
1056
+ # will be raised.
1057
+ #
1058
+ # The default +str+ is '-4712-01-01'; this is Julian
1059
+ # Day Number day 0.
1060
+ #
1061
+ # +sg+ specifies the Day of Calendar Reform.
1062
+ def self.parse(str='-4712-01-01', comp=true, sg=ITALY)
1063
+ elem = _parse(str, comp)
1064
+ new_by_frags(elem, sg)
1065
+ end
1066
+
1067
+ def self.iso8601(str='-4712-01-01', sg=ITALY) # :nodoc:
1068
+ elem = _iso8601(str)
1069
+ new_by_frags(elem, sg)
1070
+ end
1071
+
1072
+ def self.rfc3339(str='-4712-01-01T00:00:00+00:00', sg=ITALY) # :nodoc:
1073
+ elem = _rfc3339(str)
1074
+ new_by_frags(elem, sg)
1075
+ end
1076
+
1077
+ def self.xmlschema(str='-4712-01-01', sg=ITALY) # :nodoc:
1078
+ elem = _xmlschema(str)
1079
+ new_by_frags(elem, sg)
1080
+ end
1081
+
1082
+ def self.rfc2822(str='Mon, 1 Jan -4712 00:00:00 +0000', sg=ITALY) # :nodoc:
1083
+ elem = _rfc2822(str)
1084
+ new_by_frags(elem, sg)
1085
+ end
1086
+
1087
+ class << self; alias_method :rfc822, :rfc2822 end
1088
+
1089
+ def self.httpdate(str='Mon, 01 Jan -4712 00:00:00 GMT', sg=ITALY) # :nodoc:
1090
+ elem = _httpdate(str)
1091
+ new_by_frags(elem, sg)
1092
+ end
1093
+
1094
+ def self.jisx0301(str='-4712-01-01', sg=ITALY) # :nodoc:
1095
+ elem = _jisx0301(str)
1096
+ new_by_frags(elem, sg)
1097
+ end
1098
+
1099
+ # class << self
1100
+ #
1101
+ # def once(*ids) # :nodoc: -- restricted
1102
+ # for id in ids
1103
+ # module_eval <<-"end;"
1104
+ # alias_method :__#{id.object_id}__, :#{id.to_s}
1105
+ # private :__#{id.object_id}__
1106
+ # def #{id.to_s}(*args)
1107
+ # @__ca__[#{id.object_id}] ||= __#{id.object_id}__(*args)
1108
+ # end
1109
+ # end;
1110
+ # end
1111
+ # end # <<dummy
1112
+ #
1113
+ # private :once
1114
+ #
1115
+ # end
1116
+
1117
+ # *NOTE* this is the documentation for the method new!(). If
1118
+ # you are reading this as the documentation for new(), that is
1119
+ # because rdoc doesn't fully support the aliasing of the
1120
+ # initialize() method.
1121
+ # new() is in
1122
+ # fact an alias for #civil(): read the documentation for that
1123
+ # method instead.
1124
+ #
1125
+ # Create a new Date object.
1126
+ #
1127
+ # +ajd+ is the Astronomical Julian Day Number.
1128
+ # +of+ is the offset from UTC as a fraction of a day.
1129
+ # Both default to 0.
1130
+ #
1131
+ # +sg+ specifies the Day of Calendar Reform to use for this
1132
+ # Date object.
1133
+ #
1134
+ # Using one of the factory methods such as Date::civil is
1135
+ # generally easier and safer.
1136
+ def initialize(ajd=0, of=0, sg=ITALY)
1137
+ @ajd, @of, @sg = ajd, of, sg
1138
+ @__ca__ = {}
1139
+ end
1140
+
1141
+ # Get the date as an Astronomical Julian Day Number.
1142
+ def ajd() @ajd end
1143
+
1144
+ # Get the date as an Astronomical Modified Julian Day Number.
1145
+ def amjd() ajd_to_amjd(@ajd) end
1146
+
1147
+ # once :amjd
1148
+
1149
+ # Get the date as a Julian Day Number.
1150
+ def jd() ajd_to_jd(@ajd, @of)[0] end
1151
+
1152
+ # Get any fractional day part of the date.
1153
+ def day_fraction() ajd_to_jd(@ajd, @of)[1] end
1154
+
1155
+ # Get the date as a Modified Julian Day Number.
1156
+ def mjd() jd_to_mjd(jd) end
1157
+
1158
+ # Get the date as the number of days since the Day of Calendar
1159
+ # Reform (in Italy and the Catholic countries).
1160
+ def ld() jd_to_ld(jd) end
1161
+
1162
+ # once :jd, :day_fraction, :mjd, :ld
1163
+
1164
+ # Get the date as a Civil Date, [year, month, day_of_month]
1165
+ def civil() jd_to_civil(jd, @sg) end # :nodoc:
1166
+
1167
+ # Get the date as an Ordinal Date, [year, day_of_year]
1168
+ def ordinal() jd_to_ordinal(jd, @sg) end # :nodoc:
1169
+
1170
+ # Get the date as a Commercial Date, [year, week_of_year, day_of_week]
1171
+ def commercial() jd_to_commercial(jd, @sg) end # :nodoc:
1172
+
1173
+ def weeknum0() jd_to_weeknum(jd, 0, @sg) end # :nodoc:
1174
+ def weeknum1() jd_to_weeknum(jd, 1, @sg) end # :nodoc:
1175
+
1176
+ # once :civil, :ordinal, :commercial, :weeknum0, :weeknum1
1177
+ # private :civil, :ordinal, :commercial, :weeknum0, :weeknum1
1178
+
1179
+ # Get the year of this date.
1180
+ def year() civil[0] end
1181
+
1182
+ # Get the day-of-the-year of this date.
1183
+ #
1184
+ # January 1 is day-of-the-year 1
1185
+ def yday() ordinal[1] end
1186
+
1187
+ # Get the month of this date.
1188
+ #
1189
+ # January is month 1.
1190
+ def mon() civil[1] end
1191
+
1192
+ # Get the day-of-the-month of this date.
1193
+ def mday() civil[2] end
1194
+
1195
+ alias_method :month, :mon
1196
+ alias_method :day, :mday
1197
+
1198
+ def wnum0() weeknum0[1] end # :nodoc:
1199
+ def wnum1() weeknum1[1] end # :nodoc:
1200
+
1201
+ private :wnum0, :wnum1
1202
+
1203
+ # Get the time of this date as [hours, minutes, seconds,
1204
+ # fraction_of_a_second]
1205
+ def time() day_fraction_to_time(day_fraction) end # :nodoc:
1206
+
1207
+ # once :time
1208
+ # private :time
1209
+
1210
+ # Get the hour of this date.
1211
+ def hour() time[0] end
1212
+
1213
+ # Get the minute of this date.
1214
+ def min() time[1] end
1215
+
1216
+ # Get the second of this date.
1217
+ def sec() time[2] end
1218
+
1219
+ # Get the fraction-of-a-second of this date.
1220
+ def sec_fraction() time[3] end
1221
+
1222
+ alias_method :minute, :min
1223
+ alias_method :second, :sec
1224
+ alias_method :second_fraction, :sec_fraction
1225
+
1226
+ private :hour, :min, :sec, :sec_fraction,
1227
+ :minute, :second, :second_fraction
1228
+
1229
+ def zone() strftime('%:z') end
1230
+
1231
+ private :zone
1232
+
1233
+ # Get the commercial year of this date. See *Commercial* *Date*
1234
+ # in the introduction for how this differs from the normal year.
1235
+ def cwyear() commercial[0] end
1236
+
1237
+ # Get the commercial week of the year of this date.
1238
+ def cweek() commercial[1] end
1239
+
1240
+ # Get the commercial day of the week of this date. Monday is
1241
+ # commercial day-of-week 1; Sunday is commercial day-of-week 7.
1242
+ def cwday() commercial[2] end
1243
+
1244
+ # Get the week day of this date. Sunday is day-of-week 0;
1245
+ # Saturday is day-of-week 6.
1246
+ def wday() jd_to_wday(jd) end
1247
+
1248
+ # once :wday
1249
+
1250
+ =begin
1251
+ MONTHNAMES.each_with_index do |n, i|
1252
+ if n
1253
+ define_method(n.downcase + '?'){mon == i}
1254
+ end
1255
+ end
1256
+ =end
1257
+
1258
+ DAYNAMES.each_with_index do |n, i|
1259
+ define_method(n.downcase + '?'){wday == i}
1260
+ end
1261
+
1262
+ def nth_kday? (n, k)
1263
+ k == wday && jd === nth_kday_to_jd(year, mon, n, k, start)
1264
+ end
1265
+
1266
+ private :nth_kday?
1267
+
1268
+ # Is the current date old-style (Julian Calendar)?
1269
+ def julian? () jd < @sg end
1270
+
1271
+ # Is the current date new-style (Gregorian Calendar)?
1272
+ def gregorian? () !julian? end
1273
+
1274
+ # once :julian?, :gregorian?
1275
+
1276
+ def fix_style # :nodoc:
1277
+ if julian?
1278
+ then self.class::JULIAN
1279
+ else self.class::GREGORIAN end
1280
+ end
1281
+
1282
+ private :fix_style
1283
+
1284
+ # Is this a leap year?
1285
+ def leap?
1286
+ jd_to_civil(civil_to_jd(year, 3, 1, fix_style) - 1,
1287
+ fix_style)[-1] == 29
1288
+ end
1289
+
1290
+ # once :leap?
1291
+
1292
+ # When is the Day of Calendar Reform for this Date object?
1293
+ def start() @sg end
1294
+
1295
+ # Create a copy of this Date object using a new Day of Calendar Reform.
1296
+ def new_start(sg=self.class::ITALY) self.class.new!(@ajd, @of, sg) end
1297
+
1298
+ # Create a copy of this Date object that uses the Italian/Catholic
1299
+ # Day of Calendar Reform.
1300
+ def italy() new_start(self.class::ITALY) end
1301
+
1302
+ # Create a copy of this Date object that uses the English/Colonial
1303
+ # Day of Calendar Reform.
1304
+ def england() new_start(self.class::ENGLAND) end
1305
+
1306
+ # Create a copy of this Date object that always uses the Julian
1307
+ # Calendar.
1308
+ def julian() new_start(self.class::JULIAN) end
1309
+
1310
+ # Create a copy of this Date object that always uses the Gregorian
1311
+ # Calendar.
1312
+ def gregorian() new_start(self.class::GREGORIAN) end
1313
+
1314
+ def offset() @of end
1315
+
1316
+ def new_offset(of=0)
1317
+ if String === of
1318
+ of = Rational(zone_to_diff(of) || 0, 86400)
1319
+ end
1320
+ self.class.new!(@ajd, of, @sg)
1321
+ end
1322
+
1323
+ private :offset, :new_offset
1324
+
1325
+ # Return a new Date object that is +n+ days later than the
1326
+ # current one.
1327
+ #
1328
+ # +n+ may be a negative value, in which case the new Date
1329
+ # is earlier than the current one; however, #-() might be
1330
+ # more intuitive.
1331
+ #
1332
+ # If +n+ is not a Numeric, a TypeError will be thrown. In
1333
+ # particular, two Dates cannot be added to each other.
1334
+ def + (n)
1335
+ case n
1336
+ when Numeric; return self.class.new!(@ajd + n, @of, @sg)
1337
+ end
1338
+ raise TypeError, 'expected numeric'
1339
+ end
1340
+
1341
+ # If +x+ is a Numeric value, create a new Date object that is
1342
+ # +x+ days earlier than the current one.
1343
+ #
1344
+ # If +x+ is a Date, return the number of days between the
1345
+ # two dates; or, more precisely, how many days later the current
1346
+ # date is than +x+.
1347
+ #
1348
+ # If +x+ is neither Numeric nor a Date, a TypeError is raised.
1349
+ def - (x)
1350
+ case x
1351
+ when Numeric; return self.class.new!(@ajd - x, @of, @sg)
1352
+ when Date; return @ajd - x.ajd
1353
+ end
1354
+ raise TypeError, 'expected numeric or date'
1355
+ end
1356
+
1357
+ # Compare this date with another date.
1358
+ #
1359
+ # +other+ can also be a Numeric value, in which case it is
1360
+ # interpreted as an Astronomical Julian Day Number.
1361
+ #
1362
+ # Comparison is by Astronomical Julian Day Number, including
1363
+ # fractional days. This means that both the time and the
1364
+ # timezone offset are taken into account when comparing
1365
+ # two DateTime instances. When comparing a DateTime instance
1366
+ # with a Date instance, the time of the latter will be
1367
+ # considered as falling on midnight UTC.
1368
+ def <=> (other)
1369
+ case other
1370
+ when Numeric; return @ajd <=> other
1371
+ when Date; return @ajd <=> other.ajd
1372
+ else
1373
+ begin
1374
+ l, r = other.coerce(self)
1375
+ return l <=> r
1376
+ rescue NoMethodError
1377
+ end
1378
+ end
1379
+ nil
1380
+ end
1381
+
1382
+ # The relationship operator for Date.
1383
+ #
1384
+ # Compares dates by Julian Day Number. When comparing
1385
+ # two DateTime instances, or a DateTime with a Date,
1386
+ # the instances will be regarded as equivalent if they
1387
+ # fall on the same date in local time.
1388
+ def === (other)
1389
+ case other
1390
+ when Numeric; return jd == other
1391
+ when Date; return jd == other.jd
1392
+ else
1393
+ begin
1394
+ l, r = other.coerce(self)
1395
+ return l === r
1396
+ rescue NoMethodError
1397
+ end
1398
+ end
1399
+ false
1400
+ end
1401
+
1402
+ def next_day(n=1) self + n end
1403
+ def prev_day(n=1) self - n end
1404
+
1405
+ # Return a new Date one day after this one.
1406
+ def next() next_day end
1407
+
1408
+ alias_method :succ, :next
1409
+
1410
+ # Return a new Date object that is +n+ months later than
1411
+ # the current one.
1412
+ #
1413
+ # If the day-of-the-month of the current Date is greater
1414
+ # than the last day of the target month, the day-of-the-month
1415
+ # of the returned Date will be the last day of the target month.
1416
+ def >> (n)
1417
+ y, m = (year * 12 + (mon - 1) + n).divmod(12)
1418
+ m, = (m + 1) .divmod(1)
1419
+ d = mday
1420
+ until jd2 = _valid_civil?(y, m, d, @sg)
1421
+ d -= 1
1422
+ raise ArgumentError, 'invalid date' unless d > 0
1423
+ end
1424
+ self + (jd2 - jd)
1425
+ end
1426
+
1427
+ # Return a new Date object that is +n+ months earlier than
1428
+ # the current one.
1429
+ #
1430
+ # If the day-of-the-month of the current Date is greater
1431
+ # than the last day of the target month, the day-of-the-month
1432
+ # of the returned Date will be the last day of the target month.
1433
+ def << (n) self >> -n end
1434
+
1435
+ def next_month(n=1) self >> n end
1436
+ def prev_month(n=1) self << n end
1437
+
1438
+ def next_year(n=1) self >> n * 12 end
1439
+ def prev_year(n=1) self << n * 12 end
1440
+
1441
+ # Step the current date forward +step+ days at a
1442
+ # time (or backward, if +step+ is negative) until
1443
+ # we reach +limit+ (inclusive), yielding the resultant
1444
+ # date at each step.
1445
+ def step(limit, step=1) # :yield: date
1446
+ =begin
1447
+ if step.zero?
1448
+ raise ArgumentError, "step can't be 0"
1449
+ end
1450
+ =end
1451
+ unless block_given?
1452
+ return to_enum(:step, limit, step)
1453
+ end
1454
+ da = self
1455
+ op = %w(- <= >=)[step <=> 0]
1456
+ while da.__send__(op, limit)
1457
+ yield da
1458
+ da += step
1459
+ end
1460
+ self
1461
+ end
1462
+
1463
+ # Step forward one day at a time until we reach +max+
1464
+ # (inclusive), yielding each date as we go.
1465
+ def upto(max, &block) # :yield: date
1466
+ step(max, +1, &block)
1467
+ end
1468
+
1469
+ # Step backward one day at a time until we reach +min+
1470
+ # (inclusive), yielding each date as we go.
1471
+ def downto(min, &block) # :yield: date
1472
+ step(min, -1, &block)
1473
+ end
1474
+
1475
+ # Is this Date equal to +other+?
1476
+ #
1477
+ # +other+ must both be a Date object, and represent the same date.
1478
+ def eql? (other) Date === other && self == other end
1479
+
1480
+ # Calculate a hash value for this date.
1481
+ def hash() @ajd.hash end
1482
+
1483
+ # Return internal object state as a programmer-readable string.
1484
+ def inspect
1485
+ format('#<%s: %s (%s,%s,%s)>', self.class, to_s, @ajd, @of, @sg)
1486
+ end
1487
+
1488
+ # Return the date as a human-readable string.
1489
+ #
1490
+ # The format used is YYYY-MM-DD.
1491
+ def to_s() format('%.4d-%02d-%02d', year, mon, mday) end # 4p
1492
+
1493
+ # Dump to Marshal format.
1494
+ def marshal_dump() [@ajd, @of, @sg] end
1495
+
1496
+ # Load from Marshal format.
1497
+ def marshal_load(a)
1498
+ @ajd, @of, @sg, = a
1499
+ @__ca__ = {}
1500
+ end
1501
+
1502
+ end
1503
+
1504
+ # Class representing a date and time.
1505
+ #
1506
+ # See the documentation to the file date.rb for an overview.
1507
+ #
1508
+ # DateTime objects are immutable once created.
1509
+ #
1510
+ # == Other methods.
1511
+ #
1512
+ # The following methods are defined in Date, but declared private
1513
+ # there. They are made public in DateTime. They are documented
1514
+ # here.
1515
+ #
1516
+ # === hour()
1517
+ #
1518
+ # Get the hour-of-the-day of the time. This is given
1519
+ # using the 24-hour clock, counting from midnight. The first
1520
+ # hour after midnight is hour 0; the last hour of the day is
1521
+ # hour 23.
1522
+ #
1523
+ # === min()
1524
+ #
1525
+ # Get the minute-of-the-hour of the time.
1526
+ #
1527
+ # === sec()
1528
+ #
1529
+ # Get the second-of-the-minute of the time.
1530
+ #
1531
+ # === sec_fraction()
1532
+ #
1533
+ # Get the fraction of a second of the time. This is returned as
1534
+ # a +Rational+.
1535
+ #
1536
+ # === zone()
1537
+ #
1538
+ # Get the time zone as a String. This is representation of the
1539
+ # time offset such as "+1000", not the true time-zone name.
1540
+ #
1541
+ # === offset()
1542
+ #
1543
+ # Get the time zone offset as a fraction of a day. This is returned
1544
+ # as a +Rational+.
1545
+ #
1546
+ # === new_offset(of=0)
1547
+ #
1548
+ # Create a new DateTime object, identical to the current one, except
1549
+ # with a new time zone offset of +of+. +of+ is the new offset from
1550
+ # UTC as a fraction of a day.
1551
+ #
1552
+ class DateTime < Date
1553
+
1554
+ # Create a new DateTime object corresponding to the specified
1555
+ # Julian Day Number +jd+ and hour +h+, minute +min+, second +s+.
1556
+ #
1557
+ # The 24-hour clock is used. Negative values of +h+, +min+, and
1558
+ # +sec+ are treating as counting backwards from the end of the
1559
+ # next larger unit (e.g. a +min+ of -2 is treated as 58). No
1560
+ # wraparound is performed. If an invalid time portion is specified,
1561
+ # an ArgumentError is raised.
1562
+ #
1563
+ # +of+ is the offset from UTC as a fraction of a day (defaults to 0).
1564
+ # +sg+ specifies the Day of Calendar Reform.
1565
+ #
1566
+ # All day/time values default to 0.
1567
+ def self.jd(jd=0, h=0, min=0, s=0, of=0, sg=ITALY)
1568
+ unless (jd = _valid_jd?(jd, sg)) &&
1569
+ (fr = _valid_time?(h, min, s))
1570
+ raise ArgumentError, 'invalid date'
1571
+ end
1572
+ if String === of
1573
+ of = Rational(zone_to_diff(of) || 0, 86400)
1574
+ end
1575
+ new!(jd_to_ajd(jd, fr, of), of, sg)
1576
+ end
1577
+
1578
+ # Create a new DateTime object corresponding to the specified
1579
+ # Ordinal Date and hour +h+, minute +min+, second +s+.
1580
+ #
1581
+ # The 24-hour clock is used. Negative values of +h+, +min+, and
1582
+ # +sec+ are treating as counting backwards from the end of the
1583
+ # next larger unit (e.g. a +min+ of -2 is treated as 58). No
1584
+ # wraparound is performed. If an invalid time portion is specified,
1585
+ # an ArgumentError is raised.
1586
+ #
1587
+ # +of+ is the offset from UTC as a fraction of a day (defaults to 0).
1588
+ # +sg+ specifies the Day of Calendar Reform.
1589
+ #
1590
+ # +y+ defaults to -4712, and +d+ to 1; this is Julian Day Number
1591
+ # day 0. The time values default to 0.
1592
+ def self.ordinal(y=-4712, d=1, h=0, min=0, s=0, of=0, sg=ITALY)
1593
+ unless (jd = _valid_ordinal?(y, d, sg)) &&
1594
+ (fr = _valid_time?(h, min, s))
1595
+ raise ArgumentError, 'invalid date'
1596
+ end
1597
+ if String === of
1598
+ of = Rational(zone_to_diff(of) || 0, 86400)
1599
+ end
1600
+ new!(jd_to_ajd(jd, fr, of), of, sg)
1601
+ end
1602
+
1603
+ # Create a new DateTime object corresponding to the specified
1604
+ # Civil Date and hour +h+, minute +min+, second +s+.
1605
+ #
1606
+ # The 24-hour clock is used. Negative values of +h+, +min+, and
1607
+ # +sec+ are treating as counting backwards from the end of the
1608
+ # next larger unit (e.g. a +min+ of -2 is treated as 58). No
1609
+ # wraparound is performed. If an invalid time portion is specified,
1610
+ # an ArgumentError is raised.
1611
+ #
1612
+ # +of+ is the offset from UTC as a fraction of a day (defaults to 0).
1613
+ # +sg+ specifies the Day of Calendar Reform.
1614
+ #
1615
+ # +y+ defaults to -4712, +m+ to 1, and +d+ to 1; this is Julian Day
1616
+ # Number day 0. The time values default to 0.
1617
+ def self.civil(y=-4712, m=1, d=1, h=0, min=0, s=0, of=0, sg=ITALY)
1618
+ unless (jd = _valid_civil?(y, m, d, sg)) &&
1619
+ (fr = _valid_time?(h, min, s))
1620
+ raise ArgumentError, 'invalid date'
1621
+ end
1622
+ if String === of
1623
+ of = Rational(zone_to_diff(of) || 0, 86400)
1624
+ end
1625
+ new!(jd_to_ajd(jd, fr, of), of, sg)
1626
+ end
1627
+
1628
+ class << self; alias_method :new, :civil end
1629
+
1630
+ # Create a new DateTime object corresponding to the specified
1631
+ # Commercial Date and hour +h+, minute +min+, second +s+.
1632
+ #
1633
+ # The 24-hour clock is used. Negative values of +h+, +min+, and
1634
+ # +sec+ are treating as counting backwards from the end of the
1635
+ # next larger unit (e.g. a +min+ of -2 is treated as 58). No
1636
+ # wraparound is performed. If an invalid time portion is specified,
1637
+ # an ArgumentError is raised.
1638
+ #
1639
+ # +of+ is the offset from UTC as a fraction of a day (defaults to 0).
1640
+ # +sg+ specifies the Day of Calendar Reform.
1641
+ #
1642
+ # +y+ defaults to -4712, +w+ to 1, and +d+ to 1; this is
1643
+ # Julian Day Number day 0.
1644
+ # The time values default to 0.
1645
+ def self.commercial(y=-4712, w=1, d=1, h=0, min=0, s=0, of=0, sg=ITALY)
1646
+ unless (jd = _valid_commercial?(y, w, d, sg)) &&
1647
+ (fr = _valid_time?(h, min, s))
1648
+ raise ArgumentError, 'invalid date'
1649
+ end
1650
+ if String === of
1651
+ of = Rational(zone_to_diff(of) || 0, 86400)
1652
+ end
1653
+ new!(jd_to_ajd(jd, fr, of), of, sg)
1654
+ end
1655
+
1656
+ def self.weeknum(y=-4712, w=0, d=1, f=0, h=0, min=0, s=0, of=0, sg=ITALY) # :nodoc:
1657
+ unless (jd = _valid_weeknum?(y, w, d, f, sg)) &&
1658
+ (fr = _valid_time?(h, min, s))
1659
+ raise ArgumentError, 'invalid date'
1660
+ end
1661
+ if String === of
1662
+ of = Rational(zone_to_diff(of) || 0, 86400)
1663
+ end
1664
+ new!(jd_to_ajd(jd, fr, of), of, sg)
1665
+ end
1666
+
1667
+ private_class_method :weeknum
1668
+
1669
+ def self.nth_kday(y=-4712, m=1, n=1, k=1, h=0, min=0, s=0, of=0, sg=ITALY) # :nodoc:
1670
+ unless (jd = _valid_nth_kday?(y, m, n, k, sg)) &&
1671
+ (fr = _valid_time?(h, min, s))
1672
+ raise ArgumentError, 'invalid date'
1673
+ end
1674
+ if String === of
1675
+ of = Rational(zone_to_diff(of) || 0, 86400)
1676
+ end
1677
+ new!(jd_to_ajd(jd, fr, of), of, sg)
1678
+ end
1679
+
1680
+ private_class_method :nth_kday
1681
+
1682
+ def self.new_by_frags(elem, sg) # :nodoc:
1683
+ elem = rewrite_frags(elem)
1684
+ elem = complete_frags(elem)
1685
+ unless (jd = valid_date_frags?(elem, sg)) &&
1686
+ (fr = valid_time_frags?(elem))
1687
+ raise ArgumentError, 'invalid date'
1688
+ end
1689
+ fr += (elem[:sec_fraction] || 0) / 86400
1690
+ of = Rational(elem[:offset] || 0, 86400)
1691
+ new!(jd_to_ajd(jd, fr, of), of, sg)
1692
+ end
1693
+
1694
+ private_class_method :new_by_frags
1695
+
1696
+ # Create a new DateTime object by parsing from a String
1697
+ # according to a specified format.
1698
+ #
1699
+ # +str+ is a String holding a date-time representation.
1700
+ # +fmt+ is the format that the date-time is in. See
1701
+ # date/format.rb for details on supported formats.
1702
+ #
1703
+ # The default +str+ is '-4712-01-01T00:00:00+00:00', and the default
1704
+ # +fmt+ is '%FT%T%z'. This gives midnight on Julian Day Number day 0.
1705
+ #
1706
+ # +sg+ specifies the Day of Calendar Reform.
1707
+ #
1708
+ # An ArgumentError will be raised if +str+ cannot be
1709
+ # parsed.
1710
+ def self.strptime(str='-4712-01-01T00:00:00+00:00', fmt='%FT%T%z', sg=ITALY)
1711
+ elem = _strptime(str, fmt)
1712
+ new_by_frags(elem, sg)
1713
+ end
1714
+
1715
+ # Create a new DateTime object by parsing from a String,
1716
+ # without specifying the format.
1717
+ #
1718
+ # +str+ is a String holding a date-time representation.
1719
+ # +comp+ specifies whether to interpret 2-digit years
1720
+ # as 19XX (>= 69) or 20XX (< 69); the default is not to.
1721
+ # The method will attempt to parse a date-time from the String
1722
+ # using various heuristics; see #_parse in date/format.rb
1723
+ # for more details. If parsing fails, an ArgumentError
1724
+ # will be raised.
1725
+ #
1726
+ # The default +str+ is '-4712-01-01T00:00:00+00:00'; this is Julian
1727
+ # Day Number day 0.
1728
+ #
1729
+ # +sg+ specifies the Day of Calendar Reform.
1730
+ def self.parse(str='-4712-01-01T00:00:00+00:00', comp=true, sg=ITALY)
1731
+ elem = _parse(str, comp)
1732
+ new_by_frags(elem, sg)
1733
+ end
1734
+
1735
+ def self.iso8601(str='-4712-01-01T00:00:00+00:00', sg=ITALY) # :nodoc:
1736
+ elem = _iso8601(str)
1737
+ new_by_frags(elem, sg)
1738
+ end
1739
+
1740
+ def self.rfc3339(str='-4712-01-01T00:00:00+00:00', sg=ITALY) # :nodoc:
1741
+ elem = _rfc3339(str)
1742
+ new_by_frags(elem, sg)
1743
+ end
1744
+
1745
+ def self.xmlschema(str='-4712-01-01T00:00:00+00:00', sg=ITALY) # :nodoc:
1746
+ elem = _xmlschema(str)
1747
+ new_by_frags(elem, sg)
1748
+ end
1749
+
1750
+ def self.rfc2822(str='Mon, 1 Jan -4712 00:00:00 +0000', sg=ITALY) # :nodoc:
1751
+ elem = _rfc2822(str)
1752
+ new_by_frags(elem, sg)
1753
+ end
1754
+
1755
+ class << self; alias_method :rfc822, :rfc2822 end
1756
+
1757
+ def self.httpdate(str='Mon, 01 Jan -4712 00:00:00 GMT', sg=ITALY) # :nodoc:
1758
+ elem = _httpdate(str)
1759
+ new_by_frags(elem, sg)
1760
+ end
1761
+
1762
+ def self.jisx0301(str='-4712-01-01T00:00:00+00:00', sg=ITALY) # :nodoc:
1763
+ elem = _jisx0301(str)
1764
+ new_by_frags(elem, sg)
1765
+ end
1766
+
1767
+ public :hour, :min, :sec, :sec_fraction, :zone, :offset, :new_offset,
1768
+ :minute, :second, :second_fraction
1769
+
1770
+ def to_s # 4p
1771
+ format('%.4d-%02d-%02dT%02d:%02d:%02d%s',
1772
+ year, mon, mday, hour, min, sec, zone)
1773
+ end
1774
+
1775
+ end
1776
+
1777
+ class Time
1778
+
1779
+ def to_time() getlocal end
1780
+
1781
+ def to_date
1782
+ jd = Date.__send__(:civil_to_jd, year, mon, mday, Date::ITALY)
1783
+ Date.new!(Date.__send__(:jd_to_ajd, jd, 0, 0), 0, Date::ITALY)
1784
+ end
1785
+
1786
+ def to_datetime
1787
+ jd = DateTime.__send__(:civil_to_jd, year, mon, mday, DateTime::ITALY)
1788
+ fr = DateTime.__send__(:time_to_day_fraction, hour, min, [sec, 59].min) +
1789
+ Rational(nsec, 86400_000_000_000)
1790
+ of = Rational(utc_offset, 86400)
1791
+ DateTime.new!(DateTime.__send__(:jd_to_ajd, jd, fr, of),
1792
+ of, DateTime::ITALY)
1793
+ end
1794
+
1795
+ end
1796
+
1797
+ class Date
1798
+
1799
+ def to_time() Time.local(year, mon, mday) end
1800
+ def to_date() self end
1801
+ def to_datetime() DateTime.new!(jd_to_ajd(jd, 0, 0), @of, @sg) end
1802
+
1803
+ # Create a new Date object representing today.
1804
+ #
1805
+ # +sg+ specifies the Day of Calendar Reform.
1806
+ def self.today(sg=ITALY)
1807
+ t = Time.now
1808
+ jd = civil_to_jd(t.year, t.mon, t.mday, sg)
1809
+ new!(jd_to_ajd(jd, 0, 0), 0, sg)
1810
+ end
1811
+
1812
+ # Create a new DateTime object representing the current time.
1813
+ #
1814
+ # +sg+ specifies the Day of Calendar Reform.
1815
+ def self.now(sg=ITALY)
1816
+ t = Time.now
1817
+ jd = civil_to_jd(t.year, t.mon, t.mday, sg)
1818
+ fr = time_to_day_fraction(t.hour, t.min, [t.sec, 59].min) +
1819
+ Rational(t.nsec, 86400_000_000_000)
1820
+ of = Rational(t.utc_offset, 86400)
1821
+ new!(jd_to_ajd(jd, fr, of), of, sg)
1822
+ end
1823
+
1824
+ private_class_method :now
1825
+
1826
+ end
1827
+
1828
+ class DateTime < Date
1829
+
1830
+ def to_time
1831
+ d = new_offset(0)
1832
+ d.instance_eval do
1833
+ Time.utc(year, mon, mday, hour, min, sec +
1834
+ sec_fraction)
1835
+ end.
1836
+ getlocal
1837
+ end
1838
+
1839
+ def to_date() Date.new!(jd_to_ajd(jd, 0, 0), 0, @sg) end
1840
+ def to_datetime() self end
1841
+
1842
+ private_class_method :today
1843
+ public_class_method :now
1844
+
1845
+ end