From 1884261b6c355cf820757e2f0a1262088661e7fc Mon Sep 17 00:00:00 2001
From: Sloane Perrault <sloane@perrault.email>
Date: Fri, 7 Jul 2023 08:58:01 -0400
Subject: [PATCH] Ecto.ParameterizedType, `time: ...` for `new/2`

---
 CHANGELOG.md                     |  5 +++++
 lib/type_id.ex                   |  8 ++++++--
 test/{ => type_id}/spec_test.exs |  0
 test/type_id_test.exs            | 11 ++++++++++-
 4 files changed, 21 insertions(+), 3 deletions(-)
 rename test/{ => type_id}/spec_test.exs (100%)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6200bac..067ded0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,11 @@
 
 - **BREAKING:** `type/1` has been renamed to `prefix/1`
 - `Ecto.ParameterizedType` implementation
+- `new/2` now accepts an optional keyword list to specify the UUID `time:` in unix milliseconds
+    ```elixir
+    iex> TypeID.new("test", time: 0)
+    #TypeID<"test_0000000000fq893mf5039xea5j">
+    ```
 
 ## 0.2.2
 
diff --git a/lib/type_id.ex b/lib/type_id.ex
index db9db97..f74db2c 100644
--- a/lib/type_id.ex
+++ b/lib/type_id.ex
@@ -18,6 +18,9 @@ defmodule TypeID do
   @doc """
   Generates a new `t:t/0` with the given prefix.
 
+  **Optional**: Specify the time of the UUID v7 by passing
+  `time: unix_millisecond_time` as the second argument.
+
   ### Example
 
       iex> TypeID.new("acct")
@@ -25,9 +28,10 @@ defmodule TypeID do
 
   """
   @spec new(prefix :: String.t()) :: t()
-  def new(prefix) do
+  @spec new(prefix :: String.t(), Keyword.t()) :: t()
+  def new(prefix, opts \\ []) do
     suffix =
-      UUID.uuid7()
+      UUID.uuid7(opts)
       |> Base32.encode()
 
     %__MODULE__{prefix: prefix, suffix: suffix}
diff --git a/test/spec_test.exs b/test/type_id/spec_test.exs
similarity index 100%
rename from test/spec_test.exs
rename to test/type_id/spec_test.exs
diff --git a/test/type_id_test.exs b/test/type_id_test.exs
index 498b8b6..980d63f 100644
--- a/test/type_id_test.exs
+++ b/test/type_id_test.exs
@@ -1,6 +1,6 @@
 defmodule TypeIDTest do
   use ExUnit.Case
-  doctest TypeID, except: [new: 1]
+  doctest TypeID, except: [new: 2]
 
   describe "new/1" do
     test "returns a new TypeID struct" do
@@ -10,6 +10,15 @@ defmodule TypeIDTest do
     end
   end
 
+  describe "new/2" do
+    test "allows setting the time" do
+      time = ~U[1950-12-17 00:00:00Z] |> DateTime.to_unix(:millisecond)
+      tid = TypeID.new("test", time: time)
+      assert "test" == TypeID.prefix(tid)
+      assert "7zegbdn300" <> _ = TypeID.suffix(tid)
+    end
+  end
+
   describe "prefix/1" do
     test "returns the prefix of the given TypeID" do
       tid = TypeID.from_string!("test_01h44had5rfswbvpc383ktj0aa")