+2
-1
gleam.toml
+2
-1
gleam.toml
+5
-3
manifest.toml
+5
-3
manifest.toml
···
2
# You typically do not need to edit this file
3
4
packages = [
5
-
{ name = "gleam_stdlib", version = "0.43.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "69EF22E78FDCA9097CBE7DF91C05B2A8B5436826D9F66680D879182C0860A747" },
6
{ name = "gleeunit", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "F7A7228925D3EE7D0813C922E062BFD6D7E9310F0BEE585D3A42F3307E3CFD13" },
7
-
{ name = "ranger", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "ranger", source = "hex", outer_checksum = "1566C272B1D141B3BBA38B25CB761EF56E312E79EC0E2DFD4D3C19FB0CC1F98C" },
8
]
9
10
[requirements]
11
-
gleam_stdlib = { version = ">= 0.43.0 and < 2.0.0" }
12
gleeunit = { version = ">= 1.2.0 and < 2.0.0" }
13
ranger = { version = ">= 1.2.0 and < 2.0.0" }
···
2
# You typically do not need to edit this file
3
4
packages = [
5
+
{ name = "gleam_regexp", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_regexp", source = "hex", outer_checksum = "A3655FDD288571E90EE9C4009B719FEF59FA16AFCDF3952A76A125AF23CF1592" },
6
+
{ name = "gleam_stdlib", version = "0.44.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "A6E55E309A6778206AAD4038D9C49E15DF71027A1DB13C6ADA06BFDB6CF1260E" },
7
{ name = "gleeunit", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "F7A7228925D3EE7D0813C922E062BFD6D7E9310F0BEE585D3A42F3307E3CFD13" },
8
+
{ name = "ranger", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "ranger", source = "hex", outer_checksum = "B8F3AFF23A3A5B5D9526B8D18E7C43A7DFD3902B151B97EC65397FE29192B695" },
9
]
10
11
[requirements]
12
+
gleam_regexp = { version = ">= 1.0.0 and < 2.0.0" }
13
+
gleam_stdlib = { version = ">= 0.44.0 and < 2.0.0" }
14
gleeunit = { version = ">= 1.2.0 and < 2.0.0" }
15
ranger = { version = ">= 1.2.0 and < 2.0.0" }
+33
-25
src/birl.gleam
+33
-25
src/birl.gleam
···
5
import gleam/list
6
import gleam/option
7
import gleam/order
8
-
import gleam/regex
9
import gleam/result
10
import gleam/string
11
···
292
///
293
/// - `1905-12-22T16:38:23.000+03:30` -> `1905-12-22T16:38:23.000+03:30`
294
pub fn parse(value: String) -> Result(Time, Nil) {
295
-
let assert Ok(offset_pattern) = regex.from_string("(.*)([+|\\-].*)")
296
let value = string.trim(value)
297
298
use #(day_string, offsetted_time_string) <- result.then(case
···
318
True ->
319
Ok(#(day_string, string.drop_end(offsetted_time_string, 1), "+00:00"))
320
False ->
321
-
case regex.scan(offset_pattern, offsetted_time_string) {
322
-
[regex.Match(_, [option.Some(time_string), option.Some(offset_string)])] ->
323
-
Ok(#(day_string, time_string, offset_string))
324
_ ->
325
-
case regex.scan(offset_pattern, day_string) {
326
[
327
-
regex.Match(
328
_,
329
[option.Some(day_string), option.Some(offset_string)],
330
),
···
395
///
396
/// - `T16:38:23.050+03:30` -> `#(TimeOfDay(16, 38, 23, 50), "+03:30")`
397
pub fn parse_time_of_day(value: String) -> Result(#(TimeOfDay, String), Nil) {
398
-
let assert Ok(offset_pattern) = regex.from_string("(.*)([+|\\-].*)")
399
400
let time_string = case
401
string.starts_with(value, "T"),
···
410
{
411
True -> Ok(#(string.drop_end(value, 1), "+00:00"))
412
False ->
413
-
case regex.scan(offset_pattern, value) {
414
-
[regex.Match(_, [option.Some(time_string), option.Some(offset_string)])] ->
415
-
Ok(#(time_string, offset_string))
416
_ -> Error(Nil)
417
}
418
})
···
733
)
734
735
let rest = string.trim(rest)
736
-
let assert Ok(whitespace_pattern) = regex.from_string("\\s+")
737
-
case regex.split(whitespace_pattern, rest) {
738
[day_string, month_string, year_string, time_string, offset_string] -> {
739
let time_string = string.replace(time_string, ":", "")
740
case
···
1322
1323
fn parse_offset(offset: String) -> Result(Int, Nil) {
1324
use <- bool.guard(list.contains(["Z", "z"], offset), Ok(0))
1325
-
let assert Ok(re) = regex.from_string("([+-])")
1326
1327
-
use #(sign, offset) <- result.then(case regex.split(re, offset) {
1328
["", "+", offset] -> Ok(#(1, offset))
1329
["", "-", offset] -> Ok(#(-1, offset))
1330
[_] -> Ok(#(1, offset))
···
1438
case string.contains(date, "-") {
1439
True -> {
1440
let assert Ok(dash_pattern) =
1441
-
regex.from_string(
1442
"(\\d{4})(?:-(1[0-2]|0?[0-9]))?(?:-(3[0-1]|[1-2][0-9]|0?[0-9]))?",
1443
)
1444
1445
-
case regex.scan(dash_pattern, date) {
1446
-
[regex.Match(_, [option.Some(major)])] -> [
1447
int.parse(major),
1448
Ok(1),
1449
Ok(1),
1450
]
1451
1452
-
[regex.Match(_, [option.Some(major), option.Some(middle)])] -> [
1453
int.parse(major),
1454
int.parse(middle),
1455
Ok(1),
1456
]
1457
1458
[
1459
-
regex.Match(
1460
_,
1461
[option.Some(major), option.Some(middle), option.Some(minor)],
1462
),
···
1517
pattern_string: String,
1518
default: Int,
1519
) -> List(Result(Int, Nil)) {
1520
-
let assert Ok(pattern) = regex.from_string(pattern_string)
1521
-
case regex.scan(pattern, section) {
1522
-
[regex.Match(_, [option.Some(major)])] -> [
1523
int.parse(major),
1524
Ok(default),
1525
Ok(default),
1526
]
1527
1528
-
[regex.Match(_, [option.Some(major), option.Some(middle)])] -> [
1529
int.parse(major),
1530
int.parse(middle),
1531
Ok(default),
1532
]
1533
1534
[
1535
-
regex.Match(
1536
_,
1537
[option.Some(major), option.Some(middle), option.Some(minor)],
1538
),
···
5
import gleam/list
6
import gleam/option
7
import gleam/order
8
+
import gleam/regexp
9
import gleam/result
10
import gleam/string
11
···
292
///
293
/// - `1905-12-22T16:38:23.000+03:30` -> `1905-12-22T16:38:23.000+03:30`
294
pub fn parse(value: String) -> Result(Time, Nil) {
295
+
let assert Ok(offset_pattern) = regexp.from_string("(.*)([+|\\-].*)")
296
let value = string.trim(value)
297
298
use #(day_string, offsetted_time_string) <- result.then(case
···
318
True ->
319
Ok(#(day_string, string.drop_end(offsetted_time_string, 1), "+00:00"))
320
False ->
321
+
case regexp.scan(offset_pattern, offsetted_time_string) {
322
+
[
323
+
regexp.Match(
324
+
_,
325
+
[option.Some(time_string), option.Some(offset_string)],
326
+
),
327
+
] -> Ok(#(day_string, time_string, offset_string))
328
_ ->
329
+
case regexp.scan(offset_pattern, day_string) {
330
[
331
+
regexp.Match(
332
_,
333
[option.Some(day_string), option.Some(offset_string)],
334
),
···
399
///
400
/// - `T16:38:23.050+03:30` -> `#(TimeOfDay(16, 38, 23, 50), "+03:30")`
401
pub fn parse_time_of_day(value: String) -> Result(#(TimeOfDay, String), Nil) {
402
+
let assert Ok(offset_pattern) = regexp.from_string("(.*)([+|\\-].*)")
403
404
let time_string = case
405
string.starts_with(value, "T"),
···
414
{
415
True -> Ok(#(string.drop_end(value, 1), "+00:00"))
416
False ->
417
+
case regexp.scan(offset_pattern, value) {
418
+
[
419
+
regexp.Match(
420
+
_,
421
+
[option.Some(time_string), option.Some(offset_string)],
422
+
),
423
+
] -> Ok(#(time_string, offset_string))
424
_ -> Error(Nil)
425
}
426
})
···
741
)
742
743
let rest = string.trim(rest)
744
+
let assert Ok(whitespace_pattern) = regexp.from_string("\\s+")
745
+
case regexp.split(whitespace_pattern, rest) {
746
[day_string, month_string, year_string, time_string, offset_string] -> {
747
let time_string = string.replace(time_string, ":", "")
748
case
···
1330
1331
fn parse_offset(offset: String) -> Result(Int, Nil) {
1332
use <- bool.guard(list.contains(["Z", "z"], offset), Ok(0))
1333
+
let assert Ok(re) = regexp.from_string("([+-])")
1334
1335
+
use #(sign, offset) <- result.then(case regexp.split(re, offset) {
1336
["", "+", offset] -> Ok(#(1, offset))
1337
["", "-", offset] -> Ok(#(-1, offset))
1338
[_] -> Ok(#(1, offset))
···
1446
case string.contains(date, "-") {
1447
True -> {
1448
let assert Ok(dash_pattern) =
1449
+
regexp.from_string(
1450
"(\\d{4})(?:-(1[0-2]|0?[0-9]))?(?:-(3[0-1]|[1-2][0-9]|0?[0-9]))?",
1451
)
1452
1453
+
case regexp.scan(dash_pattern, date) {
1454
+
[regexp.Match(_, [option.Some(major)])] -> [
1455
int.parse(major),
1456
Ok(1),
1457
Ok(1),
1458
]
1459
1460
+
[regexp.Match(_, [option.Some(major), option.Some(middle)])] -> [
1461
int.parse(major),
1462
int.parse(middle),
1463
Ok(1),
1464
]
1465
1466
[
1467
+
regexp.Match(
1468
_,
1469
[option.Some(major), option.Some(middle), option.Some(minor)],
1470
),
···
1525
pattern_string: String,
1526
default: Int,
1527
) -> List(Result(Int, Nil)) {
1528
+
let assert Ok(pattern) = regexp.from_string(pattern_string)
1529
+
case regexp.scan(pattern, section) {
1530
+
[regexp.Match(_, [option.Some(major)])] -> [
1531
int.parse(major),
1532
Ok(default),
1533
Ok(default),
1534
]
1535
1536
+
[regexp.Match(_, [option.Some(major), option.Some(middle)])] -> [
1537
int.parse(major),
1538
int.parse(middle),
1539
Ok(default),
1540
]
1541
1542
[
1543
+
regexp.Match(
1544
_,
1545
[option.Some(major), option.Some(middle), option.Some(minor)],
1546
),
+5
-5
src/birl/duration.gleam
+5
-5
src/birl/duration.gleam
···
2
import gleam/list
3
import gleam/option
4
import gleam/order
5
-
import gleam/regex
6
import gleam/result
7
import gleam/string
8
···
316
/// numbers with no unit are considered as microseconds.
317
/// specifying `accurate:` is equivalent to using `accurate_new`.
318
pub fn parse(expression: String) -> Result(Duration, Nil) {
319
-
let assert Ok(re) = regex.from_string("([+|\\-])?\\s*(\\d+)\\s*(\\w+)?")
320
321
let #(constructor, expression) = case
322
string.starts_with(expression, "accurate:")
···
331
case
332
expression
333
|> string.lowercase
334
-
|> regex.scan(re, _)
335
|> list.try_map(fn(item) {
336
case item {
337
-
regex.Match(_, [sign_option, option.Some(amount_string)]) -> {
338
use amount <- result.then(int.parse(amount_string))
339
340
case sign_option {
···
344
}
345
}
346
347
-
regex.Match(
348
_,
349
[sign_option, option.Some(amount_string), option.Some(unit)],
350
) -> {
···
2
import gleam/list
3
import gleam/option
4
import gleam/order
5
+
import gleam/regexp
6
import gleam/result
7
import gleam/string
8
···
316
/// numbers with no unit are considered as microseconds.
317
/// specifying `accurate:` is equivalent to using `accurate_new`.
318
pub fn parse(expression: String) -> Result(Duration, Nil) {
319
+
let assert Ok(re) = regexp.from_string("([+|\\-])?\\s*(\\d+)\\s*(\\w+)?")
320
321
let #(constructor, expression) = case
322
string.starts_with(expression, "accurate:")
···
331
case
332
expression
333
|> string.lowercase
334
+
|> regexp.scan(re, _)
335
|> list.try_map(fn(item) {
336
case item {
337
+
regexp.Match(_, [sign_option, option.Some(amount_string)]) -> {
338
use amount <- result.then(int.parse(amount_string))
339
340
case sign_option {
···
344
}
345
}
346
347
+
regexp.Match(
348
_,
349
[sign_option, option.Some(amount_string), option.Some(unit)],
350
) -> {