Module: CATimeLiteral
- Defined in:
- lib/carray/time.rb
Overview
Reads a time literal (Time / DateTime / Integer unix-seconds / String) into the pieces the CATime constructors need. All parsing is UTC (an explicit offset is honoured; otherwise UTC) and DateTime-independent (Date._parse + a civil-date kernel). Internal to the time surface: nothing here is part of the public API.
Class Method Summary collapse
-
.epoch_seconds(spec, format = nil) ⇒ Object
Exact Rational seconds since the Unix epoch for a start literal (Time / DateTime / Integer unix-seconds / String).
-
.tick_index(spec, res, format = nil) ⇒ Object
Tick index of
spec's instant on theresgrid (floor toward the past). -
.to_time_array(literal, res, format, on_error) ⇒ Object
Single-literal build for time: a 1-element CATime, honouring the on_error policy (raise, or a masked cell).
-
.year_month(spec, format = nil) ⇒ Object
[year, month] (UTC) of a start literal, for a calendar-resolution grid.
Class Method Details
.epoch_seconds(spec, format = nil) ⇒ Object
Exact Rational seconds since the Unix epoch for a start literal (Time / DateTime / Integer unix-seconds / String). UTC default.
1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 |
# File 'lib/carray/time.rb', line 1654 def epoch_seconds(spec, format = nil) require 'date' require 'time' case spec when Time then spec.to_r when Integer then Rational(spec) when CATime::Element # A time element is already an instant, so it needs no parsing: a # fixed unit counts seconds directly, and a calendar one names the # first midnight of its granule (the same instant convert_instant! # gives it). This is what lets floor / ceil / to_unit output feed # straight back into time_range / time_series / .time. if CATimeUnitAlgebra::FIXED.key?(spec.unit.base) Rational(spec.value) * spec.unit.tick_ratio else Rational(CATimeUnitAlgebra.calendar_days_since_epoch(CA_INT64([spec.value]), spec.unit)[0] * 86400) end when String h = parse_date_fields(spec, format) days = CATimeCivil.days_from_civil_1(h[:year], h[:mon] || 1, h[:mday] || 1) sec = Rational(days * 86400 + (h[:hour] || 0) * 3600 + (h[:min] || 0) * 60 + (h[:sec] || 0)) sec += h[:sec_fraction] if h[:sec_fraction] sec -= h[:offset] if h[:offset] # east-of-UTC offset -> UTC sec else if defined?(DateTime) && spec.is_a?(DateTime) spec.to_time.to_r else raise ArgumentError, "cannot parse time #{spec.class}" end end end |
.tick_index(spec, res, format = nil) ⇒ Object
Tick index of spec's instant on the res grid (floor toward the past).
1720 1721 1722 1723 1724 1725 1726 1727 1728 |
# File 'lib/carray/time.rb', line 1720 def tick_index(spec, res, format = nil) if CATimeUnitAlgebra::FIXED.key?(res.base) (epoch_seconds(spec, format) / res.tick_ratio).floor else y, m = year_month(spec, format) months = (y - 1970) * 12 + (m - 1) (Rational(months) / res.tick_ratio).floor end end |
.to_time_array(literal, res, format, on_error) ⇒ Object
Single-literal build for time: a 1-element CATime, honouring the on_error policy (raise, or a masked cell).
1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 |
# File 'lib/carray/time.rb', line 1732 def to_time_array(literal, res, format, on_error) raw = CArray.int64(1) begin raw[0] = tick_index(literal, res, format) rescue ArgumentError, TypeError raise if on_error == :raise raw[0] = UNDEF end raw.time(unit: res) end |
.year_month(spec, format = nil) ⇒ Object
[year, month] (UTC) of a start literal, for a calendar-resolution grid.
1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 |
# File 'lib/carray/time.rb', line 1690 def year_month(spec, format = nil) require 'date' require 'time' case spec when Time then t = spec.utc; [t.year, t.month] when Integer then t = Time.at(spec, in: 'UTC'); [t.year, t.month] when CATime::Element # A calendar element is a month ordinal already, so read it as one # rather than going out through Time (which a :Y / :M element would # have to re-derive). Integer / and % floor, so a pre-epoch value # lands in the right month. case spec.unit.base when :M then mo = spec.value * spec.unit.count + 1970 * 12 [mo / 12, mo % 12 + 1] when :Y then [spec.value * spec.unit.count + 1970, 1] else t = spec.to_time.utc; [t.year, t.month] end when String h = parse_date_fields(spec, format) [h[:year], h[:mon] || 1] else if defined?(DateTime) && spec.is_a?(DateTime) t = spec.to_time.utc; [t.year, t.month] else raise ArgumentError, "cannot parse time #{spec.class}" end end end |