Module: UnixEpoch::ClassMethods

Included in:
DateTime
Defined in:
lib/unix_epoch.rb

Instance Method Summary collapse

Instance Method Details

#from_unix_ts(unix_ts, offset = 0) ⇒ DateTime

Create a new DateTime object from a given Unix Timestamp

Parameters:

  • unix_ts (Fixnum, Bignum)

    seconds since unix epoch (1970-01-01 00:00:00 UTC)

  • offset (Fixnum, TZInfo::Timezone) (defaults to: 0)

    offset in seconds from UTC time or an instance of TZInfo::TimeZone

Returns:

  • (DateTime)

    DateTime object representation of the given Unix TS



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/unix_epoch.rb', line 18

def from_unix_ts(unix_ts, offset = 0)

    if not (offset.respond_to? :to_i or offset.kind_of? TZInfo::Timezone) then
        raise "Invalid value passed for offset: must be an integer or TZInfo::Timezone"
    end

    # step 1) get the delta in days, seconds and nano seconds represented by unix_ts

    delta_days = UnixEpoch._floor(unix_ts / 86_400)
    unix_ts -= delta_days * 86_400

    # unix_ts cannot be negative now, so to_i instead of _floor()
    delta_secs = unix_ts.to_i
    unix_ts -= delta_secs

    delta_nano = unix_ts / 1e9

    # step 2) add these deltas to the jd day and jd sec representation of the unix epoch

    epoch_jd = UnixEpoch.jd_unix_epoch()

    epoch_jd_days = epoch_jd.to_i
    epoch_secs = UnixEpoch.get_jd_secs(epoch_jd) # get left over seconds from our epoch

    jd_days = epoch_jd_days + delta_days

    secs = epoch_secs + delta_secs
    if offset.respond_to? :to_i
        secs += offset # add tz offset back in also
    end
    jd_secs = UnixEpoch.secs_to_jd_secs(secs) + Rational(delta_nano.round, 86_400_000_000)

    if offset.respond_to? :to_i
        return DateTime.from_jd(jd_days, jd_secs, offset)
    elsif offset.kind_of? TZInfo::Timezone
        dt = DateTime.from_jd(jd_days, jd_secs, 0) # first create a new DateTime
        ldt = offset.utc_to_local(dt) # then convert it to our target TZ
        return DateTime.from_jd(ldt.jd, ldt.day_fraction, (ldt.to_i - dt.to_i)) # then create a new DateTime with the current offset
    end
end