Skip to content

Commit af40fec

Browse files
committed
add support for gleam/time types
1 parent 8f6f799 commit af40fec

File tree

4 files changed

+127
-0
lines changed

4 files changed

+127
-0
lines changed

gleam.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ internal_modules = [
1717

1818
[dependencies]
1919
gleam_stdlib = ">= 0.34.0 and < 2.0.0"
20+
gleam_time = ">= 1.1.0 and < 2.0.0"
2021

2122
[dev-dependencies]
2223
gleeunit = ">= 1.0.0 and < 2.0.0"

manifest.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33

44
packages = [
55
{ name = "gleam_stdlib", version = "0.58.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "091F2D2C4A3A4E2047986C47E2C2C9D728A4E068ABB31FDA17B0D347E6248467" },
6+
{ name = "gleam_time", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_time", source = "hex", outer_checksum = "CBAA68E215BEA961B40F3B1BA7B88741B1EB49572EF5E1154E357A5D152A2A2C" },
67
{ name = "gleeunit", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "0E6C83834BA65EDCAAF4FE4FB94AC697D9262D83E6F58A750D63C9F6C8A9D9FF" },
78
]
89

910
[requirements]
1011
gleam_stdlib = { version = ">= 0.34.0 and < 2.0.0" }
12+
gleam_time = { version = ">= 1.1.0 and < 2.0.0" }
1113
gleeunit = { version = ">= 1.0.0 and < 2.0.0" }

src/humanise.gleam

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,125 @@
22
////
33
//// For more control (e.g. work with `time.Time` or `bytes.Bytes` directly, use the given unit instead of the most optimal one), look at the `time`, `bytes` or `bytes1024` modules.
44

5+
import gleam/float
56
import gleam/int
7+
import gleam/time/calendar.{type Date, type TimeOfDay, Date, TimeOfDay}
8+
import gleam/time/duration.{type Duration}
9+
import gleam/time/timestamp.{type Timestamp}
610

711
import humanise/bytes
812
import humanise/bytes1024
913
import humanise/time
1014

15+
pub fn date_relative(from date: Timestamp, now current: Timestamp) -> String {
16+
let relative = current |> timestamp.difference(date) |> time.from_duration
17+
18+
let decompose = fn(a) {
19+
case a {
20+
time.Nanoseconds(n) -> #(time.Nanoseconds, n)
21+
time.Days(n) -> #(time.Days, n)
22+
time.Hours(n) -> #(time.Hours, n)
23+
time.Microseconds(n) -> #(time.Microseconds, n)
24+
time.Milliseconds(n) -> #(time.Milliseconds, n)
25+
time.Minutes(n) -> #(time.Minutes, n)
26+
time.Seconds(n) -> #(time.Seconds, n)
27+
time.Weeks(n) -> #(time.Weeks, n)
28+
}
29+
}
30+
31+
let #(constructor, n) = decompose(relative)
32+
33+
case n >=. 0.0 {
34+
True -> "in " <> time.to_string(relative)
35+
False -> time.to_string(constructor(float.absolute_value(n))) <> " ago"
36+
}
37+
}
38+
39+
/// Format a `Date`, `TimeOfDay` pair, automatically omitting redundant information (omit year if it matches the current year, omit month and day if it also matches the current day)
40+
///
41+
/// The given date will be compared against the provided "current" date to determine what information to omit.
42+
///
43+
/// This function does not currently support internationalization, and simply returns a string in the following largest-to-smallest format:
44+
/// ```
45+
/// <maybe year> <maybe <month> <day>> <hours>:<minutes>:<seconds>
46+
/// ```
47+
/// Note that hours are in 24 hour format, not 12 hours with AM/PM.
48+
pub fn date(from date: #(Date, TimeOfDay), now current: Date) -> String {
49+
let year_matches = case current, date.0 {
50+
Date(current, ..), Date(given, ..) if current == given -> True
51+
_, _ -> False
52+
}
53+
54+
let day_matches = case current, date.0 {
55+
Date(_, _, current), Date(_, _, given) if current == given -> True
56+
_, _ -> False
57+
}
58+
59+
let Date(year, month, day) = date.0
60+
let TimeOfDay(hours, minutes, seconds, _) = date.1
61+
62+
let maybe_year = case year_matches {
63+
True -> ""
64+
False -> int.to_string(year) <> " "
65+
}
66+
let maybe_month = case year_matches && day_matches, month {
67+
True, _ -> ""
68+
_, calendar.April -> "April "
69+
_, calendar.August -> "August "
70+
_, calendar.December -> "December "
71+
_, calendar.February -> "February "
72+
_, calendar.January -> "January "
73+
_, calendar.July -> "July "
74+
_, calendar.June -> "June "
75+
_, calendar.March -> "March "
76+
_, calendar.May -> "May "
77+
_, calendar.November -> "November "
78+
_, calendar.October -> "October "
79+
_, calendar.September -> "September "
80+
}
81+
let maybe_day = case year_matches && day_matches {
82+
True -> ""
83+
False -> int.to_string(day) <> " "
84+
}
85+
86+
let hours = case hours < 10 {
87+
True -> "0" <> int.to_string(hours)
88+
False -> int.to_string(hours)
89+
}
90+
let minutes = case minutes < 10 {
91+
True -> "0" <> int.to_string(minutes)
92+
False -> int.to_string(minutes)
93+
}
94+
let seconds = case seconds < 10 {
95+
True -> "0" <> int.to_string(seconds)
96+
False -> int.to_string(seconds)
97+
}
98+
99+
maybe_year
100+
<> maybe_month
101+
<> maybe_day
102+
<> hours
103+
<> ":"
104+
<> minutes
105+
<> ":"
106+
<> seconds
107+
}
108+
109+
/// Format a `Duration`, using the most optimal unit.
110+
pub fn duration(from duration: Duration) -> String {
111+
time.from_duration(duration) |> time.to_string
112+
}
113+
114+
/// Format *n* nanoseconds as a `Float`, converting to a more optimal unit if possible.
115+
pub fn nanoseconds_float(from n: Float) -> String {
116+
time.Nanoseconds(n) |> time.humanise |> time.to_string
117+
}
118+
119+
/// Format *n* nanoseconds as a `Float`, converting to a more optimal unit if possible.
120+
pub fn nanoseconds_int(from n: Int) -> String {
121+
time.Nanoseconds(int.to_float(n)) |> time.humanise |> time.to_string
122+
}
123+
11124
/// Format *n* microseconds as a `Float`, converting to a more optimal unit if possible.
12125
pub fn microseconds_float(from n: Float) -> String {
13126
time.Microseconds(n) |> time.humanise |> time.to_string

src/humanise/time.gleam

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import gleam/bool
1212
import gleam/float
13+
import gleam/time/duration.{type Duration}
1314

1415
import util
1516

@@ -41,6 +42,16 @@ pub type Time {
4142
Weeks(Float)
4243
}
4344

45+
/// Convert a Duration from gleam/time.
46+
///
47+
/// Example:
48+
/// ```
49+
/// duration.seconds(120) |> time.from_duration // time.Minutes(2.0)
50+
/// ```
51+
pub fn from_duration(this duration: Duration) -> Time {
52+
Seconds(duration |> duration.to_seconds) |> humanise
53+
}
54+
4455
/// Convert a value to nanoseconds.
4556
///
4657
/// Example:

0 commit comments

Comments
 (0)