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
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, 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
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
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 194 195 196 197 |
# File 'lib/timesteps/timestep.rb', line 150 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.
267 268 269 |
# File 'lib/timesteps/timestep.rb', line 267 def calendar @calendar end |
#interval ⇒ Object (readonly)
Returns the value of attribute interval.
267 268 269 |
# File 'lib/timesteps/timestep.rb', line 267 def interval @interval end |
#numeric ⇒ Object (readonly)
Returns the value of attribute numeric.
267 268 269 |
# File 'lib/timesteps/timestep.rb', line 267 def numeric @numeric end |
#origin ⇒ Object (readonly)
Returns the value of attribute origin.
267 268 269 |
# File 'lib/timesteps/timestep.rb', line 267 def origin @origin end |
#symbol ⇒ Object (readonly)
Returns the value of attribute symbol.
267 268 269 |
# File 'lib/timesteps/timestep.rb', line 267 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.
91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/timesteps/timestep.rb', line 91 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.
342 343 344 |
# File 'lib/timesteps/timestep.rb', line 342 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.
299 300 301 |
# File 'lib/timesteps/timestep.rb', line 299 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).
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 |
# File 'lib/timesteps/timestep.rb', line 416 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
633 634 635 636 |
# File 'lib/timesteps/timestep.rb', line 633 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).
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 |
# File 'lib/timesteps/timestep.rb', line 455 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) 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.
326 327 328 329 330 331 332 333 334 |
# File 'lib/timesteps/timestep.rb', line 326 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.
276 277 278 279 280 281 282 |
# File 'lib/timesteps/timestep.rb', line 276 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, truncate: false) ⇒ TimeStep
Returns new timestep object which holds the given time as origin.
523 524 525 526 527 528 529 530 531 532 |
# File 'lib/timesteps/timestep.rb', line 523 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
568 569 570 571 |
# File 'lib/timesteps/timestep.rb', line 568 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
602 603 604 |
# File 'lib/timesteps/timestep.rb', line 602 def next_time_of (time) return time_at(next_index_of(time)) end |
#offset ⇒ Rational
Returns the time offset of origin time.
306 307 308 |
# File 'lib/timesteps/timestep.rb', line 306 def offset return @origin.offset end |
#origin_spec ⇒ String
Returns a string expression for origin time section in timestep spec.
287 288 289 290 291 292 293 |
# File 'lib/timesteps/timestep.rb', line 287 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.
319 320 321 |
# File 'lib/timesteps/timestep.rb', line 319 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.
669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 |
# File 'lib/timesteps/timestep.rb', line 669 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
585 586 587 588 |
# File 'lib/timesteps/timestep.rb', line 585 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
618 619 620 |
# File 'lib/timesteps/timestep.rb', line 618 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.
700 701 702 |
# File 'lib/timesteps/timestep.rb', line 700 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.
714 715 716 |
# File 'lib/timesteps/timestep.rb', line 714 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.
497 498 499 500 501 502 503 504 505 506 |
# File 'lib/timesteps/timestep.rb', line 497 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).
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 |
# File 'lib/timesteps/timestep.rb', line 374 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
650 651 652 |
# File 'lib/timesteps/timestep.rb', line 650 def to (other) return Pair.new(self, other) end |
#truncate(time) ⇒ DateTime
Truncate the given datetime to the unit of the object.
552 553 554 |
# File 'lib/timesteps/timestep.rb', line 552 def truncate (time) return time_at(index_at(time).floor) end |