From a53611a31765bac8d2a7a8b8fc1a963ccbe599f6 Mon Sep 17 00:00:00 2001 From: Gears Date: Sun, 11 Jan 2026 11:35:32 +0000 Subject: [PATCH] Switch from birl to gleam_time --- README.md | 5 ++-- gleam.toml | 2 +- manifest.toml | 11 +++----- src/webls/atom.gleam | 29 +++++++++++---------- src/webls/rss.gleam | 56 +++++++++++++++++++++++++++++++---------- src/webls/sitemap.gleam | 19 +++++++++----- test/webls_test.gleam | 6 ++--- 7 files changed, 83 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index ddb5e48..b204aaa 100644 --- a/README.md +++ b/README.md @@ -11,13 +11,14 @@ gleam add webls ``` ```gleam +import gleam/time/timestamp import webls/sitemap import webls/rss import webls/robots pub fn sitemap() -> String { sitemap.sitemap("https://gleam.run/sitemap.xml") - |> sitemap.with_sitemap_last_modified(birl.now()) + |> sitemap.with_sitemap_last_modified(timestamp.system_time()) |> sitemap.with_sitemap_items([ sitemap.item("https://gleam.run") |> sitemap.with_item_frequency(sitemap.Monthly) @@ -37,7 +38,7 @@ pub fn rss() -> String { |> rss.with_channel_items([ rss.item("Gleam 1.0", "Gleam 1.0 is here!") |> rss.with_item_link("https://gleam.run/blog/gleam-1.0") - |> rss.with_item_pub_date(birl.now()) + |> rss.with_item_pub_date(timestamp.system_time()) |> rss.with_item_guid(#("gleam 1.0", Some(False))), rss.item("Gleam 0.10", "Gleam 0.10 is here!") |> rss.with_item_link("https://gleam.run/blog/gleam-0.10") diff --git a/gleam.toml b/gleam.toml index a2a45c1..6768466 100644 --- a/gleam.toml +++ b/gleam.toml @@ -7,7 +7,7 @@ repository = { type = "github", user = "versecafe", repo = "webls" } [dependencies] gleam_stdlib = ">= 0.34.0 and < 2.0.0" -birl = ">= 1.7.1 and < 2.0.0" +gleam_time = ">= 1.6.0 and < 2.0.0" [dev-dependencies] gleeunit = ">= 1.0.0 and < 2.0.0" diff --git a/manifest.toml b/manifest.toml index 1167f4c..9c91f51 100644 --- a/manifest.toml +++ b/manifest.toml @@ -2,15 +2,12 @@ # You typically do not need to edit this file packages = [ - { name = "birl", version = "1.8.0", build_tools = ["gleam"], requirements = ["gleam_regexp", "gleam_stdlib", "ranger"], otp_app = "birl", source = "hex", outer_checksum = "2AC7BA26F998E3DFADDB657148BD5DDFE966958AD4D6D6957DD0D22E5B56C400" }, - { name = "gleam_regexp", version = "1.1.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_regexp", source = "hex", outer_checksum = "9C215C6CA84A5B35BB934A9B61A9A306EC743153BE2B0425A0D032E477B062A9" }, - { name = "gleam_stdlib", version = "0.62.1", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "0080706D3A5A9A36C40C68481D1D231D243AF602E6D2A2BE67BA8F8F4DFF45EC" }, - { name = "gleam_yielder", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_yielder", source = "hex", outer_checksum = "8E4E4ECFA7982859F430C57F549200C7749823C106759F4A19A78AEA6687717A" }, - { name = "gleeunit", version = "1.6.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "FDC68A8C492B1E9B429249062CD9BAC9B5538C6FBF584817205D0998C42E1DAC" }, - { name = "ranger", version = "1.4.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "gleam_yielder"], otp_app = "ranger", source = "hex", outer_checksum = "C8988E8F8CDBD3E7F4D8F2E663EF76490390899C2B2885A6432E942495B3E854" }, + { name = "gleam_stdlib", version = "0.68.1", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "F7FAEBD8EF260664E86A46C8DBA23508D1D11BB3BCC6EE1B89B3BC3E5C83FF1E" }, + { name = "gleam_time", version = "1.6.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_time", source = "hex", outer_checksum = "0DF3834D20193F0A38D0EB21F0A78D48F2EC276C285969131B86DF8D4EF9E762" }, + { name = "gleeunit", version = "1.9.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "DA9553CE58B67924B3C631F96FE3370C49EB6D6DC6B384EC4862CC4AAA718F3C" }, ] [requirements] -birl = { version = ">= 1.7.1 and < 2.0.0" } gleam_stdlib = { version = ">= 0.34.0 and < 2.0.0" } +gleam_time = { version = ">= 1.6.0 and < 2.0.0" } gleeunit = { version = ">= 1.0.0 and < 2.0.0" } diff --git a/src/webls/atom.gleam b/src/webls/atom.gleam index af4669c..c823889 100644 --- a/src/webls/atom.gleam +++ b/src/webls/atom.gleam @@ -1,8 +1,9 @@ -import birl.{type Time} import gleam/int import gleam/list import gleam/option.{type Option, None, Some} import gleam/result +import gleam/time/calendar +import gleam/time/timestamp.{type Timestamp} // Stringify ------------------------------------------------------------------ @@ -21,7 +22,7 @@ fn atom_feed_to_string(feed: AtomFeed) -> String { <> text_to_string(feed.title) <> "\n" <> "" - <> birl.to_iso8601(feed.updated) + <> timestamp.to_rfc3339(feed.updated, calendar.utc_offset) <> "\n" <> list.map(feed.authors, person_to_string) |> list.reduce(fn(acc, author) { acc <> author }) @@ -70,7 +71,7 @@ fn atom_entry_to_string(entry: AtomEntry) -> String { <> text_to_string(entry.title) <> "\n" <> "" - <> birl.to_iso8601(entry.updated) + <> timestamp.to_rfc3339(entry.updated, calendar.utc_offset) <> "\n" <> list.map(entry.authors, person_to_string) |> list.reduce(fn(acc, author) { acc <> author }) @@ -95,7 +96,9 @@ fn atom_entry_to_string(entry: AtomEntry) -> String { |> result.unwrap("") <> case entry.published { Some(published) -> - "" <> birl.to_iso8601(published) <> "\n" + "" + <> timestamp.to_rfc3339(published, calendar.utc_offset) + <> "\n" None -> "" } <> case entry.rights { @@ -189,7 +192,7 @@ fn source_to_string(source: Source) -> String { <> source.title <> "\n" <> "" - <> birl.to_iso8601(source.updated) + <> timestamp.to_rfc3339(source.updated, calendar.utc_offset) <> "\n" <> "\n" } @@ -271,7 +274,7 @@ pub fn with_person_uri(person: Person, uri: String) -> Person { Person(..person, uri: Some(uri)) } -pub fn feed(id: String, title: Text, updated: Time) -> AtomFeed { +pub fn feed(id: String, title: Text, updated: Timestamp) -> AtomFeed { AtomFeed( id: id, title: title, @@ -289,7 +292,7 @@ pub fn feed(id: String, title: Text, updated: Time) -> AtomFeed { ) } -pub fn entry(id: String, title: Text, updated: Time) -> AtomEntry { +pub fn entry(id: String, title: Text, updated: Timestamp) -> AtomEntry { AtomEntry( id: id, title: title, @@ -314,7 +317,7 @@ pub fn with_entry_title(entry: AtomEntry, title: Text) -> AtomEntry { AtomEntry(..entry, title: title) } -pub fn with_entry_updated(entry: AtomEntry, updated: Time) -> AtomEntry { +pub fn with_entry_updated(entry: AtomEntry, updated: Timestamp) -> AtomEntry { AtomEntry(..entry, updated: updated) } @@ -351,7 +354,7 @@ pub fn with_entry_contributors( ) } -pub fn with_entry_published(entry: AtomEntry, published: Time) -> AtomEntry { +pub fn with_entry_published(entry: AtomEntry, published: Timestamp) -> AtomEntry { AtomEntry(..entry, published: Some(published)) } @@ -434,7 +437,7 @@ pub type AtomFeed { AtomFeed( id: String, title: Text, - updated: Time, + updated: Timestamp, authors: List(Person), link: Option(Link), categories: List(Category), @@ -475,14 +478,14 @@ pub type AtomEntry { AtomEntry( id: String, title: Text, - updated: Time, + updated: Timestamp, authors: List(Person), content: Option(Text), link: Option(Link), summary: Option(Text), categories: List(Category), contributors: List(Person), - published: Option(Time), + published: Option(Timestamp), rights: Option(Text), source: Option(Source), ) @@ -495,5 +498,5 @@ pub type Text { } pub type Source { - Source(id: String, title: String, updated: Time) + Source(id: String, title: String, updated: Timestamp) } diff --git a/src/webls/rss.gleam b/src/webls/rss.gleam index 217c645..bcf9d2d 100644 --- a/src/webls/rss.gleam +++ b/src/webls/rss.gleam @@ -1,8 +1,9 @@ -import birl.{type Time} import gleam/int import gleam/list import gleam/option.{type Option, None, Some} import gleam/result +import gleam/time/calendar +import gleam/time/timestamp.{type Timestamp} // Stringify ------------------------------------------------------------------ @@ -55,13 +56,15 @@ fn rss_channel_to_string(channel: RssChannel) -> String { } <> case channel.pub_date { Some(pub_date) -> - "" <> pub_date |> birl.to_iso8601 <> "\n" + "" + <> pub_date |> timestamp.to_rfc3339(calendar.utc_offset) + <> "\n" _ -> "" } <> case channel.last_build_date { Some(last_build_date) -> "" - <> last_build_date |> birl.to_iso8601 + <> last_build_date |> timestamp.to_rfc3339(calendar.utc_offset) <> "\n" _ -> "" } @@ -158,7 +161,7 @@ fn rss_channel_to_string(channel: RssChannel) -> String { True -> { "" <> list.map(channel.skip_days, fn(day) { - "" <> day |> birl.weekday_to_string <> "" + "" <> day |> weekday_to_string <> "" }) |> list.reduce(fn(acc, day) { acc <> "\n" <> day }) |> result.unwrap("") @@ -196,7 +199,9 @@ fn rss_item_to_string(item: RssItem) -> String { } <> case item.pub_date { Some(pub_date) -> - "" <> pub_date |> birl.to_iso8601 <> "\n" + "" + <> pub_date |> timestamp.to_rfc3339(calendar.utc_offset) + <> "\n" _ -> "" } <> item.categories @@ -234,6 +239,18 @@ fn rss_item_to_string(item: RssItem) -> String { <> "" } +fn weekday_to_string(weekday: Weekday) -> String { + case weekday { + Monday -> "Monday" + Tuesday -> "Tuesday" + Wednesday -> "Wednesday" + Thursday -> "Thursday" + Friday -> "Friday" + Saturday -> "Saturday" + Sunday -> "Sunday" + } +} + // Builder Pattern ------------------------------------------------------------- /// Creates a base RSS channel @@ -294,14 +311,17 @@ pub fn with_channel_web_master( } /// Sets the publication date of the RSS channel -pub fn with_channel_pub_date(channel: RssChannel, pub_date: Time) -> RssChannel { +pub fn with_channel_pub_date( + channel: RssChannel, + pub_date: Timestamp, +) -> RssChannel { RssChannel(..channel, pub_date: Some(pub_date)) } /// Sets the last build date of the RSS channel pub fn with_channel_last_build_date( channel: RssChannel, - last_build_date: Time, + last_build_date: Timestamp, ) -> RssChannel { RssChannel(..channel, last_build_date: Some(last_build_date)) } @@ -378,7 +398,7 @@ pub fn with_channel_skip_hours( /// Sets a list of days to skip in the RSS channel pub fn with_channel_skip_days( channel: RssChannel, - skip_days: List(birl.Weekday), + skip_days: List(Weekday), ) -> RssChannel { RssChannel(..channel, skip_days: skip_days) } @@ -443,7 +463,7 @@ pub fn with_item_guid(item: RssItem, guid: #(String, Option(Bool))) -> RssItem { } /// Sets the publication date of the RSS item -pub fn with_item_pub_date(item: RssItem, pub_date: Time) -> RssItem { +pub fn with_item_pub_date(item: RssItem, pub_date: Timestamp) -> RssItem { RssItem(..item, pub_date: Some(pub_date)) } @@ -472,9 +492,9 @@ pub type RssChannel { /// The web master’s email address web_master: Option(String), /// The publication date of the RSS channel - pub_date: Option(Time), + pub_date: Option(Timestamp), /// The last build date of the RSS channel - last_build_date: Option(Time), + last_build_date: Option(Timestamp), /// A list of categories for the RSS channel categories: List(String), /// The generator program of the RSS channel, feel free to shout webls out! @@ -492,7 +512,7 @@ pub type RssChannel { /// A list of hours in GMT which content aggregation should be skipped skip_hours: List(Int), /// A list of days to skip in the RSS channel - skip_days: List(birl.Weekday), + skip_days: List(Weekday), /// A list of items in the RSS channel items: List(RssItem), ) @@ -574,7 +594,7 @@ pub type RssItem { /// The RSS channel the item came from source: Option(String), /// The publication date of the RSS item - pub_date: Option(Time), + pub_date: Option(Timestamp), /// A list of categories for the RSS item categories: List(String), /// An optional enclosure resource for the RSS item @@ -583,3 +603,13 @@ pub type RssItem { guid: Option(#(String, Option(Bool))), ) } + +pub type Weekday { + Monday + Tuesday + Wednesday + Thursday + Friday + Saturday + Sunday +} diff --git a/src/webls/sitemap.gleam b/src/webls/sitemap.gleam index f53fba2..8deaef7 100644 --- a/src/webls/sitemap.gleam +++ b/src/webls/sitemap.gleam @@ -1,8 +1,9 @@ -import birl.{type Time} import gleam/float import gleam/list import gleam/option.{type Option, None, Some} import gleam/result +import gleam/time/calendar +import gleam/time/timestamp.{type Timestamp} // Stringify ------------------------------------------------------------------ @@ -25,7 +26,10 @@ fn sitemap_item_to_string(item: SitemapItem) -> String { <> item.loc <> "\n" <> case item.last_modified { - Some(date) -> "" <> date |> birl.to_iso8601 <> "\n" + Some(date) -> + "" + <> date |> timestamp.to_rfc3339(calendar.utc_offset) + <> "\n" _ -> "" } <> case item.change_frequency { @@ -73,7 +77,7 @@ pub fn with_sitemap_item(sitemap: Sitemap, item: SitemapItem) -> Sitemap { /// Add a last modified time to the sitemap pub fn with_sitemap_last_modified( sitemap: Sitemap, - last_modified: Time, + last_modified: Timestamp, ) -> Sitemap { Sitemap(..sitemap, last_modified: Some(last_modified)) } @@ -102,7 +106,10 @@ pub fn with_item_priority(item: SitemapItem, priority: Float) -> SitemapItem { } /// Add a last modified time to the sitemap item -pub fn with_item_last_modified(item: SitemapItem, modified: Time) -> SitemapItem { +pub fn with_item_last_modified( + item: SitemapItem, + modified: Timestamp, +) -> SitemapItem { SitemapItem(..item, last_modified: Some(modified)) } @@ -114,7 +121,7 @@ pub type Sitemap { /// The url location of the sitemap url: String, /// The time of last modification of the sitemap - last_modified: Option(Time), + last_modified: Option(Timestamp), /// The list of items contained within the sitemap items: List(SitemapItem), ) @@ -126,7 +133,7 @@ pub type SitemapItem { /// The location/url of the page loc: String, /// The time of last modification of the page - last_modified: Option(Time), + last_modified: Option(Timestamp), /// How frequently the page is likely to continue to change change_frequency: Option(ChangeFrequency), /// The priority of the page compared to others within the sitemap diff --git a/test/webls_test.gleam b/test/webls_test.gleam index 65f2520..2bcc145 100644 --- a/test/webls_test.gleam +++ b/test/webls_test.gleam @@ -1,6 +1,6 @@ -import birl import gleam/option.{Some} import gleam/string +import gleam/time/timestamp import gleeunit import gleeunit/should import webls/robots @@ -20,7 +20,7 @@ pub fn rss_to_string_test() -> Nil { |> rss.with_channel_items([ rss.item("Gleam 1.0", "Gleam 1.0 is here!") |> rss.with_item_link("https://gleam.run/blog/gleam-1.0") - |> rss.with_item_pub_date(birl.now()) + |> rss.with_item_pub_date(timestamp.system_time()) |> rss.with_item_guid(#("gleam 1.0", Some(False))), rss.item("Gleam 0.10", "Gleam 0.10 is here!") |> rss.with_item_link("https://gleam.run/blog/gleam-0.10") @@ -42,7 +42,7 @@ pub fn rss_to_string_test() -> Nil { pub fn sitemap_to_string_test() -> Nil { let sitemap = sitemap.sitemap("https://gleam.run/sitemap.xml") - |> sitemap.with_sitemap_last_modified(birl.now()) + |> sitemap.with_sitemap_last_modified(timestamp.system_time()) |> sitemap.with_sitemap_items([ sitemap.item("https://gleam.run") |> sitemap.with_item_frequency(sitemap.Monthly)