Class: Date

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/date.rb,
lib/date.rb,
lib/date.rb,
lib/date/format.rb

Overview

Class representing a date.

See the documentation to the file date.rb for an overview.

Internally, the date is represented as an Astronomical Julian Day Number, ajd. The Day of Calendar Reform, sg, is also stored, for conversions to other date formats. (There is also an of field for a time zone offset, but this is only for the use of the DateTime subclass.)

A new Date object is created using one of the object creation class methods named after the corresponding date format, and the arguments appropriate to that date format; for instance, Date::civil() (aliased to Date::new()) with year, month, and day-of-month, or Date::ordinal() with year and day-of-year. All of these object creation class methods also take the Day of Calendar Reform as an optional argument.

Date objects are immutable once created.

Once a Date has been created, date values can be retrieved for the different date formats supported using instance methods. For instance, #mon() gives the Civil month, #cwday() gives the Commercial day of the week, and #yday() gives the Ordinal day of the year. Date values can be retrieved in any format, regardless of what format was used to create the Date instance.

The Date class includes the Comparable module, allowing date objects to be compared and sorted, ranges of dates to be created, and so forth.

Direct Known Subclasses

DateTime

Defined Under Namespace

Modules: Format Classes: Infinity

Constant Summary collapse

MONTHNAMES =

Full month names, in English. Months count from 1 to 12; a month's numerical representation indexed into this array gives the name of that month (hence the first element is nil).

[nil] + %w(January
DAYNAMES =

Full names of days of the week, in English. Days of the week count from 0 to 6 (except in the commercial week); a day's numerical representation indexed into this array gives the name of that day.

%w(Sunday
ABBR_MONTHNAMES =

Abbreviated month names, in English.

[nil] + %w(Jan
ABBR_DAYNAMES =

Abbreviated day names, in English.

%w(Sun
ITALY =

The Julian Day Number of the Day of Calendar Reform for Italy and the Catholic countries.

2299161
ENGLAND =

The Julian Day Number of the Day of Calendar Reform for England and her Colonies.

2361222
JULIAN =

A constant used to indicate that a Date should always use the Julian calendar.

Infinity.new
GREGORIAN =

A constant used to indicate that a Date should always use the Gregorian calendar.

Infinity.new
UNIXEPOCH =

1970-01-01 :nodoc:

2440588

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(ajd = 0, of = 0, sg = ITALY) ⇒ Date

NOTE this is the documentation for the method new!(). If you are reading this as the documentation for new(), that is because rdoc doesn???t fully support the aliasing of the initialize() method. new() is in fact an alias for #civil(): read the documentation for that method instead.

Create a new Date object.

ajd is the Astronomical Julian Day Number. of is the offset from UTC as a fraction of a day. Both default to 0.

sg specifies the Day of Calendar Reform to use for this Date object.

Using one of the factory methods such as Date::civil is generally easier and safer.



1015
# File 'lib/date.rb', line 1015

def initialize(ajd=0, of=0, sg=ITALY) @ajd, @of, @sg = ajd, of, sg end

Class Method Details

._load(str) ⇒ Object

Load from Marshall format.



1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
# File 'lib/date.rb', line 1355

def self._load(str)
  a = Marshal.load(str)
  if a.size == 2
    ajd,     sg = a
         of = 0
    ajd -= 1.to_r/2
  else
    ajd, of, sg = a
  end
  new!(ajd, of, sg)
end

._parse(str, comp = false) ⇒ Object



958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
# File 'lib/date/format.rb', line 958

def self._parse(str, comp=false)
  str = str.dup

  e = Format::Bag.new

  e._comp = comp

  str.gsub!(/[^-+',.\/:0-9@a-z\x80-\xff]+/in, ' ')

  _parse_time(str, e) # || _parse_beat(str, e)
  _parse_day(str, e)

  _parse_eu(str, e)     ||
  _parse_us(str, e)     ||
  _parse_iso(str, e)    ||
  _parse_jis(str, e)    ||
  _parse_vms(str, e)    ||
  _parse_sla_us(str, e) ||
  _parse_iso2(str, e)   ||
  _parse_year(str, e)   ||
  _parse_mon(str, e)    ||
  _parse_mday(str, e)   ||
  _parse_ddd(str, e)

  if str.sub!(/\b(bc\b|bce\b|b\.c\.|b\.c\.e\.)/in, ' ')
    if e.year
	e.year = -e.year + 1
    end
  end

  if str.sub!(/\A\s*(\d{1,2})\s*\z/n, ' ')
    if e.hour && !e.mday
	v = $1.to_i
	if (1..31) === v
 e.mday = v
	end
    end
    if e.mday && !e.hour
	v = $1.to_i
	if (0..24) === v
 e.hour = v
	end
    end
  end

  if e._comp and e.year
    if e.year >= 0 and e.year <= 99
	if e.year >= 69
 e.year += 1900
	else
 e.year += 2000
	end
    end
  end

  e.offset ||= zone_to_diff(e.zone) if e.zone

  e.to_hash
end

._parse_beat(str, e) ⇒ Object

:nodoc:



738
739
740
741
742
743
744
745
746
747
748
749
750
751
# File 'lib/date/format.rb', line 738

def self._parse_beat(str, e) # :nodoc:
  if str.sub!(/@\s*(\d+)(?:[,.](\d*))?/, ' ')
    beat = $1.to_i.to_r
    beat += $2.to_i.to_r / (10**$2.size) if $2
    secs = beat.to_r / 1000
    h, min, s, fr = self.day_fraction_to_time(secs)
    e.hour = h
    e.min = min
    e.sec = s
    e.sec_fraction = fr * 86400
    e.zone = '+01:00'
    true
  end
end

._parse_day(str, e) ⇒ Object

:nodoc:



669
670
671
672
673
674
675
676
677
678
679
# File 'lib/date/format.rb', line 669

def self._parse_day(str, e) # :nodoc:
  if str.sub!(/\b(#{Format::ABBR_DAYS.keys.join('|')})[^-\d\s]*/ino, ' ')
    e.wday = Format::ABBR_DAYS[$1.downcase]
    true
=begin
  elsif str.sub!(/\b(?!\dth)(su|mo|tu|we|th|fr|sa)\b/in, ' ')
    e.wday = %w(su mo tu we th fr sa).index($1.downcase)
    true
=end
  end
end

._parse_ddd(str, e) ⇒ Object

:nodoc:



887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
# File 'lib/date/format.rb', line 887

def self._parse_ddd(str, e) # :nodoc:
  if str.sub!(
/([-+]?)(\d{2,14})
  (?:
    \s*
    T?
    \s*
    (\d{2,6})(?:[,.](\d*))?
  )?
  (?:
    \s*
    (
      Z
    |
      [-+]\d{1,4}
    )
    \b
  )?
/inx,
' ')
    case $2.size
    when 2
	e.mday = $2[ 0, 2].to_i
    when 4
	e.mon  = $2[ 0, 2].to_i
	e.mday = $2[ 2, 2].to_i
    when 6
	e.year = ($1 + $2[ 0, 2]).to_i
	e.mon  = $2[ 2, 2].to_i
	e.mday = $2[ 4, 2].to_i
    when 8, 10, 12, 14
	e.year = ($1 + $2[ 0, 4]).to_i
	e.mon  = $2[ 4, 2].to_i
	e.mday = $2[ 6, 2].to_i
	e.hour = $2[ 8, 2].to_i if $2.size >= 10
	e.min  = $2[10, 2].to_i if $2.size >= 12
	e.sec  = $2[12, 2].to_i if $2.size >= 14
	e._comp = false
    when 3
	e.yday = $2[ 0, 3].to_i
    when 5
	e.year = ($1 + $2[ 0, 2]).to_i
	e.yday = $2[ 2, 3].to_i
    when 7
	e.year = ($1 + $2[ 0, 4]).to_i
	e.yday = $2[ 4, 3].to_i
    end
    if $3
	case $3.size
	when 2, 4, 6
 e.hour = $3[ 0, 2].to_i
 e.min  = $3[ 2, 2].to_i if $3.size >= 4
 e.sec  = $3[ 4, 2].to_i if $3.size >= 6
	end
    end
    if $4
	e.sec_fraction = $4.to_i.to_r / (10**$4.size)
    end
    if $5
	e.zone = $5
    end
    true
  end
end

._parse_eu(str, e) ⇒ Object

:nodoc:



753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
# File 'lib/date/format.rb', line 753

def self._parse_eu(str, e) # :nodoc:
  if str.sub!(
/'?(\d+)[^-\d\s]*
 \s*
 (#{Format::ABBR_MONTHS.keys.join('|')})[^-\d\s']*
 (?:
   \s*
   (c(?:e|\.e\.)|b(?:ce|\.c\.e\.)|a(?:d|\.d\.)|b(?:c|\.c\.))?
   \s*
   ('?-?\d+(?:(?:st|nd|rd|th)\b)?)
 )?
/inox,
' ') # '
    s3e(e, $4, Format::ABBR_MONTHS[$2.downcase], $1,
 $3 && $3[0,1].downcase == 'b')
    true
  end
end

._parse_iso(str, e) ⇒ Object

:nodoc:



791
792
793
794
795
796
# File 'lib/date/format.rb', line 791

def self._parse_iso(str, e) # :nodoc:
  if str.sub!(/('?[-+]?\d+)-(\d+)-('?-?\d+)/n, ' ')
    s3e(e, $1, $2, $3)
    true
  end
end

._parse_iso2(str, e) ⇒ Object

:nodoc:



798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
# File 'lib/date/format.rb', line 798

def self._parse_iso2(str, e) # :nodoc:
  if str.sub!(/\b(\d{2}|\d{4})?-?w(\d{2})(?:-?(\d+))?/in, ' ')
    e.cwyear = $1.to_i if $1
    e.cweek = $2.to_i
    e.cwday = $3.to_i if $3
    true
  elsif str.sub!(/--(\d{2})-(\d{2})\b/n, ' ')
    e.mon = $1.to_i
    e.mday = $2.to_i
    true
  elsif str.sub!(/\b(\d{2}|\d{4})-(\d{2,3})\b/n, ' ')
    e.year = $1.to_i
    if $2.size < 3
	e.mon = $2.to_i
    else
	e.yday = $2.to_i
    end
    true
  end
end

._parse_jis(str, e) ⇒ Object

:nodoc:



819
820
821
822
823
824
825
826
827
828
829
830
831
# File 'lib/date/format.rb', line 819

def self._parse_jis(str, e) # :nodoc:
  if str.sub!(/\b([MTSH])(\d+)\.(\d+)\.(\d+)/in, ' ')
    era = { 'm'=>1867,
     't'=>1911,
     's'=>1925,
     'h'=>1988
 }[$1.downcase]
    e.year = $2.to_i + era
    e.mon = $3.to_i
    e.mday = $4.to_i
    true
  end
end

._parse_mday(str, e) ⇒ Object

:nodoc:



880
881
882
883
884
885
# File 'lib/date/format.rb', line 880

def self._parse_mday(str, e) # :nodoc:
  if str.sub!(/(\d+)(st|nd|rd|th)\b/in, ' ')
    e.mday = $1.to_i
    true
  end
end

._parse_mon(str, e) ⇒ Object

:nodoc:



873
874
875
876
877
878
# File 'lib/date/format.rb', line 873

def self._parse_mon(str, e) # :nodoc:
  if str.sub!(/\b(#{Format::ABBR_MONTHS.keys.join('|')})\S*/ino, ' ')
    e.mon = Format::ABBR_MONTHS[$1.downcase]
    true
  end
end

._parse_sla_eu(str, e) ⇒ Object

:nodoc:



852
853
854
855
856
857
# File 'lib/date/format.rb', line 852

def self._parse_sla_eu(str, e) # :nodoc:
  if str.sub!(%r|('?-?\d+)[/.]\s*('?\d+)(?:[^\d]\s*('?-?\d+))?|n, ' ') # '
    s3e(e, $3, $2, $1)
    true
  end
end

._parse_sla_ja(str, e) ⇒ Object

:nodoc:



845
846
847
848
849
850
# File 'lib/date/format.rb', line 845

def self._parse_sla_ja(str, e) # :nodoc:
  if str.sub!(%r|('?-?\d+)[/.]\s*('?\d+)(?:[^\d]\s*('?-?\d+))?|n, ' ') # '
    s3e(e, $1, $2, $3)
    true
  end
end

._parse_sla_us(str, e) ⇒ Object

:nodoc:



859
860
861
862
863
864
# File 'lib/date/format.rb', line 859

def self._parse_sla_us(str, e) # :nodoc:
  if str.sub!(%r|('?-?\d+)[/.]\s*('?\d+)(?:[^\d]\s*('?-?\d+))?|n, ' ') # '
    s3e(e, $3, $1, $2)
    true
  end
end

._parse_time(str, e) ⇒ Object

:nodoc:



681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
# File 'lib/date/format.rb', line 681

def self._parse_time(str, e) # :nodoc:
  if str.sub!(
/(
   (?:
     \d+\s*:\s*\d+
     (?:
       \s*:\s*\d+(?:[,.]\d*)?
     )?
   |
     \d+\s*h(?:\s*\d+m?(?:\s*\d+s?)?)?
   )
   (?:
     \s*
     [ap](?:m\b|\.m\.)
   )?
 |
   \d+\s*[ap](?:m\b|\.m\.)
 )
 (?:
   \s*
   (
     (?:gmt|utc?)?[-+]\d+(?:[,.:]\d+(?::\d+)?)?
   |
     [a-z.\s]+(?:standard|daylight)\stime\b
   |
     [a-z]+(?:\sdst)?\b
   )
 )?
/inx,
' ')

    t = $1
    e.zone = $2 if $2

    t =~ /\A(\d+)h?
     (?:\s*:?\s*(\d+)m?
(?:
  \s*:?\s*(\d+)(?:[,.](\d+))?s?
)?
     )?
   (?:\s*([ap])(?:m\b|\.m\.))?/inx

    e.hour = $1.to_i
    e.min = $2.to_i if $2
    e.sec = $3.to_i if $3
    e.sec_fraction = $4.to_i.to_r / (10**$4.size) if $4

    if $5
	e.hour %= 12
	if $5.downcase == 'p'
 e.hour += 12
	end
    end
    true
  end
end

._parse_us(str, e) ⇒ Object

:nodoc:



772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
# File 'lib/date/format.rb', line 772

def self._parse_us(str, e) # :nodoc:
  if str.sub!(
/\b(#{Format::ABBR_MONTHS.keys.join('|')})[^-\d\s']*
 \s*
 ('?\d+)[^-\d\s']*
 (?:
   \s*
   (c(?:e|\.e\.)|b(?:ce|\.c\.e\.)|a(?:d|\.d\.)|b(?:c|\.c\.))?
   \s*
   ('?-?\d+)
 )?
/inox,
' ') # '
    s3e(e, $4, Format::ABBR_MONTHS[$1.downcase], $2,
 $3 && $3[0,1].downcase == 'b')
    true
  end
end

._parse_vms(str, e) ⇒ Object

:nodoc:



833
834
835
836
837
838
839
840
841
842
843
# File 'lib/date/format.rb', line 833

def self._parse_vms(str, e) # :nodoc:
  if str.sub!(/('?-?\d+)-(#{Format::ABBR_MONTHS.keys.join('|')})[^-]*
-('?-?\d+)/inox, ' ')
    s3e(e, $3, Format::ABBR_MONTHS[$2.downcase], $1)
    true
  elsif str.sub!(/\b(#{Format::ABBR_MONTHS.keys.join('|')})[^-]*
-('?-?\d+)(?:-('?-?\d+))?/inox, ' ')
    s3e(e, $3, Format::ABBR_MONTHS[$1.downcase], $2)
    true
  end
end

._parse_year(str, e) ⇒ Object

:nodoc:



866
867
868
869
870
871
# File 'lib/date/format.rb', line 866

def self._parse_year(str, e) # :nodoc:
  if str.sub!(/'(\d+)\b/in, ' ')
    e.year = $1.to_i
    true
  end
end

._strptime(str, fmt = '%F')) ⇒ Object



581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
# File 'lib/date/format.rb', line 581

def self._strptime(str, fmt='%F')
  e = Format::Bag.new
  return unless _strptime_i(str.dup, fmt, e)

  if e._cent
    if e.cwyear
	e.cwyear += e._cent * 100
    end
    if e.year
	e.  year += e._cent * 100
    end
  end

  if e._merid
    if e.hour
	e.hour %= 12
	e.hour += e._merid
    end
  end

  e.to_hash
end

._strptime_i(str, fmt, e) ⇒ Object

:nodoc:



384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
# File 'lib/date/format.rb', line 384

def self._strptime_i(str, fmt, e) # :nodoc:
  fmt.scan(/%[EO]?(:{1,3}z|.)|(.)/m) do |s, c|
    if s
	case s
	when 'A', 'a'
 return unless str.sub!(/\A(#{Format::DAYS.keys.join('|')})/io, '') ||
	str.sub!(/\A(#{Format::ABBR_DAYS.keys.join('|')})/io, '')
 val = Format::DAYS[$1.downcase] || Format::ABBR_DAYS[$1.downcase]
 return unless val
 e.wday = val
	when 'B', 'b', 'h'
 return unless str.sub!(/\A(#{Format::MONTHS.keys.join('|')})/io, '') ||
	str.sub!(/\A(#{Format::ABBR_MONTHS.keys.join('|')})/io, '')
 val = Format::MONTHS[$1.downcase] || Format::ABBR_MONTHS[$1.downcase]
 return unless val
 e.mon = val
	when 'C'
 return unless str.sub!(if num_pattern?($')
		 then /\A([-+]?\d{1,2})/
		 else /\A([-+]?\d{1,})/
		 end, '')
 val = $1.to_i
 e._cent = val
	when 'c'
 return unless _strptime_i(str, '%a %b %e %H:%M:%S %Y', e)
	when 'D'
 return unless _strptime_i(str, '%m/%d/%y', e)
	when 'd', 'e'
 return unless str.sub!(/\A( \d|\d{1,2})/, '')
 val = $1.to_i
 return unless (1..31) === val
 e.mday = val
	when 'F'
 return unless _strptime_i(str, '%Y-%m-%d', e)
	when 'G'
 return unless str.sub!(if num_pattern?($')
		 then /\A([-+]?\d{1,4})/
		 else /\A([-+]?\d{1,})/
		 end, '')
 val = $1.to_i
 e.cwyear = val
	when 'g'
 return unless str.sub!(/\A(\d{1,2})/, '')
 val = $1.to_i
 return unless (0..99) === val
 e.cwyear = val
 e._cent ||= if val >= 69 then 19 else 20 end
	when 'H', 'k'
 return unless str.sub!(/\A( \d|\d{1,2})/, '')
 val = $1.to_i
 return unless (0..24) === val
 e.hour = val
	when 'I', 'l'
 return unless str.sub!(/\A( \d|\d{1,2})/, '')
 val = $1.to_i
 return unless (1..12) === val
 e.hour = val
	when 'j'
 return unless str.sub!(/\A(\d{1,3})/, '')
 val = $1.to_i
 return unless (1..366) === val
 e.yday = val
	when 'L'
 return unless str.sub!(if num_pattern?($')
		 then /\A([-+]?\d{1,3})/
		 else /\A([-+]?\d{1,})/
		 end, '')
#	  val = $1.to_i.to_r / (10**3)
 val = $1.to_i.to_r / (10**$1.size)
 e.sec_fraction = val
	when 'M'
 return unless str.sub!(/\A(\d{1,2})/, '')
 val = $1.to_i
 return unless (0..59) === val
 e.min = val
	when 'm'
 return unless str.sub!(/\A(\d{1,2})/, '')
 val = $1.to_i
 return unless (1..12) === val
 e.mon = val
	when 'N'
 return unless str.sub!(if num_pattern?($')
		 then /\A([-+]?\d{1,9})/
		 else /\A([-+]?\d{1,})/
		 end, '')
#	  val = $1.to_i.to_r / (10**9)
 val = $1.to_i.to_r / (10**$1.size)
 e.sec_fraction = val
	when 'n', 't'
 return unless _strptime_i(str, "\s", e)
	when 'P', 'p'
 return unless str.sub!(/\A([ap])(?:m\b|\.m\.)/i, '')
 e._merid = if $1.downcase == 'a' then 0 else 12 end
	when 'Q'
 return unless str.sub!(/\A(-?\d{1,})/, '')
 val = $1.to_i.to_r / 10**3
 e.seconds = val
	when 'R'
 return unless _strptime_i(str, '%H:%M', e)
	when 'r'
 return unless _strptime_i(str, '%I:%M:%S %p', e)
	when 'S'
 return unless str.sub!(/\A(\d{1,2})/, '')
 val = $1.to_i
 return unless (0..60) === val
 e.sec = val
	when 's'
 return unless str.sub!(/\A(-?\d{1,})/, '')
 val = $1.to_i
 e.seconds = val
	when 'T'
 return unless _strptime_i(str, '%H:%M:%S', e)
	when 'U', 'W'
 return unless str.sub!(/\A(\d{1,2})/, '')
 val = $1.to_i
 return unless (0..53) === val
 e.__send__(if s == 'U' then :wnum0= else :wnum1= end, val)
	when 'u'
 return unless str.sub!(/\A(\d{1})/, '')
 val = $1.to_i
 return unless (1..7) === val
 e.cwday = val
	when 'V'
 return unless str.sub!(/\A(\d{1,2})/, '')
 val = $1.to_i
 return unless (1..53) === val
 e.cweek = val
	when 'v'
 return unless _strptime_i(str, '%e-%b-%Y', e)
	when 'w'
 return unless str.sub!(/\A(\d{1})/, '')
 val = $1.to_i
 return unless (0..6) === val
 e.wday = val
	when 'X'
 return unless _strptime_i(str, '%H:%M:%S', e)
	when 'x'
 return unless _strptime_i(str, '%m/%d/%y', e)
	when 'Y'
 return unless str.sub!(if num_pattern?($')
		 then /\A([-+]?\d{1,4})/
		 else /\A([-+]?\d{1,})/
		 end, '')
 val = $1.to_i
 e.year = val
	when 'y'
 return unless str.sub!(/\A(\d{1,2})/, '')
 val = $1.to_i
 return unless (0..99) === val
 e.year = val
 e._cent ||= if val >= 69 then 19 else 20 end
	when 'Z', /\A:{0,3}z/
 return unless str.sub!(/\A((?:gmt|utc?)?[-+]\d+(?:[,.:]\d+(?::\d+)?)?
		    |[a-z.\s]+(?:standard|daylight)\s+time\b
		    |[a-z]+(?:\s+dst)?\b
		    )/ix, '')
 val = $1
 e.zone = val
 offset = zone_to_diff(val)
 e.offset = offset
	when '%'
 return unless str.sub!(/\A%/, '')
	when '+'
 return unless _strptime_i(str, '%a %b %e %H:%M:%S %Z %Y', e)
	when '1'
 if $VERBOSE
   warn("warning: strptime: %1 is deprecated; forget this")
 end
 return unless str.sub!(/\A(\d+)/, '')
 val = $1.to_i
 e.jd = val
	when '2'
 if $VERBOSE
   warn("warning: strptime: %2 is deprecated; use '%Y-%j'")
 end
 return unless _strptime_i(str, '%Y-%j', e)
	when '3'
 if $VERBOSE
   warn("warning: strptime: %3 is deprecated; use '%F'")
 end
 return unless _strptime_i(str, '%F', e)
	else
 return unless str.sub!(Regexp.new('\\A' + Regexp.quote(s)), '')
	end
    else
	case c
	when /\A[\s\v]/
 str.sub!(/\A[\s\v]+/, '')
	else
 return unless str.sub!(Regexp.new('\\A' + Regexp.quote(c)), '')
	end
    end
  end
end

.ajd_to_amjd(ajd) ⇒ Object

Convert an Astronomical Julian Day Number to an Astronomical Modified Julian Day Number.



513
# File 'lib/date.rb', line 513

def self.ajd_to_amjd(ajd) ajd - 4800001.to_r/2 end

.ajd_to_jd(ajd, of = 0) ⇒ Object

Convert an Astronomical Julian Day Number to a (civil) Julian Day Number.

ajd is the Astronomical Julian Day Number to convert. of is the offset from UTC as a fraction of a day (defaults to 0).

Returns the (civil) Julian Day Number as [day_number, fraction] where fraction is always 1/2.



479
# File 'lib/date.rb', line 479

def self.ajd_to_jd(ajd, of=0) (ajd + of + 1.to_r/2).divmod(1) end

.amjd_to_ajd(amjd) ⇒ Object

Convert an Astronomical Modified Julian Day Number to an Astronomical Julian Day Number.



509
# File 'lib/date.rb', line 509

def self.amjd_to_ajd(amjd) amjd + 4800001.to_r/2 end

.civil(y = 4712, m = 1, d = 1, sg = ITALY) ⇒ Object Also known as: new

Create a new Date object for the Civil Date specified by year y, month m, and day-of-month d.

m and d can be negative, in which case they count backwards from the end of the year and the end of the month respectively. No wraparound is performed, however, and invalid values cause an ArgumentError to be raised. can be negative

y defaults to -4712, m to 1, and d to 1; this is Julian Day Number day 0.

sg specifies the Day of Calendar Reform.



725
726
727
728
729
730
# File 'lib/date.rb', line 725

def self.civil(y=-4712, m=1, d=1, sg=ITALY)
  unless jd = valid_civil?(y, m, d, sg)
    raise ArgumentError, 'invalid date'
  end
  new!(jd_to_ajd(jd, 0, 0), 0, sg)
end

.civil_to_jd(y, m, d, sg = GREGORIAN) ⇒ Object

Convert a Civil Date to a Julian Day Number. y, m, and d are the year, month, and day of the month. sg specifies the Day of Calendar Reform.

Returns the corresponding Julian Day Number.



383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
# File 'lib/date.rb', line 383

def self.civil_to_jd(y, m, d, sg=GREGORIAN)
  if m <= 2
    y -= 1
    m += 12
  end
  a = (y / 100.0).floor
  b = 2 - a + (a / 4.0).floor
  jd = (365.25 * (y + 4716)).floor +
    (30.6001 * (m + 1)).floor +
    d + b - 1524
  if julian?(jd, sg)
    jd -= b
  end
  jd
end

.commercial(y = 1582, w = 41, d = 5, sg = ITALY) ⇒ Object

Create a new Date object for the Commercial Date specified by year y, week-of-year w, and day-of-week d.

Monday is day-of-week 1; Sunday is day-of-week 7.

w and d can be negative, in which case they count backwards from the end of the year and the end of the week respectively. No wraparound is performed, however, and invalid values cause an ArgumentError to be raised.

y defaults to 1582, w to 41, and d to 5, the Day of Calendar Reform for Italy and the Catholic countries.

sg specifies the Day of Calendar Reform.



748
749
750
751
752
753
# File 'lib/date.rb', line 748

def self.commercial(y=1582, w=41, d=5, sg=ITALY)
  unless jd = valid_commercial?(y, w, d, sg)
    raise ArgumentError, 'invalid date'
  end
  new!(jd_to_ajd(jd, 0, 0), 0, sg)
end

.commercial_to_jd(y, w, d, ns = GREGORIAN) ⇒ Object

Convert a Commercial Date to a Julian Day Number.

y, w, and d are the (commercial) year, week of the year, and day of the week of the Commercial Date to convert. sg specifies the Day of Calendar Reform.



432
433
434
435
436
437
# File 'lib/date.rb', line 432

def self.commercial_to_jd(y, w, d, ns=GREGORIAN)
  jd = civil_to_jd(y, 1, 4, ns)
  (jd - (((jd - 1) + 1) % 7)) +
    7 * (w - 1) +
    (d - 1)
end

.complete_frags(elem) ⇒ Object

:nodoc:



784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
# File 'lib/date.rb', line 784

def self.complete_frags(elem) # :nodoc:
  i = 0
  g = [[:time, [:hour, :min, :sec]],
[nil, [:jd]],
[:ordinal, [:year, :yday, :hour, :min, :sec]],
[:civil, [:year, :mon, :mday, :hour, :min, :sec]],
[:commercial, [:cwyear, :cweek, :cwday, :hour, :min, :sec]],
[:wday, [:wday, :hour, :min, :sec]],
[:wnum0, [:year, :wnum0, :wday, :hour, :min, :sec]],
[:wnum1, [:year, :wnum1, :wday, :hour, :min, :sec]],
[nil, [:cwyear, :cweek, :wday, :hour, :min, :sec]],
[nil, [:year, :wnum0, :cwday, :hour, :min, :sec]],
[nil, [:year, :wnum1, :cwday, :hour, :min, :sec]]].
    collect{|k, a| e = elem.values_at(*a).compact; [k, a, e]}.
    select{|k, a, e| e.size > 0}.
    sort_by{|k, a, e| [e.size, i -= 1]}.last

  d = nil

  if g && g[0] && (g[1].size - g[2].size) != 0
    d ||= Date.today

    case g[0]
    when :ordinal
	elem[:year] ||= d.year
	elem[:yday] ||= 1
    when :civil
	g[1].each do |e|
 break if elem[e]
 elem[e] = d.__send__(e)
	end
	elem[:mon]  ||= 1
	elem[:mday] ||= 1
    when :commercial
	g[1].each do |e|
 break if elem[e]
 elem[e] = d.__send__(e)
	end
	elem[:cweek] ||= 1
	elem[:cwday] ||= 1
    when :wday
	elem[:jd] ||= (d - d.wday + elem[:wday]).jd
    when :wnum0
	g[1].each do |e|
 break if elem[e]
 elem[e] = d.__send__(e)
	end
	elem[:wnum0] ||= 0
	elem[:wday]  ||= 0
    when :wnum1
	g[1].each do |e|
 break if elem[e]
 elem[e] = d.__send__(e)
	end
	elem[:wnum1] ||= 0
	elem[:wday]  ||= 0
    end
  end

  if g && g[0] == :time
    if self <= DateTime
	d ||= Date.today
	elem[:jd] ||= d.jd
    end
  end

  elem[:hour] ||= 0
  elem[:min]  ||= 0
  elem[:sec]  ||= 0
  elem[:sec] = [elem[:sec], 59].min

  elem
end

.day_fraction_to_time(fr) ⇒ Object

Convert a fractional day fr to [hours, minutes, seconds, fraction_of_a_second]



494
495
496
497
498
499
# File 'lib/date.rb', line 494

def self.day_fraction_to_time(fr)
  h,   fr = fr.divmod(1.to_r/24)
  min, fr = fr.divmod(1.to_r/1440)
  s,   fr = fr.divmod(1.to_r/86400)
  return h, min, s, fr
end

.fix_style(jd, sg) ⇒ Object

:nodoc:



347
348
349
350
351
# File 'lib/date.rb', line 347

def self.fix_style(jd, sg) # :nodoc:
  if julian?(jd, sg)
  then JULIAN
  else GREGORIAN end
end

.gregorian?(jd, sg) ⇒ Boolean

Does a given Julian Day Number fall inside the new-style (Gregorian) calendar?

The reverse of self.os? See the documentation for that method for more details.

Returns:

  • (Boolean)


345
# File 'lib/date.rb', line 345

def self.gregorian? (jd, sg) !julian?(jd, sg) end

.gregorian_leap?(y) ⇒ Boolean Also known as: leap?

Is a year a leap year in the Gregorian calendar?

All years divisible by 4 are leap years in the Gregorian calendar, except for years divisible by 100 and not by 400.

Returns:

  • (Boolean)


545
# File 'lib/date.rb', line 545

def self.gregorian_leap? (y) y % 4 == 0 && y % 100 != 0 || y % 400 == 0 end

.jd(jd = 0, sg = ITALY) ⇒ Object

Create a new Date object from a Julian Day Number.

jd is the Julian Day Number; if not specified, it defaults to 0. sg specifies the Day of Calendar Reform.



690
691
692
693
# File 'lib/date.rb', line 690

def self.jd(jd=0, sg=ITALY)
  jd = valid_jd?(jd, sg)
  new!(jd_to_ajd(jd, 0, 0), 0, sg)
end

.jd_to_ajd(jd, fr, of = 0) ⇒ Object

Convert a (civil) Julian Day Number to an Astronomical Julian Day Number.

jd is the Julian Day Number to convert, and fr is a fractional day. of is the offset from UTC as a fraction of a day (defaults to 0).

Returns the Astronomical Julian Day Number as a single numeric value.



490
# File 'lib/date.rb', line 490

def self.jd_to_ajd(jd, fr, of=0) jd + fr - of - 1.to_r/2 end

.jd_to_civil(jd, sg = GREGORIAN) ⇒ Object

Convert a Julian Day Number to a Civil Date. jd is the Julian Day Number. sg specifies the Day of Calendar Reform.

Returns the corresponding [year, month, day_of_month] as a three-element array.



405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
# File 'lib/date.rb', line 405

def self.jd_to_civil(jd, sg=GREGORIAN)
  if julian?(jd, sg)
    a = jd
  else
    x = ((jd - 1867216.25) / 36524.25).floor
    a = jd + 1 + x - (x / 4.0).floor
  end
  b = a + 1524
  c = ((b - 122.1) / 365.25).floor
  d = (365.25 * c).floor
  e = ((b - d) / 30.6001).floor
  dom = b - d - (30.6001 * e).floor
  if e <= 13
    m = e - 1
    y = c - 4716
  else
    m = e - 13
    y = c - 4715
  end
  return y, m, dom
end

.jd_to_commercial(jd, sg = GREGORIAN) ⇒ Object

Convert a Julian Day Number to a Commercial Date

jd is the Julian Day Number to convert. sg specifies the Day of Calendar Reform.

Returns the corresponding Commercial Date as

commercial_year, week_of_year, day_of_week


446
447
448
449
450
451
452
453
454
# File 'lib/date.rb', line 446

def self.jd_to_commercial(jd, sg=GREGORIAN)
  ns = fix_style(jd, sg)
  a = jd_to_civil(jd - 3, ns)[0]
  y = if jd >= commercial_to_jd(a + 1, 1, 1, ns) then a + 1 else a end
  w = 1 + ((jd - commercial_to_jd(y, 1, 1, ns)) / 7).floor
  d = (jd + 1) % 7
  d = 7 if d == 0
  return y, w, d
end

.jd_to_ld(jd) ⇒ Object

Convert a Julian Day Number to the number of days since the adoption of the Gregorian Calendar (in Italy).



529
# File 'lib/date.rb', line 529

def self.jd_to_ld(jd) jd - 2299160 end

.jd_to_mjd(jd) ⇒ Object

Convert a Julian Day Number to a Modified Julian Day Number.



521
# File 'lib/date.rb', line 521

def self.jd_to_mjd(jd) jd - 2400001 end

.jd_to_ordinal(jd, sg = GREGORIAN) ⇒ Object

Convert a Julian Day Number to an Ordinal Date.

jd is the Julian Day Number to convert. sg specifies the Day of Calendar Reform.

Returns the corresponding Ordinal Date as

year, day_of_year


372
373
374
375
376
# File 'lib/date.rb', line 372

def self.jd_to_ordinal(jd, sg=GREGORIAN)
  y = jd_to_civil(jd, sg)[0]
  doy = jd - civil_to_jd(y - 1, 12, 31, fix_style(jd, sg))
  return y, doy
end

.jd_to_wday(jd) ⇒ Object

Convert a Julian Day Number to the day of the week.

Sunday is day-of-week 0; Saturday is day-of-week 6.



534
# File 'lib/date.rb', line 534

def self.jd_to_wday(jd) (jd + 1) % 7 end

.jd_to_weeknum(jd, f = 0, sg = GREGORIAN) ⇒ Object

:nodoc:



461
462
463
464
465
466
467
# File 'lib/date.rb', line 461

def self.jd_to_weeknum(jd, f=0, sg=GREGORIAN) # :nodoc:
  ns = fix_style(jd, sg)
  y, m, d = jd_to_civil(jd, ns)
  a = civil_to_jd(y, 1, 1, ns) + 6
  w, d = (jd - (a - ((a - f) + 1) % 7) + 7).divmod(7)
  return y, w, d
end

.julian?(jd, sg) ⇒ Boolean

Does a given Julian Day Number fall inside the old-style (Julian) calendar?

jd is the Julian Day Number in question. sg may be Date::GREGORIAN, in which case the answer is false; it may be Date::JULIAN, in which case the answer is true; or it may a number representing the Day of Calendar Reform. Date::ENGLAND and Date::ITALY are two possible such days.

Returns:

  • (Boolean)


327
328
329
330
331
332
333
334
335
336
337
338
# File 'lib/date.rb', line 327

def self.julian? (jd, sg)
  case sg
  when Numeric
    jd < sg
  else
    if $VERBOSE
	warn("#{caller.shift.sub(/:in .*/, '')}: " \
"warning: do not use non-numerical object as julian day number anymore")
    end
    not sg
  end
end

.julian_leap?(y) ⇒ Boolean

Is a year a leap year in the Julian calendar?

All years divisible by 4 are leap years in the Julian calendar.

Returns:

  • (Boolean)


539
# File 'lib/date.rb', line 539

def self.julian_leap? (y) y % 4 == 0 end

.ld_to_jd(ld) ⇒ Object

Convert a count of the number of days since the adoption of the Gregorian Calendar (in Italy) to a Julian Day Number.



525
# File 'lib/date.rb', line 525

def self.ld_to_jd(ld) ld + 2299160 end

.mjd_to_jd(mjd) ⇒ Object

Convert a Modified Julian Day Number to a Julian Day Number.



517
# File 'lib/date.rb', line 517

def self.mjd_to_jd(mjd) mjd + 2400001 end

.new_by_frags(elem, sg) ⇒ Object

:nodoc:



927
928
929
930
931
932
933
934
# File 'lib/date.rb', line 927

def self.new_by_frags(elem, sg) # :nodoc:
  elem = rewrite_frags(elem)
  elem = complete_frags(elem)
  unless jd = valid_date_frags?(elem, sg)
    raise ArgumentError, 'invalid date'
  end
  new!(jd_to_ajd(jd, 0, 0), 0, sg)
end

.now(sg = ITALY) ⇒ Object

Create a new DateTime object representing the current time.

sg specifies the Day of Calendar Reform.



1635
1636
1637
1638
1639
1640
1641
1642
# File 'lib/date.rb', line 1635

def self.now(sg=ITALY)
  t = Time.now
  jd = civil_to_jd(t.year, t.mon, t.mday, sg)
  fr = time_to_day_fraction(t.hour, t.min, [t.sec, 59].min) +
    Rational(t.usec, 86400_000_000)
  of = Rational(t.utc_offset, 86400)
  new!(jd_to_ajd(jd, fr, of), of, sg)
end

.num_pattern?(s) ⇒ Boolean

def iso8601() strftime('%F') end

def rfc3339() iso8601 end

def rfc2822() strftime('%a, %-d %b %Y %T %z') end

alias_method :rfc822, :rfc2822

def jisx0301
  if jd < 2405160
    iso8601
  else
    case jd
    when 2405160...2419614

g = 'M%02d' % (year - 1867)

when 2419614...2424875

g = 'T%02d' % (year - 1911)

when 2424875...2447535

g = 'S%02d' % (year - 1925)

else

g = 'H%02d' % (year - 1988)

    end
    g + strftime('.%m.%d')
  end
end

def beat(n=0)
  i, f = (new_offset(1.to_r/24).day_fraction * 1000).divmod(1)
  ('@%03d' % i) +
    if n < 1

"

else

'.%0*d' % [n, (f / (1.to_r/(10**n))).round]

    end
end

Returns:

  • (Boolean)


378
379
380
# File 'lib/date/format.rb', line 378

def self.num_pattern? (s) # :nodoc:
  /\A%[EO]?[CDdeFGgHIjkLlMmNQRrSsTUuVvWwXxYy\d]/ =~ s || /\A\d/ =~ s
end

.ordinal(y = 4712, d = 1, sg = ITALY) ⇒ Object

Create a new Date object from an Ordinal Date, specified by year y and day-of-year d. d can be negative, in which it counts backwards from the end of the year. No year wraparound is performed, however. An invalid value for d results in an ArgumentError being raised.

y defaults to -4712, and d to 1; this is Julian Day Number day 0.

sg specifies the Day of Calendar Reform.



705
706
707
708
709
710
# File 'lib/date.rb', line 705

def self.ordinal(y=-4712, d=1, sg=ITALY)
  unless jd = valid_ordinal?(y, d, sg)
    raise ArgumentError, 'invalid date'
  end
  new!(jd_to_ajd(jd, 0, 0), 0, sg)
end

.ordinal_to_jd(y, d, sg = GREGORIAN) ⇒ Object

Convert an Ordinal Date to a Julian Day Number.

y and d are the year and day-of-year to convert. sg specifies the Day of Calendar Reform.

Returns the corresponding Julian Day Number.



361
362
363
# File 'lib/date.rb', line 361

def self.ordinal_to_jd(y, d, sg=GREGORIAN)
  civil_to_jd(y, 1, d, sg)
end

.parse(str = '-4712-01-01',, comp = false, sg = ITALY) ⇒ Object

Create a new Date object by parsing from a String, without specifying the format.

str is a String holding a date representation. comp specifies whether to interpret 2-digit years as 19XX (>= 69) or 20XX (< 69); the default is not to. The method will attempt to parse a date from the String using various heuristics; see #_parse in date/format.rb for more details. If parsing fails, an ArgumentError will be raised.

The default str is '-4712-01-01'; this is Julian Day Number day 0.

sg specifies the Day of Calendar Reform.



973
974
975
976
# File 'lib/date.rb', line 973

def self.parse(str='-4712-01-01', comp=false, sg=ITALY)
  elem = _parse(str, comp)
  new_by_frags(elem, sg)
end

.rewrite_frags(elem) ⇒ Object

:nodoc:



764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
# File 'lib/date.rb', line 764

def self.rewrite_frags(elem) # :nodoc:
  elem ||= {}
  if seconds = elem[:seconds]
    d,   fr = seconds.divmod(86400)
    h,   fr = fr.divmod(3600)
    min, fr = fr.divmod(60)
    s,   fr = fr.divmod(1)
    elem[:jd] = UNIXEPOCH + d
    elem[:hour] = h
    elem[:min] = min
    elem[:sec] = s
    elem[:sec_fraction] = fr
    elem.delete(:seconds)
    elem.delete(:offset)
  end
  elem
end

.s3e(e, y, m, d, bc = false) ⇒ Object



604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
# File 'lib/date/format.rb', line 604

def self.s3e(e, y, m, d, bc=false)
  unless String === m
    m = m.to_s
  end

  if y == nil
    if d && d.size > 2
	y = d
	d = nil
    end
    if d && d[0,1] == "'"
	y = d
	d = nil
    end
  end

  if y
    y.scan(/(\d+)(.+)?/)
    if $2
	y, d = d, $1
    end
  end

  if m
    if m[0,1] == "'" || m.size > 2
	y, m, d = m, d, y # us -> be
    end
  end

  if d
    if d[0,1] == "'" || d.size > 2
	y, d = d, y
    end
  end

  if y
    y =~ /([-+])?(\d+)/
    if $1 || $2.size > 2
	c = false
    end
    iy = $&.to_i
    if bc
	iy = -iy + 1
    end
    e.year = iy
  end

  if m
    m =~ /\d+/
    e.mon = $&.to_i
  end

  if d
    d =~ /\d+/
    e.mday = $&.to_i
  end

  if c != nil
    e._comp = c
  end

end

.strptime(str = '-4712-01-01',, fmt = '%F',, sg = ITALY) ⇒ Object

Create a new Date object by parsing from a String according to a specified format.

str is a String holding a date representation. fmt is the format that the date is in. See date/format.rb for details on supported formats.

The default str is '-4712-01-01', and the default fmt is '%F', which means Year-Month-Day_of_Month. This gives Julian Day Number day 0.

sg specifies the Day of Calendar Reform.

An ArgumentError will be raised if str cannot be parsed.



953
954
955
956
# File 'lib/date.rb', line 953

def self.strptime(str='-4712-01-01', fmt='%F', sg=ITALY)
  elem = _strptime(str, fmt)
  new_by_frags(elem, sg)
end

.time_to_day_fraction(h, min, s) ⇒ Object

Convert an h hour, min minutes, s seconds period to a fractional day.



503
504
505
# File 'lib/date.rb', line 503

def self.time_to_day_fraction(h, min, s)
  h.to_r/24 + min.to_r/1440 + s.to_r/86400
end

.today(sg = ITALY) ⇒ Object

Create a new Date object representing today.

sg specifies the Day of Calendar Reform.



1626
1627
1628
1629
1630
# File 'lib/date.rb', line 1626

def self.today(sg=ITALY)
  t = Time.now
  jd = civil_to_jd(t.year, t.mon, t.mday, sg)
  new!(jd_to_ajd(jd, 0, 0), 0, sg)
end

.valid_civil?(y, m, d, sg = ITALY) ⇒ Boolean Also known as: valid_date?

Do year y, month m, and day-of-month d make a valid Civil Date? Returns the corresponding Julian Day Number if they do, nil if they don't.

m and d can be negative, in which case they count backwards from the end of the year and the end of the month respectively. No wraparound is performed, however, and invalid values cause an ArgumentError to be raised. A date falling in the period skipped in the Day of Calendar Reform adjustment is not valid.

sg specifies the Day of Calendar Reform.

Returns:

  • (Boolean)


595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
# File 'lib/date.rb', line 595

def self.valid_civil? (y, m, d, sg=ITALY)
  if m < 0
    m += 13
  end
  if d < 0
    ny, nm = (y * 12 + m).divmod(12)
    nm,    = (nm + 1).divmod(1)
    jd = civil_to_jd(ny, nm, d + 1, sg)
    ns = fix_style(jd, sg)
    return unless [y, m] == jd_to_civil(jd, sg)[0..1]
    return unless [ny, nm, 1] == jd_to_civil(jd - d, ns)
  else
    jd = civil_to_jd(y, m, d, sg)
    return unless [y, m, d] == jd_to_civil(jd, sg)
  end
  jd
end

.valid_commercial?(y, w, d, sg = ITALY) ⇒ Boolean

Do year y, week-of-year w, and day-of-week d make a valid Commercial Date? Returns the corresponding Julian Day Number if they do, nil if they don't.

Monday is day-of-week 1; Sunday is day-of-week 7.

w and d can be negative, in which case they count backwards from the end of the year and the end of the week respectively. No wraparound is performed, however, and invalid values cause an ArgumentError to be raised. A date falling in the period skipped in the Day of Calendar Reform adjustment is not valid.

sg specifies the Day of Calendar Reform.

Returns:

  • (Boolean)


629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
# File 'lib/date.rb', line 629

def self.valid_commercial? (y, w, d, sg=ITALY)
  if d < 0
    d += 8
  end
  if w < 0
    ny, nw, nd =
	jd_to_commercial(commercial_to_jd(y + 1, 1, 1) + w * 7)
    return unless ny == y
    w = nw
  end
  jd = commercial_to_jd(y, w, d)
  return unless gregorian?(jd, sg)
  return unless [y, w, d] == jd_to_commercial(jd)
  jd
end

.valid_date_frags?(elem, sg) ⇒ Boolean

:nodoc:

Returns:

  • (Boolean)


860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
# File 'lib/date.rb', line 860

def self.valid_date_frags?(elem, sg) # :nodoc:
  catch :jd do
    a = elem.values_at(:jd)
    if a.all?
	if jd = valid_jd?(*(a << sg))
 throw :jd, jd
	end
    end

    a = elem.values_at(:year, :yday)
    if a.all?
	if jd = valid_ordinal?(*(a << sg))
 throw :jd, jd
	end
    end

    a = elem.values_at(:year, :mon, :mday)
    if a.all?
	if jd = valid_civil?(*(a << sg))
 throw :jd, jd
	end
    end

    a = elem.values_at(:cwyear, :cweek, :cwday)
    if a[2].nil? && elem[:wday]
	a[2] = elem[:wday].nonzero? || 7
    end
    if a.all?
	if jd = valid_commercial?(*(a << sg))
 throw :jd, jd
	end
    end

    a = elem.values_at(:year, :wnum0, :wday)
    if a[2].nil? && elem[:cwday]
	a[2] = elem[:cwday] % 7
    end
    if a.all?
	if jd = valid_weeknum?(*(a << 0 << sg))
 throw :jd, jd
	end
    end

    a = elem.values_at(:year, :wnum1, :wday)
    if a[2]
	a[2] = (a[2] - 1) % 7
    end
    if a[2].nil? && elem[:cwday]
	a[2] = (elem[:cwday] - 1) % 7
    end
    if a.all?
	if jd = valid_weeknum?(*(a << 1 << sg))
 throw :jd, jd
	end
    end
  end
end

.valid_jd?(jd, sg = ITALY) ⇒ Boolean

Is jd a valid Julian Day Number?

If it is, returns it. In fact, any value is treated as a valid Julian Day Number.

Returns:

  • (Boolean)


554
# File 'lib/date.rb', line 554

def self.valid_jd? (jd, sg=ITALY) jd end

.valid_ordinal?(y, d, sg = ITALY) ⇒ Boolean

Do the year y and day-of-year d make a valid Ordinal Date? Returns the corresponding Julian Day Number if they do, or nil if they don't.

d can be a negative number, in which case it counts backwards from the end of the year (-1 being the last day of the year). No year wraparound is performed, however, so valid values of d are -365 .. -1, 1 .. 365 on a non-leap-year, -366 .. -1, 1 .. 366 on a leap year. A date falling in the period skipped in the Day of Calendar Reform adjustment is not valid.

sg specifies the Day of Calendar Reform.

Returns:

  • (Boolean)


569
570
571
572
573
574
575
576
577
578
579
580
581
# File 'lib/date.rb', line 569

def self.valid_ordinal? (y, d, sg=ITALY)
  if d < 0
    ny, = (y + 1).divmod(1)
    jd = ordinal_to_jd(ny, d + 1, sg)
    ns = fix_style(jd, sg)
    return unless [y] == jd_to_ordinal(jd, sg)[0..0]
    return unless [ny, 1] == jd_to_ordinal(jd - d, ns)
  else
    jd = ordinal_to_jd(y, d, sg)
    return unless [y, d] == jd_to_ordinal(jd, sg)
  end
  jd
end

.valid_time?(h, min, s) ⇒ Boolean

Do hour h, minute min, and second s constitute a valid time?

If they do, returns their value as a fraction of a day. If not, returns nil.

The 24-hour clock is used. Negative values of h, min, and sec are treating as counting backwards from the end of the next larger unit (e.g. a min of -2 is treated as 58). No wraparound is performed.

Returns:

  • (Boolean)


672
673
674
675
676
677
678
679
680
681
682
683
# File 'lib/date.rb', line 672

def self.valid_time? (h, min, s)
  h   += 24 if h   < 0
  min += 60 if min < 0
  s   += 60 if s   < 0
  return unless ((0..23) === h &&
   (0..59) === min &&
   (0..59) === s) ||
  (24 == h &&
    0 == min &&
    0 == s)
  time_to_day_fraction(h, min, s)
end

.valid_time_frags?(elem) ⇒ Boolean

:nodoc:

Returns:

  • (Boolean)


920
921
922
923
# File 'lib/date.rb', line 920

def self.valid_time_frags? (elem) # :nodoc:
  h, min, s = elem.values_at(:hour, :min, :sec)
  valid_time?(h, min, s)
end

.valid_weeknum?(y, w, d, f, sg = ITALY) ⇒ Boolean

:nodoc:

Returns:

  • (Boolean)


645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
# File 'lib/date.rb', line 645

def self.valid_weeknum? (y, w, d, f, sg=ITALY) # :nodoc:
  if d < 0
    d += 7
  end
  if w < 0
    ny, nw, nd, nf =
	jd_to_weeknum(weeknum_to_jd(y + 1, 1, f, f) + w * 7, f)
    return unless ny == y
    w = nw
  end
  jd = weeknum_to_jd(y, w, d, f)
  return unless gregorian?(jd, sg)
  return unless [y, w, d] == jd_to_weeknum(jd, f)
  jd
end

.weeknum(y = 1582, w = 41, d = 5, f = 0, sg = ITALY) ⇒ Object

:nodoc:



755
756
757
758
759
760
# File 'lib/date.rb', line 755

def self.weeknum(y=1582, w=41, d=5, f=0, sg=ITALY) # :nodoc:
  unless jd = valid_weeknum?(y, w, d, f, sg)
    raise ArgumentError, 'invalid date'
  end
  new!(jd_to_ajd(jd, 0, 0), 0, sg)
end

.weeknum_to_jd(y, w, d, f = 0, ns = GREGORIAN) ⇒ Object

:nodoc:



456
457
458
459
# File 'lib/date.rb', line 456

def self.weeknum_to_jd(y, w, d, f=0, ns=GREGORIAN) # :nodoc:
  a = civil_to_jd(y, 1, 1, ns) + 6
  (a - ((a - f) + 1) % 7 - 7) + 7 * w + d
end

.zone_to_diff(zone) ⇒ Object

:nodoc:



1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
# File 'lib/date/format.rb', line 1018

def self.zone_to_diff(zone) # :nodoc:
  zone = zone.downcase
  if zone.sub!(/\s+(standard|daylight)\s+time\z/, '')
    dst = $1 == 'daylight'
  else
    dst = zone.sub!(/\s+dst\z/, '')
  end
  if Format::ZONES.include?(zone)
    offset = Format::ZONES[zone]
    offset += 3600 if dst
  elsif zone.sub!(/\A(?:gmt|utc?)?([-+])/, '')
    sign = $1
    if zone.include?(':')
	hour, min, sec, = zone.split(':')
    elsif zone.include?(',') || zone.include?('.')
	hour, fr, = zone.split(/[,.]/)
	min = fr.to_i.to_r / (10**fr.size) * 60
    else
	case zone.size
	when 3
 hour = zone[0,1]
 min = zone[1,2]
	else
 hour = zone[0,2]
 min = zone[2,2]
 sec = zone[4,2]
	end
    end
    offset = hour.to_i * 3600 + min.to_i * 60 + sec.to_i
    offset *= -1 if sign == '-'
  end
  offset
end

Instance Method Details

#+(n) ⇒ Object

Return a new Date object that is n days later than the current one.

n may be a negative value, in which case the new Date is earlier than the current one; however, #-() might be more intuitive.

If n is not a Numeric, a TypeError will be thrown. In particular, two Dates cannot be added to each other.

Raises:

  • (TypeError)


1200
1201
1202
1203
1204
1205
# File 'lib/date.rb', line 1200

def + (n)
  case n
  when Numeric; return self.class.new!(@ajd + n, @of, @sg)
  end
  raise TypeError, 'expected numeric'
end

#-(x) ⇒ Object

If x is a Numeric value, create a new Date object that is x days earlier than the current one.

If x is a Date, return the number of days between the two dates; or, more precisely, how many days later the current date is than x.

If x is neither Numeric nor a Date, a TypeError is raised.

Raises:

  • (TypeError)


1215
1216
1217
1218
1219
1220
1221
# File 'lib/date.rb', line 1215

def - (x)
  case x
  when Numeric; return self.class.new!(@ajd - x, @of, @sg)
  when Date;    return @ajd - x.ajd
  end
  raise TypeError, 'expected numeric or date'
end

#<<(n) ⇒ Object

Return a new Date object that is n months earlier than the current one.

If the day-of-the-month of the current Date is greater than the last day of the target month, the day-of-the-month of the returned Date will be the last day of the target month.



1290
# File 'lib/date.rb', line 1290

def << (n) self >> -n end

#<=>(other) ⇒ Object

Compare this date with another date.

other can also be a Numeric value, in which case it is interpreted as an Astronomical Julian Day Number.

Comparison is by Astronomical Julian Day Number, including fractional days. This means that both the time and the timezone offset are taken into account when comparing two DateTime instances. When comparing a DateTime instance with a Date instance, the time of the latter will be considered as falling on midnight UTC.



1234
1235
1236
1237
1238
1239
1240
# File 'lib/date.rb', line 1234

def <=> (other)
  case other
  when Numeric; return @ajd <=> other
  when Date;    return @ajd <=> other.ajd
  end
  nil
end

#===(other) ⇒ Object

The relationship operator for Date.

Compares dates by Julian Day Number. When comparing two DateTime instances, or a DateTime with a Date, the instances will be regarded as equivalent if they fall on the same date in local time.



1248
1249
1250
1251
1252
1253
1254
# File 'lib/date.rb', line 1248

def === (other)
  case other
  when Numeric; return jd == other
  when Date;    return jd == other.jd
  end
  false
end

#>>(n) ⇒ Object

Return a new Date object that is n months later than the current one.

If the day-of-the-month of the current Date is greater than the last day of the target month, the day-of-the-month of the returned Date will be the last day of the target month.



1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
# File 'lib/date.rb', line 1272

def >> (n)
  y, m = (year * 12 + (mon - 1) + n).divmod(12)
  m,   = (m + 1)                    .divmod(1)
  d = mday
  until jd2 = self.class.valid_civil?(y, m, d, fix_style)
    d -= 1
    raise ArgumentError, 'invalid date' unless d > 0
  end

  self + (jd2 - jd)
end

#_dump(limit) ⇒ Object

Dump to Marshal format.



1350
# File 'lib/date.rb', line 1350

def _dump(limit) Marshal.dump([@ajd, @of, @sg], -1) end

#ajdObject

Get the date as an Astronomical Julian Day Number.



1018
# File 'lib/date.rb', line 1018

def ajd() @ajd end

#amjdObject

Get the date as an Astronomical Modified Julian Day Number.



1021
# File 'lib/date.rb', line 1021

def amjd() self.class.ajd_to_amjd(@ajd) end

#asctimeObject Also known as: ctime

alias_method :format, :strftime



336
# File 'lib/date/format.rb', line 336

def asctime() strftime('%c') end

#cwdayObject

Get the commercial day of the week of this date. Monday is commercial day-of-week 1; Sunday is commercial day-of-week 7.



1114
# File 'lib/date.rb', line 1114

def cwday() commercial[2] end

#cweekObject

Get the commercial week of the year of this date.



1110
# File 'lib/date.rb', line 1110

def cweek() commercial[1] end

#cwyearObject

Get the commercial year of this date. See Commercial Date in the introduction for how this differs from the normal year.



1107
# File 'lib/date.rb', line 1107

def cwyear() commercial[0] end

#day_fractionObject

Get any fractional day part of the date.



1029
# File 'lib/date.rb', line 1029

def day_fraction() self.class.ajd_to_jd(@ajd, @of)[1] end

#downto(min, &block) ⇒ Object

Step backward one day at a time until we reach min (inclusive), yielding each date as we go.



1329
1330
1331
# File 'lib/date.rb', line 1329

def downto(min, &block) # :yield: date
  step(min, -1, &block)
end

#englandObject

Create a copy of this Date object that uses the English/Colonial Day of Calendar Reform.



1170
# File 'lib/date.rb', line 1170

def england() new_start(self.class::ENGLAND) end

#eql?(other) ⇒ Boolean

Is this Date equal to other?

other must both be a Date object, and represent the same date.

Returns:

  • (Boolean)


1336
# File 'lib/date.rb', line 1336

def eql? (other) Date === other && self == other end

#gregorianObject

Create a copy of this Date object that always uses the Gregorian Calendar.



1178
# File 'lib/date.rb', line 1178

def gregorian() new_start(self.class::GREGORIAN) end

#gregorian?Boolean

Is the current date new-style (Gregorian Calendar)?

Returns:

  • (Boolean)


1138
# File 'lib/date.rb', line 1138

def gregorian? () self.class.gregorian?(jd, @sg) end

#hashObject

Calculate a hash value for this date.



1339
# File 'lib/date.rb', line 1339

def hash() @ajd.hash end

#inspectObject

Return internal object state as a programmer-readable string.



1342
# File 'lib/date.rb', line 1342

def inspect() format('#<%s: %s,%s,%s>', self.class, @ajd, @of, @sg) end

#italyObject

Create a copy of this Date object that uses the Italian/Catholic Day of Calendar Reform.



1166
# File 'lib/date.rb', line 1166

def italy() new_start(self.class::ITALY) end

#jdObject

Get the date as a Julian Day Number.



1026
# File 'lib/date.rb', line 1026

def jd() self.class.ajd_to_jd(@ajd, @of)[0] end

#julianObject

Create a copy of this Date object that always uses the Julian Calendar.



1174
# File 'lib/date.rb', line 1174

def julian() new_start(self.class::JULIAN) end

#julian?Boolean

Is the current date old-style (Julian Calendar)?

Returns:

  • (Boolean)


1135
# File 'lib/date.rb', line 1135

def julian? () self.class.julian?(jd, @sg) end

#ldObject

Get the date as the number of days since the Day of Calendar Reform (in Italy and the Catholic countries).



1036
# File 'lib/date.rb', line 1036

def ld() self.class.jd_to_ld(jd) end

#leap?Boolean

Is this a leap year?

Returns:

  • (Boolean)


1151
1152
1153
1154
# File 'lib/date.rb', line 1151

def leap?
  self.class.jd_to_civil(self.class.civil_to_jd(year, 3, 1, fix_style) - 1,
     fix_style)[-1] == 29
end

#mdayObject Also known as: day

Get the day-of-the-month of this date.



1069
# File 'lib/date.rb', line 1069

def mday() civil[2] end

#mjdObject

Get the date as a Modified Julian Day Number.



1032
# File 'lib/date.rb', line 1032

def mjd() self.class.jd_to_mjd(jd) end

#monObject Also known as: month

Get the month of this date.

January is month 1.



1066
# File 'lib/date.rb', line 1066

def mon() civil[1] end

#new_start(sg = self.class::ITALY) ⇒ Object

Create a copy of this Date object using a new Day of Calendar Reform.



1162
# File 'lib/date.rb', line 1162

def new_start(sg=self.class::ITALY) self.class.new!(@ajd, @of, sg) end

#nextObject Also known as: succ

Return a new Date one day after this one.



1262
# File 'lib/date.rb', line 1262

def next() next_day end

#startObject

When is the Day of Calendar Reform for this Date object?



1159
# File 'lib/date.rb', line 1159

def start() @sg end

#step(limit, step = 1) ⇒ Object

Step the current date forward step days at a time (or backward, if step is negative) until we reach limit (inclusive), yielding the resultant date at each step.



1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
# File 'lib/date.rb', line 1306

def step(limit, step=1) # :yield: date
=begin
  unless block_given?
    return to_enum(:step, limit, step)
  end
=end
  da = self
  op = %w(- <= >=)[step <=> 0]
  while da.__send__(op, limit)
    yield da
    da += step
  end
  self
end

#strftime(fmt = '%F')) ⇒ Object



200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
# File 'lib/date/format.rb', line 200

def strftime(fmt='%F')
  fmt.gsub(/%([-_0^#]+)?(\d+)?[EO]?(:{1,3}z|.)/m) do |m|
    f = {}
    s, w, c = $1, $2, $3
    if s
	s.scan(/./) do |k|
 case k
 when '-'; f[:p] = '-'
 when '_'; f[:p] = "\s"
 when '0'; f[:p] = '0'
 when '^'; f[:u] = true
 when '#'; f[:x] = true
 end
	end
    end
    if w
	f[:w] = w.to_i
    end
    case c
    when 'A'; emit_ad(DAYNAMES[wday], 0, f)
    when 'a'; emit_ad(ABBR_DAYNAMES[wday], 0, f)
    when 'B'; emit_ad(MONTHNAMES[mon], 0, f)
    when 'b'; emit_ad(ABBR_MONTHNAMES[mon], 0, f)
    when 'C'; emit_sn((year / 100).floor, 2, f)
    when 'c'; emit_a(strftime('%a %b %e %H:%M:%S %Y'), 0, f)
    when 'D'; emit_a(strftime('%m/%d/%y'), 0, f)
    when 'd'; emit_n(mday, 2, f)
    when 'e'; emit_a(mday, 2, f)
    when 'F'
	if m == '%F'
 format('%.4d-%02d-%02d', year, mon, mday) # 4p
	else
 emit_a(strftime('%Y-%m-%d'), 0, f)
	end
    when 'G'; emit_sn(cwyear, 4, f)
    when 'g'; emit_n(cwyear % 100, 2, f)
    when 'H'; emit_n(hour, 2, f)
    when 'h'; emit_ad(strftime('%b'), 0, f)
    when 'I'; emit_n((hour % 12).nonzero? || 12, 2, f)
    when 'j'; emit_n(yday, 3, f)
    when 'k'; emit_a(hour, 2, f)
    when 'L'
	emit_n((sec_fraction / (1.to_r/86400/(10**3))).floor, 3, f)
    when 'l'; emit_a((hour % 12).nonzero? || 12, 2, f)
    when 'M'; emit_n(min, 2, f)
    when 'm'; emit_n(mon, 2, f)
    when 'N'
	emit_n((sec_fraction / (1.to_r/86400/(10**9))).floor, 9, f)
    when 'n'; "\n"
    when 'P'; emit_ad(strftime('%p').downcase, 0, f)
    when 'p'; emit_au(if hour < 12 then 'AM' else 'PM' end, 0, f)
    when 'Q'
	d = ajd - self.class.jd_to_ajd(self.class::UNIXEPOCH, 0)
	s = (d * 86400*10**3).to_i
	emit_sn(s, 1, f)
    when 'R'; emit_a(strftime('%H:%M'), 0, f)
    when 'r'; emit_a(strftime('%I:%M:%S %p'), 0, f)
    when 'S'; emit_n(sec, 2, f)
    when 's'
	d = ajd - self.class.jd_to_ajd(self.class::UNIXEPOCH, 0)
	s = (d * 86400).to_i
	emit_sn(s, 1, f)
    when 'T'
	if m == '%T'
 format('%02d:%02d:%02d', hour, min, sec) # 4p
	else
 emit_a(strftime('%H:%M:%S'), 0, f)
	end
    when 't'; "\t"
    when 'U', 'W'
	emit_n(if c == 'U' then wnum0 else wnum1 end, 2, f)
    when 'u'; emit_n(cwday, 1, f)
    when 'V'; emit_n(cweek, 2, f)
    when 'v'; emit_a(strftime('%e-%b-%Y'), 0, f)
    when 'w'; emit_n(wday, 1, f)
    when 'X'; emit_a(strftime('%H:%M:%S'), 0, f)
    when 'x'; emit_a(strftime('%m/%d/%y'), 0, f)
    when 'Y'; emit_sn(year, 4, f)
    when 'y'; emit_n(year % 100, 2, f)
    when 'Z'; emit_au(strftime('%:z'), 0, f)
    when /\A(:{0,3})z/
	t = $1.size
	sign = if offset < 0 then -1 else +1 end
	fr = offset.abs
	hh, fr = fr.divmod(1.to_r/24)
	mm, fr = fr.divmod(1.to_r/1440)
	ss, fr = fr.divmod(1.to_r/86400)
	if t == 3
 if    ss.nonzero? then t =  2
 elsif mm.nonzero? then t =  1
 else                   t = -1
 end
	end
	case t
	when -1
 tail = []
 sep = ''
	when 0
 f[:w] -= 2 if f[:w]
 tail = ['%02d' % mm]
 sep = ''
	when 1
 f[:w] -= 3 if f[:w]
 tail = ['%02d' % mm]
 sep = ':'
	when 2
 f[:w] -= 6 if f[:w]
 tail = ['%02d' % mm, '%02d' % ss]
 sep = ':'
	end
	([emit_z(sign * hh, 2, f)] + tail).join(sep)
    when '%'; emit_a('%', 0, f)
    when '+'; emit_a(strftime('%a %b %e %H:%M:%S %Z %Y'), 0, f)
    when '1'
	if $VERBOSE
 warn("warning: strftime: %1 is deprecated; forget this")
	end
	emit_n(jd, 1, f)
    when '2'
	if $VERBOSE
 warn("warning: strftime: %2 is deprecated; use '%Y-%j'")
	end
	emit_a(strftime('%Y-%j'), 0, f)
    when '3'
	if $VERBOSE
 warn("warning: strftime: %3 is deprecated; use '%F'")
	end
	emit_a(strftime('%F'), 0, f)
    else
	c
    end
  end
end

#to_sObject

Return the date as a human-readable string.

The format used is YYYY-MM-DD.



1347
# File 'lib/date.rb', line 1347

def to_s() strftime end

#upto(max, &block) ⇒ Object

Step forward one day at a time until we reach max (inclusive), yielding each date as we go.



1323
1324
1325
# File 'lib/date.rb', line 1323

def upto(max, &block) # :yield: date
  step(max, +1, &block)
end

#wdayObject

Get the week day of this date. Sunday is day-of-week 0; Saturday is day-of-week 6.



1118
# File 'lib/date.rb', line 1118

def wday() self.class.jd_to_wday(jd) end

#ydayObject

Get the day-of-the-year of this date.

January 1 is day-of-the-year 1



1061
# File 'lib/date.rb', line 1061

def yday() ordinal[1] end

#yearObject

Get the year of this date.



1056
# File 'lib/date.rb', line 1056

def year() civil[0] end