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