commit 69b2fa02a346b5dbff41dfc4b4ea64a48988e969 Author: pswsm <53122461+pswsm@users.noreply.github.com> Date: Tue Nov 12 18:28:03 2024 +0100 chore(timestamps): bring timestamps from pswsm-repo/sequences diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..be97e7a --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,23 @@ +name: test + +on: + push: + branches: + - master + - main + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: erlef/setup-beam@v1 + with: + otp-version: "26.0.2" + gleam-version: "1.5.1" + rebar3-version: "3" + # elixir-version: "1.15.4" + - run: gleam deps download + - run: gleam test + - run: gleam format --check src test diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..599be4e --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.beam +*.ez +/build +erl_crash.dump diff --git a/README.md b/README.md new file mode 100644 index 0000000..cdd517d --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# timestamps + +[![Package Version](https://img.shields.io/hexpm/v/timestamps)](https://hex.pm/packages/timestamps) +[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/timestamps/) + +```sh +gleam add timestamps@1 +``` +```gleam +import timestamps + +pub fn main() { + let now = timestamps.now() + io.println("The current time is: " <> now |> timestamps.to_string) +} +``` + +Further documentation can be found at . + +## Development + +```sh +gleam run # Run the project +gleam test # Run the tests +``` diff --git a/gleam.toml b/gleam.toml new file mode 100644 index 0000000..6b358d5 --- /dev/null +++ b/gleam.toml @@ -0,0 +1,20 @@ +name = "timestamps" +version = "1.0.0" + +# Fill out these fields if you intend to generate HTML documentation or publish +# your project to the Hex package manager. +# +# description = "" +# licences = ["Apache-2.0"] +# repository = { type = "github", user = "", repo = "" } +# links = [{ title = "Website", href = "" }] +# +# For a full reference of all the available options, you can have a look at +# https://gleam.run/writing-gleam/gleam-toml/. + +[dependencies] +gleam_stdlib = ">= 0.34.0 and < 2.0.0" +gleam_erlang = ">= 0.30.0 and < 1.0.0" + +[dev-dependencies] +gleeunit = ">= 1.0.0 and < 2.0.0" diff --git a/manifest.toml b/manifest.toml new file mode 100644 index 0000000..ffd40e3 --- /dev/null +++ b/manifest.toml @@ -0,0 +1,13 @@ +# This file was generated by Gleam +# You typically do not need to edit this file + +packages = [ + { name = "gleam_erlang", version = "0.30.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "760618870AE4A497B10C73548E6E44F43B76292A54F0207B3771CBB599C675B4" }, + { name = "gleam_stdlib", version = "0.41.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "1B2F80CB1B66B027E3198A2FF71EF3F2F31DF89ED97AD606F25FD387A4C3C1EF" }, + { name = "gleeunit", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "F7A7228925D3EE7D0813C922E062BFD6D7E9310F0BEE585D3A42F3307E3CFD13" }, +] + +[requirements] +gleam_erlang = { version = ">= 0.30.0 and < 1.0.0" } +gleam_stdlib = { version = ">= 0.34.0 and < 2.0.0" } +gleeunit = { version = ">= 1.0.0 and < 2.0.0" } diff --git a/src/timestamps.gleam b/src/timestamps.gleam new file mode 100644 index 0000000..bf84871 --- /dev/null +++ b/src/timestamps.gleam @@ -0,0 +1,76 @@ +import gleam/erlang +import gleam/int + +/// A timestamp in milliseconds. +/// +/// To create a new timestamp use `timestamp.new()`. +pub opaque type Timestamp { + Timestamp(value: Int) +} + +/// Returns the current time as a timestamp in milliseconds. +/// +/// Example: +/// ```gleam +/// let ts = new() +/// // -> 1731431350344 +/// ``` +pub fn new() -> Timestamp { + Timestamp(erlang.system_time(erlang.Millisecond)) +} + +/// Creates a timestamp from given milliseconds. +/// +/// Example: +/// ```gleam +/// let ts = from_millis(1731431350344) +/// // -> 1731431350344 +/// ``` +pub fn from_millis(milliseconds millis: Int) -> Timestamp { + Timestamp(millis) +} + +/// Returns a timestamp that is `hours` hours after the given timestamp. +/// +/// Example: +/// ```gleam +/// let ts = from_millis(1731431350344) +/// let ts_plus_2_hours = add_hours(ts, 2) +/// // -> 1731438550344 +/// ``` +pub fn add_hours(to_this timestamp: Timestamp, no_of hours: Int) -> Timestamp { + Timestamp(timestamp.value + hours * 60 * 60 * 1000) +} + +/// Checks if the first timestamp is before the second timestamp. +/// +/// Example: +/// ```gleam +/// let ts1 = from_millis(1731431350344) +/// let ts2 = from_millis(1731431350345) +/// is_before(ts1, ts2) // -> True +/// ``` +pub fn is_after(timestamp1 t1: Timestamp, timestamp2 t2: Timestamp) -> Bool { + value_of(t1) > value_of(t2) +} + +/// Checks if the given timestamp is in the future. +/// +/// Example: +/// ```gleam +/// let ts = from_millis(2031431350344) +/// is_future(ts) // -> True +/// ``` +pub fn is_future(timestamp t: Timestamp) -> Bool { + t |> is_after(new()) +} + +/// Returns the value of the timestamp. +pub fn value_of(timestamp t: Timestamp) -> Int { + t.value +} + +/// Returns the value of the timestamp as a string. +pub fn to_string(timestamp t: Timestamp) -> String { + int.to_string(t.value) +} diff --git a/test/timestamps_test.gleam b/test/timestamps_test.gleam new file mode 100644 index 0000000..c454742 --- /dev/null +++ b/test/timestamps_test.gleam @@ -0,0 +1,37 @@ +import gleeunit +import gleeunit/should +import timestamps + +pub fn main() { + gleeunit.main() +} + +pub fn timestamp_from_millis_test() { + timestamps.from_millis(0) |> timestamps.value_of |> should.equal(0) +} + +pub fn timestamp_add_hours_test() { + timestamps.from_millis(0) + |> timestamps.add_hours(1) + |> timestamps.value_of + |> should.equal(3_600_000) +} + +pub fn timestamp_is_after_test() { + timestamps.from_millis(1) + |> timestamps.is_after(timestamps.from_millis(0)) + |> should.equal(True) +} + +pub fn timestamp_is_before_test() { + timestamps.from_millis(0) + |> timestamps.is_after(timestamps.from_millis(1)) + |> should.equal(False) +} + +pub fn timestamp_is_future_test() { + timestamps.new() + |> timestamps.add_hours(1) + |> timestamps.is_future + |> should.equal(True) +}