I'm in a migration mood, looking at migrating @Ian McLerran's roc-isodate's library. Hopefully, it shouldn't take too long, but I do have one question: how should I migrate parametrized modules? For example:
# Now.roc
module { now!, now_to_nanos } -> [date_time!, date!, time!]
and:
import dt.Now {
now!: Utc.now!,
now_to_nanos: Utc.to_nanos_since_epoch,
}
I guess the new approach is simply to define an opaque type like this:
Now :: { now! : ({} => Now), now_to_nanos: (Now -> U64) }.{ ... }
which can then be used like this:
import dt.Now
now = Now.create({now!: Utc.now!, now_to_nanos: Utc.to_nanos_since_epoch))
datetime = now.date_time!({})
Does this look good to you?
Seems logical to me
Thanks @Anton
Mmh, I just noticed that roc-isodate depends on two libraries:
They are only used for a few functions, so I think I'll just reimplement them locally rather than port two more libraries.
From rutils:
split_at_indicessplit_with_delimsunwrappad_left_asciiThe roc-tinyparse library is only used to implement parse_frac_fmt so I think I'll use roc-parser instead since I just migrated it.
I've almost finished migrating roc-isodate to the new compiler, all the tests pass, I just need to port the examples now. However, I don't know where to find Utc.now!, it looks like it's not in the basic-cli platform anymore (@Luke Boswell ?)
Also, one example requires a platform that provides the Http.send! function. Does such a platform exist yet? Or maybe I should just simplify this example for now to avoid depending on Http?
Edit: the latest basic-cli 0.21.0 platform includes everything I need: Utc.now!, Sleep.millis!, and Http.send!.
Oh and pf.Sleep is also missing.
Finished at last! Migrating this package was particularly tricky because of all the Int * that I had to replace with concrete integer types, and all the resulting conversions I had to implement. Will someone kindly review the PR?
If you want to try it out, I've created a temporary release.
For example, the following code queries https://timeapi.io/ to get the local time in Paris, then it parses the JSON output to get the ISO 8601 string, and roc-isodate's Datetime.from_iso_str parses that string, so the script can print the result nicely.
app [main!] {
pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.21.0/4rAQg8kUYZ3Vksr4qMQHpaFYNiHSn9GgS7gVxghd1XYV.tar.zst",
http: "https://github.com/roc-lang/http/releases/download/2.0.0/6ZUwqYhCS8PU9Mo6MF7oV82ET2o7KYb57CLKDq4cq4sS.tar.zst",
dt: "https://github.com/ageron/roc-isodate/releases/download/0.8.0/B2h6tefXQtEz9VG6QukLDBoGXhRtwGLj9sZHDEJaTHkS.tar.zst",
}
import pf.Stdout
import pf.Http
import http.Method
import http.Request
import dt.DateTime as DT
main! = |_| {
timezone = "Europe/Paris"
request = Request.from_method(GET)
.with_uri("https://timeapi.io/api/v1/timezone/zone?timeZone=${timezone}")
.with_timeout(TimeoutMilliseconds(3000))
response = Http.send!(request)?
if response.status() >= 200 and response.status() <= 299 {
iso_str = get_iso_str(response.body())?
dt_now = DT.from_iso_str(iso_str)?
date_str = dt_now.format("{YYYY}-{MM}-{DD}")
time_str = dt_now.format("{hh}:{mm}:{ss}")
_ = Stdout.line!("The current Zulu date is: ${date_str}")
_ = Stdout.line!("The current Zulu time is: ${time_str}")
Ok({})
} else {
Err(FailedToGetServerResponse(response.status()))
}
}
get_iso_str : List(U8) -> Try(Str, _)
get_iso_str = |bytes| {
str = bytes->Str.from_utf8()?
response : { local_time : Str }
response = Json.parse(str)?
Ok(response.local_time)
}
Note: timeapi.io doesn't actually give the right time. :smile:
very nice! :smiley:
if you want to get fancy with it, a thing you can do with the new compiler is expose a function that takes a formatting Str and then returns a Try containing a function which formats a date string using that format
then you can do like:
Ok(format) = DT.formatter("{YYYY}-{MM}")
and if you have a syntax error in your format string, you'll find out at compile time
and if not, then you can just call format(str) and it'll be even more efficient because it doesn't need to parse the YYYY-MM string at runtime, since that work already happened at compile time! :rocket:
Last updated: Aug 12 2026 at 12:35 UTC