97jaz / gregor

Date and time library for Racket
45 stars 10 forks source link

approximating `seconds->date` #43

Closed mbutterick closed 4 years ago

mbutterick commented 4 years ago

Is it possible — and if so how — to take the result from Racket’s usual (current-seconds) or (current-exact-milliseconds) functions and turn them into Gregor objects. For instance, what would be the Gregor equivalent of Racket’s usual seconds->date.

I fiddled with +period thinking I could treat the result of (current-seconds) as an “absolute” time, but it didn’t work. Though I am probably missing something obvious.

LiberalArtist commented 4 years ago

I do this with (with-timezone (posix->datetime posix) 0) to get a moment in UTC, then use adjust-timezone as needed. (The functions current-posix-seconds, now/moment, and now/moment/utc might also be helpful.) It does seem odd, though, that there isn't a posix->moment built in: unless there's something I'm misunderstanding, a POSIX time does "represent an absolute moment in time" (per the docs), so I think it should correspond to a moment, rather than a datetime.

97jaz commented 4 years ago

Huh. There is a posix->moment, but it isn't re-provided by main.rkt. I don't think that was intentional.

Anyhow, the general thing is that gregor works with real?-valued posix seconds (a.k.a unix timestamps). So the result of current-seconds is directly usable as the input to any posix->* function. To use current-inexact-milliseconds, of course, you can just divide the value by 1000.

Phillip's workaround will work for moments. Or you could directly require posix->moment from moment.rkt. (But I should put out a new release that fixes this.) For datetimes, use posix->datetime. If you want a date, you can do (datetime->date (posix->datetime seconds)).

(If you need the date to be localized to some particular TZ, you'll need to start with a moment. See clock.rkt for how gregor does this stuff for the current time.)

97jaz commented 4 years ago

Oh, also you could do what you described and use +period (though +seconds would be a somewhat leaner alternative). Posix times are seconds since the unix epoch (1970-01-01T00:00:00 UTC), so you need to add seconds to that:

(+seconds (datetime 1970) (current-seconds))
;; which is the same thing as
(now/utc)
;; or you could use a moment
(+seconds (moment 1970 #:tz 0) (current-seconds))

But the posix->* functions are meant specifically for what you're doing.

mbutterick commented 4 years ago

I will close this. With an extenuating request that posix->moment be added to the public interface & docs. Thanks.