From 44bccbded8edd4a3ded3f40bbda8ee16b6338ad4 Mon Sep 17 00:00:00 2001 From: tadf Date: Fri, 22 Sep 2006 16:05:19 +0000 Subject: updated based on date2 3.9.2. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@10996 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- lib/date.rb | 135 +++++++++++++++++++++++++++-------------------------- lib/date/format.rb | 115 +++++++++++++++++++++++++++++++-------------- 2 files changed, 151 insertions(+), 99 deletions(-) (limited to 'lib') diff --git a/lib/date.rb b/lib/date.rb index 28491dea10..47c462b8bb 100644 --- a/lib/date.rb +++ b/lib/date.rb @@ -6,7 +6,7 @@ # Documentation: William Webber # #-- -# $Id: date.rb,v 2.23 2006-09-09 22:44:21+09 tadf Exp $ +# $Id: date.rb,v 2.24 2006-09-22 23:26:52+09 tadf Exp $ #++ # # == Overview @@ -249,6 +249,10 @@ class Date # Abbreviated day names, in English. ABBR_DAYNAMES = %w(Sun Mon Tue Wed Thu Fri Sat) + [MONTHNAMES, DAYNAMES, ABBR_MONTHNAMES, ABBR_DAYNAMES].each do |xs| + xs.each{|x| x.freeze}.freeze + end + class Infinity < Numeric # :nodoc: include Comparable @@ -309,6 +313,8 @@ class Date # Gregorian calendar. GREGORIAN = -Infinity.new + UNIXEPOCH = 2440588 # 1970-01-01 :nodoc: + # Does a given Julian Day Number fall inside the old-style (Julian) # calendar? # @@ -394,16 +400,6 @@ class Date return y, m, dom end - # 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. - def self.ordinal_to_jd(y, d, sg=GREGORIAN) - civil_to_jd(y, 1, d, sg) - end - # Convert a Julian Day Number to an Ordinal Date. # # +jd+ is the Julian Day Number to convert. @@ -417,6 +413,16 @@ class Date return y, doy end + # 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. + def self.ordinal_to_jd(y, d, sg=GREGORIAN) + civil_to_jd(y, 1, d, sg) + end + # Convert a Julian Day Number to a Commercial Date # # +jd+ is the Julian Day Number to convert. @@ -449,7 +455,7 @@ class Date def self.jd_to_weeknum(jd, k=0, sg=GREGORIAN) # :nodoc: y, m, d = jd_to_civil(jd, sg) a = civil_to_jd(y, 1, 1, sg) + 6 - w, d = clfloor(jd - (a - ((a - k) + 1) % 7) + 7, 7) + w, d = (jd - (a - ((a - k) + 1) % 7) + 7).divmod(7) return y, w, d end @@ -458,20 +464,6 @@ class Date (a - ((a - k) + 1) % 7 - 7) + 7 * w + d end - %w(self.clfloor clfloor).each do |name| - module_eval <<-"end;" - def #{name}(x, y=1) - q, r = x.divmod(y) - q = q.to_i - return q, r - end - end; - end - - private_class_method :clfloor - private :clfloor - - # Convert an Astronomical Julian Day Number to a (civil) Julian # Day Number. # @@ -480,7 +472,7 @@ class Date # # Returns the (civil) Julian Day Number as [day_number, # fraction] where +fraction+ is always 1/2. - def self.ajd_to_jd(ajd, of=0) clfloor(ajd + of + 1.to_r/2) end + def self.ajd_to_jd(ajd, of=0) (ajd + of + 1.to_r/2).divmod(1) end # Convert a (civil) Julian Day Number to an Astronomical Julian # Day Number. @@ -496,9 +488,9 @@ class Date # Convert a fractional day +fr+ to [hours, minutes, seconds, # fraction_of_a_second] def self.day_fraction_to_time(fr) - h, fr = clfloor(fr, 1.to_r/24) - min, fr = clfloor(fr, 1.to_r/1440) - s, fr = clfloor(fr, 1.to_r/86400) + 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 @@ -582,7 +574,7 @@ class Date # +sg+ specifies the Day of Calendar Reform. def self.valid_ordinal? (y, d, sg=ITALY) if d < 0 - ny, = clfloor(y + 1, 1) + 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] @@ -628,8 +620,8 @@ class Date m += 13 end if d < 0 - ny, nm = clfloor(y * 12 + m, 12) - nm, = clfloor(nm + 1, 1) + 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] @@ -730,11 +722,11 @@ class Date def self.rewrite_hash(elem) # :nodoc: elem ||= {} if seconds = elem[:seconds] - d, fr = clfloor(seconds, 86400) - h, fr = clfloor(fr, 3600) - min, fr = clfloor(fr, 60) - s, fr = clfloor(fr, 1) - elem[:jd] = civil_to_jd(1970, 1, 1) + d + 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 @@ -852,14 +844,6 @@ class Date new_with_hash(elem, sg) end - # Create a new Date object representing today. - # - # +sg+ specifies the Day of Calendar Reform. - def self.today(sg=ITALY) - jd = civil_to_jd(*(Time.now.to_a[3..5].reverse << sg)) - new0(jd_to_ajd(jd, 0, 0), 0, sg) - end - class << self def once(*ids) # :nodoc: @@ -1005,8 +989,8 @@ class Date def fix_style # :nodoc: if julian? - then Date::JULIAN - else Date::GREGORIAN end + then self.class::JULIAN + else self.class::GREGORIAN end end private :fix_style @@ -1111,6 +1095,11 @@ class Date false end + # Return a new Date one day after this one. + def succ() self + 1 end + + alias_method :next, :succ + # Return a new Date object that is +n+ months later than # the current one. # @@ -1118,8 +1107,8 @@ class Date # 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. def >> (n) - y, m = clfloor(year * 12 + (mon - 1) + n, 12) - m, = clfloor(m + 1, 1) + y, m = (year * 12 + (mon - 1) + n).divmod(12) + m, = (m + 1).divmod(1) d = mday d -= 1 until jd2 = self.class.valid_civil?(y, m, d, fix_style) self + (jd2 - jd) @@ -1159,11 +1148,6 @@ class Date step(min, -1, &block) end - # Return a new Date one day after this one. - def succ() self + 1 end - - alias_method :next, :succ - # Is this Date equal to +other+? # # +other+ must both be a Date object, and represent the same date. @@ -1263,9 +1247,12 @@ class DateTime < Date h += 24 if h < 0 min += 60 if min < 0 s += 60 if s < 0 - return unless (0..24) === h and - (0..59) === min and - (0..59) === s + return unless ((0..23) === h and + (0..59) === min and + (0..59) === s) or + (24 == h and + 0 == min and + 0 == s) time_to_day_fraction(h, min, s) end @@ -1278,6 +1265,8 @@ class DateTime < Date valid_time?(h, min, s) end + private_class_method :valid_time_with_hash? + # Create a new DateTime object corresponding to the specified # Julian Day Number +jd+ and hour +h+, minute +min+, second +s+. # @@ -1390,14 +1379,14 @@ class DateTime < Date # +fmt+ is the format that the date-time is in. See # date/format.rb for details on supported formats. # - # The default +str+ is '-4712-01-01T00:00:00Z', and the default - # +fmt+ is '%FT%T%Z'. This gives midnight on Julian Day Number day 0. + # The default +str+ is '-4712-01-01T00:00:00+00:00', and the default + # +fmt+ is '%FT%T%z'. This gives midnight on Julian Day Number day 0. # # +sg+ specifies the Day of Calendar Reform. # # An ArgumentError will be raised if +str+ cannot be # parsed. - def self.strptime(str='-4712-01-01T00:00:00Z', fmt='%FT%T%Z', sg=ITALY) + def self.strptime(str='-4712-01-01T00:00:00+00:00', fmt='%FT%T%z', sg=ITALY) elem = _strptime(str, fmt) new_with_hash(elem, sg) end @@ -1413,15 +1402,33 @@ class DateTime < Date # for more details. If parsing fails, an ArgumentError # will be raised. # - # The default +str+ is '-4712-01-01T00:00:00Z'; this is Julian + # The default +str+ is '-4712-01-01T00:00:00+00:00'; this is Julian # Day Number day 0. # # +sg+ specifies the Day of Calendar Reform. - def self.parse(str='-4712-01-01T00:00:00Z', comp=false, sg=ITALY) + def self.parse(str='-4712-01-01T00:00:00+00:00', comp=false, sg=ITALY) elem = _parse(str, comp) new_with_hash(elem, sg) end + public :hour, :min, :sec, :sec_fraction, :zone, :offset, :new_offset + +end + +class Date + + # Create a new Date object representing today. + # + # +sg+ specifies the Day of Calendar Reform. + def self.today(sg=ITALY) + jd = civil_to_jd(*(Time.now.to_a[3..5].reverse << sg)) + new0(jd_to_ajd(jd, 0, 0), 0, sg) + end + +end + +class DateTime < Date + class << self; undef_method :today end # Create a new DateTime object representing the current time. @@ -1436,8 +1443,6 @@ class DateTime < Date new0(jd_to_ajd(jd, fr, of), of, sg) end - public :hour, :min, :sec, :sec_fraction, :zone, :offset, :new_offset - end class Date diff --git a/lib/date/format.rb b/lib/date/format.rb index ccfd013036..9ae9041d65 100644 --- a/lib/date/format.rb +++ b/lib/date/format.rb @@ -1,5 +1,5 @@ # format.rb: Written by Tadayoshi Funaba 1999-2006 -# $Id: format.rb,v 2.23 2006-09-09 23:55:00+09 tadf Exp $ +# $Id: format.rb,v 2.24 2006-09-22 23:26:52+09 tadf Exp $ require 'rational' @@ -90,6 +90,10 @@ class Date 'yakutsk' => 32400 } + [MONTHS, DAYS, ABBR_MONTHS, ABBR_DAYS, ZONES].each do |x| + x.freeze + end + class Bag # :nodoc: def method_missing(t, *args, &block) @@ -98,8 +102,10 @@ class Date t = '@' + t if set instance_variable_set(t, *args) - elsif instance_variable_defined?(t) - instance_variable_get(t) + else + if instance_variables.include?(t) + instance_variable_get(t) + end end end @@ -455,7 +461,7 @@ class Date ' ') e.mon = Format::ABBR_MONTHS[$1.downcase] - unless $2.size > 2 && $3.nil? + unless $2.size > 2 && $4.nil? e.mday = $2.to_i else e.year = $2.to_i @@ -529,6 +535,22 @@ class Date e._comp = false end true + elsif str.sub!(/(#{e._parse_monthpat})[^-]*-(-?\d+)(?:-(-?\d+))?/in, ' ') + e.mon = Format::ABBR_MONTHS[$1.downcase] + + unless $2.size > 2 && $3.nil? + e.mday = $2.to_i + else + e.year = $2.to_i + end + + if $3 + e.year = $3.to_i + if $3.size > 2 + e._comp = false + end + end + true end end @@ -719,6 +741,21 @@ class Date 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 @@ -847,7 +884,7 @@ class Date :emit_a, :emit_ad, :emit_au def strftime(fmt='%F') - fmt.gsub(/%([-_0^#]+)?(\d+)?[EO]?(:{1,3}z|.)/m) do |_| + fmt.gsub(/%([-_0^#]+)?(\d+)?[EO]?(:{1,3}z|.)/m) do |m| f = {} s, w, c = $1, $2, $3 if s @@ -870,60 +907,70 @@ class Date when 'B'; emit_ad(MONTHNAMES[mon], 0, f) when 'b'; emit_ad(ABBR_MONTHNAMES[mon], 0, f) when 'C'; emit_sn(year / 100, 2, f) - when 'c'; emit_a(strftime('%a %b %e %H:%M:%S %Y'), 1, f) - when 'D'; emit_a(strftime('%m/%d/%y'), 1, 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'; emit_a(strftime('%Y-%m-%d'), 1, 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'), 1, 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)), 3, f) + 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)), 9, f) + emit_n((sec_fraction / (1.to_r/86400/(10**9))).floor, 9, f) when 'n'; "\n" - when 'P'; emit_ad(strftime('%p').downcase, 1, f) - when 'p'; emit_au(if hour < 12 then 'AM' else 'PM' end, 1, f) + 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.civil_to_jd(1970,1,1), 0) + d = ajd - self.class.jd_to_ajd(self.class::UNIXEPOCH, 0) s = (d * 86400*10**3).to_i emit_n(s, 1, f) - when 'R'; emit_a(strftime('%H:%M'), 1, f) - when 'r'; emit_a(strftime('%I:%M:%S %p'), 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.civil_to_jd(1970,1,1), 0) + d = ajd - self.class.jd_to_ajd(self.class::UNIXEPOCH, 0) s = (d * 86400).to_i emit_n(s, 1, f) - when 'T'; emit_a(strftime('%H:%M:%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' k = if c == 'U' then 0 else 1 end emit_n(self.class.jd_to_weeknum(jd, k, fix_style)[1], 2, f) when 'u'; emit_n(cwday, 1, f) when 'V'; emit_n(cweek, 2, f) - when 'v'; emit_a(strftime('%e-%b-%Y'), 1, 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'), 1, f) - when 'x'; emit_a(strftime('%m/%d/%y'), 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'), 1, f) + when 'Z'; emit_au(strftime('%:z'), 0, f) when /\A(:{0,3})z/ t = $1.size - p = if offset < 0 then -1 else +1 end - of = offset.abs - hh, fr = of.divmod(1.to_r/24) - mm, fr = fr.divmod(1.to_r/1440) - ss, fr = fr.divmod(1.to_r/86400) + sign = if offset < 0 then -1 else +1 end + fr = offset.abs.to_f + hh, fr = fr.divmod(1.0/24) + mm, fr = fr.divmod(1.0/1440) + ss, fr = fr.divmod(1.0/86400) if t == 3 if ss.nonzero? then t = 2 elsif mm.nonzero? then t = 1 @@ -947,9 +994,9 @@ class Date tail = ['%02d' % mm, '%02d' % ss] sep = ':' end - ([emit_z(p * hh, 2, f)] + tail).join(sep) - when '%'; emit_a('%', 1, f) - when '+'; emit_a(strftime('%a %b %e %H:%M:%S %Z %Y'), 1, f) + ([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") @@ -959,12 +1006,12 @@ class Date if $VERBOSE warn("warning: strftime: %2 is deprecated; use '%Y-%j'") end - emit_a(strftime('%Y-%j'), 1, f) + emit_a(strftime('%Y-%j'), 0, f) when '3' if $VERBOSE warn("warning: strftime: %3 is deprecated; use '%F'") end - emit_a(strftime('%F'), 1, f) + emit_a(strftime('%F'), 0, f) else c end @@ -1023,9 +1070,9 @@ class DateTime < Date if n < 1 '' else - '.%0*d' % [n, (sec_fraction / (1.to_r/86400/(10**n)))] + '.%0*d' % [n, (sec_fraction / (1.to_r/86400/(10**n))).floor] end + - '%Z') + '%:z') end private :iso8601_timediv -- cgit v1.2.3