mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-02 20:58:15 +00:00
Merge branch 'master' of https://github.com/odin-lang/Odin
This commit is contained in:
+107
-1
@@ -187,4 +187,110 @@ scan_digits :: proc(s: string, sep: string, count: int) -> (res: int, ok: bool)
|
|||||||
found_sep |= rune(s[count]) == v
|
found_sep |= rune(s[count]) == v
|
||||||
}
|
}
|
||||||
return res, found_sep
|
return res, found_sep
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Serialize the timestamp as a RFC 3339 string.
|
||||||
|
|
||||||
|
The boolean `ok` is false if the `time` is not a valid datetime, or if allocating the result string fails.
|
||||||
|
|
||||||
|
**Inputs**:
|
||||||
|
- `utc_offset`: offset in minutes wrt UTC (ie. the timezone)
|
||||||
|
- `include_nanos`: whether to include nanoseconds in the result.
|
||||||
|
*/
|
||||||
|
time_to_rfc3339 :: proc(time: Time, utc_offset : int = 0, include_nanos := true, allocator := context.allocator) -> (res: string, ok: bool) {
|
||||||
|
utc_offset := utc_offset
|
||||||
|
|
||||||
|
// convert to datetime
|
||||||
|
datetime := time_to_datetime(time) or_return
|
||||||
|
|
||||||
|
if datetime.year < 0 || datetime.year >= 10_000 { return "", false }
|
||||||
|
|
||||||
|
temp_string := [36]u8{}
|
||||||
|
offset : uint = 0
|
||||||
|
|
||||||
|
print_as_fixed_int :: proc(dst: []u8, offset: ^uint, width: i8, i: i64) {
|
||||||
|
i := i
|
||||||
|
width := width
|
||||||
|
for digit_idx in 0..<width {
|
||||||
|
last_digit := i % 10
|
||||||
|
dst[offset^ + uint(width) - uint(digit_idx)-1] = '0' + u8(last_digit)
|
||||||
|
i = i / 10
|
||||||
|
}
|
||||||
|
|
||||||
|
offset^ += uint(width)
|
||||||
|
}
|
||||||
|
|
||||||
|
print_as_fixed_int(temp_string[:], &offset, 4, datetime.year)
|
||||||
|
temp_string[offset] = '-'
|
||||||
|
offset += 1
|
||||||
|
print_as_fixed_int(temp_string[:], &offset, 2, i64(datetime.month))
|
||||||
|
temp_string[offset] = '-'
|
||||||
|
offset += 1
|
||||||
|
print_as_fixed_int(temp_string[:], &offset, 2, i64(datetime.day))
|
||||||
|
temp_string[offset] = 'T'
|
||||||
|
offset += 1
|
||||||
|
print_as_fixed_int(temp_string[:], &offset, 2, i64(datetime.hour))
|
||||||
|
temp_string[offset] = ':'
|
||||||
|
offset += 1
|
||||||
|
print_as_fixed_int(temp_string[:], &offset, 2, i64(datetime.minute))
|
||||||
|
temp_string[offset] = ':'
|
||||||
|
offset += 1
|
||||||
|
print_as_fixed_int(temp_string[:], &offset, 2, i64(datetime.second))
|
||||||
|
|
||||||
|
// turn 123_450_000 to 12345, 5
|
||||||
|
strip_trailing_zeroes_nanos :: proc(n: i64) -> (res: i64, n_digits: i8) {
|
||||||
|
res = n
|
||||||
|
n_digits = 9
|
||||||
|
for res % 10 == 0 {
|
||||||
|
res = res / 10
|
||||||
|
n_digits -= 1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// pre-epoch times: turn, say, -400ms to +600ms for display
|
||||||
|
nanos := time._nsec % 1_000_000_000
|
||||||
|
if nanos < 0 {
|
||||||
|
nanos += 1_000_000_000
|
||||||
|
}
|
||||||
|
|
||||||
|
if nanos != 0 && include_nanos {
|
||||||
|
temp_string[offset] = '.'
|
||||||
|
offset += 1
|
||||||
|
|
||||||
|
// remove trailing zeroes
|
||||||
|
nanos_nonzero, n_digits := strip_trailing_zeroes_nanos(nanos)
|
||||||
|
assert(nanos_nonzero != 0)
|
||||||
|
|
||||||
|
// write digits, right-to-left
|
||||||
|
for digit_idx : i8 = n_digits-1; digit_idx >= 0; digit_idx -= 1 {
|
||||||
|
digit := u8(nanos_nonzero % 10)
|
||||||
|
temp_string[offset + uint(digit_idx)] = '0' + u8(digit)
|
||||||
|
nanos_nonzero /= 10
|
||||||
|
}
|
||||||
|
offset += uint(n_digits)
|
||||||
|
}
|
||||||
|
|
||||||
|
if utc_offset == 0 {
|
||||||
|
temp_string[offset] = 'Z'
|
||||||
|
offset += 1
|
||||||
|
} else {
|
||||||
|
temp_string[offset] = utc_offset > 0 ? '+' : '-'
|
||||||
|
offset += 1
|
||||||
|
utc_offset = abs(utc_offset)
|
||||||
|
print_as_fixed_int(temp_string[:], &offset, 2, i64(utc_offset / 60))
|
||||||
|
temp_string[offset] = ':'
|
||||||
|
offset += 1
|
||||||
|
print_as_fixed_int(temp_string[:], &offset, 2, i64(utc_offset % 60))
|
||||||
|
}
|
||||||
|
|
||||||
|
res_as_slice, res_alloc := make_slice([]u8, len=offset, allocator = allocator)
|
||||||
|
if res_alloc != nil {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(res_as_slice, temp_string[:offset])
|
||||||
|
|
||||||
|
return string(res_as_slice), true
|
||||||
|
}
|
||||||
|
|||||||
@@ -196,6 +196,36 @@ test_parse_rfc3339_string :: proc(t: ^testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test
|
||||||
|
test_print_rfc3339 :: proc(t: ^testing.T) {
|
||||||
|
TestCase :: struct {
|
||||||
|
printed: string,
|
||||||
|
time: i64,
|
||||||
|
utc_offset: int,
|
||||||
|
}
|
||||||
|
|
||||||
|
tests :: [?]TestCase {
|
||||||
|
{"1985-04-12T23:20:50.52Z", 482196050520000000, 0},
|
||||||
|
{"1985-04-12T23:20:50.52001905Z", 482196050520019050, 0},
|
||||||
|
{"1996-12-19T16:39:57-08:00", 851013597000000000, -480},
|
||||||
|
{"1996-12-20T00:39:57Z", 851042397000000000, 0},
|
||||||
|
{"1937-01-01T12:00:27.87+00:20", -1041335972130000000, +20},
|
||||||
|
}
|
||||||
|
|
||||||
|
for test in tests {
|
||||||
|
timestamp := time.Time { _nsec = test.time }
|
||||||
|
printed_timestamp, ok := time.time_to_rfc3339(time=timestamp, utc_offset=test.utc_offset)
|
||||||
|
defer delete_string(printed_timestamp)
|
||||||
|
|
||||||
|
testing.expect(t, ok, "expected printing to work fine")
|
||||||
|
|
||||||
|
testing.expectf(
|
||||||
|
t, printed_timestamp == test.printed,
|
||||||
|
"expected is %w, printed is %w", test.printed, printed_timestamp,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@test
|
@test
|
||||||
test_parse_iso8601_string :: proc(t: ^testing.T) {
|
test_parse_iso8601_string :: proc(t: ^testing.T) {
|
||||||
for test in iso8601_tests {
|
for test in iso8601_tests {
|
||||||
@@ -318,4 +348,4 @@ date_component_roundtrip_test :: proc(t: ^testing.T, moment: dt.DateTime) {
|
|||||||
"Expected %4d-%2d-%2d %2d:%2d:%2d, got %4d-%2d-%2d %2d:%2d:%2d",
|
"Expected %4d-%2d-%2d %2d:%2d:%2d, got %4d-%2d-%2d %2d:%2d:%2d",
|
||||||
moment.year, moment.month, moment.day, moment.hour, moment.minute, moment.second, YYYY, MM, DD, hh, mm, ss,
|
moment.year, moment.month, moment.day, moment.hour, moment.minute, moment.second, YYYY, MM, DD, hh, mm, ss,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user