class DateTimeLike
Base class for DateTime::NoLeap
, DateTime::AllLeap
, DateTime::Fixed360Day
Constants
- ABBR_DAYNAMES
@private Abbreviated day names, in English.
- ABBR_MONTHNAMES
@private Abbreviated month names, in English.
- DAYNAMES
@private 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.
- MILLISECONDS_IN_DAY
@private
- MILLISECONDS_IN_SECOND
@private
- MONTHNAMES
@private 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).
- NANOSECONDS_IN_DAY
@private
- NANOSECONDS_IN_SECOND
@private
- SECONDS_IN_DAY
@private
Attributes
Public Class Methods
Creates a DateTime
object denoting the given calendar date.
@param year [Integer] @param month [Integer] @param day [Integer] @param hour [Integer] @param minute [Integer] @param second [Integer] @param offset [Integer] @param start [Integer]
# File lib/timesteps/datetimelike.rb, line 65 def initialize (year = -4712, month = 1, day = 1, hour = 0, minute = 0, second = 0.0, offset = 0, start = nil) @year = year.to_i @month = month.to_i @day = day.to_i @hour = hour.to_i @minute = minute.to_i @second = second @offset = offset check_valid_datetime() end
Public Instance Methods
Returns a date object pointing other days after self.
@param days [Numeric]
@return [DateTimeFixedDPY]
# File lib/timesteps/datetimelike.rb, line 190 def + (days) days = days.to_r + fraction jday = jd.floor + days.floor fday = (days - days.floor)*24 hour = fday.floor fday = (fday - hour)*60 min = fday.floor sec = (fday - min)*60 return self.class.jd(jday, hour, min, sec, offset) end
Returns the difference between the two dates if the other is a datetime object. If the other is a numeric value, returns a date object pointing other days before self.
# File lib/timesteps/datetimelike.rb, line 205 def - (other_or_days) case other_or_days when Numeric return self + (-other_or_days) when self.class return self.jd - other_or_days.jd else raise "other shoud be date-time object or numeric value" end end
Returns a date object pointing n months before self.
@param n [Integer]
@return [DateTimeFixedDPY]
# File lib/timesteps/datetimelike.rb, line 230 def << (n) return add_months(-n) end
Compares the two dates and returns -1, zero, 1 or nil. The other should be a date object or a numeric value as an astronomical Julian day number.
# File lib/timesteps/datetimelike.rb, line 363 def <=> (other) return self.ajd <=> other.ajd end
Returns a date object pointing n months after self.
@param n [Integer]
@return [DateTimeFixedDPY]
# File lib/timesteps/datetimelike.rb, line 221 def >> (n) return add_months(n) end
Calculates astronomical Julian day number.
@return [Numeric]
# File lib/timesteps/datetimelike.rb, line 159 def ajd return jd + fraction - @offset - 1.quo(2) end
# File lib/timesteps/datetimelike.rb, line 385 def compare_d (other) sday = self.day + self.fraction + self.offset oday = other.day + other.fraction + other.offset if sday > oday return 1 elsif sday < oday return -1 else return 0 end end
# File lib/timesteps/datetimelike.rb, line 367 def compare_md (other) sday = self.day + self.fraction + self.offset oday = other.day + other.fraction + other.offset if self.month > other.month return 1 elsif self.month < other.month return -1 else if sday > oday return 1 elsif sday < oday return -1 else return 0 end end end
Calculate difference between the object and other object in months.
@return [Integer]
# File lib/timesteps/datetimelike.rb, line 409 def difference_in_months (other) my = self.new_offset(0) other = other.new_offset(0) return 12*(my.year - other.year) + my.month - other.month + my.compare_d(other).quo(2) end
Calculate difference between the object and other object in years.
@return [Integer]
# File lib/timesteps/datetimelike.rb, line 400 def difference_in_years (other) my = self.new_offset(0) other = other.new_offset(0) return my.year - other.year + my.compare_md(other).quo(2) end
Returns time fraction in day units.
@return [Rational]
# File lib/timesteps/datetimelike.rb, line 315 def fraction () return (60*(60*@hour + @minute) + @second.to_r).quo(86400) end
Returns the value as a string for inspection.
# File lib/timesteps/datetimelike.rb, line 352 def inspect sec = fraction*86400 isec = sec.floor fsec = ((sec - isec)*1000000).round offs = (offset*86400).round format("#<%s: %s ((%dj,%ds,%dn),%+ds)>", self.class, to_s, jd, isec, fsec, offs) end
Calculates Julian day number from date part. Note that this method does not take into account the offset and time. If you need a Julian day number that takes the time into account, use ajd
.
@return [Integer]
# File lib/timesteps/datetimelike.rb, line 152 def jd return (self.class::DPY) * (@year + 4712) + (yday - 1) end
Duplicates self and resets its offset.
@param offset [Numeric]
@return [DateTime]
# File lib/timesteps/datetimelike.rb, line 128 def new_offset (offset = 0) gmt = jd + fraction - @offset + offset.to_r jday = gmt.floor fday = gmt - gmt.floor return self.class.jd(jday, 0, 0, 0, offset) + fday end
Returns a date object pointing n days after self.
@param n [Integer]
@return [DateTimeFixedDPY]
# File lib/timesteps/datetimelike.rb, line 284 def next_day (n = 1) return add_days(n) end
Returns a date object pointing n months after self.
@param n [Integer]
@return [DateTimeFixedDPY]
# File lib/timesteps/datetimelike.rb, line 257 def next_month (n = 1) return add_months(n) end
Returns a date object pointing n years after self.
@param n [Integer]
@return [DateTimeFixedDPY]
# File lib/timesteps/datetimelike.rb, line 239 def next_year (n = 1) return self.class::new(@year+n, @month, @day, @hour, @minute, @second, @offset) end
Returns a date object pointing n days before self.
@param n [Integer]
@return [DateTimeFixedDPY]
# File lib/timesteps/datetimelike.rb, line 293 def prev_day (n = 1) return add_days(-n) end
Returns a date object pointing n months before self.
@param n [Integer]
@return [DateTimeFixedDPY]
# File lib/timesteps/datetimelike.rb, line 266 def prev_month (n = 1) return add_months(-n) end
Returns a date object pointing n years before self.
@param n [Integer]
@return [DateTimeFixedDPY]
# File lib/timesteps/datetimelike.rb, line 248 def prev_year (n = 1) return self.class::new(@year-n, @month, @day, @hour, @minute, @second, @offset) end
Returns the second (0-59)
@return [Rational]
# File lib/timesteps/datetimelike.rb, line 106 def second return @second.floor end
Returns the fractional part of the second.
@return [Rational]
# File lib/timesteps/datetimelike.rb, line 113 def second_fraction return @second.to_r - @second.floor end
# File lib/timesteps/datetimelike_format.rb, line 132 def strftime(fmt='%F') fmt.gsub(/%([-_0^#]+)?(\d+)?([EO]?(?::{1,3}z|.))/m) do |m| f = {} a = $& 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[month], 0, f) when 'b'; emit_ad(ABBR_MONTHNAMES[month], 0, f) when 'C', 'EC'; emit_sn((year / 100).floor, 2, f) when 'c', 'Ec'; emit_a(strftime('%a %b %e %H:%M:%S %Y'), 0, f) when 'D'; emit_a(strftime('%m/%d/%y'), 0, f) when 'd', 'Od'; emit_n(day, 2, f) when 'e', 'Oe'; emit_a(day, 2, f) when 'F' if m == '%F' format('%.4d-%02d-%02d', year, month, day) # 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', 'OH'; emit_n(hour, 2, f) when 'h'; emit_ad(strftime('%b'), 0, f) when 'I', 'OI'; 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 / MILLISECONDS_IN_SECOND).round, 3, f) when 'l'; emit_a((hour % 12).nonzero? || 12, 2, f) when 'M', 'OM'; emit_n(minute, 2, f) when 'm', 'Om'; emit_n(month, 2, f) when 'N' emit_n((sec_fraction / NANOSECONDS_IN_SECOND).round, 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' s = ((ajd - self::class::UNIX_EPOCH_IN_AJD) / MILLISECONDS_IN_DAY).round 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', 'OS'; emit_n(second.floor, 2, f) when 's' s = ((ajd - self::class::UNIX_EPOCH_IN_AJD) / SECONDS_IN_DAY).round emit_sn(s, 1, f) when 'T' if m == '%T' format('%02d:%02d:%02d', hour, minute, second) # 4p else emit_a(strftime('%H:%M:%S'), 0, f) end when 't'; "\t" when 'U', 'W', 'OU', 'OW' emit_n(if c[-1,1] == 'U' then wnum0 else wnum1 end, 2, f) when 'u', 'Ou'; emit_n(cwday, 1, f) when 'V', 'OV'; emit_n(cweek, 2, f) when 'v'; emit_a(strftime('%e-%b-%Y'), 0, f) when 'w', 'Ow'; emit_n(wday, 1, f) when 'X', 'EX'; emit_a(strftime('%H:%M:%S'), 0, f) when 'x', 'Ex'; emit_a(strftime('%m/%d/%y'), 0, f) when 'Y', 'EY'; emit_sn(year, 4, f) when 'y', 'Ey', 'Oy'; 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 ss = fr.div(SECONDS_IN_DAY) # 4p hh, ss = ss.divmod(3600) mm, ss = ss.divmod(60) 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) else a end end end
Returns a datetime object denoting the following day.
@return [DateTime]
# File lib/timesteps/datetimelike.rb, line 306 def succ return add_days(1) end
Returns a string in an ISO 8601 format.
# File lib/timesteps/datetimelike.rb, line 342 def to_s format("%04d-%02d-%02dT%02d:%02d:%02d%s%s", @year, @month, @day, @hour, @minute, @second.floor, format_microsec, format_offset) end
Returns the day of week (0-6, Sunday is zero).
@return [Integer]
# File lib/timesteps/datetimelike.rb, line 166 def wday return (jd + 1 ) % 7 end
Returns Day of Year
@return [Integer]
# File lib/timesteps/datetimelike.rb, line 138 def yday dpm = self.class::DPM doy = @day (@month-1).step(1,-1) do |m| doy += dpm[m] end return doy end
Private Instance Methods
# File lib/timesteps/datetimelike.rb, line 297 def add_days (days) return self.class::jd(jd+days.to_i, @hour, @minute, @second, @offset) end
# File lib/timesteps/datetimelike.rb, line 270 def add_months (months) months = (@month + months).to_i - 1 years = months / 12 month = months % 12 + 1 return self.class::new(@year+years, month, @day, @hour, @minute, @second, @offset) end
# File lib/timesteps/datetimelike.rb, line 76 def check_valid_datetime unless valid_date? raise "invalid date for #{self.class} [year: #{@year}, month: #{@month}, day: #{@day}]" end unless valid_time? raise "invalid time for #{self.class} [hour: #{@hour}, minute: #{@minute}, second: #{@second}]" end end
Returns the day of week (0-6, Sunday is zero).
@return [Integer]
# File lib/timesteps/datetimelike.rb, line 173 def commercial jd0 = (self.class::DPY) * (@year + 4712) wday0 = (jd0 + 1 ) % 7 cwyear = @year yday1 = yday - wday0 cweek = yday / 7 + 1 cwday = yday % 7 + 1 return cwyear, cweek, cwday end
# File lib/timesteps/datetimelike.rb, line 329 def format_microsec microsec = ((@second - @second.floor)*1000000).round if microsec == 0 "" else ".%06d" % microsec end end
# File lib/timesteps/datetimelike.rb, line 319 def format_offset oh = @offset*24 return [ oh >= 0 ? "+" : "-", "%02i" % oh.abs.to_i, ":", "%02i" % ((oh.abs - oh.abs.to_i)*60).round ].join("") end
# File lib/timesteps/datetimelike.rb, line 85 def valid_time? begin DateTime.new(2001, 1, 1, @hour, @minute, @second) true rescue false end end