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
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.
344 345 346 |
# File 'lib/timesteps/timestep.rb', line 344 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).
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 |
# File 'lib/timesteps/timestep.rb', line 418 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
636 637 638 639 |
# File 'lib/timesteps/timestep.rb', line 636 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).
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 482 483 484 |
# File 'lib/timesteps/timestep.rb', line 457 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.
328 329 330 331 332 333 334 335 336 |
# File 'lib/timesteps/timestep.rb', line 328 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.
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_origin(time, truncate: false) ⇒ TimeStep
Returns new timestep object which holds the given time as origin.
526 527 528 529 530 531 532 533 534 535 |
# File 'lib/timesteps/timestep.rb', line 526 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
571 572 573 574 |
# File 'lib/timesteps/timestep.rb', line 571 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
605 606 607 |
# File 'lib/timesteps/timestep.rb', line 605 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.
321 322 323 |
# File 'lib/timesteps/timestep.rb', line 321 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.
672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 |
# File 'lib/timesteps/timestep.rb', line 672 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
588 589 590 591 |
# File 'lib/timesteps/timestep.rb', line 588 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
621 622 623 |
# File 'lib/timesteps/timestep.rb', line 621 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.
703 704 705 |
# File 'lib/timesteps/timestep.rb', line 703 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.
717 718 719 |
# File 'lib/timesteps/timestep.rb', line 717 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.
500 501 502 503 504 505 506 507 508 509 |
# File 'lib/timesteps/timestep.rb', line 500 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).
376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 |
# File 'lib/timesteps/timestep.rb', line 376 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
653 654 655 |
# File 'lib/timesteps/timestep.rb', line 653 def to (other) return Pair.new(self, other) end |
#truncate(time) ⇒ DateTime
Truncate the given datetime to the unit of the object.
555 556 557 |
# File 'lib/timesteps/timestep.rb', line 555 def truncate (time) return time_at(index_at(time).floor) end |