Class: TimeStep
- Inherits:
-
Object
- Object
- TimeStep
- Defined in:
- lib/timesteps/timestep.rb,
lib/timesteps/timestep_query.rb,
lib/timesteps/timestep_calendar.rb,
lib/timesteps/timestep_datetime_ext.rb
Overview
TimeStep class
Direct Known Subclasses
Defined Under Namespace
Modules: DateTimeExt Classes: Calendar, Converter, Pair, Query, Range
Instance Attribute Summary collapse
-
#calendar ⇒ Object
readonly
Returns the value of attribute calendar.
-
#interval ⇒ Object
readonly
Returns the value of attribute interval.
-
#numeric ⇒ Object
readonly
Returns the value of attribute numeric.
-
#origin ⇒ Object
readonly
Returns the value of attribute origin.
-
#symbol ⇒ Object
readonly
Returns the value of attribute symbol.
Class Method Summary collapse
-
.split_interval_spec(spec) ⇒ Array(Numeric, String)
Extracts numeric part and symbol part from the given interval specification.
Instance Method Summary collapse
-
#==(other) ⇒ Boolean
Returns true if other has same contents of ‘definition` and `calendar` as self has.
-
#definition ⇒ String
Returns a string expression of definition of timestep.
-
#duration_at(*indices) ⇒ DateTime+
Calculate the duration (array) in day unit since origin time at the given index (indices).
-
#in(unit) ⇒ TimeStep::Pair
Creates new timestep pair object which refers ‘other` as other unit.
-
#index_at(*times, format: nil) ⇒ Numeric+
Returns the index (indices) for the given time (array).
-
#initialize(spec, since: nil, offset: nil, format: nil, calendar: "standard", tz: nil) ⇒ TimeStep
constructor
Constructs the object.
-
#inspect ⇒ String
Returns a string for inspection.
-
#interval_spec ⇒ String
Returns a string expression for interval section in timestem spec.
-
#new_offset(offset) ⇒ TimeStep
Returns the timestep object with new_offset.
-
#new_origin(time, truncate: false) ⇒ TimeStep
Returns new timestep object which holds the given time as origin.
-
#next_index_of(time) ⇒ Numeric
Returns next integer index of the given time.
-
#next_time_of(time) ⇒ DateTime
Returns next time of the given time.
-
#offset ⇒ Rational
Returns the time offset of origin time.
-
#origin_spec ⇒ String
Returns a string expression for origin time section in timestep spec.
-
#parse(time, format: nil) ⇒ DateTime
Parses datetime string and return datetime object.
-
#period(start, last, ends: "[]") ⇒ TimePeriod
Creates new timeperiod object corresponding given time or index for start and last.
-
#prev_index_of(time) ⇒ Numeric
Returns previous integer index of the given time.
-
#prev_time_of(time) ⇒ DateTime
Returns previous time of the given time.
- #query(format = nil) ⇒ Object
-
#range(start, last = nil, count: nil, ends: "[]") ⇒ TimeStep::Range
Creates new timestep range object.
-
#right_time?(time) ⇒ TimeStep::Range
Check whether the given time is right or not for timestep.
-
#shift_origin(index, with: "index") ⇒ TimeStep
Returns new timestep object which has new origin time specified by ‘index`.
-
#time_at(*indices) ⇒ DateTime+
(also: #[])
Returns the datetime object (array) for the given index (indices).
-
#to(other) ⇒ TimeStep::Pair
Creates new timestep pair object which refers ‘other` from `self`.
-
#truncate(time) ⇒ DateTime
Truncate the given datetime to the unit of the object.
Constructor Details
#initialize(spec, since: nil, offset: nil, format: nil, calendar: "standard", tz: nil) ⇒ TimeStep
Constructs the object.
The argument ‘spec` specifies the time step definition, which has the form,
"<INTERVAL> since <TIME>"
For example,
* "second since 1970-01-01 00:00:00 +00:00"
* "hour since 2001-01-01 00:00:00 JST"
* "3 days since 2001-01-01 00:00:00 +00:00"
* "10 years since 1901-01-01 00:00:00 +00:00"
The symbol for time unit symbols should be one of
* ayears, ayear (astronomical year: 365.242198781 day)
* years, year
* months, month
* days, day, d
* hours, hour, hrs, hr, h
* minutes, minute, mins, min
* seconds, second, secs, sec, s
* milliseconds, millisecond, msecs, msec, ms
* microseconds, microsecond
If you have already origin time object or general date string, you can use ‘since` option,
TimeStep.new("3 hours", since: time)
TimeStep.new("3 hours", since: "2001010121", format: '%Y%m%d%H')
When origin time is specified in both ‘spec’ and ‘since’ option, the origin time in ‘spec’ has priority. If origin time is not specified in neither ‘spec’ and ‘since’ option, the default value is set to the origin time (“0000-01-01 00:00:00” for date and “1970-01-01 00:00:00” for time). The time offset from UTC can be set by ‘offset’ option. The option ‘calendar` specifies the name of calendar for datetime calculation,
* "standard", "gregorian" -> DateTime with Date::ITALY as start
* "proleptic_gregorian" -> DateTime with Date::GREGORIAN as start
* "proleptic_julian", "julian" -> DateTime with Date::JULIAN as start
* "noleap", "365_day" -> DateTimeNoLeap
* "allleap", "366_day" -> DateTimeAllLeap
* "360_day" -> DateTimeFixed360Day
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/timesteps/timestep.rb', line 152 def initialize (spec, since: nil, offset: nil, format: nil, calendar: "standard", tz: nil) case calendar when String if tz raise "tz option can be used only with 'standard' calendar type" if calendar != "standard" @calendar = Calendar.new(calendar, tz: tz) else @calendar = CALENDARS[calendar] raise "specified calendar type '#{calendar}' is invalid" unless @calendar end when TimeStep::Calendar @calendar = calendar else raise "invalid object for option 'calendar'" end if spec =~ /\s+since\s+/ interval_spec, time_spec = $~.pre_match, $~.post_match parse_interval(interval_spec) @origin = @calendar.parse(time_spec, offset: offset) else parse_interval(spec) @origin = case since when nil case @symbol when :hours, :minutes, :seconds @calendar.parse("1970-1-1", offset: offset) else @calendar.parse("0000-1-1", offset: offset) end when String @calendar.parse(since, format: format, offset: offset) when Time since.to_datetime else raise "datetime mismatched with calendar type" unless @calendar.valid_datetime_type?(since) since end end if @wday origin = @origin - @origin.wday + WDAY[@wday] origin -= 7 unless @origin >= origin @origin = origin end end |
Instance Attribute Details
#calendar ⇒ Object (readonly)
Returns the value of attribute calendar.
269 270 271 |
# File 'lib/timesteps/timestep.rb', line 269 def calendar @calendar end |
#interval ⇒ Object (readonly)
Returns the value of attribute interval.
269 270 271 |
# File 'lib/timesteps/timestep.rb', line 269 def interval @interval end |
#numeric ⇒ Object (readonly)
Returns the value of attribute numeric.
269 270 271 |
# File 'lib/timesteps/timestep.rb', line 269 def numeric @numeric end |
#origin ⇒ Object (readonly)
Returns the value of attribute origin.
269 270 271 |
# File 'lib/timesteps/timestep.rb', line 269 def origin @origin end |
#symbol ⇒ Object (readonly)
Returns the value of attribute symbol.
269 270 271 |
# File 'lib/timesteps/timestep.rb', line 269 def symbol @symbol end |
Class Method Details
.split_interval_spec(spec) ⇒ Array(Numeric, String)
Extracts numeric part and symbol part from the given interval specification.
93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/timesteps/timestep.rb', line 93 def self.split_interval_spec (spec) if spec.strip =~ /\A(#{PATTERN_NUMERIC}|)\s*((?:#{PATTERN_UNITS}).*)\z/i numeric = if $1 == "" 1 else Float($1) end numeric = numeric.to_i if numeric.denominator == 1 symbol = $2 else raise "the interval specification '#{spec}' is invalid." end return numeric, symbol end |
Instance Method Details
#==(other) ⇒ Boolean
Returns true if other has same contents of ‘definition` and `calendar` as self has.
356 357 358 |
# File 'lib/timesteps/timestep.rb', line 356 def == (other) return definition == other.definition && @calendar == other.calendar end |
#definition ⇒ String
Returns a string expression of definition of timestep. The return value can be used for constructs other TimeStep object.
301 302 303 |
# File 'lib/timesteps/timestep.rb', line 301 def definition format("%s since %s", interval_spec, origin_spec) end |
#duration_at(*indices) ⇒ DateTime+
Calculate the duration (array) in day unit since origin time at the given index (indices).
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 |
# File 'lib/timesteps/timestep.rb', line 430 def duration_at (*indices) if indices.size == 1 index = indices.first days = case @symbol when :years unless (index*@numeric).denominator == 1 raise ArgumentError, "index argument should be an integer for years" end @origin.next_year(@numeric*index) - @origin when :months unless (index*@numeric).denominator == 1 raise ArgumentError, "index argument should be an integer for months" end @origin.next_month(@numeric*index) - @origin else user_to_days(index) end days = days.to_i if days.denominator == 1 return days else return indices.map{ |index| duration_at(index) } end end |
#in(unit) ⇒ TimeStep::Pair
Creates new timestep pair object which refers ‘other` as other unit
648 649 650 651 |
# File 'lib/timesteps/timestep.rb', line 648 def in (unit) other = TimeStep.new(unit, since: @origin, calendar: @calendar) return Pair.new(self, other) end |
#index_at(*times, format: nil) ⇒ Numeric+
Returns the index (indices) for the given time (array).
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 |
# File 'lib/timesteps/timestep.rb', line 469 def index_at (*times, format: nil) if times.size == 1 time = times.first time = time.to_datetime if time.is_a?(Time) time = @calendar.parse(time, format: format, offset: @origin.offset) if time.is_a?(String) time = time.new_offset(@origin.offset) if time.offset != @origin.offset case @symbol when :years diff = time.difference_in_years(@origin) frac = diff - diff.floor index = diff.floor.quo(@numeric.to_i) + frac when :months diff = time.difference_in_months(@origin) frac = diff - diff.floor index = diff.floor.quo(@numeric.to_i) + frac else jday = @calendar.date2jday(time.year, time.month, time.day) fday = time.fraction udays = days_to_user(jday - @origin.jd) utime = days_to_user(time.fraction - time.offset - (@origin.fraction - @origin.offset)) index = udays + utime end index = index.to_i if index.denominator == 1 return index else return times.map{|time| index_at(time, format: format) } end end |
#inspect ⇒ String
Returns a string for inspection.
340 341 342 343 344 345 346 347 348 |
# File 'lib/timesteps/timestep.rb', line 340 def inspect = "" case @calendar.name when "standard", "gregorian" else << " calendar='#{calendar.name}'" end "#<TimeStep definition='#{definition}'#{options}>" end |
#interval_spec ⇒ String
Returns a string expression for interval section in timestem spec.
278 279 280 281 282 283 284 |
# File 'lib/timesteps/timestep.rb', line 278 def interval_spec if @wday return format("%g %s", @numeric, WDAY_NAME[@wday]) else return format("%g %s", @numeric, @symbol) end end |
#new_offset(offset) ⇒ TimeStep
Returns the timestep object with new_offset
316 317 318 319 320 321 322 |
# File 'lib/timesteps/timestep.rb', line 316 def new_offset (offset) obj = clone obj.instance_eval { @origin = @origin.new_offset(offset) } return obj end |
#new_origin(time, truncate: false) ⇒ TimeStep
Returns new timestep object which holds the given time as origin.
538 539 540 541 542 543 544 545 546 547 |
# File 'lib/timesteps/timestep.rb', line 538 def new_origin (time, truncate: false) time = @calendar.parse(time, offset: @origin.offset) if time.is_a?(String) time = self.truncate(time) if truncate if @wday origin = time - time.wday + WDAY[@wday] origin -= 7 unless time >= origin time = origin end return TimeStep.new(interval_spec, since: time, calendar: @calendar) end |
#next_index_of(time) ⇒ Numeric
Returns next integer index of the given time
583 584 585 586 |
# File 'lib/timesteps/timestep.rb', line 583 def next_index_of (time) time = @calendar.parse(time) if time.is_a?(String) return index_at(time).floor + 1 end |
#next_time_of(time) ⇒ DateTime
Returns next time of the given time
617 618 619 |
# File 'lib/timesteps/timestep.rb', line 617 def next_time_of (time) return time_at(next_index_of(time)) end |
#offset ⇒ Rational
Returns the time offset of origin time.
308 309 310 |
# File 'lib/timesteps/timestep.rb', line 308 def offset return @origin.offset end |
#origin_spec ⇒ String
Returns a string expression for origin time section in timestep spec.
289 290 291 292 293 294 295 |
# File 'lib/timesteps/timestep.rb', line 289 def origin_spec if @calendar.tz return @origin.strftime("%Y-%m-%d %H:%M:%S.%N %:z %Z") else return @origin.strftime("%Y-%m-%d %H:%M:%S.%N %:z") end end |
#parse(time, format: nil) ⇒ DateTime
Parses datetime string and return datetime object. In the parsing, the calendar of the object is used. If ‘format` option is given, `strptime` method is used for the parsing. Otherwise, the `parse` is used.
333 334 335 |
# File 'lib/timesteps/timestep.rb', line 333 def parse (time, format: nil) return @calendar.parse(time, format: format, offset: @origin.offset) end |
#period(start, last, ends: "[]") ⇒ TimePeriod
Creates new timeperiod object corresponding given time or index for start and last.
684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 |
# File 'lib/timesteps/timestep.rb', line 684 def period (start, last, ends: "[]") idx1 = if start.kind_of?(Numeric) start else index_at(start) end idx2 = if last.kind_of?(Numeric) last else index_at(last) end origin = time_at(idx1) numeric = (idx2 - idx1) * @numeric interval_spec = format("%g %s", numeric, @symbol) return TimePeriod.new(interval_spec, since: origin, calendar: @calendar, ends: ends) end |
#prev_index_of(time) ⇒ Numeric
Returns previous integer index of the given time
600 601 602 603 |
# File 'lib/timesteps/timestep.rb', line 600 def prev_index_of (time) time = @calendar.parse(time) if time.is_a?(String) return index_at(time).ceil - 1 end |
#prev_time_of(time) ⇒ DateTime
Returns previous time of the given time
633 634 635 |
# File 'lib/timesteps/timestep.rb', line 633 def prev_time_of (time) return time_at(prev_index_of(time)) end |
#query(format = nil) ⇒ Object
52 53 54 |
# File 'lib/timesteps/timestep_query.rb', line 52 def query (format = nil) return TimeStep::Query.new(self, format: format) end |
#range(start, last = nil, count: nil, ends: "[]") ⇒ TimeStep::Range
Creates new timestep range object.
715 716 717 |
# File 'lib/timesteps/timestep.rb', line 715 def range (start, last = nil, count: nil, ends: "[]") return TimeStep::Range.new(self, start, last, count: count, ends: ends) end |
#right_time?(time) ⇒ TimeStep::Range
Check whether the given time is right or not for timestep.
729 730 731 |
# File 'lib/timesteps/timestep.rb', line 729 def right_time? (time) return index_at(time).integer? end |
#shift_origin(index, with: "index") ⇒ TimeStep
Returns new timestep object which has new origin time specified by ‘index`.
512 513 514 515 516 517 518 519 520 521 |
# File 'lib/timesteps/timestep.rb', line 512 def shift_origin (index, with: "index") case with when :index, "index" time = time_at(index) return TimeStep.new(interval_spec, since: time, calendar: @calendar) when :duration, "duration", :days, "days" time = @origin + index return TimeStep.new(interval_spec, since: time, calendar: @calendar) end end |
#time_at(*indices) ⇒ DateTime+ Also known as: []
Returns the datetime object (array) for the given index (indices).
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 |
# File 'lib/timesteps/timestep.rb', line 388 def time_at (*indices) if indices.size == 1 index = indices.first raise ArgumentError, "index argument should be a numeric" unless index.is_a?(Numeric) case @symbol when :years unless (index*@numeric).denominator == 1 raise ArgumentError, "index argument should be an integer for years" end return @origin.next_year(index*@numeric) when :months unless (index*@numeric).denominator == 1 raise ArgumentError, "index argument should be an integer for months" end return @origin.next_month(index*@numeric) else days = user_to_days(index) + @origin.jd + @origin.fraction - @origin.offset jday = days.floor fday = days - days.floor return (@calendar.jday2date(jday) + fday).new_offset(@origin.offset) end else return indices.map{|index| time_at(index) } end end |
#to(other) ⇒ TimeStep::Pair
Creates new timestep pair object which refers ‘other` from `self`
665 666 667 |
# File 'lib/timesteps/timestep.rb', line 665 def to (other) return Pair.new(self, other) end |
#truncate(time) ⇒ DateTime
Truncate the given datetime to the unit of the object.
567 568 569 |
# File 'lib/timesteps/timestep.rb', line 567 def truncate (time) return time_at(index_at(time).floor) end |