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