Class: TimeStep
- Inherits:
-
Object
- Object
- TimeStep
- Defined in:
- lib/timesteps/timestep.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
definitionandcalendaras 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
otheras 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_origin(time) ⇒ 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.
-
#range(start, last = nil, count: nil, ends: "[]") ⇒ TimeStep::Range
Creates new timestep range object.
-
#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
otherfromself. -
#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
146 147 148 149 150 151 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 |
# File 'lib/timesteps/timestep.rb', line 146 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.
263 264 265 |
# File 'lib/timesteps/timestep.rb', line 263 def calendar @calendar end |
#interval ⇒ Object (readonly)
Returns the value of attribute interval.
263 264 265 |
# File 'lib/timesteps/timestep.rb', line 263 def interval @interval end |
#numeric ⇒ Object (readonly)
Returns the value of attribute numeric.
263 264 265 |
# File 'lib/timesteps/timestep.rb', line 263 def numeric @numeric end |
#origin ⇒ Object (readonly)
Returns the value of attribute origin.
263 264 265 |
# File 'lib/timesteps/timestep.rb', line 263 def origin @origin end |
#symbol ⇒ Object (readonly)
Returns the value of attribute symbol.
263 264 265 |
# File 'lib/timesteps/timestep.rb', line 263 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.
87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/timesteps/timestep.rb', line 87 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.
338 339 340 |
# File 'lib/timesteps/timestep.rb', line 338 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.
295 296 297 |
# File 'lib/timesteps/timestep.rb', line 295 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).
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 |
# File 'lib/timesteps/timestep.rb', line 412 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
627 628 629 630 |
# File 'lib/timesteps/timestep.rb', line 627 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).
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 |
# File 'lib/timesteps/timestep.rb', line 451 def index_at (*times, format: nil) if times.size == 1 time = times.first time = @calendar.parse(time, format: format, offset: @origin.offset) if time.is_a?(String) 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.
322 323 324 325 326 327 328 329 330 |
# File 'lib/timesteps/timestep.rb', line 322 def inspect = "" case @calendar.name when "standard", "gregorian" else << " calendar='#{calendar.name}'" end "#<TimeStep definition='#{definition}'#{}>" end |
#interval_spec ⇒ String
Returns a string expression for interval section in timestem spec.
272 273 274 275 276 277 278 |
# File 'lib/timesteps/timestep.rb', line 272 def interval_spec if @wday return format("%g %s", @numeric, WDAY_NAME[@wday]) else return format("%g %s", @numeric, @symbol) end end |
#new_origin(time) ⇒ TimeStep
Returns new timestep object which holds the given time as origin.
518 519 520 521 522 523 524 525 526 |
# File 'lib/timesteps/timestep.rb', line 518 def new_origin (time) time = @calendar.parse(time, offset: @origin.offset) if time.is_a?(String) 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
562 563 564 565 |
# File 'lib/timesteps/timestep.rb', line 562 def next_index_of (time) time = @calendar.parse(time, offset: @origin.offset) if time.is_a?(String) return index_at(time).floor + 1 end |
#next_time_of(time) ⇒ DateTime
Returns next time of the given time
596 597 598 |
# File 'lib/timesteps/timestep.rb', line 596 def next_time_of (time) return time_at(next_index_of(time)) end |
#offset ⇒ Rational
Returns the time offset of origin time.
302 303 304 |
# File 'lib/timesteps/timestep.rb', line 302 def offset return @origin.offset end |
#origin_spec ⇒ String
Returns a string expression for origin time section in timestep spec.
283 284 285 286 287 288 289 |
# File 'lib/timesteps/timestep.rb', line 283 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.
315 316 317 |
# File 'lib/timesteps/timestep.rb', line 315 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.
663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 |
# File 'lib/timesteps/timestep.rb', line 663 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
579 580 581 582 |
# File 'lib/timesteps/timestep.rb', line 579 def prev_index_of (time) time = @calendar.parse(time, offset: @origin.offset) if time.is_a?(String) return index_at(time).ceil - 1 end |
#prev_time_of(time) ⇒ DateTime
Returns previous time of the given time
612 613 614 |
# File 'lib/timesteps/timestep.rb', line 612 def prev_time_of (time) return time_at(prev_index_of(time)) end |
#range(start, last = nil, count: nil, ends: "[]") ⇒ TimeStep::Range
Creates new timestep range object.
694 695 696 |
# File 'lib/timesteps/timestep.rb', line 694 def range (start, last = nil, count: nil, ends: "[]") return TimeStep::Range.new(self, start, last, count: count, ends: ends) end |
#shift_origin(index, with: "index") ⇒ TimeStep
Returns new timestep object which has new origin time specified by index.
492 493 494 495 496 497 498 499 500 501 |
# File 'lib/timesteps/timestep.rb', line 492 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).
370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 |
# File 'lib/timesteps/timestep.rb', line 370 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
644 645 646 |
# File 'lib/timesteps/timestep.rb', line 644 def to (other) return Pair.new(self, other) end |
#truncate(time) ⇒ DateTime
Truncate the given datetime to the unit of the object.
546 547 548 |
# File 'lib/timesteps/timestep.rb', line 546 def truncate (time) return time_at(index_at(time).floor) end |