From 8dace85cd97a27a2f864518b7a07ac5f70edfc58 Mon Sep 17 00:00:00 2001 From: FObersteiner Date: Wed, 28 Aug 2024 16:44:27 +0200 Subject: [PATCH] revise ergonomics / stringIO --- README.md | 20 ++-- docs/change.log | 5 + examples/ex_datetime.zig | 1 - examples/ex_demo.zig | 2 +- examples/ex_offsetTz.zig | 1 - examples/ex_strings.zig | 11 +- examples/ex_timezones.zig | 1 - lib/Timezone.zig | 4 +- lib/tzdata/zoneinfo/America/Bahia_Banderas | Bin 1152 -> 1100 bytes lib/tzdata/zoneinfo/America/Cancun | Bin 834 -> 864 bytes lib/tzdata/zoneinfo/America/Chihuahua | Bin 1102 -> 1102 bytes lib/tzdata/zoneinfo/America/Ciudad_Juarez | Bin 1538 -> 1538 bytes lib/tzdata/zoneinfo/America/Ensenada | Bin 2374 -> 2458 bytes lib/tzdata/zoneinfo/America/Hermosillo | Bin 456 -> 388 bytes lib/tzdata/zoneinfo/America/Mazatlan | Bin 1128 -> 1060 bytes lib/tzdata/zoneinfo/America/Merida | Bin 1004 -> 1004 bytes lib/tzdata/zoneinfo/America/Mexico_City | Bin 1222 -> 1222 bytes lib/tzdata/zoneinfo/America/Monterrey | Bin 980 -> 1114 bytes lib/tzdata/zoneinfo/America/Ojinaga | Bin 1524 -> 1524 bytes lib/tzdata/zoneinfo/America/Santa_Isabel | Bin 2374 -> 2458 bytes lib/tzdata/zoneinfo/America/Tijuana | Bin 2374 -> 2458 bytes lib/tzdata/zoneinfo/Mexico/BajaNorte | Bin 2374 -> 2458 bytes lib/tzdata/zoneinfo/Mexico/BajaSur | Bin 1128 -> 1060 bytes lib/tzdata/zoneinfo/Mexico/General | Bin 1222 -> 1222 bytes lib/windows/windows_tznames.zig | 2 +- tests/test_stringIO.zig | 115 ++++++++++----------- tests/test_timezone.zig | 111 ++++++++++---------- util/gen_test_tzones.py | 8 +- zdt.zig | 7 +- 29 files changed, 150 insertions(+), 138 deletions(-) diff --git a/README.md b/README.md index f161bac..ae06bc6 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ +[![Zig](https://img.shields.io/badge/-Zig-F7A41D?style=flat&logo=zig&logoColor=white)](https://ziglang.org/) [![tests](https://github.com/FObersteiner/zdt/actions/workflows/zdt-tests.yml/badge.svg)](https://github.com/FObersteiner/zdt/actions/workflows/zdt-tests.yml) [![License: MPL 2.0](https://img.shields.io/badge/License-MPL_2.0-brightgreen.svg)](https://github.com/FObersteiner/zdt/blob/master/LICENSE) # zdt @@ -7,15 +8,19 @@ - [on Codeberg](https://codeberg.org/FObersteiner/zdt) - [on github](https://github.com/FObersteiner/zdt) -Demo: +[Demo](https://github.com/FObersteiner/zdt/blob/master/examples/ex_demo.zig): ```zig + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + defer _ = gpa.deinit(); + const allocator = gpa.allocator(); + var tz_LA = try zdt.Timezone.fromTzfile("America/Los_Angeles", allocator); defer tz_LA.deinit(); var tz_Paris = try zdt.Timezone.fromTzfile("Europe/Paris", allocator); defer tz_Paris.deinit(); - const a_datetime = try zdt.stringIO.parseISO8601("2022-03-07"); + const a_datetime = try zdt.parseISO8601("2022-03-07"); const this_time_LA = try a_datetime.tzLocalize(tz_LA); const this_time_Paris = try this_time_LA.tzConvert(tz_Paris); @@ -55,17 +60,18 @@ See [changelog](https://codeberg.org/FObersteiner/zdt/src/branch/main/docs/chang ## Zig version -This library is developed with Zig `0.14.0-dev`, might not compile with older versions. As of 2024-08-07, Zig-0.13 stable or higher should work. +This library is developed with Zig `0.14.0-dev`, might not compile with older versions. As of 2024-08-28, Zig-0.13 stable or higher should work. -## Dependencies +## IANA timezone database version -- none +- `zdt v0.2.1`: `2024a` +- `zdt v0.2.0`: `2024a` -## Time zone database +## Dependencies, Development and Time zone database `zdt` comes with [eggert/tz](https://github.com/eggert/tz). The database is compiled and shipped with `zdt` (as-is; not tar-balled or compressed). If you wish to use your own version of the [IANA time zone db](https://www.iana.org/time-zones), you can set a path to it using the `-Dprefix-tzdb="path/to/your/tzdb"` option. See also `zig build --help` -For development, to update the time zone database and the version info, run the following build steps: `zig build update-tz-database && zig build update-tz-version`. +For development, to update the time zone database and the version info, run the following build steps: `zig build update-tz-database && zig build update-tz-version`. Some of the code generation is done with Python scripts, which require Python >= 3.9 (no third party packages required). ## License diff --git a/docs/change.log b/docs/change.log index b724b95..53c629a 100644 --- a/docs/change.log +++ b/docs/change.log @@ -1,5 +1,10 @@ # CHANGELOG +## 2024-08-28, v0.2.1 + +- change of ergonomics: `formatToString`, `parseToDatetime` and `parseISO8601` functions are now methods of the `zdt` struct (formerly `stringIO.[...]`). After importing zdt, they can be called like `zdt.formatToString` etc. +- this is the first version that will be on github only. Having the same repository at both Codeberg and github is just too cumbersome. + ## 2024-08-07, v0.2.0 - add a complete embedding of the IANA tzdb that allows cross-compilation diff --git a/examples/ex_datetime.zig b/examples/ex_datetime.zig index 11008ad..262f14c 100644 --- a/examples/ex_datetime.zig +++ b/examples/ex_datetime.zig @@ -5,7 +5,6 @@ const zdt = @import("zdt"); const Datetime = zdt.Datetime; const Duration = zdt.Duration; const Tz = zdt.Timezone; -const str = zdt.stringIO; pub fn main() !void { println("---> datetime example", .{}); diff --git a/examples/ex_demo.zig b/examples/ex_demo.zig index 5edac4b..a22abc2 100644 --- a/examples/ex_demo.zig +++ b/examples/ex_demo.zig @@ -11,7 +11,7 @@ pub fn main() !void { var tz_Paris = try zdt.Timezone.fromTzfile("Europe/Paris", allocator); defer tz_Paris.deinit(); - const a_datetime = try zdt.stringIO.parseISO8601("2022-03-07"); + const a_datetime = try zdt.parseISO8601("2022-03-07"); const this_time_LA = try a_datetime.tzLocalize(tz_LA); const this_time_Paris = try this_time_LA.tzConvert(tz_Paris); diff --git a/examples/ex_offsetTz.zig b/examples/ex_offsetTz.zig index 202a872..d9ab147 100644 --- a/examples/ex_offsetTz.zig +++ b/examples/ex_offsetTz.zig @@ -4,7 +4,6 @@ const builtin = @import("builtin"); const zdt = @import("zdt"); const Datetime = zdt.Datetime; const Tz = zdt.Timezone; -const str = zdt.stringIO; pub fn main() !void { println("---> UTC offset time zone example", .{}); diff --git a/examples/ex_strings.zig b/examples/ex_strings.zig index f0cb638..d158488 100644 --- a/examples/ex_strings.zig +++ b/examples/ex_strings.zig @@ -6,7 +6,6 @@ const zdt = @import("zdt"); const Datetime = zdt.Datetime; const Duration = zdt.Duration; const Timezone = zdt.Timezone; -const str = zdt.stringIO; pub fn main() !void { println("---> datetime example", .{}); @@ -18,20 +17,20 @@ pub fn main() !void { println("", .{}); println("---> (usage) ISO8601: parse some allowed formats", .{}); const date_only = "2014-08-23"; - var parsed = try str.parseISO8601(date_only); + var parsed = try zdt.parseISO8601(date_only); assert(parsed.hour == 0); println("parsed '{s}'\n to {s}", .{ date_only, parsed }); // the default string representation of a zdt.Datetime instance is always ISO8601 // we can have fractional seconds: const datetime_with_frac = "2014-08-23 12:15:56.123456789"; - parsed = try str.parseISO8601(datetime_with_frac); + parsed = try zdt.parseISO8601(datetime_with_frac); assert(parsed.nanosecond == 123456789); println("parsed '{s}'\n to {s}", .{ datetime_with_frac, parsed }); // we can also have a leap second, and a time zone specifier (Z == UTC): const leap_datetime = "2016-12-31T23:59:60Z"; - parsed = try str.parseISO8601(leap_datetime); + parsed = try zdt.parseISO8601(leap_datetime); assert(parsed.second == 60); assert(std.meta.eql(parsed.tzinfo.?, Timezone.UTC)); println("parsed '{s}'\n to {s}", .{ leap_datetime, parsed }); @@ -41,7 +40,7 @@ pub fn main() !void { println("", .{}); println("---> (usage): parse some non-standard format", .{}); const dayfirst_dtstr = "23.7.2021, 9:45h"; - parsed = try str.parseToDatetime("%d.%m.%Y, %H:%Mh", dayfirst_dtstr); + parsed = try zdt.parseToDatetime("%d.%m.%Y, %H:%Mh", dayfirst_dtstr); assert(parsed.day == 23); println("parsed '{s}'\n to {s}", .{ dayfirst_dtstr, parsed }); @@ -55,7 +54,7 @@ pub fn main() !void { var s = std.ArrayList(u8).init(allocator); defer s.deinit(); // the formatting directive is comptime-known: - try str.formatToString(s.writer(), "%a, %b %d %Y, %H:%Mh", parsed); + try zdt.formatToString(s.writer(), "%a, %b %d %Y, %H:%Mh", parsed); println("formatted {s}\n to '{s}'", .{ parsed, s.items }); } diff --git a/examples/ex_timezones.zig b/examples/ex_timezones.zig index b67600e..83eb41c 100644 --- a/examples/ex_timezones.zig +++ b/examples/ex_timezones.zig @@ -4,7 +4,6 @@ const builtin = @import("builtin"); const zdt = @import("zdt"); const Datetime = zdt.Datetime; const Tz = zdt.Timezone; -const str = zdt.stringIO; pub fn main() !void { println("---> time zones example", .{}); diff --git a/lib/Timezone.zig b/lib/Timezone.zig index 181af72..e44c101 100644 --- a/lib/Timezone.zig +++ b/lib/Timezone.zig @@ -67,7 +67,7 @@ pub fn abbreviation(tz: *Timezone) []const u8 { return std.mem.sliceTo(tz.tzOffset.?.__abbrev_data[0..], 0); } -/// Make a time zone from a IANA tz database TZif data, taken from the embedded tzdata. +/// Make a time zone from IANA tz database TZif data, taken from the embedded tzdata. /// The caller must make sure to de-allocate memory used for storing the TZif file's content /// by calling the deinit method of the returned TZ instance. pub fn fromTzdata(identifier: []const u8, allocator: std.mem.Allocator) TzError!Timezone { @@ -90,6 +90,8 @@ pub fn fromTzdata(identifier: []const u8, allocator: std.mem.Allocator) TzError! } /// Make a time zone from a IANA tz database TZif file. The identifier must be comptime-known. +/// This method allows the usage of a user-supplied tzdata; that path has to be specified +/// via the tzdb_prefix option in the build.zig. /// The caller must make sure to de-allocate memory used for storing the TZif file's content /// by calling the deinit method of the returned TZ instance. pub fn fromTzfile(comptime identifier: []const u8, allocator: std.mem.Allocator) !Timezone { diff --git a/lib/tzdata/zoneinfo/America/Bahia_Banderas b/lib/tzdata/zoneinfo/America/Bahia_Banderas index ae4a8a754617b8b918daffb6a45a067df2fd2fe6..3a493e3d5a93f08201c41cb25616015963254589 100644 GIT binary patch delta 280 zcmZqRJi{?T+>o7tfdPa;z!r!>Y>}ngUKFhVs9mrvEi7TXqiw+s9Pt0PISlA?4nQ*|#iY$sOJ2x;2OrFRnCgkiA!oa`?vH(U+5ckDu?|&cw*$tvW q_Je4U8$dM39UvOy7BCHT4~Pc2X|plYc1F@%C4uQGF6ZD7GcEvc+)=Io delta 374 zcmX@Z(ZD%D+>(QVfdPa;z#fP}Y>B1YUKFhVl=om;T3Et%=SvAYc+3)Z{B8Si`c+}V zjfq=6FfbG}O!T;K&dS1!2eL8YfRkew6}kEw7zF+Ymkq0Jn`~af>OavtB;~T=@ z92~;n3dGJXKpKb{7(tE$0w^6akx|SStGoXL0m$tj#US^C0LTv@8srZU0Qm((gZu*m VAU|zh#;C|Rz`o*Q1^U^P3ji|ZWQYI& delta 385 zcmaFBc8G0)xGp;b0|N+yfEEyg*dj}}-AWK^yP9B_p8mn8=vRWVyXOa!pgRc@Jto#O zGl3v03n9q-|Npub3=IGOuU^2w^8f$w1B@L1|L@$uzylN6xq(ptBI4s4!r&Yn!rxgA7<+z+BbegM%Re}HI^UpDV% QRAj6k5Z`bCJ!#4X0AcZ9e*gdg diff --git a/lib/tzdata/zoneinfo/America/Chihuahua b/lib/tzdata/zoneinfo/America/Chihuahua index e0910396704ffda1d7f39e70a369249aeb4b0353..667a2191145170e34271bb2200b93a2eec41d2ba 100644 GIT binary patch delta 47 ucmX@dagJkxA@@h^f^BJG3ELfQ3pU!UWE2MS{{sO?3`B#(H~(M^V*&sm=@=yd delta 47 ucmX@dagJkxA@`@e2iwxZ61F>EO4w+#l2I7Q{|^KpF%S(B-~59yj0pf=(Hffo diff --git a/lib/tzdata/zoneinfo/America/Ciudad_Juarez b/lib/tzdata/zoneinfo/America/Ciudad_Juarez index eb1e53961c1ebe1e147dd42248753ad30817a349..29af5982ac1c04357634570f15454d6f7fc30e04 100644 GIT binary patch delta 47 tcmZqTY2uk+$o)~fU|U*P!gfd7f{ivdOu|6^e;@#ffoPEU=5D5PW&rvh7T*8> delta 47 tcmZqTY2uk+$o(nr!M3!pgze6k5;oe{FbMmG)s7bvhQpL1_llwmRP#&MZwBS|AO@&EgQC_r4($J7GT)H_36XuSG^6Fl)n^Q zn!E19b?Hck8xyyDxXr-MaQi^|7 z&Sh3+oIQCWvn(^v#K{|(b(w)COn%5Lq65c24 I1!`si0In-yJOBUy delta 115 zcmbOwd`xJ9vguR?1_llwmRP#&MZwBS|AO_OYCddBODWhcEx@pY>(htRuX-CUDSs)r zG;>$Mb?Hck8xyyD*jTWaX|fh)#N=*fWyYzK*E7p919eS4&#Ws9RP`SSKq^5rNcCoW KmZvO0FT+>n)lfdPa;fES2CY=NcQUKFhVs9mrvEi7TXqiw+s9FfcHJOkkXNK*|)Wk^g}JWGsjV84aRA#)D{(6_fcH WB_^9Qngh*Nz+pDfd@i7s=3D@&tvSm8 literal 456 zcmWHE%1kq2zyRz(5fBCeejo<1MV4-RQLz3~-h*vvVF}xvFD2~YF-zF-x9!8}SA_{T zCT{t_z);X&nBF2_R4mqD?4BlI67-|NRNX_s%;;7FBNGcV3lj?~kOaa1|EK?8VEF%k z?gR!Pd-Vba4iL%60~6_QU=Vhj0$Z3|MxdA2u%LREG85X9KyiB2r>^wO%ON5YR!Kj w09gg1LDqq2kd+`BWbNdKj1mGM4#ZB7fdvhle==@o#A>qyrp;Ww!6D{c0Ki95D*ylh diff --git a/lib/tzdata/zoneinfo/America/Merida b/lib/tzdata/zoneinfo/America/Merida index 17654cb59991e52537f87d9d9a2b56396f9c5c7e..c4b9b4e8801cd9447d3bbb6ebff71e26df669c3c 100644 GIT binary patch delta 35 lcmaFE{)T;mA$!*|1__m01sg4z7`cIL5CHKvA7xZ$0s!a83$y?L delta 35 mcmaFE{)T;mA$!}^1PLGSfQ=SSjNCvr0}z1tn~yT8GXVhP3=2E} diff --git a/lib/tzdata/zoneinfo/America/Mexico_City b/lib/tzdata/zoneinfo/America/Mexico_City index 68176daa4976b015fb79026f3053e74e4a7457ab..ad70cf3e08498845aaafc38e4eccca7461c8d337 100644 GIT binary patch delta 47 ucmX@cd5m*{A@@h^f^BJG3ELfQ3pUzZWfTVT{{sO?3`B#(H>)r$VgdjlQWv}c delta 47 ucmX@cd5m*{A@`@e2iwxZ61F>EO4w*~l~EYT{|^KpF%S(B->ky4hzS5+IvO$n diff --git a/lib/tzdata/zoneinfo/America/Monterrey b/lib/tzdata/zoneinfo/America/Monterrey index 5eb723c80949d0cf2a99603ea6aba4688ade6b21..2d7993a0d71720493175bd05b2b0b7409d67407a 100644 GIT binary patch delta 414 zcmcb@ev4y*xGp;b0|N+yfE^Hn*dj}}-AY*hQM+JUT3Et%N85rOJZ1?y{ zg_(tkl}z~m|H3Z}4FCVnoxs5I|NrU*3>+Ymkq0KSa|5FQMBK+WguypBguxkzeO-Vw z5Hm0W-Np&TAew<;g19SI$NvWckOx3C$P*wMEO4w*)&Lj-v{|5q)7>EXmZ*F7CV+H_W2O1;* diff --git a/lib/tzdata/zoneinfo/America/Santa_Isabel b/lib/tzdata/zoneinfo/America/Santa_Isabel index 63dfdf48a68d02240737ecd6af081e02eb0b6317..0fe73912cacab6c8aabef4f4264d1710825888e7 100644 GIT binary patch delta 180 zcmX>mG)s7bvhQpL1_llwmRP#&MZwBS|AO@&EgQC_r4($J7GT)H_36XuSG^6Fl)n^Q zn!E19b?Hck8xyyDxXr-MaQi^|7 z&Sh3+oIQCWvn(^v#K{|(b(w)COn%5Lq65c24 I1!`si0In-yJOBUy delta 115 zcmbOwd`xJ9vguR?1_llwmRP#&MZwBS|AO_OYCddBODWhcEx@pY>(htRuX-CUDSs)r zG;>$Mb?Hck8xyyD*jTWaX|fh)#N=*fWyYzK*E7p919eS4&#Ws9RP`SSKq^5rNcCoW KmZvO0mG)s7bvhQpL1_llwmRP#&MZwBS|AO@&EgQC_r4($J7GT)H_36XuSG^6Fl)n^Q zn!E19b?Hck8xyyDxXr-MaQi^|7 z&Sh3+oIQCWvn(^v#K{|(b(w)COn%5Lq65c24 I1!`si0In-yJOBUy delta 115 zcmbOwd`xJ9vguR?1_llwmRP#&MZwBS|AO_OYCddBODWhcEx@pY>(htRuX-CUDSs)r zG;>$Mb?Hck8xyyD*jTWaX|fh)#N=*fWyYzK*E7p919eS4&#Ws9RP`SSKq^5rNcCoW KmZvO0mG)s7bvhQpL1_llwmRP#&MZwBS|AO@&EgQC_r4($J7GT)H_36XuSG^6Fl)n^Q zn!E19b?Hck8xyyDxXr-MaQi^|7 z&Sh3+oIQCWvn(^v#K{|(b(w)COn%5Lq65c24 I1!`si0In-yJOBUy delta 115 zcmbOwd`xJ9vguR?1_llwmRP#&MZwBS|AO_OYCddBODWhcEx@pY>(htRuX-CUDSs)r zG;>$Mb?Hck8xyyD*jTWaX|fh)#N=*fWyYzK*E7p919eS4&#Ws9RP`SSKq^5rNcCoW KmZvO0hj0$Z3|MxdA2u%LREG85X9KyiB2r>^wO%ON5YR!Kj w09gg1LDqq2kd+`BWbNdKj1mGM4#ZB7fdvhle==@o#A>qyrp;Ww!6D{c0Ki95D*ylh diff --git a/lib/tzdata/zoneinfo/Mexico/General b/lib/tzdata/zoneinfo/Mexico/General index 68176daa4976b015fb79026f3053e74e4a7457ab..ad70cf3e08498845aaafc38e4eccca7461c8d337 100644 GIT binary patch delta 47 ucmX@cd5m*{A@@h^f^BJG3ELfQ3pUzZWfTVT{{sO?3`B#(H>)r$VgdjlQWv}c delta 47 ucmX@cd5m*{A@`@e2iwxZ61F>EO4w*~l~EYT{|^KpF%S(B->ky4hzS5+IvO$n diff --git a/lib/windows/windows_tznames.zig b/lib/windows/windows_tznames.zig index bee773c..9f9a135 100644 --- a/lib/windows/windows_tznames.zig +++ b/lib/windows/windows_tznames.zig @@ -3,7 +3,7 @@ // // --- Do not edit --- // -// latest referesh: 2024-08-07T15:27:54+00:00 +// latest referesh: 2024-08-28T14:40:36+00:00 // windows_names are sorted alphabetically so we can do binary search (later) pub const windows_names = [_][]const u8{ "AUS Central Standard Time", diff --git a/tests/test_stringIO.zig b/tests/test_stringIO.zig index c4407fb..1070855 100644 --- a/tests/test_stringIO.zig +++ b/tests/test_stringIO.zig @@ -14,7 +14,6 @@ const zdt = @import("zdt"); const Datetime = zdt.Datetime; const td = zdt.Duration; const Tz = zdt.Timezone; -const str = zdt.stringIO; const TestCase = struct { string: []const u8, @@ -58,7 +57,7 @@ test "format naive datetimes with format string api" { for (cases) |case| { var s = std.ArrayList(u8).init(testing.allocator); defer s.deinit(); - try str.formatToString(s.writer(), "%Y-%m-%d %H:%M:%S", case.dt); + try zdt.formatToString(s.writer(), "%Y-%m-%d %H:%M:%S", case.dt); try testing.expectEqualStrings(case.string, s.items); } } @@ -119,7 +118,7 @@ test "format datetime with literal characters in format string" { for (cases) |case| { var s = std.ArrayList(u8).init(testing.allocator); defer s.deinit(); - try str.formatToString(s.writer(), case.directive, case.dt); + try zdt.formatToString(s.writer(), case.directive, case.dt); try testing.expectEqualStrings(case.string, s.items); } } @@ -131,7 +130,7 @@ test "format with z" { const dt = try Datetime.fromFields(.{ .year = 2021, .month = 2, .day = 18, .hour = 17, .tzinfo = tzinfo }); const string = "2021-02-18T17:00:00+01:00"; const directive = "%Y-%m-%dT%H:%M:%S%z"; - try str.formatToString(s.writer(), directive, dt); + try zdt.formatToString(s.writer(), directive, dt); try testing.expectEqualStrings(string, s.items); } @@ -142,7 +141,7 @@ test "format with z, full day off" { const dt = try Datetime.fromFields(.{ .year = 1970, .month = 2, .day = 13, .hour = 12, .tzinfo = tzinfo }); const string = "1970-02-13T12:00:00-24:00"; const directive = "%Y-%m-%dT%H:%M:%S%z"; - try str.formatToString(s.writer(), directive, dt); + try zdt.formatToString(s.writer(), directive, dt); try testing.expectEqualStrings(string, s.items); } @@ -153,7 +152,7 @@ test "format with z, strange directive" { const dt = try Datetime.fromFields(.{ .year = 2023, .month = 12, .day = 9, .hour = 1, .minute = 2, .second = 3, .tzinfo = tzinfo }); const string = "% 2023-12-09 % 01:02:03 % +00:15"; const directive = "%% %Y-%m-%d %% %H:%M:%S %% %z"; - try str.formatToString(s.writer(), directive, dt); + try zdt.formatToString(s.writer(), directive, dt); try testing.expectEqualStrings(string, s.items); } @@ -164,7 +163,7 @@ test "format with Z" { const dt = try Datetime.fromFields(.{ .year = 2023, .month = 12, .day = 9, .hour = 1, .minute = 2, .second = 3, .tzinfo = tz_utc }); const string = "2023-12-09T01:02:03+00:00Z"; const directive = "%Y-%m-%dT%H:%M:%S%z%Z"; - try str.formatToString(s.writer(), directive, dt); + try zdt.formatToString(s.writer(), directive, dt); try testing.expectEqualStrings(string, s.items); var tz_pacific = try Tz.fromTzfile("America/Los_Angeles", testing.allocator); @@ -174,14 +173,14 @@ test "format with Z" { defer s_std.deinit(); const directive_us = "%Y-%m-%dT%H:%M:%S%z %Z"; const string_std = "2023-12-08T17:02:03-08:00 PST"; - try str.formatToString(s_std.writer(), directive_us, dt_std); + try zdt.formatToString(s_std.writer(), directive_us, dt_std); try testing.expectEqualStrings(string_std, s_std.items); const dt_dst = try dt_std.add(td.fromTimespanMultiple(6 * 4, td.Timespan.week)); var s_dst = std.ArrayList(u8).init(testing.allocator); defer s_dst.deinit(); const string_dst = "2024-05-24T18:02:03-07:00 PDT"; - try str.formatToString(s_dst.writer(), directive_us, dt_dst); + try zdt.formatToString(s_dst.writer(), directive_us, dt_dst); try testing.expectEqualStrings(string_dst, s_dst.items); } @@ -193,7 +192,7 @@ test "format with abbreviated day name" { const dt = Datetime.epoch; const string = "Thu"; const directive = "%a"; - try str.formatToString(s.writer(), directive, dt); + try zdt.formatToString(s.writer(), directive, dt); try testing.expectEqualStrings(string, s.items); } @@ -205,7 +204,7 @@ test "format with day name" { const dt = Datetime.epoch; const string = "Thursday"; const directive = "%A"; - try str.formatToString(s.writer(), directive, dt); + try zdt.formatToString(s.writer(), directive, dt); try testing.expectEqualStrings(string, s.items); } @@ -217,7 +216,7 @@ test "format with abbreviated month name" { const dt = Datetime.epoch; const string = "Jan"; const directive = "%b"; - try str.formatToString(s.writer(), directive, dt); + try zdt.formatToString(s.writer(), directive, dt); try testing.expectEqualStrings(string, s.items); } @@ -229,7 +228,7 @@ test "format with month name" { const dt = Datetime.epoch; const string = "January"; const directive = "%B"; - try str.formatToString(s.writer(), directive, dt); + try zdt.formatToString(s.writer(), directive, dt); try testing.expectEqualStrings(string, s.items); } @@ -248,7 +247,7 @@ test "comptime parse with comptime format string" { }; for (cases) |case| { - const dt = try str.parseToDatetime("%Y-%m-%d %H:%M:%S", case.string); + const dt = try zdt.parseToDatetime("%Y-%m-%d %H:%M:%S", case.string); try testing.expectEqual(case.dt, dt); } } @@ -266,7 +265,7 @@ test "comptime parse ISO " { }; for (cases) |case| { - const dt = try str.parseToDatetime("%T", case.string); + const dt = try zdt.parseToDatetime("%T", case.string); try testing.expectEqual(case.dt, dt); } } @@ -312,7 +311,7 @@ test "comptime parse with fractional part" { }; for (cases) |case| { - const dt = try str.parseToDatetime("%Y-%m-%dT%H:%M:%S.%f", case.string); + const dt = try zdt.parseToDatetime("%Y-%m-%dT%H:%M:%S.%f", case.string); try testing.expectEqual(case.dt, dt); } } @@ -330,22 +329,22 @@ test "parse single digits" { }; for (cases) |case| { - const dt = try str.parseToDatetime("%Y-%m-%d %H:%M:%S", case.string); + const dt = try zdt.parseToDatetime("%Y-%m-%d %H:%M:%S", case.string); try testing.expectEqual(case.dt, dt); } } test "parsing directives do not match fields in string" { - var err = str.parseToDatetime("%Y-%m-%d %H%%%M%%%S", "1970-01-01 00:00:00"); + var err = zdt.parseToDatetime("%Y-%m-%d %H%%%M%%%S", "1970-01-01 00:00:00"); try testing.expectError(error.InvalidFormat, err); - err = str.parseToDatetime("%Y-%m-%dT%H:%M:%S", "1970-01-01 00:00:00"); + err = zdt.parseToDatetime("%Y-%m-%dT%H:%M:%S", "1970-01-01 00:00:00"); try testing.expectError(error.InvalidFormat, err); - err = str.parseToDatetime("%", "1970-01-01 00:00:00"); + err = zdt.parseToDatetime("%", "1970-01-01 00:00:00"); try testing.expectError(error.InvalidFormat, err); - err = str.parseToDatetime("%Y-%m-%d %H:%M:%S %z", "1970-01-01 00:00:00 +7"); + err = zdt.parseToDatetime("%Y-%m-%d %H:%M:%S %z", "1970-01-01 00:00:00 +7"); try testing.expectError(error.InvalidFormat, err); } @@ -361,7 +360,7 @@ test "parse with literal characters" { }, }; for (cases) |case| { - const dt = try str.parseToDatetime("datetime %Y-%m-%d %H:%M:%S", case.string); + const dt = try zdt.parseToDatetime("datetime %Y-%m-%d %H:%M:%S", case.string); try testing.expectEqual(case.dt, dt); try testing.expect(dt.tzinfo == null); } @@ -377,7 +376,7 @@ test "parse with literal characters" { }, }; for (cases) |case| { - const dt = try str.parseToDatetime("%Y-%m-%d %H:%M:%S datetime", case.string); + const dt = try zdt.parseToDatetime("%Y-%m-%d %H:%M:%S datetime", case.string); try testing.expectEqual(case.dt, dt); try testing.expect(dt.tzinfo == null); } @@ -392,7 +391,7 @@ test "parse with literal characters" { }, }; for (cases) |case| { - const dt = try str.parseToDatetime("%Y-%m-%d %%%% %H:%M:%S", case.string); + const dt = try zdt.parseToDatetime("%Y-%m-%d %%%% %H:%M:%S", case.string); try testing.expectEqual(case.dt, dt); try testing.expect(dt.tzinfo == null); } @@ -407,7 +406,7 @@ test "parse with literal characters" { }, }; for (cases) |case| { - const dt = try str.parseToDatetime("%%%Y-%m-%d %H:%M:%S", case.string); + const dt = try zdt.parseToDatetime("%%%Y-%m-%d %H:%M:%S", case.string); try testing.expectEqual(case.dt, dt); try testing.expect(dt.tzinfo == null); } @@ -422,7 +421,7 @@ test "parse with literal characters" { }, }; for (cases) |case| { - const dt = try str.parseToDatetime("%Y-%m-%d %H%%%M%%%S", case.string); + const dt = try zdt.parseToDatetime("%Y-%m-%d %H%%%M%%%S", case.string); try testing.expectEqual(case.dt, dt); try testing.expect(dt.tzinfo == null); } @@ -432,7 +431,7 @@ test "parse with z" { var tzinfo = try Tz.fromOffset(3600, ""); var dt_ref = try Datetime.fromFields(.{ .year = 2021, .month = 2, .day = 18, .hour = 17, .tzinfo = tzinfo }); const s_hhmm = "2021-02-18T17:00:00+01:00"; - var dt = try str.parseToDatetime("%Y-%m-%dT%H:%M:%S%z", s_hhmm); + var dt = try zdt.parseToDatetime("%Y-%m-%dT%H:%M:%S%z", s_hhmm); try testing.expectEqual(dt_ref.year, dt.year); var off_want = dt_ref.tzinfo.?.tzOffset.?.seconds_east; @@ -444,7 +443,7 @@ test "parse with z" { tzinfo = try Tz.fromOffset(-3601, ""); dt_ref = try Datetime.fromFields(.{ .year = 2021, .month = 2, .day = 18, .hour = 17, .tzinfo = tzinfo }); const s_hhmmss = "2021-02-18T17:00:00-01:00:01"; - dt = try str.parseToDatetime("%Y-%m-%dT%H:%M:%S%z", s_hhmmss); + dt = try zdt.parseToDatetime("%Y-%m-%dT%H:%M:%S%z", s_hhmmss); try testing.expectEqual(dt_ref.year, dt.year); off_want = dt_ref.tzinfo.?.tzOffset.?.seconds_east; @@ -458,7 +457,7 @@ test "parse with z" { tzinfo = try Tz.fromOffset(0, ""); dt_ref = try Datetime.fromFields(.{ .year = 2021, .month = 2, .day = 18, .hour = 17, .tzinfo = tzinfo }); const Z = "2021-02-18T17:00:00Z"; - dt = try str.parseToDatetime("%Y-%m-%dT%H:%M:%S%z", Z); + dt = try zdt.parseToDatetime("%Y-%m-%dT%H:%M:%S%z", Z); try testing.expectEqual(dt_ref.year, dt.year); off_want = dt_ref.tzinfo.?.tzOffset.?.seconds_east; off_have = dt.tzinfo.?.tzOffset.?.seconds_east; @@ -472,8 +471,8 @@ test "string -> datetime -> string roundtrip with offset TZ" { defer string_out.deinit(); const string_in = "2023-12-09T01:02:03+09:15"; const directive = "%Y-%m-%dT%H:%M:%S%z"; - const dt = try str.parseToDatetime(directive, string_in); - try str.formatToString(string_out.writer(), directive, dt); + const dt = try zdt.parseToDatetime(directive, string_in); + try zdt.formatToString(string_out.writer(), directive, dt); try testing.expectEqualStrings(string_in, string_out.items); // no name or abbreviation if it's only a UTC offset try testing.expectEqual(@as(usize, 0), dt.tzinfo.?.__name_data_len); @@ -483,100 +482,100 @@ test "string -> datetime -> string roundtrip with offset TZ" { test "parse ISO" { const tzutc = Tz.UTC; var dt_ref = try Datetime.fromFields(.{ .year = 2014, .month = 8 }); - var dt = try str.parseISO8601("2014-08"); + var dt = try zdt.parseISO8601("2014-08"); try testing.expect(std.meta.eql(dt_ref, dt)); dt_ref = try Datetime.fromFields(.{ .year = 2014, .month = 8, .day = 23 }); - dt = try str.parseISO8601("2014-08-23"); + dt = try zdt.parseISO8601("2014-08-23"); try testing.expect(std.meta.eql(dt_ref, dt)); dt_ref = try Datetime.fromFields(.{ .year = 2014, .month = 8, .day = 23, .hour = 12, .minute = 15 }); - dt = try str.parseISO8601("2014-08-23 12:15"); + dt = try zdt.parseISO8601("2014-08-23 12:15"); try testing.expect(std.meta.eql(dt_ref, dt)); dt_ref = try Datetime.fromFields(.{ .year = 2014, .month = 8, .day = 23, .hour = 12, .minute = 15, .second = 56 }); - dt = try str.parseISO8601("2014-08-23 12:15:56"); + dt = try zdt.parseISO8601("2014-08-23 12:15:56"); try testing.expect(std.meta.eql(dt_ref, dt)); dt_ref = try Datetime.fromFields(.{ .year = 2016, .month = 12, .day = 31, .hour = 23, .minute = 59, .second = 60 }); - dt = try str.parseISO8601("2016-12-31T23:59:60"); + dt = try zdt.parseISO8601("2016-12-31T23:59:60"); try testing.expect(std.meta.eql(dt_ref, dt)); dt_ref = try Datetime.fromFields(.{ .year = 2014, .month = 8, .day = 23, .hour = 12, .minute = 15, .second = 56, .nanosecond = 123400000 }); - dt = try str.parseISO8601("2014-08-23 12:15:56,1234"); + dt = try zdt.parseISO8601("2014-08-23 12:15:56,1234"); try testing.expect(std.meta.eql(dt_ref, dt)); dt_ref = try Datetime.fromFields(.{ .year = 2014, .month = 8, .day = 23, .hour = 12, .minute = 15, .second = 56, .nanosecond = 123000000 }); - dt = try str.parseISO8601("2014-08-23 12:15:56,123"); + dt = try zdt.parseISO8601("2014-08-23 12:15:56,123"); try testing.expect(std.meta.eql(dt_ref, dt)); dt_ref = try Datetime.fromFields(.{ .year = 2014, .month = 8, .day = 23, .hour = 12, .minute = 15, .second = 56, .nanosecond = 123456000 }); - dt = try str.parseISO8601("2014-08-23 12:15:56,123456"); + dt = try zdt.parseISO8601("2014-08-23 12:15:56,123456"); try testing.expect(std.meta.eql(dt_ref, dt)); dt_ref = try Datetime.fromFields(.{ .year = 2014, .month = 8, .day = 23, .hour = 12, .minute = 15, .second = 56, .tzinfo = tzutc }); - dt = try str.parseISO8601("2014-08-23 12:15:56Z"); + dt = try zdt.parseISO8601("2014-08-23 12:15:56Z"); try testing.expect(std.meta.eql(dt_ref, dt)); dt_ref = try Datetime.fromFields(.{ .year = 2014, .month = 8, .day = 23, .hour = 12, .minute = 15, .second = 56, .nanosecond = 123400000, .tzinfo = tzutc }); - dt = try str.parseISO8601("2014-08-23 12:15:56.1234Z"); + dt = try zdt.parseISO8601("2014-08-23 12:15:56.1234Z"); try testing.expect(std.meta.eql(dt_ref, dt)); dt_ref = try Datetime.fromFields(.{ .year = 2014, .month = 8, .day = 23, .hour = 12, .minute = 15, .second = 56, .nanosecond = 99, .tzinfo = tzutc }); - dt = try str.parseISO8601("2014-08-23 12:15:56.000000099Z"); + dt = try zdt.parseISO8601("2014-08-23 12:15:56.000000099Z"); try testing.expect(std.meta.eql(dt_ref, dt)); var tzinfo = try Tz.fromOffset(0, ""); dt_ref = try Datetime.fromFields(.{ .year = 2014, .month = 8, .day = 23, .hour = 12, .minute = 15, .second = 56, .nanosecond = 99, .tzinfo = tzinfo }); - dt = try str.parseISO8601("2014-08-23 12:15:56.000000099+00"); + dt = try zdt.parseISO8601("2014-08-23 12:15:56.000000099+00"); try testing.expect(std.meta.eql(dt_ref, dt)); - dt = try str.parseISO8601("2014-08-23 12:15:56.000000099+00:00"); + dt = try zdt.parseISO8601("2014-08-23 12:15:56.000000099+00:00"); try testing.expect(std.meta.eql(dt_ref, dt)); - dt = try str.parseISO8601("2014-08-23 12:15:56.000000099+00:00:00"); + dt = try zdt.parseISO8601("2014-08-23 12:15:56.000000099+00:00:00"); try testing.expect(std.meta.eql(dt_ref, dt)); tzinfo = try Tz.fromOffset(2 * 3600 + 15 * 60 + 30, ""); dt_ref = try Datetime.fromFields(.{ .year = 2014, .month = 8, .day = 23, .hour = 12, .minute = 15, .second = 56, .tzinfo = tzinfo }); - dt = try str.parseISO8601("2014-08-23T12:15:56+02:15:30"); + dt = try zdt.parseISO8601("2014-08-23T12:15:56+02:15:30"); try testing.expect(std.meta.eql(dt_ref, dt)); tzinfo = try Tz.fromOffset(-2 * 3600, ""); dt_ref = try Datetime.fromFields(.{ .year = 2014, .month = 8, .day = 23, .hour = 12, .minute = 15, .second = 56, .tzinfo = tzinfo }); - dt = try str.parseISO8601("2014-08-23T12:15:56-0200"); + dt = try zdt.parseISO8601("2014-08-23T12:15:56-0200"); try testing.expect(std.meta.eql(dt_ref, dt)); } test "not ISO8601" { - var err = str.parseISO8601("2014-08-23T12:15:56+-0200"); // invalid offset + var err = zdt.parseISO8601("2014-08-23T12:15:56+-0200"); // invalid offset try testing.expectError(error.InvalidFormat, err); - err = str.parseISO8601("2014"); // year-only not allowed + err = zdt.parseISO8601("2014"); // year-only not allowed try testing.expectError(error.InvalidFormat, err); - err = str.parseISO8601("2014-12-32"); // invalid month + err = zdt.parseISO8601("2014-12-32"); // invalid month try testing.expectError(error.DayOutOfRange, err); - err = str.parseISO8601("2014-12-31Z"); // date cannot have tz + err = zdt.parseISO8601("2014-12-31Z"); // date cannot have tz try testing.expectError(error.InvalidFormat, err); - err = str.parseISO8601("2014-12-31-12:15"); // - is not a date/time separator + err = zdt.parseISO8601("2014-12-31-12:15"); // - is not a date/time separator try testing.expectError(error.InvalidFormat, err); - err = str.parseISO8601("2014-2-03"); // 1-digit fields not allowed + err = zdt.parseISO8601("2014-2-03"); // 1-digit fields not allowed try testing.expectError(error.InvalidFormat, err); - err = str.parseISO8601("14-02-03"); // 2-digit year not allowed + err = zdt.parseISO8601("14-02-03"); // 2-digit year not allowed try testing.expectError(error.InvalidFormat, err); - err = str.parseISO8601("2014-02-03T13:60"); // invlid minute + err = zdt.parseISO8601("2014-02-03T13:60"); // invlid minute try testing.expectError(error.MinuteOutOfRange, err); - err = str.parseISO8601("2014-02-03T24:00"); // invlid hour + err = zdt.parseISO8601("2014-02-03T24:00"); // invlid hour try testing.expectError(error.HourOutOfRange, err); - err = str.parseISO8601("2014-02-03T23:00:00."); // ends with non-numeric + err = zdt.parseISO8601("2014-02-03T23:00:00."); // ends with non-numeric try testing.expectError(error.InvalidFormat, err); - err = str.parseISO8601("2014-02-03T23:00:00..314"); // invlid fractional secs separator + err = zdt.parseISO8601("2014-02-03T23:00:00..314"); // invlid fractional secs separator try testing.expectError(error.InvalidFormat, err); } diff --git a/tests/test_timezone.zig b/tests/test_timezone.zig index 600949d..7e9e120 100644 --- a/tests/test_timezone.zig +++ b/tests/test_timezone.zig @@ -9,7 +9,6 @@ const Duration = zdt.Duration; const Tz = zdt.Timezone; const ZdtError = zdt.ZdtError; const TzError = zdt.TzError; -const str = zdt.stringIO; const log = std.log.scoped(.test_timezone); @@ -50,7 +49,7 @@ test "offset manifests in Unix time" { defer s.deinit(); const string = "1970-01-01T00:00:00+01:00"; const directive = "%Y-%m-%dT%H:%M:%S%z"; - try str.formatToString(s.writer(), directive, dt); + try zdt.formatToString(s.writer(), directive, dt); try testing.expectEqualStrings(string, s.items); } @@ -137,12 +136,12 @@ test "DST transitions" { try testing.expect(dt_dst.tzinfo.?.tzOffset.?.is_dst); var s = std.ArrayList(u8).init(testing.allocator); - try str.formatToString(s.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_std); + try zdt.formatToString(s.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_std); try testing.expectEqualStrings("2023-03-26T01:59:59+01:00", s.items); s.deinit(); s = std.ArrayList(u8).init(testing.allocator); - try str.formatToString(s.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_dst); + try zdt.formatToString(s.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_dst); try testing.expectEqualStrings("2023-03-26T03:00:00+02:00", s.items); s.deinit(); @@ -153,12 +152,12 @@ test "DST transitions" { try testing.expect(dt_dst.tzinfo.?.tzOffset.?.is_dst); s = std.ArrayList(u8).init(testing.allocator); - try str.formatToString(s.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_dst); + try zdt.formatToString(s.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_dst); try testing.expectEqualStrings("2023-10-29T02:59:59+02:00", s.items); s.deinit(); s = std.ArrayList(u8).init(testing.allocator); - try str.formatToString(s.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_std); + try zdt.formatToString(s.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_std); try testing.expectEqualStrings("2023-10-29T02:00:00+01:00", s.items); s.deinit(); } @@ -1087,9 +1086,9 @@ test "conversion between random time zones" { dt_b = try Datetime.fromUnix(-1391111626, Duration.Resolution.second, tz_b); dt_c = try dt_a.tzConvert(tz_b); dt_b = try dt_b.tzConvert(tz_a); - try str.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); + try zdt.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); try testing.expectEqualStrings("1925-12-02T02:06:14-02:00", s_b.items); - try str.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); + try zdt.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); try testing.expectEqualStrings("1917-03-04T01:47:39+02:57:40", s_c.items); tz_a.deinit(); tz_b.deinit(); @@ -1102,9 +1101,9 @@ test "conversion between random time zones" { dt_b = try Datetime.fromUnix(-422363402, Duration.Resolution.second, tz_b); dt_c = try dt_a.tzConvert(tz_b); dt_b = try dt_b.tzConvert(tz_a); - try str.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); + try zdt.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); try testing.expectEqualStrings("1956-08-13T14:49:58+02:00", s_b.items); - try str.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); + try zdt.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); try testing.expectEqualStrings("1933-11-17T12:12:01-04:00", s_c.items); tz_a.deinit(); tz_b.deinit(); @@ -1117,9 +1116,9 @@ test "conversion between random time zones" { dt_b = try Datetime.fromUnix(1669207832, Duration.Resolution.second, tz_b); dt_c = try dt_a.tzConvert(tz_b); dt_b = try dt_b.tzConvert(tz_a); - try str.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); + try zdt.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); try testing.expectEqualStrings("2022-11-23T23:50:32+11:00", s_b.items); - try str.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); + try zdt.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); try testing.expectEqualStrings("1976-06-01T14:53:53+07:00", s_c.items); tz_a.deinit(); tz_b.deinit(); @@ -1132,9 +1131,9 @@ test "conversion between random time zones" { dt_b = try Datetime.fromUnix(551161374, Duration.Resolution.second, tz_b); dt_c = try dt_a.tzConvert(tz_b); dt_b = try dt_b.tzConvert(tz_a); - try str.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); + try zdt.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); try testing.expectEqualStrings("1987-06-20T01:22:54-03:00", s_b.items); - try str.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); + try zdt.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); try testing.expectEqualStrings("1988-04-08T00:32:04+11:00", s_c.items); tz_a.deinit(); tz_b.deinit(); @@ -1147,9 +1146,9 @@ test "conversion between random time zones" { dt_b = try Datetime.fromUnix(1349104459, Duration.Resolution.second, tz_b); dt_c = try dt_a.tzConvert(tz_b); dt_b = try dt_b.tzConvert(tz_a); - try str.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); + try zdt.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); try testing.expectEqualStrings("2012-10-01T12:14:19-03:00", s_b.items); - try str.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); + try zdt.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); try testing.expectEqualStrings("1916-09-03T16:07:54+03:04:18", s_c.items); tz_a.deinit(); tz_b.deinit(); @@ -1162,9 +1161,9 @@ test "conversion between random time zones" { dt_b = try Datetime.fromUnix(-1123806767, Duration.Resolution.second, tz_b); dt_c = try dt_a.tzConvert(tz_b); dt_b = try dt_b.tzConvert(tz_a); - try str.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); + try zdt.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); try testing.expectEqualStrings("1934-05-23T11:46:25+12:19:12", s_b.items); - try str.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); + try zdt.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); try testing.expectEqualStrings("2030-09-20T18:09:16+08:00", s_c.items); tz_a.deinit(); tz_b.deinit(); @@ -1177,9 +1176,9 @@ test "conversion between random time zones" { dt_b = try Datetime.fromUnix(-1247650419, Duration.Resolution.second, tz_b); dt_c = try dt_a.tzConvert(tz_b); dt_b = try dt_b.tzConvert(tz_a); - try str.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); + try zdt.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); try testing.expectEqualStrings("1930-06-19T16:26:21+02:00", s_b.items); - try str.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); + try zdt.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); try testing.expectEqualStrings("1909-01-28T03:37:00+08:30", s_c.items); tz_a.deinit(); tz_b.deinit(); @@ -1192,9 +1191,9 @@ test "conversion between random time zones" { dt_b = try Datetime.fromUnix(1363693749, Duration.Resolution.second, tz_b); dt_c = try dt_a.tzConvert(tz_b); dt_b = try dt_b.tzConvert(tz_a); - try str.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); + try zdt.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); try testing.expectEqualStrings("2013-03-19T07:49:09-04:00", s_b.items); - try str.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); + try zdt.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); try testing.expectEqualStrings("1945-09-02T13:18:38-05:00", s_c.items); tz_a.deinit(); tz_b.deinit(); @@ -1207,9 +1206,9 @@ test "conversion between random time zones" { dt_b = try Datetime.fromUnix(287718809, Duration.Resolution.second, tz_b); dt_c = try dt_a.tzConvert(tz_b); dt_b = try dt_b.tzConvert(tz_a); - try str.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); + try zdt.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); try testing.expectEqualStrings("1979-02-12T22:53:29-03:00", s_b.items); - try str.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); + try zdt.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); try testing.expectEqualStrings("2022-05-28T10:00:48-02:00", s_c.items); tz_a.deinit(); tz_b.deinit(); @@ -1222,9 +1221,9 @@ test "conversion between random time zones" { dt_b = try Datetime.fromUnix(-452535075, Duration.Resolution.second, tz_b); dt_c = try dt_a.tzConvert(tz_b); dt_b = try dt_b.tzConvert(tz_a); - try str.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); + try zdt.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); try testing.expectEqualStrings("1955-08-30T00:48:45-07:00", s_b.items); - try str.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); + try zdt.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); try testing.expectEqualStrings("1991-02-09T22:54:48-04:00", s_c.items); tz_a.deinit(); tz_b.deinit(); @@ -1237,9 +1236,9 @@ test "conversion between random time zones" { dt_b = try Datetime.fromUnix(-106361335, Duration.Resolution.second, tz_b); dt_c = try dt_a.tzConvert(tz_b); dt_b = try dt_b.tzConvert(tz_a); - try str.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); + try zdt.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); try testing.expectEqualStrings("1966-08-19T11:56:05+12:45", s_b.items); - try str.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); + try zdt.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); try testing.expectEqualStrings("1922-03-14T05:23:11+10:00", s_c.items); tz_a.deinit(); tz_b.deinit(); @@ -1252,9 +1251,9 @@ test "conversion between random time zones" { dt_b = try Datetime.fromUnix(504113205, Duration.Resolution.second, tz_b); dt_c = try dt_a.tzConvert(tz_b); dt_b = try dt_b.tzConvert(tz_a); - try str.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); + try zdt.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); try testing.expectEqualStrings("1985-12-22T10:26:45-05:00", s_b.items); - try str.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); + try zdt.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); try testing.expectEqualStrings("2032-11-18T22:25:46-07:00", s_c.items); tz_a.deinit(); tz_b.deinit(); @@ -1267,9 +1266,9 @@ test "conversion between random time zones" { dt_b = try Datetime.fromUnix(1997132129, Duration.Resolution.second, tz_b); dt_c = try dt_a.tzConvert(tz_b); dt_b = try dt_b.tzConvert(tz_a); - try str.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); + try zdt.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); try testing.expectEqualStrings("2033-04-15T00:55:29+02:00", s_b.items); - try str.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); + try zdt.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); try testing.expectEqualStrings("1928-03-06T11:16:26+03:00", s_c.items); tz_a.deinit(); tz_b.deinit(); @@ -1282,9 +1281,9 @@ test "conversion between random time zones" { dt_b = try Datetime.fromUnix(-1955947824, Duration.Resolution.second, tz_b); dt_c = try dt_a.tzConvert(tz_b); dt_b = try dt_b.tzConvert(tz_a); - try str.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); + try zdt.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); try testing.expectEqualStrings("1908-01-08T18:09:36+01:00", s_b.items); - try str.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); + try zdt.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); try testing.expectEqualStrings("1997-07-27T09:55:22+03:00", s_c.items); tz_a.deinit(); tz_b.deinit(); @@ -1297,9 +1296,9 @@ test "conversion between random time zones" { dt_b = try Datetime.fromUnix(763622303, Duration.Resolution.second, tz_b); dt_c = try dt_a.tzConvert(tz_b); dt_b = try dt_b.tzConvert(tz_a); - try str.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); + try zdt.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); try testing.expectEqualStrings("1994-03-14T08:18:23+03:00", s_b.items); - try str.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); + try zdt.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); try testing.expectEqualStrings("1954-09-07T21:57:46+07:00", s_c.items); tz_a.deinit(); tz_b.deinit(); @@ -1312,9 +1311,9 @@ test "conversion between random time zones" { dt_b = try Datetime.fromUnix(-1665590578, Duration.Resolution.second, tz_b); dt_c = try dt_a.tzConvert(tz_b); dt_b = try dt_b.tzConvert(tz_a); - try str.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); + try zdt.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); try testing.expectEqualStrings("1917-03-22T03:57:02-04:00", s_b.items); - try str.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); + try zdt.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); try testing.expectEqualStrings("1973-03-23T00:21:18+12:00", s_c.items); tz_a.deinit(); tz_b.deinit(); @@ -1327,9 +1326,9 @@ test "conversion between random time zones" { dt_b = try Datetime.fromUnix(-130203183, Duration.Resolution.second, tz_b); dt_c = try dt_a.tzConvert(tz_b); dt_b = try dt_b.tzConvert(tz_a); - try str.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); + try zdt.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); try testing.expectEqualStrings("1965-11-16T02:26:57+02:00", s_b.items); - try str.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); + try zdt.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); try testing.expectEqualStrings("1944-07-03T01:45:40+00:00", s_c.items); tz_a.deinit(); tz_b.deinit(); @@ -1342,9 +1341,9 @@ test "conversion between random time zones" { dt_b = try Datetime.fromUnix(-678498351, Duration.Resolution.second, tz_b); dt_c = try dt_a.tzConvert(tz_b); dt_b = try dt_b.tzConvert(tz_a); - try str.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); + try zdt.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); try testing.expectEqualStrings("1948-07-02T00:14:09+00:00", s_b.items); - try str.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); + try zdt.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); try testing.expectEqualStrings("1960-06-09T19:47:08+07:30", s_c.items); tz_a.deinit(); tz_b.deinit(); @@ -1357,9 +1356,9 @@ test "conversion between random time zones" { dt_b = try Datetime.fromUnix(-1786706330, Duration.Resolution.second, tz_b); dt_c = try dt_a.tzConvert(tz_b); dt_b = try dt_b.tzConvert(tz_a); - try str.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); + try zdt.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); try testing.expectEqualStrings("1913-05-20T08:24:22-04:16:48", s_b.items); - try str.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); + try zdt.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); try testing.expectEqualStrings("1940-01-05T09:55:52-06:00", s_c.items); tz_a.deinit(); tz_b.deinit(); @@ -1372,9 +1371,9 @@ test "conversion between random time zones" { dt_b = try Datetime.fromUnix(-1292830223, Duration.Resolution.second, tz_b); dt_c = try dt_a.tzConvert(tz_b); dt_b = try dt_b.tzConvert(tz_a); - try str.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); + try zdt.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); try testing.expectEqualStrings("1929-01-12T18:29:37+02:00", s_b.items); - try str.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); + try zdt.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); try testing.expectEqualStrings("2024-06-21T03:00:49+14:00", s_c.items); tz_a.deinit(); tz_b.deinit(); @@ -1387,9 +1386,9 @@ test "conversion between random time zones" { dt_b = try Datetime.fromUnix(-848311788, Duration.Resolution.second, tz_b); dt_c = try dt_a.tzConvert(tz_b); dt_b = try dt_b.tzConvert(tz_a); - try str.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); + try zdt.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); try testing.expectEqualStrings("1943-02-13T03:50:12-10:00", s_b.items); - try str.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); + try zdt.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); try testing.expectEqualStrings("1991-04-14T12:07:07-08:00", s_c.items); tz_a.deinit(); tz_b.deinit(); @@ -1402,9 +1401,9 @@ test "conversion between random time zones" { dt_b = try Datetime.fromUnix(-2118943269, Duration.Resolution.second, tz_b); dt_c = try dt_a.tzConvert(tz_b); dt_b = try dt_b.tzConvert(tz_a); - try str.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); + try zdt.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); try testing.expectEqualStrings("1902-11-09T14:38:51+10:00", s_b.items); - try str.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); + try zdt.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); try testing.expectEqualStrings("2000-11-05T22:39:53-03:00", s_c.items); tz_a.deinit(); tz_b.deinit(); @@ -1417,9 +1416,9 @@ test "conversion between random time zones" { dt_b = try Datetime.fromUnix(1647602753, Duration.Resolution.second, tz_b); dt_c = try dt_a.tzConvert(tz_b); dt_b = try dt_b.tzConvert(tz_a); - try str.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); + try zdt.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); try testing.expectEqualStrings("2022-03-18T22:25:53+11:00", s_b.items); - try str.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); + try zdt.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); try testing.expectEqualStrings("2020-05-02T07:21:04+00:00", s_c.items); tz_a.deinit(); tz_b.deinit(); @@ -1432,9 +1431,9 @@ test "conversion between random time zones" { dt_b = try Datetime.fromUnix(-729899108, Duration.Resolution.second, tz_b); dt_c = try dt_a.tzConvert(tz_b); dt_b = try dt_b.tzConvert(tz_a); - try str.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); + try zdt.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); try testing.expectEqualStrings("1946-11-15T02:14:52+00:00", s_b.items); - try str.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); + try zdt.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); try testing.expectEqualStrings("1946-09-03T02:47:40-04:00", s_c.items); tz_a.deinit(); tz_b.deinit(); @@ -1447,9 +1446,9 @@ test "conversion between random time zones" { dt_b = try Datetime.fromUnix(-1075050004, Duration.Resolution.second, tz_b); dt_c = try dt_a.tzConvert(tz_b); dt_b = try dt_b.tzConvert(tz_a); - try str.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); + try zdt.formatToString(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); try testing.expectEqualStrings("1935-12-08T10:06:48+03:06:52", s_b.items); - try str.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); + try zdt.formatToString(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); try testing.expectEqualStrings("1984-04-19T00:45:46+05:30", s_c.items); tz_a.deinit(); tz_b.deinit(); diff --git a/util/gen_test_tzones.py b/util/gen_test_tzones.py index 05e1d05..f79282d 100644 --- a/util/gen_test_tzones.py +++ b/util/gen_test_tzones.py @@ -1,8 +1,8 @@ +import random +import zoneinfo from datetime import datetime from pathlib import Path from zoneinfo import ZoneInfo -import zoneinfo -import random OPEN_BRACE = "{" CLOSE_BRACE = "}" @@ -60,9 +60,9 @@ dt_b = try Datetime.fromUnix({tb}, Duration.Resolution.second, tz_b); dt_c = try dt_a.tzConvert(tz_b); dt_b = try dt_b.tzConvert(tz_a); - try str.formatDatetime(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); + try zdt.formatDatetime(s_b.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_b); try testing.expectEqualStrings("{s_b}", s_b.items); - try str.formatDatetime(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); + try zdt.formatDatetime(s_c.writer(), "%Y-%m-%dT%H:%M:%S%z", dt_c); try testing.expectEqualStrings("{s_c}", s_c.items); tz_a.deinit(); tz_b.deinit(); diff --git a/zdt.zig b/zdt.zig index 41301a0..ffe4006 100644 --- a/zdt.zig +++ b/zdt.zig @@ -14,10 +14,15 @@ pub const WinTzError = @import("./lib/errors.zig").WinTzError; pub const ZdtError = @import("./lib/errors.zig").ZdtError; pub const calendar = @import("./lib/calendar.zig"); -pub const stringIO = @import("./lib/stringIO.zig"); +const stringIO = @import("./lib/stringIO.zig"); const tzif = @import("./lib/tzif.zig"); +// available as zdt.[method] : +pub const formatToString = @import("./lib/stringIO.zig").formatToString; +pub const parseToDatetime = @import("./lib/stringIO.zig").parseToDatetime; +pub const parseISO8601 = @import("./lib/stringIO.zig").parseISO8601; + // make sure 'internal' tests are also executed: test { _ = Datetime;