Browse Source

Add `time.time_to_datetime`

Feoramund 11 months ago
parent
commit
f6f2c67f37
2 changed files with 43 additions and 0 deletions
  1. 18 0
      core/time/time.odin
  2. 25 0
      tests/core/time/test_core_time.odin

+ 18 - 0
core/time/time.odin

@@ -954,6 +954,24 @@ Convert datetime components into time.
 */
 datetime_to_time :: proc{components_to_time, compound_to_time}
 
+/*
+Convert time into datetime.
+*/
+time_to_datetime :: proc "contextless" (t: Time) -> (dt.DateTime, bool) {
+	unix_epoch := dt.DateTime{{1970, 1, 1}, {0, 0, 0, 0}}
+
+	datetime, err := dt.add(unix_epoch, dt.Delta{ nanos = t._nsec })
+	if err != .None {
+		return {}, false
+	}
+	return datetime, true
+}
+
+/*
+Alias for `time_to_datetime`.
+*/
+time_to_compound :: time_to_datetime
+
 /*
 Check if a year is a leap year.
 */

+ 25 - 0
tests/core/time/test_core_time.odin

@@ -253,6 +253,31 @@ test_parse_iso8601_string :: proc(t: ^testing.T) {
 	}
 }
 
+@test
+test_time_to_datetime_roundtrip :: proc(t: ^testing.T) {
+	// Roundtrip a time through `time_to_datetime` to `DateTime` and back.
+	// Select `N` evenly-distributed points throughout the positive signed 64-bit number line.
+	N :: 1024
+	for i in 0..=i64(N) {
+		n := i * (max(i64) / N)
+		x := time.unix(0, n)
+
+		y, ttd_err := time.time_to_datetime(x)
+		testing.expectf(t, ttd_err,
+			"Time<%i> failed to convert to DateTime",
+			n) or_continue
+
+		z, dtt_err := time.datetime_to_time(y)
+		testing.expectf(t, dtt_err,
+			"DateTime<%v> failed to convert to Time",
+			y) or_continue
+
+		testing.expectf(t, x == z,
+			"Roundtrip conversion of Time to DateTime and back failed: got %v, expected %v",
+			z, x)
+	}
+}
+
 MONTH_DAYS := []int{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
 YEAR_START :: 1900
 YEAR_END   :: 2024