Compare commits

..

No commits in common. "main" and "v0.2.0" have entirely different histories.
main ... v0.2.0

54 changed files with 3080 additions and 2450 deletions

View file

@ -3,7 +3,7 @@ name: Release
on: on:
push: push:
tags: tags:
- "v*" - 'v*'
workflow_dispatch: workflow_dispatch:
permissions: permissions:
@ -17,180 +17,78 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
# macOS
- target: x86_64-macos - target: x86_64-macos
os: macos-latest os: macos-latest
rust-target: x86_64-apple-darwin rust-target: x86_64-apple-darwin
cross-packages: ""
cargo-linker-env: ""
cargo-linker: ""
- target: aarch64-macos - target: aarch64-macos
os: macos-latest os: macos-latest
rust-target: aarch64-apple-darwin rust-target: aarch64-apple-darwin
cross-packages: ""
cargo-linker-env: ""
cargo-linker: ""
# Linux (esbuild tier)
- target: x86_64-linux-gnu - target: x86_64-linux-gnu
os: ubuntu-latest os: ubuntu-latest
rust-target: x86_64-unknown-linux-gnu rust-target: x86_64-unknown-linux-gnu
cross-packages: ""
cargo-linker-env: ""
cargo-linker: ""
- target: aarch64-linux-gnu - target: aarch64-linux-gnu
os: ubuntu-latest os: ubuntu-latest
rust-target: aarch64-unknown-linux-gnu rust-target: aarch64-unknown-linux-gnu
cross-packages: gcc-aarch64-linux-gnu
cargo-linker-env: ""
cargo-linker: ""
- target: x86-linux-gnu
os: ubuntu-latest
rust-target: i686-unknown-linux-gnu
cross-packages: gcc-i686-linux-gnu
cargo-linker-env: ""
cargo-linker: ""
- target: arm-linux-gnueabihf
os: ubuntu-latest
rust-target: armv7-unknown-linux-gnueabihf
cross-packages: gcc-arm-linux-gnueabihf
cargo-linker-env: CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER
cargo-linker: arm-linux-gnueabihf-gcc
- target: loongarch64-linux-gnu
os: ubuntu-latest
rust-target: loongarch64-unknown-linux-gnu
cross-packages: ""
cargo-linker-env: CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNU_LINKER
cargo-linker: zig cc -target loongarch64-linux-gnu
- target: powerpc64le-linux-gnu
os: ubuntu-latest
rust-target: powerpc64le-unknown-linux-gnu
cross-packages: gcc-powerpc64le-linux-gnu
cargo-linker-env: ""
cargo-linker: ""
- target: riscv64-linux-gnu
os: ubuntu-latest
rust-target: riscv64gc-unknown-linux-gnu
cross-packages: gcc-riscv64-linux-gnu
cargo-linker-env: ""
cargo-linker: ""
- target: s390x-linux-gnu
os: ubuntu-latest
rust-target: s390x-unknown-linux-gnu
cross-packages: gcc-s390x-linux-gnu
cargo-linker-env: ""
cargo-linker: ""
# Windows
- target: x86_64-windows-gnu - target: x86_64-windows-gnu
os: ubuntu-latest os: ubuntu-latest
rust-target: x86_64-pc-windows-gnu rust-target: x86_64-pc-windows-gnu
cross-packages: mingw-w64
cargo-linker-env: ""
cargo-linker: ""
- target: aarch64-windows-gnu - target: aarch64-windows-gnu
os: ubuntu-latest os: ubuntu-latest
rust-target: aarch64-pc-windows-gnullvm rust-target: aarch64-pc-windows-gnullvm
cross-packages: mingw-w64
cargo-linker-env: ""
cargo-linker: ""
- target: x86-windows-gnu
os: ubuntu-latest
rust-target: i686-pc-windows-gnu
cross-packages: mingw-w64
cargo-linker-env: ""
cargo-linker: ""
# BSD (esbuild tier; use zig cc as cargo linker)
- target: x86_64-freebsd
os: ubuntu-latest
rust-target: x86_64-unknown-freebsd
cross-packages: ""
cargo-linker-env: CARGO_TARGET_X86_64_UNKNOWN_FREEBSD_LINKER
cargo-linker: zig cc -target x86_64-freebsd
- target: x86_64-netbsd
os: ubuntu-latest
rust-target: x86_64-unknown-netbsd
cross-packages: ""
cargo-linker-env: CARGO_TARGET_X86_64_UNKNOWN_NETBSD_LINKER
cargo-linker: zig cc -target x86_64-netbsd
# Additional targets
- target: wasm32-freestanding - target: wasm32-freestanding
os: ubuntu-latest os: ubuntu-latest
rust-target: wasm32-unknown-unknown rust-target: wasm32-unknown-unknown
cross-packages: ""
cargo-linker-env: ""
cargo-linker: ""
- target: wasm32-wasi - target: wasm32-wasi
os: ubuntu-latest os: ubuntu-latest
rust-target: wasm32-wasip1 rust-target: wasm32-wasip1
cross-packages: ""
cargo-linker-env: ""
cargo-linker: ""
- target: x86_64-linux-musl - target: x86_64-linux-musl
os: ubuntu-latest os: ubuntu-latest
rust-target: x86_64-unknown-linux-musl rust-target: x86_64-unknown-linux-musl
cross-packages: ""
cargo-linker-env: ""
cargo-linker: ""
- target: aarch64-linux-musl - target: aarch64-linux-musl
os: ubuntu-latest os: ubuntu-latest
rust-target: aarch64-unknown-linux-musl rust-target: aarch64-unknown-linux-musl
cross-packages: ""
cargo-linker-env: ""
cargo-linker: ""
- target: aarch64-linux-android - target: aarch64-linux-android
os: ubuntu-latest os: ubuntu-latest
rust-target: aarch64-linux-android rust-target: aarch64-linux-android
cross-packages: ""
cargo-linker-env: ""
cargo-linker: ""
- target: aarch64-ios - target: aarch64-ios
os: macos-latest os: macos-latest
rust-target: aarch64-apple-ios rust-target: aarch64-apple-ios
cross-packages: ""
cargo-linker-env: ""
cargo-linker: ""
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup Zig - name: Setup Zig
uses: mlugg/setup-zig@v2 uses: mlugg/setup-zig@v2
with: with:
version: 0.17.0-dev.1398+cb5635714 version: 0.16.0-dev.2860+9c5460316
- name: Setup Rust - name: Setup Rust
uses: dtolnay/rust-toolchain@stable uses: dtolnay/rust-toolchain@stable
with: with:
targets: ${{ matrix.rust-target }} targets: ${{ matrix.rust-target }}
- name: Install cross-compilers - name: Install cross-compilers (Linux-aarch64)
if: matrix.cross-packages != '' if: contains(matrix.target, 'aarch64-linux')
run: | run: |
sudo apt-get update sudo apt-get update
sudo apt-get install -y ${{ matrix.cross-packages }} sudo apt-get install -y gcc-aarch64-linux-gnu
- name: Install cross-compilers (Windows-mingw)
if: contains(matrix.target, 'windows-gnu')
run: |
sudo apt-get update
sudo apt-get install -y mingw-w64
- name: Build Package - name: Build Package
run: | run: |
if [ -n "${{ matrix.cargo-linker-env }}" ]; then cd pkg/temporal
export "${{ matrix.cargo-linker-env }}=${{ matrix.cargo-linker }}"
fi
cd lib
zig build -Dbuild-rust -Dtarget=${{ matrix.target }} -Doptimize=ReleaseSafe zig build -Dbuild-rust -Dtarget=${{ matrix.target }} -Doptimize=ReleaseSafe
- name: Package artifact
run: |
cd lib
mkdir -p dist
tar -czf "dist/${{ matrix.target }}.tar.gz" -C "zig-out/lib/${{ matrix.target }}" .
- name: Upload Artifact - name: Upload Artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: ${{ matrix.target }} name: lib-${{ matrix.target }}
path: lib/dist/${{ matrix.target }}.tar.gz path: pkg/temporal/zig-out/lib/
retention-days: 1 retention-days: 1
release: release:
@ -199,18 +97,30 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/') if: startsWith(github.ref, 'refs/tags/')
steps: steps:
- uses: actions/checkout@v4 - name: Checkout code
uses: actions/checkout@v4
- name: Download all artifacts - name: Download all artifacts
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:
path: dist path: all-libs
pattern: lib-*
merge-multiple: true merge-multiple: true
- name: Prepare Release Artifact
run: |
mkdir -p release/lib
cp -r all-libs/* release/lib/
cd release
tar -czf ../libtemporal.tar.gz lib/
zip -r ../libtemporal.zip lib/
- name: Release - name: Release
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v2
with: with:
files: dist/*.tar.gz files: |
libtemporal.tar.gz
libtemporal.zip
generate_release_notes: true generate_release_notes: true
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

@ -2,17 +2,9 @@ name: CI
on: on:
push: push:
branches: [main] branches: [ main ]
paths:
- 'src/**'
- 'lib/**'
- 'test/**'
- 'build.zig'
- 'build.zig.zon'
- '.github/workflows/ci.yml'
pull_request: pull_request:
branches: [main] branches: [ main ]
jobs: jobs:
build: build:
@ -21,34 +13,59 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest] os: [ubuntu-latest, windows-latest, macos-latest]
# os: [ubuntu-latest, macos-latest]
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Setup Zig - name: Setup Zig
uses: mlugg/setup-zig@v2 uses: mlugg/setup-zig@v2
with: with:
version: 0.17.0-dev.1398+cb5635714 version: 0.16.0-dev.2860+9c5460316
- name: Build and run project - name: Build project
run: cd test && zig build run run: zig build
- name: Verify executable
run: |
./zig-out/bin/zx --help || echo "Executable built successfully"
shell: bash
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: temporalz-${{ matrix.os }}
path: zig-out/
retention-days: 1
test: test:
name: Test (${{ matrix.os }}) name: Test (${{ matrix.os }})
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
needs: build
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest] os: [ubuntu-latest, windows-latest, macos-latest]
# os: [ubuntu-latest, macos-latest]
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Setup Zig - name: Setup Zig
uses: mlugg/setup-zig@v2 uses: mlugg/setup-zig@v2
with: with:
version: 0.17.0-dev.1398+cb5635714 version: 0.16.0-dev.2860+9c5460316
- name: Run tests - name: Download build artifacts
run: zig build test uses: actions/download-artifact@v4
with:
name: temporalz-${{ matrix.os }}
path: zig-out/
- name: Make executable (Unix)
if: runner.os != 'Windows'
run: chmod +x zig-out/bin/temporalz
- name: Run tests
run: zig build test

View file

@ -1,55 +0,0 @@
name: Docs
on:
push:
branches:
- main
paths:
- 'src/**'
- 'lib/**'
- '.github/workflows/docs.yml'
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Zig
uses: mlugg/setup-zig@v2
with:
version: 0.17.0-dev.1398+cb5635714
- name: Setup Pages
uses: actions/configure-pages@v5
- name: Build Docs
run: zig build docs
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./zig-out/docs
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

5
.gitignore vendored
View file

@ -3,4 +3,7 @@ zig-out
zig-pkg zig-pkg
target target
.tool-versions lib
tmp
test/test262/polyfill-injected.js

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "test/temporal-test262-runner"]
path = test/temporal-test262-runner
url = https://github.com/js-temporal/temporal-test262-runner.git

1
.tool-versions Normal file
View file

@ -0,0 +1 @@
zig master

View file

@ -6,11 +6,12 @@ A Zig library for working with temporal types based on the [Temporal Standard](h
Temporalz provides Zig bindings to the Rust-based [temporal_rs](https://github.com/boa-dev/temporal) library for handling dates, times, and durations with proper timezone support. Temporalz provides Zig bindings to the Rust-based [temporal_rs](https://github.com/boa-dev/temporal) library for handling dates, times, and durations with proper timezone support.
## Installation ## Installation
#### Prerequisites #### Prerequisites
- Zig 0.17.0-dev.1398+cb5635714 - Zig 0.16.0-dev.2860+9c5460316
- Rust toolchain (only required if [prebuilt staticlibs](#prebuilt) are not available for your platform) - Rust toolchain (only required if [prebuilt staticlibs](#prebuilt) are not available for your platform)
#### Add as a Dependency #### Add as a Dependency
@ -34,31 +35,36 @@ const exe = b.addExecutable(.{...});
exe.root_module.addImport("temporalz", temporalz.module("temporalz")); exe.root_module.addImport("temporalz", temporalz.module("temporalz"));
``` ```
## Checklist
| Namespace | Status | ## Checklist ([Test262](https://github.com/tc39/test262/tree/main/test/built-ins/Temporal))
| -------------- | ------ |
| Instant | ✅ | | Namespace | Test262 (todo) |
| Duration | ✅ | | --- | --- |
| PlainDate | ✅ | | Instant | 0/0 |
| PlainTime | ✅ | | Duration | 0/0 |
| PlainDateTime | ✅ | | PlainDate | 0/0 |
| PlainYearMonth | ✅ | | PlainTime | 0/0 |
| PlainMonthDay | ✅ | | PlainDateTime | 0/0 |
| ZonedDateTime | ✅ | | PlainYearMonth | 0/0 |
| PlainMonthDay | 0/0 |
| ZonedDateTime | 0/0 |
## Prebuilt ## Prebuilt
Prebuilt libraries are included for the following platforms: Prebuilt libraries are included for the following platforms:
- `x86_64-macos`, `aarch64-macos` - `x86_64-macos`
- `x86_64-linux-gnu`, `aarch64-linux-gnu`, `x86-linux-gnu`, `arm-linux-gnueabihf` - `aarch64-macos`
- `loongarch64-linux-gnu`, `powerpc64le-linux-gnu`, `riscv64-linux-gnu`, `s390x-linux-gnu` - `x86_64-linux-gnu`
- `x86_64-windows-gnu`, `aarch64-windows-gnu`, `x86-windows-gnu` - `aarch64-linux-gnu`
- `x86_64-freebsd`, `x86_64-netbsd` - `x86_64-windows-gnu`
- `wasm32-freestanding`, `wasm32-wasi` - `aarch64-windows-gnu`
- `x86_64-linux-musl`, `aarch64-linux-musl` - `wasm32-freestanding`
- `aarch64-linux-android`, `aarch64-ios` - `wasm32-wasi`
- `x86_64-linux-musl`
- `aarch64-linux-musl`
- `aarch64-linux-android`
- `aarch64-ios`
For other platforms, the library will build from source; you need the Rust toolchain installed. For other platforms, the library will build from source; you need the Rust toolchain installed.
@ -75,12 +81,6 @@ cd temporalz
```bash ```bash
zig build run zig build run
# Node.js
zig build run -Dtarget=wasm32-freestanding
# wasmtime
zig build run -Dtarget=wasm32-wasi
``` ```
#### Run Tests #### Run Tests
@ -88,3 +88,8 @@ zig build run -Dtarget=wasm32-wasi
```bash ```bash
zig build test zig build test
``` ```
## License
MIT

298
SPEC.md Normal file
View file

@ -0,0 +1,298 @@
Temporal.Duration
Temporal.Instant
Temporal.Now
Temporal.PlainDate
Temporal.PlainDateTime
Temporal.PlainMonthDay
Temporal.PlainTime
Temporal.PlainYearMonth
Temporal.ZonedDateTime
Temporal.Duration
Constructor
Temporal.Duration()
Static methods
compare()
from()
Instance methods
abs()
add()
negated()
round()
subtract()
toJSON()
toLocaleString()
toString()
total()
valueOf()
with()
Instance properties
blank
days
hours
microseconds
milliseconds
minutes
months
nanoseconds
seconds
sign
weeks
years
Temporal.Instant
Constructor
Temporal.Instant()
Experimental
Static methods
compare()
from()
fromEpochMilliseconds()
fromEpochNanoseconds()
Instance methods
add()
equals()
round()
since()
subtract()
toJSON()
toLocaleString()
toString()
toZonedDateTimeISO()
until()
valueOf()
Instance properties
epochMilliseconds
epochNanoseconds
Temporal.Now
Static methods
instant()
plainDateISO()
plainDateTimeISO()
plainTimeISO()
timeZoneId()
zonedDateTimeISO()
Temporal.PlainDate
Constructor
Temporal.PlainDate()
Experimental
Static methods
compare()
from()
Instance methods
add()
equals()
since()
subtract()
toJSON()
toLocaleString()
toPlainDateTime()
toPlainMonthDay()
toPlainYearMonth()
toString()
toZonedDateTime()
until()
valueOf()
with()
withCalendar()
Instance properties
calendarId
day
dayOfWeek
dayOfYear
daysInMonth
daysInWeek
daysInYear
era
eraYear
inLeapYear
month
monthCode
monthsInYear
weekOfYear
year
yearOfWeek
Temporal.PlainDateTime
Constructor
Temporal.PlainDateTime()
Experimental
Static methods
compare()
from()
Instance methods
add()
equals()
round()
since()
subtract()
toJSON()
toLocaleString()
toPlainDate()
toPlainTime()
toString()
toZonedDateTime()
until()
valueOf()
with()
withCalendar()
withPlainTime()
Instance properties
calendarId
day
dayOfWeek
dayOfYear
daysInMonth
daysInWeek
daysInYear
era
eraYear
hour
inLeapYear
microsecond
millisecond
minute
month
monthCode
monthsInYear
nanosecond
second
weekOfYear
year
yearOfWeek
Temporal.PlainMonthDay
Constructor
Temporal.PlainMonthDay()
Experimental
Static methods
from()
Instance methods
equals()
toJSON()
toLocaleString()
toPlainDate()
toString()
valueOf()
with()
Instance properties
calendarId
day
monthCode
Temporal.PlainTime
Constructor
Temporal.PlainTime()
Static methods
compare()
from()
Instance methods
add()
equals()
round()
since()
subtract()
toJSON()
toLocaleString()
toString()
until()
valueOf()
with()
Instance properties
hour
microsecond
millisecond
minute
nanosecond
second
Temporal.PlainYearMonth
Constructor
Temporal.PlainYearMonth()
Experimental
Static methods
compare()
from()
Instance methods
add()
equals()
since()
subtract()
toJSON()
toLocaleString()
toPlainDate()
toString()
until()
valueOf()
with()
Instance properties
calendarId
daysInMonth
daysInYear
era
eraYear
inLeapYear
month
monthCode
monthsInYear
year
Temporal.ZonedDateTime
Constructor
Temporal.ZonedDateTime()
Experimental
Static methods
compare()
from()
Instance methods
add()
equals()
getTimeZoneTransition()
round()
since()
startOfDay()
subtract()
toInstant()
toJSON()
toLocaleString()
toPlainDate()
toPlainDateTime()
toPlainTime()
toString()
until()
valueOf()
with()
withCalendar()
withPlainTime()
withTimeZone()
Instance properties
calendarId
day
dayOfWeek
dayOfYear
daysInMonth
daysInWeek
daysInYear
epochMilliseconds
epochNanoseconds
era
eraYear
hour
hoursInDay
inLeapYear
microsecond
millisecond
minute
month
monthCode
monthsInYear
nanosecond
offset
offsetNanoseconds
second
timeZoneId
weekOfYear
year
yearOfWeek

View file

@ -3,38 +3,66 @@ const std = @import("std");
pub fn build(b: *std.Build) !void { pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{}); const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{}); const optimize = b.standardOptimizeOption(.{});
const is_wasm_freestanding = target.result.cpu.arch.isWasm() and target.result.os.tag == .freestanding;
// --- Rust C ABI & Pre-built via temporal-rs subpackage --- // // --- Rust C ABI & Pre-built via temporal-rs subpackage --- //
const build_rust = b.option(bool, "build-rust", "Build Rust library from source") orelse false; const temporal = b.dependency("temporal", .{
const libtemporal = b.dependency("libtemporal", .{
.target = target, .target = target,
.optimize = optimize, .optimize = optimize,
.@"build-rust" = build_rust,
}); });
// --- Module: temporalz --- // // --- Zig Module: temporalz --- //
const mod = b.addModule("temporalz", .{ const mod = b.addModule("temporalz", .{
.root_source_file = b.path("src/root.zig"), .root_source_file = b.path("src/root.zig"),
.target = target, .target = target,
.optimize = optimize, .optimize = optimize,
}); });
mod.addImport("libtemporal", libtemporal.module("libtemporal")); mod.addImport("temporal_rs", temporal.module("temporal_rs"));
// --- Step: run --- // // --- Zig Executable: temporalz --- //
const exe = b.addExecutable(.{
.name = "temporalz",
.root_module = b.createModule(.{
.root_source_file = if (is_wasm_freestanding)
b.path("example/src/wasm.zig")
else
b.path("example/src/main.zig"),
.target = target,
.optimize = optimize,
.imports = &.{
.{ .name = "temporalz", .module = mod },
},
}),
});
exe.root_module.link_libc = !is_wasm_freestanding;
exe.rdynamic = is_wasm_freestanding;
b.installArtifact(exe);
// --- Steps: Run --- //
{ {
const run_step = b.step("run", "Run the test project"); const run_step = b.step("run", "Run the app");
const run_cmd = b.addSystemCommand(&.{ switch (target.result.os.tag) {
b.graph.zig_exe, .freestanding => {
"build", const run_cmd = b.addSystemCommand(&.{ "node", "example/src/main.mjs" });
"run", run_cmd.step.dependOn(b.getInstallStep());
b.fmt("-Dtarget={s}", .{try target.result.zigTriple(b.allocator)}), run_step.dependOn(&run_cmd.step);
}); },
run_cmd.setCwd(b.path("test")); .wasi => {
run_cmd.addPassthruArgs(); const run_cmd = b.addSystemCommand(&.{"wasmtime"});
run_step.dependOn(&run_cmd.step); run_cmd.addFileArg(exe.getEmittedBin());
run_cmd.step.dependOn(b.getInstallStep());
run_step.dependOn(&run_cmd.step);
},
else => {
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd.addArgs(args);
run_step.dependOn(&run_cmd.step);
},
}
} }
// --- Step: docs --- // // --- Steps: Docs --- //
{ {
const docs_step = b.step("docs", "Build the temporalz docs"); const docs_step = b.step("docs", "Build the temporalz docs");
const docs_obj = b.addObject(.{ .name = "temporalz", .root_module = mod }); const docs_obj = b.addObject(.{ .name = "temporalz", .root_module = mod });
@ -47,7 +75,7 @@ pub fn build(b: *std.Build) !void {
}).step); }).step);
} }
// --- Step: test --- // // --- Steps: Test --- //
{ {
const test_step = b.step("test", "Run tests"); const test_step = b.step("test", "Run tests");
const mod_tests = b.addTest(.{ const mod_tests = b.addTest(.{
@ -57,7 +85,20 @@ pub fn build(b: *std.Build) !void {
.mode = .simple, .mode = .simple,
}, },
}); });
mod_tests.root_module.link_libc = target.result.os.tag != .freestanding; mod_tests.root_module.link_libc = !is_wasm_freestanding;
test_step.dependOn(&b.addRunArtifact(mod_tests).step); test_step.dependOn(&b.addRunArtifact(mod_tests).step);
if (!is_wasm_freestanding) {
const exe_tests = b.addTest(.{ .root_module = exe.root_module });
test_step.dependOn(&b.addRunArtifact(exe_tests).step);
}
}
// --- Steps: test-262 --- //
{
const test262_step = b.step("test262", "Run test-262 tests");
const run_cmd = b.addSystemCommand(&.{ "node", "test/test262/runner.mjs" });
if (b.args) |args| run_cmd.addArgs(args);
run_cmd.step.dependOn(b.getInstallStep());
test262_step.dependOn(&run_cmd.step);
} }
} }

View file

@ -1,11 +1,11 @@
.{ .{
.name = .temporalz, .name = .temporalz,
.version = "0.2.4", .version = "0.2.0",
.fingerprint = 0xd8d79d59acc4faae, .fingerprint = 0xd8d79d59acc4faae,
.minimum_zig_version = "0.17.0-dev.1398+cb5635714", .minimum_zig_version = "0.16.0-dev.2860+9c5460316",
.dependencies = .{ .dependencies = .{
.libtemporal = .{ .temporal = .{
.path = "lib", .path = "pkg/temporal",
}, },
}, },
.paths = .{ .paths = .{
@ -14,6 +14,6 @@
"README.md", "README.md",
"LICENCE", "LICENCE",
"src", "src",
"lib", "pkg",
}, },
} }

View file

@ -3,7 +3,7 @@ const std = @import("std");
pub fn build(b: *std.Build) void { pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{}); const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{}); const optimize = b.standardOptimizeOption(.{});
const is_freestanding = target.result.os.tag == .freestanding; const is_wasm_freestanding = target.result.cpu.arch.isWasm() and target.result.os.tag == .freestanding;
const temporalz = b.dependency("temporalz", .{ const temporalz = b.dependency("temporalz", .{
.target = target, .target = target,
@ -12,18 +12,14 @@ pub fn build(b: *std.Build) void {
const exe = b.addExecutable(.{ const exe = b.addExecutable(.{
.name = "temporalz", .name = "temporalz",
.root_module = b.createModule(.{ .root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"), .root_source_file = b.path(if (is_wasm_freestanding) "src/wasm.zig" else "src/main.zig"),
.target = target, .target = target,
.optimize = optimize, .optimize = optimize,
.link_libc = !is_freestanding,
.imports = &.{}, .imports = &.{},
}), }),
}); });
exe.root_module.addImport("temporalz", temporalz.module("temporalz")); exe.root_module.addImport("temporalz", temporalz.module("temporalz"));
exe.rdynamic = is_freestanding;
if (is_freestanding) exe.entry = .disabled;
b.installArtifact(exe); b.installArtifact(exe);
b.enable_wasmtime = true; // This doesn't work since Zig 0.17.0 release
const run_step = b.step("run", "Run the app"); const run_step = b.step("run", "Run the app");
switch (target.result.os.tag) { switch (target.result.os.tag) {
@ -41,7 +37,7 @@ pub fn build(b: *std.Build) void {
else => { else => {
const run_cmd = b.addRunArtifact(exe); const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep()); run_cmd.step.dependOn(b.getInstallStep());
run_cmd.addPassthruArgs(); if (b.args) |args| run_cmd.addArgs(args);
run_step.dependOn(&run_cmd.step); run_step.dependOn(&run_cmd.step);
}, },
} }

View file

@ -1,7 +1,8 @@
.{ .{
.name = .temporalz_example, .name = .temporalz_example,
.version = "0.0.0", .version = "0.1.2",
.fingerprint = 0x686c9dfc777f9593, .fingerprint = 0x686c9dfc777f9593,
.minimum_zig_version = "0.16.0-dev.2860+9c5460316",
.dependencies = .{ .dependencies = .{
.temporalz = .{ .temporalz = .{
.path = "../", .path = "../",

17
example/src/main.mjs Normal file
View file

@ -0,0 +1,17 @@
import { readFile } from 'fs/promises';
let memory = null;
const buffer = await readFile('zig-out/bin/temporalz.wasm');
const temporalz = await WebAssembly.instantiate(buffer, {
env: {
console(ptr, len) {
const bytes = new Uint8Array(memory.buffer, ptr, len);
const message = new TextDecoder().decode(bytes);
console.log(message);
},
},
});
memory = temporalz.instance.exports.memory;
temporalz.instance.exports._start();

9
example/src/main.zig Normal file
View file

@ -0,0 +1,9 @@
const std = @import("std");
const program = @import("root.zig");
pub fn main(init: std.process.Init) !void {
const allocator = init.arena.allocator();
const io = init.io;
try program.run(allocator, io);
}

482
example/src/root.zig Normal file
View file

@ -0,0 +1,482 @@
const std = @import("std");
const builtin = @import("builtin");
const Temporal = @import("temporalz");
pub fn run(allocator: std.mem.Allocator, io_optional: ?std.Io) !void {
// --- Instant --- //
const instant = try Temporal.Instant.init(1_704_067_200_000_000_000); // 2024-01-01 00:00:00 UTC
defer instant.deinit();
std.log.info(
\\Instant
\\ - milliseconds: {}
\\ - nanoseconds: {}
\\ - toString(): {s}
\\
\\
, .{
instant.epochMilliseconds(),
instant.epochNanoseconds(),
try instant.toString(allocator, .{}),
});
// --- Duration --- //
const dur = try Temporal.Duration.from("PT1H");
defer dur.deinit();
std.log.info(
\\Duration
\\ - nanoseconds: {}
\\ - milliseconds: {}
\\ - seconds: {}
\\ - minutes: {}
\\ - hours: {}
\\ - days: {}
\\ - weeks: {}
\\ - months: {}
\\ - years: {}
\\ - toString(): {s}
\\
\\
, .{
dur.nanoseconds(),
dur.milliseconds(),
dur.seconds(),
dur.minutes(),
dur.hours(),
dur.days(),
dur.weeks(),
dur.months(),
dur.years(),
try dur.toString(allocator, .{}),
});
// --- Now --- //
if (io_optional) |io| {
const now_instant = try Temporal.Now.instant(io);
defer now_instant.deinit();
const now_date = try Temporal.Now.plainDateISO(io);
defer now_date.deinit();
const now_datetime = try Temporal.Now.plainDateTimeISO(io);
const now_time = try Temporal.Now.plainTimeISO(io);
std.log.info(
\\Now
\\ - instant: {s}
\\ - date: {s}
\\ - datetime: {s}
\\ - time: {s}
\\
\\
, .{
try now_instant.toString(allocator, .{}),
try now_date.toString(allocator, .{}),
try now_datetime.toString(allocator, .{}),
try now_time.toString(allocator),
});
}
// --- PlainDate --- //
const date = try Temporal.PlainDate.init(2024, 2, 2);
defer date.deinit();
std.log.info(
\\PlainDate
\\ - year: {}
\\ - month: {}
\\ - day: {}
\\ - toString(): {s}
\\
\\
, .{
date.year(),
date.month(),
date.day(),
try date.toString(allocator, .{}),
});
// --- PlainDateTime --- //
const dt = try Temporal.PlainDateTime.init(2024, 2, 2, 13, 45, 30, 123, 456, 789);
std.log.info(
\\PlainDateTime
\\ - year: {}
\\ - month: {}
\\ - day: {}
\\ - hour: {}
\\ - minute: {}
\\ - second: {}
\\ - toString(): {s}
\\
\\
, .{
dt.year(),
dt.month(),
dt.day(),
dt.hour(),
dt.minute(),
dt.second(),
try dt.toString(allocator, .{}),
});
// --- PlainMonthDay --- //
const md = try Temporal.PlainMonthDay.init(2, 2, null);
std.log.info(
\\PlainMonthDay
\\ - monthCode: {s}
\\ - day: {}
\\ - toString(): {s}
\\
\\
, .{
try md.monthCode(allocator),
md.day(),
try md.toString(allocator),
});
// --- PlainTime --- //
const tm = try Temporal.PlainTime.init(13, 45, 30, 123, 456, 789);
std.log.info(
\\PlainTime
\\ - hour: {}
\\ - minute: {}
\\ - second: {}
\\ - toString(): {s}
\\
\\
, .{
tm.hour(),
tm.minute(),
tm.second(),
try tm.toString(allocator),
});
// --- PlainYearMonth --- //
const ym = try Temporal.PlainYearMonth.init(2024, 2, null);
std.log.info(
\\PlainYearMonth
\\ - year: {}
\\ - month: {}
\\ - toString(): {s}
\\
\\
, .{ ym.year(), ym.month(), try ym.toString(allocator) });
// --- ZonedDateTime --- //
const tz = try Temporal.ZonedDateTime.TimeZone.init("UTC");
// Example: 2024-02-02T13:45:30.123456789Z in nanoseconds since epoch
const zdt_epoch_ns: i128 = 1706881530123456789;
const zdt = try Temporal.ZonedDateTime.fromEpochNanoseconds(zdt_epoch_ns, tz);
defer zdt.deinit();
std.log.info(
\\ZonedDateTime
\\ - year: {}
\\ - month: {}
\\ - day: {}
\\ - hour: {}
\\ - minute: {}
\\ - second: {}
\\ - timeZone: {s}
\\ - toString(): {s}
\\
\\
, .{
zdt.year(),
zdt.month(),
zdt.day(),
zdt.hour(),
zdt.minute(),
zdt.second(),
try zdt.timeZoneId(allocator),
try zdt.toString(allocator, .{}),
});
// ----
// More complex Temporal API examples
// ----
// Duration arithmetic
const dur1 = try Temporal.Duration.from("P1DT2H");
const dur2 = try Temporal.Duration.from("PT30M");
const dur_sum = try dur1.add(dur2);
std.log.info(
\\Duration Arithmetic
\\ - dur1: {s}
\\ - dur2: {s}
\\ - dur1 + dur2: {s}
\\
\\
, .{
try dur1.toString(allocator, .{}),
try dur2.toString(allocator, .{}),
try dur_sum.toString(allocator, .{}),
});
// Instant comparison and arithmetic
const inst1 = try Temporal.Instant.init(1_704_067_200_000_000_000);
const inst2 = try Temporal.Instant.init(1_704_153_600_000_000_000); // +1 day
const inst_diff = try inst2.since(inst1, Temporal.Instant.DifferenceSettings{});
std.log.info(
\\Instant Comparison
\\ - inst1: {s}
\\ - inst2: {s}
\\ - inst2.since(inst1): {s}
\\
\\
, .{
try inst1.toString(allocator, .{}),
try inst2.toString(allocator, .{}),
try inst_diff.toString(allocator, .{}),
});
// PlainDate to PlainDateTime and back
const pd = try Temporal.PlainDate.init(2024, 2, 2);
const pdt = try pd.toPlainDateTime(try Temporal.PlainTime.init(12, 0, 0, 0, 0, 0));
std.log.info(
\\PlainDate/PlainDateTime Conversion
\\ - PlainDate: {s}
\\ - toPlainDateTime(12:00): {s}
\\ - toPlainDate(): {s}
\\
\\
, .{
try pd.toString(allocator, .{}),
try pdt.toString(allocator, .{}),
try (try pdt.toPlainDate()).toString(allocator, .{}),
});
// ZonedDateTime to Instant and back
const zdt2 = try Temporal.ZonedDateTime.fromEpochNanoseconds(1706881530123456789, tz);
const zdt2_inst = try zdt2.toInstant();
const zdt2_from_inst = try Temporal.ZonedDateTime.fromEpochNanoseconds(zdt2_inst.epochNanoseconds(), tz);
std.log.info(
\\ZonedDateTime/Instant Conversion
\\ - ZonedDateTime: {s}
\\ - toInstant(): {s}
\\ - fromEpochNanoseconds(instant): {s}
\\
\\
, .{
try zdt2.toString(allocator, .{}),
try zdt2_inst.toString(allocator, .{}),
try zdt2_from_inst.toString(allocator, .{}),
});
// ----
// Further more complex examples covering more methods
// ----
// Duration: abs, negated, round, subtract, total, valueOf
const dur_neg = dur.negated();
const dur_abs = dur_neg.abs();
const dur_sub = try dur.subtract(dur2);
const dur_rounded = try dur.round(.{ .smallest_unit = Temporal.Duration.Unit.hour });
const dur_total_hours = try dur.total(.{ .unit = Temporal.Duration.Unit.hour });
std.log.info(
\\Duration Advanced
\\ - negated: {s}
\\ - abs: {s}
\\ - subtract dur2: {s}
\\ - round to hour: {s}
\\ - total hours: {d}
\\
\\
, .{
try dur_neg.toString(allocator, .{}),
try dur_abs.toString(allocator, .{}),
try dur_sub.toString(allocator, .{}),
try dur_rounded.toString(allocator, .{}),
dur_total_hours,
});
// Instant: add, subtract, round, equals, valueOf
const inst_add = try inst1.add(@constCast(&dur));
const inst_sub = try inst2.subtract(@constCast(&dur));
const inst_rounded = try inst1.round(.{ .smallest_unit = Temporal.Instant.Unit.second });
const inst_eq = Temporal.Instant.compare(inst1, inst1) == 0;
std.log.info(
\\Instant Advanced
\\ - add duration: {s}
\\ - subtract duration: {s}
\\ - round to second: {s}
\\ - inst1 equals inst1: {}
\\
\\
, .{
try inst_add.toString(allocator, .{}),
try inst_sub.toString(allocator, .{}),
try inst_rounded.toString(allocator, .{}),
inst_eq,
});
// PlainDate: add, subtract, with, equals, since, until, withCalendar
const date_added = try date.add(dur);
const date_sub = try date.subtract(dur);
// const date_with = try date.with(.{ .year = 2025 });
const date_eq = date.equals(date);
const date_since = try date.since(date, Temporal.PlainDate.DifferenceSettings{});
const date_until = try date.until(date, Temporal.PlainDate.DifferenceSettings{});
const date_with_cal = try date.withCalendar("iso8601");
std.log.info(
\\PlainDate Advanced
\\ - equals self: {}
\\ - add duration: {s}
\\ - subtract duration: {s}
\\ - since self: {s}
\\ - until self: {s}
\\ - withCalendar: {s}
\\ - with year=2025: {{s}}
\\
\\
,
.{
date_eq,
try date_added.toString(allocator, .{}),
try date_sub.toString(allocator, .{}),
try date_since.toString(allocator, .{}),
try date_until.toString(allocator, .{}),
try date_with_cal.toString(allocator, .{}),
// try date_with.toString(allocator, .{}),
},
);
// PlainDateTime: add, subtract, round, with, equals, since, until, withCalendar, withPlainTime
const dt_added = try dt.add(dur);
const dt_sub = try dt.subtract(dur);
const dt_rounded = try dt.round(.{ .smallest_unit = Temporal.PlainDateTime.Unit.minute });
const dt_with = try dt.with(.{ .year = 2025 });
const dt_eq = dt.equals(dt);
const dt_since = try dt.since(dt, Temporal.PlainDateTime.DifferenceSettings{});
const dt_until = try dt.until(dt, Temporal.PlainDateTime.DifferenceSettings{});
const dt_with_cal = try dt.withCalendar("iso8601");
const dt_with_time = try dt.withPlainTime(try Temporal.PlainTime.init(1, 2, 3, 4, 5, 6));
std.log.info(
\\PlainDateTime Advanced
\\ - add duration: {s}
\\ - subtract duration: {s}
\\ - round to minute: {s}
\\ - with year=2025: {s}
\\ - equals self: {}
\\ - since self: {s}
\\ - until self: {s}
\\ - withCalendar: {s}
\\ - withPlainTime: {s}
\\
\\
, .{
try dt_added.toString(allocator, .{}),
try dt_sub.toString(allocator, .{}),
try dt_rounded.toString(allocator, .{}),
try dt_with.toString(allocator, .{}),
dt_eq,
try dt_since.toString(allocator, .{}),
try dt_until.toString(allocator, .{}),
try dt_with_cal.toString(allocator, .{}),
try dt_with_time.toString(allocator, .{}),
});
// PlainTime: add, subtract, round, with, equals, since, until
const tm_added = try tm.add(dur);
const tm_sub = try tm.subtract(dur);
const tm_rounded = try tm.round(.{ .smallest_unit = Temporal.PlainTime.Unit.second });
const tm_with = try tm.with(.{ .hour = 1 });
const tm_eq = tm.equals(tm);
const tm_since = try tm.since(tm, Temporal.PlainTime.DifferenceSettings{});
const tm_until = try tm.until(tm, Temporal.PlainTime.DifferenceSettings{});
std.log.info(
\\PlainTime Advanced
\\ - add duration: {s}
\\ - subtract duration: {s}
\\ - round to second: {s}
\\ - with hour=1: {s}
\\ - equals self: {}
\\ - since self: {s}
\\ - until self: {s}
\\
\\
, .{
try tm_added.toString(allocator),
try tm_sub.toString(allocator),
try tm_rounded.toString(allocator),
try tm_with.toString(allocator),
tm_eq,
try tm_since.toString(allocator, .{}),
try tm_until.toString(allocator, .{}),
});
// PlainYearMonth: add, subtract, with, equals, since, until, withCalendar
const dur_ym = try Temporal.Duration.from("P1M");
defer dur_ym.deinit();
const ym_added = try ym.add(dur_ym);
const ym_sub = try ym.subtract(dur_ym);
const ym_with = try ym.with(.{ .year = 2025 });
const ym_eq = ym.equals(ym);
const ym_since = try ym.since(ym, Temporal.PlainYearMonth.DifferenceSettings{});
const ym_until = try ym.until(ym, Temporal.PlainYearMonth.DifferenceSettings{});
std.log.info(
\\PlainYearMonth Advanced
\\ - add duration: {s}
\\ - subtract duration: {s}
\\ - with year=2025: {s}
\\ - equals self: {}
\\ - since self: {s}
\\ - until self: {s}
\\
\\
, .{
try ym_added.toString(allocator),
try ym_sub.toString(allocator),
try ym_with.toString(allocator),
ym_eq,
try ym_since.toString(allocator, .{}),
try ym_until.toString(allocator, .{}),
});
// ZonedDateTime: add, subtract, round, with, equals, since, until, withCalendar, withPlainTime, withTimeZone
const zdt_added = try zdt.add(dur);
const zdt_sub = try zdt.subtract(dur);
const zdt_rounded = try zdt.round(.{ .smallest_unit = Temporal.ZonedDateTime.Unit.hour });
// const zdt_with = try zdt.with(allocator, .{ .year = 2025 });
const zdt_eq = zdt.equals(zdt);
const zdt_since = try zdt.since(zdt, Temporal.ZonedDateTime.DifferenceSettings{});
const zdt_until = try zdt.until(zdt, Temporal.ZonedDateTime.DifferenceSettings{});
const zdt_with_cal = try zdt.withCalendar("iso8601");
const zdt_with_time = try zdt.withPlainTime(try Temporal.PlainTime.init(1, 2, 3, 4, 5, 6));
const zdt_with_tz = try zdt.withTimeZone(tz);
std.log.info(
\\ZonedDateTime Advanced
\\ - add duration: {s}
\\ - subtract duration: {s}
\\ - round to hour: {s}
\\ - with year=2025: {{s}}
\\ - equals self: {}
\\ - since self: {s}
\\ - until self: {s}
\\ - withCalendar: {s}
\\ - withPlainTime: {s}
\\ - withTimeZone: {s}
\\
\\
, .{
try zdt_added.toString(allocator, .{}),
try zdt_sub.toString(allocator, .{}),
try zdt_rounded.toString(allocator, .{}),
// try zdt_with.toString(allocator, .{}),
zdt_eq,
try zdt_since.toString(allocator, .{}),
try zdt_until.toString(allocator, .{}),
try zdt_with_cal.toString(allocator, .{}),
try zdt_with_time.toString(allocator, .{}),
try zdt_with_tz.toString(allocator, .{}),
});
}
extern fn consoleLog(ptr: [*]u8, len: u32) void;
pub fn logFn(comptime message_level: std.log.Level, comptime scope: @TypeOf(.enum_literal), comptime format: []const u8, args: anytype) void {
if (builtin.os.tag == .freestanding) {
const prefix = if (scope == .default) "" else "(" ++ @tagName(scope) ++ ") ";
const formatted = std.fmt.allocPrint(std.heap.wasm_allocator, prefix ++ format, args) catch return;
consoleLog(formatted.ptr, formatted.len);
}
std.log.defaultLog(message_level, scope, format, args);
}
pub const std_options: std.Options = .{
.logFn = logFn,
};

842
example/src/wasm.zig Normal file
View file

@ -0,0 +1,842 @@
const std = @import("std");
const program = @import("root.zig");
const Temporal = @import("temporalz");
export fn _start() void {
const allocator = std.heap.page_allocator;
program.run(allocator, null) catch {};
}
const wasm_allocator = std.heap.wasm_allocator;
const PolyfillError = error{InvalidHandle};
var instants_init = false;
var durations_init = false;
var instants: std.ArrayList(?Temporal.Instant) = .empty;
var durations: std.ArrayList(?Temporal.Duration) = .empty;
var plain_dates_init = false;
var plain_dates: std.ArrayList(?Temporal.PlainDate) = .empty;
var last_error: ?[]u8 = null;
fn ensureInstants() void {
if (!instants_init) {
instants = .empty;
instants_init = true;
}
}
fn ensureDurations() void {
if (!durations_init) {
durations = .empty;
durations_init = true;
}
}
fn ensurePlainDates() void {
if (!plain_dates_init) {
plain_dates = .empty;
plain_dates_init = true;
}
}
fn addInstant(inst: Temporal.Instant) u32 {
ensureInstants();
instants.append(wasm_allocator, inst) catch return 0;
return @intCast(instants.items.len);
}
fn getInstant(handle: u32) !Temporal.Instant {
ensureInstants();
if (handle == 0 or handle > instants.items.len) return PolyfillError.InvalidHandle;
return instants.items[handle - 1] orelse PolyfillError.InvalidHandle;
}
fn removeInstant(handle: u32) void {
if (!instants_init or handle == 0 or handle > instants.items.len) return;
if (instants.items[handle - 1]) |inst| {
inst.deinit();
instants.items[handle - 1] = null;
}
}
fn addDuration(dur: Temporal.Duration) u32 {
ensureDurations();
durations.append(wasm_allocator, dur) catch return 0;
return @intCast(durations.items.len);
}
fn getDuration(handle: u32) !Temporal.Duration {
ensureDurations();
if (handle == 0 or handle > durations.items.len) return PolyfillError.InvalidHandle;
return durations.items[handle - 1] orelse PolyfillError.InvalidHandle;
}
fn removeDuration(handle: u32) void {
if (!durations_init or handle == 0 or handle > durations.items.len) return;
if (durations.items[handle - 1]) |dur| {
dur.deinit();
durations.items[handle - 1] = null;
}
}
fn addPlainDate(date: Temporal.PlainDate) u32 {
ensurePlainDates();
plain_dates.append(wasm_allocator, date) catch return 0;
return @intCast(plain_dates.items.len);
}
fn getPlainDate(handle: u32) !Temporal.PlainDate {
ensurePlainDates();
if (handle == 0 or handle > plain_dates.items.len) return PolyfillError.InvalidHandle;
return plain_dates.items[handle - 1] orelse PolyfillError.InvalidHandle;
}
fn removePlainDate(handle: u32) void {
if (!plain_dates_init or handle == 0 or handle > plain_dates.items.len) return;
if (plain_dates.items[handle - 1]) |date| {
date.deinit();
plain_dates.items[handle - 1] = null;
}
}
fn clearLastError() void {
if (last_error) |msg| {
wasm_allocator.free(msg);
last_error = null;
}
}
fn setLastError(err: anyerror) void {
clearLastError();
const msg = std.fmt.allocPrint(wasm_allocator, "{s}", .{@errorName(err)}) catch return;
last_error = msg;
}
fn setLastErrorMessage(msg: []const u8) void {
clearLastError();
const owned = wasm_allocator.alloc(u8, msg.len) catch return;
std.mem.copyForwards(u8, owned, msg);
last_error = owned;
}
fn packPtrLen(ptr: [*]u8, len: usize) u64 {
const ptr_u32: u32 = @intCast(@intFromPtr(ptr));
const len_u32: u32 = @intCast(len);
return (@as(u64, ptr_u32) << 32) | @as(u64, len_u32);
}
fn unpackI128Hi(value: i128) i64 {
const bits: u128 = @bitCast(value);
const hi_bits: u64 = @intCast(bits >> 64);
return @bitCast(hi_bits);
}
fn unpackI128Lo(value: i128) u64 {
const bits: u128 = @bitCast(value);
return @intCast(bits & 0xFFFFFFFFFFFFFFFF);
}
fn joinI128(hi: i64, lo: u64) i128 {
const hi_bits: u64 = @bitCast(hi);
const value: u128 = (@as(u128, hi_bits) << 64) | @as(u128, lo);
return @bitCast(value);
}
fn unitFromCode(code: u8) ?Temporal.Duration.Unit {
return switch (code) {
1 => .nanosecond,
2 => .microsecond,
3 => .millisecond,
4 => .second,
5 => .minute,
6 => .hour,
7 => .day,
8 => .week,
9 => .month,
10 => .year,
11 => .auto,
else => null,
};
}
fn roundingModeFromCode(code: u8) ?Temporal.Duration.RoundingMode {
return switch (code) {
1 => .ceil,
2 => .floor,
3 => .expand,
4 => .trunc,
5 => .half_ceil,
6 => .half_floor,
7 => .half_expand,
8 => .half_trunc,
9 => .half_even,
else => null,
};
}
export fn temporalz_last_error_ptr() usize {
return if (last_error) |msg| @intFromPtr(msg.ptr) else 0;
}
export fn temporalz_last_error_len() usize {
return if (last_error) |msg| msg.len else 0;
}
export fn temporalz_last_error_clear() void {
clearLastError();
}
export fn temporalz_alloc(len: usize) usize {
clearLastError();
const buf = wasm_allocator.alloc(u8, len) catch |err| {
setLastError(err);
return 0;
};
return @intFromPtr(buf.ptr);
}
export fn temporalz_free(ptr: usize, len: usize) void {
if (ptr == 0 or len == 0) return;
const slice = @as([*]u8, @ptrFromInt(ptr))[0..len];
wasm_allocator.free(slice);
}
export fn temporalz_string_free(ptr: usize, len: usize) void {
temporalz_free(ptr, len);
}
export fn temporalz_instant_from_utf8(ptr: [*]const u8, len: usize) u32 {
clearLastError();
const text = ptr[0..len];
const inst = Temporal.Instant.from(text) catch |err| {
setLastError(err);
return 0;
};
return addInstant(inst);
}
export fn temporalz_instant_from_epoch_milliseconds(epoch_ms: i64) u32 {
clearLastError();
const inst = Temporal.Instant.fromEpochMilliseconds(epoch_ms) catch |err| {
setLastError(err);
return 0;
};
return addInstant(inst);
}
export fn temporalz_instant_from_epoch_nanoseconds_parts(hi: i64, lo: u64) u32 {
clearLastError();
const epoch_ns = joinI128(hi, lo);
const inst = Temporal.Instant.fromEpochNanoseconds(epoch_ns) catch |err| {
setLastError(err);
return 0;
};
return addInstant(inst);
}
export fn temporalz_instant_epoch_milliseconds(handle: u32) i64 {
clearLastError();
const inst = getInstant(handle) catch |err| {
setLastError(err);
return 0;
};
return inst.epochMilliseconds();
}
export fn temporalz_instant_epoch_nanoseconds_hi(handle: u32) i64 {
clearLastError();
const inst = getInstant(handle) catch |err| {
setLastError(err);
return 0;
};
return unpackI128Hi(inst.epochNanoseconds());
}
export fn temporalz_instant_epoch_nanoseconds_lo(handle: u32) u64 {
clearLastError();
const inst = getInstant(handle) catch |err| {
setLastError(err);
return 0;
};
return unpackI128Lo(inst.epochNanoseconds());
}
export fn temporalz_instant_to_string(handle: u32) u64 {
clearLastError();
const inst = getInstant(handle) catch |err| {
setLastError(err);
return 0;
};
const text = inst.toString(wasm_allocator, .{}) catch |err| {
setLastError(err);
return 0;
};
return packPtrLen(text.ptr, text.len);
}
export fn temporalz_instant_add(handle: u32, duration_handle: u32) u32 {
clearLastError();
const inst = getInstant(handle) catch |err| {
setLastError(err);
return 0;
};
var dur = getDuration(duration_handle) catch |err| {
setLastError(err);
return 0;
};
const res = inst.add(&dur) catch |err| {
setLastError(err);
return 0;
};
return addInstant(res);
}
export fn temporalz_instant_subtract(handle: u32, duration_handle: u32) u32 {
clearLastError();
const inst = getInstant(handle) catch |err| {
setLastError(err);
return 0;
};
var dur = getDuration(duration_handle) catch |err| {
setLastError(err);
return 0;
};
const res = inst.subtract(&dur) catch |err| {
setLastError(err);
return 0;
};
return addInstant(res);
}
export fn temporalz_instant_compare(handle_a: u32, handle_b: u32) i32 {
clearLastError();
const a = getInstant(handle_a) catch |err| {
setLastError(err);
return 0;
};
const b = getInstant(handle_b) catch |err| {
setLastError(err);
return 0;
};
return @intCast(Temporal.Instant.compare(a, b));
}
export fn temporalz_instant_equals(handle_a: u32, handle_b: u32) u8 {
clearLastError();
const a = getInstant(handle_a) catch |err| {
setLastError(err);
return 0;
};
const b = getInstant(handle_b) catch |err| {
setLastError(err);
return 0;
};
return if (Temporal.Instant.equals(a, b)) 1 else 0;
}
export fn temporalz_instant_round(
handle: u32,
smallest_unit: u8,
rounding_mode: u8,
rounding_increment: u32,
) u32 {
clearLastError();
const inst = getInstant(handle) catch |err| {
setLastError(err);
return 0;
};
var opts = Temporal.Instant.RoundingOptions{};
if (smallest_unit != 255) {
opts.smallest_unit = unitFromCode(smallest_unit) orelse {
setLastErrorMessage("Invalid smallestUnit");
return 0;
};
}
if (rounding_mode != 255) {
opts.rounding_mode = roundingModeFromCode(rounding_mode) orelse {
setLastErrorMessage("Invalid roundingMode");
return 0;
};
}
if (rounding_increment != 0) {
opts.rounding_increment = rounding_increment;
}
const res = inst.round(opts) catch |err| {
setLastError(err);
return 0;
};
return addInstant(res);
}
export fn temporalz_instant_destroy(handle: u32) void {
removeInstant(handle);
}
export fn temporalz_duration_from_utf8(ptr: [*]const u8, len: usize) u32 {
clearLastError();
const text = ptr[0..len];
const dur = Temporal.Duration.from(text) catch |err| {
setLastError(err);
return 0;
};
return addDuration(dur);
}
export fn temporalz_duration_from_parts(
mask: u32,
years: i64,
months: i64,
weeks: i64,
days: i64,
hours: i64,
minutes: i64,
seconds: i64,
milliseconds: i64,
microseconds: f64,
nanoseconds: f64,
) u32 {
clearLastError();
var partial = Temporal.Duration.PartialDuration{};
if ((mask & 0x1) != 0) partial.years = years;
if ((mask & 0x2) != 0) partial.months = months;
if ((mask & 0x4) != 0) partial.weeks = weeks;
if ((mask & 0x8) != 0) partial.days = days;
if ((mask & 0x10) != 0) partial.hours = hours;
if ((mask & 0x20) != 0) partial.minutes = minutes;
if ((mask & 0x40) != 0) partial.seconds = seconds;
if ((mask & 0x80) != 0) partial.milliseconds = milliseconds;
if ((mask & 0x100) != 0) partial.microseconds = microseconds;
if ((mask & 0x200) != 0) partial.nanoseconds = nanoseconds;
const dur = Temporal.Duration.from(partial) catch |err| {
setLastError(err);
return 0;
};
return addDuration(dur);
}
export fn temporalz_duration_init(
years: i64,
months: i64,
weeks: i64,
days: i64,
hours: i64,
minutes: i64,
seconds: i64,
milliseconds: i64,
microseconds: f64,
nanoseconds: f64,
) u32 {
clearLastError();
const dur = Temporal.Duration.init(
years,
months,
weeks,
days,
hours,
minutes,
seconds,
milliseconds,
microseconds,
nanoseconds,
) catch |err| {
setLastError(err);
return 0;
};
return addDuration(dur);
}
export fn temporalz_duration_to_string(handle: u32) u64 {
clearLastError();
const dur = getDuration(handle) catch |err| {
setLastError(err);
return 0;
};
const text = dur.toString(wasm_allocator, .{}) catch |err| {
setLastError(err);
return 0;
};
return packPtrLen(text.ptr, text.len);
}
export fn temporalz_duration_years(handle: u32) i64 {
clearLastError();
const dur = getDuration(handle) catch |err| {
setLastError(err);
return 0;
};
return dur.years();
}
export fn temporalz_duration_months(handle: u32) i64 {
clearLastError();
const dur = getDuration(handle) catch |err| {
setLastError(err);
return 0;
};
return dur.months();
}
export fn temporalz_duration_weeks(handle: u32) i64 {
clearLastError();
const dur = getDuration(handle) catch |err| {
setLastError(err);
return 0;
};
return dur.weeks();
}
export fn temporalz_duration_days(handle: u32) i64 {
clearLastError();
const dur = getDuration(handle) catch |err| {
setLastError(err);
return 0;
};
return dur.days();
}
export fn temporalz_duration_hours(handle: u32) i64 {
clearLastError();
const dur = getDuration(handle) catch |err| {
setLastError(err);
return 0;
};
return dur.hours();
}
export fn temporalz_duration_minutes(handle: u32) i64 {
clearLastError();
const dur = getDuration(handle) catch |err| {
setLastError(err);
return 0;
};
return dur.minutes();
}
export fn temporalz_duration_seconds(handle: u32) i64 {
clearLastError();
const dur = getDuration(handle) catch |err| {
setLastError(err);
return 0;
};
return dur.seconds();
}
export fn temporalz_duration_milliseconds(handle: u32) i64 {
clearLastError();
const dur = getDuration(handle) catch |err| {
setLastError(err);
return 0;
};
return dur.milliseconds();
}
export fn temporalz_duration_microseconds(handle: u32) f64 {
clearLastError();
const dur = getDuration(handle) catch |err| {
setLastError(err);
return 0;
};
return dur.microseconds();
}
export fn temporalz_duration_nanoseconds(handle: u32) f64 {
clearLastError();
const dur = getDuration(handle) catch |err| {
setLastError(err);
return 0;
};
return dur.nanoseconds();
}
export fn temporalz_duration_sign(handle: u32) i32 {
clearLastError();
const dur = getDuration(handle) catch |err| {
setLastError(err);
return 0;
};
return switch (dur.sign()) {
.positive => 1,
.zero => 0,
.negative => -1,
};
}
export fn temporalz_duration_blank(handle: u32) u8 {
clearLastError();
const dur = getDuration(handle) catch |err| {
setLastError(err);
return 0;
};
return if (dur.blank()) 1 else 0;
}
export fn temporalz_duration_abs(handle: u32) u32 {
clearLastError();
const dur = getDuration(handle) catch |err| {
setLastError(err);
return 0;
};
return addDuration(dur.abs());
}
export fn temporalz_duration_negated(handle: u32) u32 {
clearLastError();
const dur = getDuration(handle) catch |err| {
setLastError(err);
return 0;
};
return addDuration(dur.negated());
}
export fn temporalz_duration_add(handle_a: u32, handle_b: u32) u32 {
clearLastError();
const a = getDuration(handle_a) catch |err| {
setLastError(err);
return 0;
};
const b = getDuration(handle_b) catch |err| {
setLastError(err);
return 0;
};
const res = a.add(b) catch |err| {
setLastError(err);
return 0;
};
return addDuration(res);
}
export fn temporalz_duration_subtract(handle_a: u32, handle_b: u32) u32 {
clearLastError();
const a = getDuration(handle_a) catch |err| {
setLastError(err);
return 0;
};
const b = getDuration(handle_b) catch |err| {
setLastError(err);
return 0;
};
const res = a.subtract(b) catch |err| {
setLastError(err);
return 0;
};
return addDuration(res);
}
export fn temporalz_duration_compare(handle_a: u32, handle_b: u32) i32 {
clearLastError();
const a = getDuration(handle_a) catch |err| {
setLastError(err);
return 0;
};
const b = getDuration(handle_b) catch |err| {
setLastError(err);
return 0;
};
const res = a.compare(b, .{}) catch |err| {
setLastError(err);
return 0;
};
return @intCast(res);
}
export fn temporalz_duration_total(handle: u32, unit_code: u8) f64 {
clearLastError();
const unit = unitFromCode(unit_code) orelse {
setLastErrorMessage("Invalid unit");
return 0;
};
const dur = getDuration(handle) catch |err| {
setLastError(err);
return 0;
};
return dur.total(.{ .unit = unit }) catch |err| {
setLastError(err);
return 0;
};
}
export fn temporalz_duration_round(
handle: u32,
smallest_unit: u8,
largest_unit: u8,
rounding_mode: u8,
rounding_increment: u32,
) u32 {
clearLastError();
const dur = getDuration(handle) catch |err| {
setLastError(err);
return 0;
};
var opts = Temporal.Duration.RoundingOptions{};
if (smallest_unit != 255) {
opts.smallest_unit = unitFromCode(smallest_unit) orelse {
setLastErrorMessage("Invalid smallestUnit");
return 0;
};
}
if (largest_unit != 255) {
opts.largest_unit = unitFromCode(largest_unit) orelse {
setLastErrorMessage("Invalid largestUnit");
return 0;
};
}
if (rounding_mode != 255) {
opts.rounding_mode = roundingModeFromCode(rounding_mode) orelse {
setLastErrorMessage("Invalid roundingMode");
return 0;
};
}
if (rounding_increment != 0) {
opts.rounding_increment = rounding_increment;
}
const res = dur.round(opts) catch |err| {
setLastError(err);
return 0;
};
return addDuration(res);
}
export fn temporalz_duration_compare_plain_date(handle_a: u32, handle_b: u32, date_handle: u32) i32 {
clearLastError();
const a = getDuration(handle_a) catch |err| {
setLastError(err);
return 0;
};
const b = getDuration(handle_b) catch |err| {
setLastError(err);
return 0;
};
const date = getPlainDate(date_handle) catch |err| {
setLastError(err);
return 0;
};
const res = a.compare(b, .{ .relative_to = .{ .plain_date = date } }) catch |err| {
setLastError(err);
return 0;
};
return @intCast(res);
}
export fn temporalz_duration_total_plain_date(handle: u32, unit_code: u8, date_handle: u32) f64 {
clearLastError();
const unit = unitFromCode(unit_code) orelse {
setLastErrorMessage("Invalid unit");
return 0;
};
const dur = getDuration(handle) catch |err| {
setLastError(err);
return 0;
};
const date = getPlainDate(date_handle) catch |err| {
setLastError(err);
return 0;
};
return dur.total(.{ .unit = unit, .relative_to = .{ .plain_date = date } }) catch |err| {
setLastError(err);
return 0;
};
}
export fn temporalz_duration_round_plain_date(
handle: u32,
smallest_unit: u8,
largest_unit: u8,
rounding_mode: u8,
rounding_increment: u32,
date_handle: u32,
) u32 {
clearLastError();
const dur = getDuration(handle) catch |err| {
setLastError(err);
return 0;
};
const date = getPlainDate(date_handle) catch |err| {
setLastError(err);
return 0;
};
var opts = Temporal.Duration.RoundingOptions{};
if (smallest_unit != 255) {
opts.smallest_unit = unitFromCode(smallest_unit) orelse {
setLastErrorMessage("Invalid smallestUnit");
return 0;
};
}
if (largest_unit != 255) {
opts.largest_unit = unitFromCode(largest_unit) orelse {
setLastErrorMessage("Invalid largestUnit");
return 0;
};
}
if (rounding_mode != 255) {
opts.rounding_mode = roundingModeFromCode(rounding_mode) orelse {
setLastErrorMessage("Invalid roundingMode");
return 0;
};
}
if (rounding_increment != 0) {
opts.rounding_increment = rounding_increment;
}
opts.relative_to = .{ .plain_date = date };
const res = dur.round(opts) catch |err| {
setLastError(err);
return 0;
};
return addDuration(res);
}
export fn temporalz_plain_date_from_utf8(ptr: [*]const u8, len: usize) u32 {
clearLastError();
const text = ptr[0..len];
const date = Temporal.PlainDate.from(text) catch |err| {
setLastError(err);
return 0;
};
return addPlainDate(date);
}
export fn temporalz_plain_date_init(year: i32, month: u8, day: u8) u32 {
clearLastError();
const date = Temporal.PlainDate.init(year, month, day) catch |err| {
setLastError(err);
return 0;
};
return addPlainDate(date);
}
export fn temporalz_plain_date_to_string(handle: u32) u64 {
clearLastError();
const date = getPlainDate(handle) catch |err| {
setLastError(err);
return 0;
};
const text = date.toString(wasm_allocator, .{}) catch |err| {
setLastError(err);
return 0;
};
return packPtrLen(text.ptr, text.len);
}
export fn temporalz_plain_date_destroy(handle: u32) void {
removePlainDate(handle);
}
export fn temporalz_duration_destroy(handle: u32) void {
removeDuration(handle);
}
extern fn console(ptr: [*]u8, len: u32) void;
fn logFn(comptime _: anytype, comptime _: anytype, comptime format: []const u8, args: anytype) void {
const formatted = std.fmt.allocPrint(std.heap.wasm_allocator, format, args) catch return;
console(formatted.ptr, formatted.len);
}
pub const std_options: std.Options = .{ .logFn = logFn };

View file

@ -1,144 +0,0 @@
const std = @import("std");
const targets = @import("targets.zig");
pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const force_build_rust = b.option(bool, "build-rust", "Always build Rust library from source") orelse false;
const arch_str = @tagName(target.result.cpu.arch);
const os_str = @tagName(target.result.os.tag);
const abi = target.result.abi;
const target_triple = if (abi == .none)
b.fmt("{s}-{s}", .{ arch_str, os_str })
else
b.fmt("{s}-{s}-{s}", .{ arch_str, os_str, @tagName(abi) });
const prebuilt_name = targets.prebuiltName(b, target);
const lib_name = if (target.result.os.tag == .windows and abi == .msvc)
"temporal_capi.lib"
else
"libtemporal_capi.a";
// --- Module --- //
const is_freestanding = target.result.os.tag == .freestanding;
const mod = b.addModule("libtemporal", .{
.root_source_file = b.path("src/root.zig"),
.target = target,
.optimize = optimize,
.link_libc = !is_freestanding,
});
const temporal_rs = b.dependency("temporal_rs", .{
.target = target,
.optimize = optimize,
});
const translated = b.addTranslateC(.{
.root_source_file = b.path("src/lib.h"),
.target = target,
.optimize = optimize,
.link_libc = false,
});
translated.addIncludePath(temporal_rs.path("temporal_capi/bindings/c"));
translated.addIncludePath(b.path("src/stubs/c_headers"));
mod.addImport("lib", translated.createModule());
// --- Rust Misc Deps --- //
if (target.result.os.tag == .windows) mod.linkSystemLibrary("userenv", .{});
const unwind_stubs = b.addLibrary(.{ .linkage = .static, .name = "unwind_stubs", .root_module = b.createModule(.{
.root_source_file = b.path("src/stubs/unwind.zig"),
.target = target,
.optimize = optimize,
}) });
mod.linkLibrary(unwind_stubs);
// --- Steps: update prebuilt dependency hashes --- //
{
const update_step = b.step("update", "Fetch prebuilt packages and update build.zig.zon");
addPrebuiltDependencyFetches(b, update_step);
}
// --- Static lib resolution (prebuilt or source) --- //
var selected_lib_file: std.Build.LazyPath = undefined;
if (!force_build_rust and targets.isDeclared(prebuilt_name)) {
const prebuilt_dep = b.lazyDependency(prebuilt_name, .{}) orelse {
return;
};
// std.log.info("using prebuilt libtemporal for {s}", .{prebuilt_name});
selected_lib_file = prebuilt_dep.path(lib_name);
} else {
std.log.info("building libtemporal from source for {s}, requires Rust toolchain", .{target_triple});
const build_crab = @import("build_crab");
var zig_target = target.result;
if (zig_target.os.tag == .windows) zig_target.abi = .gnu;
const rust_target_str: []const u8 = if (zig_target.cpu.arch == .arm and zig_target.os.tag == .linux)
switch (zig_target.abi) {
.gnueabihf, .eabihf => "armv7-unknown-linux-gnueabihf",
.gnueabi, .eabi => "armv7-unknown-linux-gnueabi",
.musleabihf => "armv7-unknown-linux-musleabihf",
.musleabi => "armv7-unknown-linux-musleabi",
else => "armv7-unknown-linux-gnueabihf",
}
else blk: {
const rust_target = build_crab.rust.Target.fromZig(zig_target) catch
@panic("unable to convert target triple to Rust");
break :blk b.fmt("{f}", .{rust_target});
};
const build_dir = build_crab.addCargoBuild(
b,
.{
.manifest_path = b.path("Cargo.toml"),
.cargo_args = if (optimize == .Debug) &.{} else &.{"--release"},
.rust_target = .{ .value = rust_target_str },
},
.{
.optimize = .ReleaseSafe,
},
);
selected_lib_file = build_dir.path(b, lib_name);
}
mod.addObjectFile(selected_lib_file);
// --- Install Step (for publishing) --- //
const install_lib = b.addInstallFile(selected_lib_file, b.fmt("lib/{s}/{s}", .{ prebuilt_name, lib_name }));
b.getInstallStep().dependOn(&install_lib.step);
}
fn addPrebuiltDependencyFetches(b: *std.Build, parent: *std.Build.Step) void {
var prev_save: ?*std.Build.Step = null;
inline for (targets.config.targets) |target_triple| {
const url = targets.releaseUrl(b, target_triple);
const fetch = b.addSystemCommand(&.{ b.graph.zig_exe, "fetch", url });
fetch.setName(b.fmt("fetch {s}", .{target_triple}));
fetch.setCwd(b.path("."));
fetch.has_side_effects = true;
fetch.expectExitCode(0);
_ = fetch.captureStdErr(.{});
const save = b.addSystemCommand(&.{
b.graph.zig_exe,
"fetch",
b.fmt("--save={s}", .{target_triple}),
url,
});
save.setName(b.fmt("save {s}", .{target_triple}));
save.setCwd(b.path("."));
save.has_side_effects = true;
save.expectExitCode(0);
_ = save.captureStdErr(.{});
save.step.dependOn(&fetch.step);
if (prev_save) |prev| {
save.step.dependOn(prev);
}
parent.dependOn(&save.step);
prev_save = &save.step;
}
}

View file

@ -1,127 +0,0 @@
.{
.name = .libtemporal,
.version = "0.2.4",
.fingerprint = 0xded01f16f20c2a64,
.dependencies = .{
.temporal_rs = .{
.url = "git+https://github.com/boa-dev/temporal?ref=v0.2.4#a5cebbcce231552bf6ed985d7ea13b0c7b195f02",
.hash = "N-V-__8AALjnOQBiCk4NffYgEewZ5v9qlLlDyXO22FIyzNdf",
},
.build_crab = .{
.url = "git+https://github.com/nurulhudaapon/build.crab?ref=zig-dev#69a630f8fa9ccca37a8ba2e898e7934e3b5b8fe2",
.hash = "build_crab-0.2.1-U0id_zfKAAAvOuam-kPYKMuEQpHuEBjrP96uQCVj94yr",
},
.@"aarch64-ios" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/aarch64-ios.tar.gz",
.hash = "N-V-__8AAJAyaADZvWvrmaGR5reVCH4y8JZ3-Gfxu_9-pcHB",
.lazy = true,
},
.@"aarch64-linux-android" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/aarch64-linux-android.tar.gz",
.hash = "N-V-__8AAKYEkwCQonhHp5MAYaRE8IFcWN493Y2a5nqWJmF7",
.lazy = true,
},
.@"aarch64-linux-gnu" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/aarch64-linux-gnu.tar.gz",
.hash = "N-V-__8AAGSQjQDYfN0voDb4c1sCM374u570U8hcEJYoAoTc",
.lazy = true,
},
.@"aarch64-linux-musl" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/aarch64-linux-musl.tar.gz",
.hash = "N-V-__8AAE7bjwA2arkXXgbgaMe8oHdmJEez8y2XFeCUvSnn",
.lazy = true,
},
.@"aarch64-macos" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/aarch64-macos.tar.gz",
.hash = "N-V-__8AAFBxZwC9MEuiOD8EihBoSl_00IDUJnpQsjmnpkmK",
.lazy = true,
},
.@"aarch64-windows-gnu" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/aarch64-windows-gnu.tar.gz",
.hash = "N-V-__8AADKDagD1bmYDywq4IZPBo2la8m1xzSObPCsxyfmW",
.lazy = true,
},
.@"arm-linux-gnueabihf" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/arm-linux-gnueabihf.tar.gz",
.hash = "N-V-__8AAIAAfgDYWro4rWudgosfdPK1tzxLe77uoRBtL4rl",
.lazy = true,
},
.@"loongarch64-linux-gnu" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/loongarch64-linux-gnu.tar.gz",
.hash = "N-V-__8AAEKptADVBZFKw7ZKvLurwzp_WA-FD-OwZFgEMf4q",
.lazy = true,
},
.@"powerpc64le-linux-gnu" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/powerpc64le-linux-gnu.tar.gz",
.hash = "N-V-__8AAKwdfQDZIHVuhOtUOs9tKx-RJCM_1HnX-FwGA0l2",
.lazy = true,
},
.@"riscv64-linux-gnu" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/riscv64-linux-gnu.tar.gz",
.hash = "N-V-__8AAPBiogBQe_5VZhzDgpZrfwuzfj_54IyUFK2igsQo",
.lazy = true,
},
.@"s390x-linux-gnu" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/s390x-linux-gnu.tar.gz",
.hash = "N-V-__8AAEiKkwC4qkNJoOuzgxHuS_q46SIbqITuODu9Hz3Q",
.lazy = true,
},
.@"wasm32-freestanding" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/wasm32-freestanding.tar.gz",
.hash = "N-V-__8AACjsTwB3jX1mva0svtTn39kCz5aabikQbczLJlp9",
.lazy = true,
},
.@"wasm32-wasi" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/wasm32-wasi.tar.gz",
.hash = "N-V-__8AAPbTQADoTDaLXmk3KlebN5pZWX-eXhD6BLPJuxpt",
.lazy = true,
},
.@"x86-linux-gnu" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/x86-linux-gnu.tar.gz",
.hash = "N-V-__8AALzUbwBdOV8TmU7vPbofrSgkCz70GG0SwvHZGWEZ",
.lazy = true,
},
.@"x86-windows-gnu" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/x86-windows-gnu.tar.gz",
.hash = "N-V-__8AAAgSYQAjy_QNLkxQurUPnbT8s4fNjunaYgPQjiwB",
.lazy = true,
},
.@"x86_64-freebsd" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/x86_64-freebsd.tar.gz",
.hash = "N-V-__8AAJAFkQCAz3khARx91vZb6HMPqV3oBdmJM8kaxd9Y",
.lazy = true,
},
.@"x86_64-linux-gnu" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/x86_64-linux-gnu.tar.gz",
.hash = "N-V-__8AACAdiQB3WUysJXS42gsJZdpzna_04l6omEQGzJZa",
.lazy = true,
},
.@"x86_64-linux-musl" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/x86_64-linux-musl.tar.gz",
.hash = "N-V-__8AAGhKiwDlW7Ecy5CJf7-PEGSdDgr4VnCNLkl9cery",
.lazy = true,
},
.@"x86_64-macos" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/x86_64-macos.tar.gz",
.hash = "N-V-__8AAHDyZwCPo6HVOYeFWas2bcTqi67vJuxoL2huROlC",
.lazy = true,
},
.@"x86_64-netbsd" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/x86_64-netbsd.tar.gz",
.hash = "N-V-__8AAL7_lgBmD0lfXqzAxRdjDiPLi6bgLvnVVbQszw3p",
.lazy = true,
},
.@"x86_64-windows-gnu" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/x86_64-windows-gnu.tar.gz",
.hash = "N-V-__8AAD5eTQDfQ9ddNZh3g8e6SaA9CnVSQRMozhHs_jWt",
.lazy = true,
},
},
.paths = .{
"build.zig",
"build.zig.zon",
"targets.zon",
"targets.zig",
"src",
},
}

View file

@ -1,18 +0,0 @@
#include "AnyCalendarKind.h"
#include "Calendar.h"
#include "Duration.h"
#include "ErrorKind.h"
#include "I128Nanoseconds.h"
#include "Instant.h"
#include "OwnedRelativeTo.h"
#include "ParsedDate.h"
#include "ParsedDateTime.h"
#include "ParsedZonedDateTime.h"
#include "PlainDate.h"
#include "PlainDateTime.h"
#include "PlainMonthDay.h"
#include "PlainTime.h"
#include "PlainYearMonth.h"
#include "RelativeTo.h"
#include "TimeZone.h"
#include "ZonedDateTime.h"

View file

@ -1 +0,0 @@
pub const c = @import("lib");

View file

@ -1,57 +0,0 @@
const std = @import("std");
const builtin = @import("builtin");
pub const config = @import("targets.zon");
const manifest = @import("build.zig.zon");
/// Zig `-Dtarget` triple for the host platform's prebuilt dependency name.
pub fn depName() []const u8 {
const triple = targetTripleFromBuiltin();
if (!isDeclared(triple)) {
@compileError(std.fmt.comptimePrint(
"no prebuilt libtemporal for host {s}",
.{triple},
));
}
return triple;
}
pub fn prebuiltName(b: *std.Build, target: std.Build.ResolvedTarget) []const u8 {
const arch = @tagName(target.result.cpu.arch);
const os = target.result.os.tag;
const abi = target.result.abi;
if (os == .wasi and (abi == .musl or abi == .none))
return b.fmt("{s}-wasi", .{arch});
if (abi == .none)
return b.fmt("{s}-{s}", .{ arch, @tagName(os) });
return b.fmt("{s}-{s}-{s}", .{ arch, @tagName(os), @tagName(abi) });
}
pub fn isDeclared(target_triple: []const u8) bool {
inline for (config.targets) |supported| {
if (std.mem.eql(u8, supported, target_triple)) {
return comptime @hasField(@TypeOf(manifest.dependencies), supported);
}
}
return false;
}
pub fn releaseUrl(b: *std.Build, target_triple: []const u8) []const u8 {
return b.fmt(
"https://github.com/nurulhudaapon/temporalz/releases/download/v{s}/{s}.tar.gz",
.{ config.version, target_triple },
);
}
fn targetTripleFromBuiltin() []const u8 {
if (builtin.os.tag == .wasi and (builtin.abi == .musl or builtin.abi == .none))
return std.fmt.comptimePrint("{s}-wasi", .{@tagName(builtin.cpu.arch)});
const abi = builtin.abi;
return if (abi == .none)
std.fmt.comptimePrint("{s}-{s}", .{ @tagName(builtin.cpu.arch), @tagName(builtin.os.tag) })
else
std.fmt.comptimePrint("{s}-{s}-{s}", .{ @tagName(builtin.cpu.arch), @tagName(builtin.os.tag), @tagName(abi) });
}

View file

@ -1,26 +0,0 @@
.{
.version = "0.2.4",
.targets = .{
"x86_64-macos",
"aarch64-macos",
"x86_64-linux-gnu",
"aarch64-linux-gnu",
"x86-linux-gnu",
"arm-linux-gnueabihf",
"loongarch64-linux-gnu",
"powerpc64le-linux-gnu",
"riscv64-linux-gnu",
"s390x-linux-gnu",
"x86_64-windows-gnu",
"aarch64-windows-gnu",
"x86-windows-gnu",
"x86_64-freebsd",
"x86_64-netbsd",
"wasm32-freestanding",
"wasm32-wasi",
"x86_64-linux-musl",
"aarch64-linux-musl",
"aarch64-linux-android",
"aarch64-ios",
},
}

View file

@ -16,9 +16,9 @@ checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3"
[[package]] [[package]]
name = "calendrical_calculations" name = "calendrical_calculations"
version = "0.2.4" version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5abbd6eeda6885048d357edc66748eea6e0268e3dd11f326fff5bd248d779c26" checksum = "3a0b39595c6ee54a8d0900204ba4c401d0ab4eb45adaf07178e8d017541529e7"
dependencies = [ dependencies = [
"core_maths", "core_maths",
"displaydoc", "displaydoc",
@ -45,9 +45,9 @@ dependencies = [
[[package]] [[package]]
name = "diplomat" name = "diplomat"
version = "0.15.0" version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7935649d00000f5c5d735448ad3dc07b9738160727017914cf42138b8e8e6611" checksum = "9adb46b05e2f53dcf6a7dfc242e4ce9eb60c369b6b6eb10826a01e93167f59c6"
dependencies = [ dependencies = [
"diplomat_core", "diplomat_core",
"proc-macro2", "proc-macro2",
@ -57,15 +57,15 @@ dependencies = [
[[package]] [[package]]
name = "diplomat-runtime" name = "diplomat-runtime"
version = "0.15.1" version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "970ac38ad677632efcee6d517e783958da9bc78ec206d8d5e35b459ffc5e4864" checksum = "0569bd3caaf13829da7ee4e83dbf9197a0e1ecd72772da6d08f0b4c9285c8d29"
[[package]] [[package]]
name = "diplomat_core" name = "diplomat_core"
version = "0.15.0" version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cf41b94101a4bce993febaf0098092b0bb31deaf0ecaf6e0a2562465f61b383" checksum = "51731530ed7f2d4495019abc7df3744f53338e69e2863a6a64ae91821c763df1"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -88,9 +88,9 @@ dependencies = [
[[package]] [[package]]
name = "icu_calendar" name = "icu_calendar"
version = "2.2.1" version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2b2acc6263f494f1df50685b53ff8e57869e47d5c6fe39c23d518ae9a4f3e45" checksum = "d6f0e52e009b6b16ba9c0693578796f2dd4aaa59a7f8f920423706714a89ac4e"
dependencies = [ dependencies = [
"calendrical_calculations", "calendrical_calculations",
"displaydoc", "displaydoc",
@ -104,19 +104,18 @@ dependencies = [
[[package]] [[package]]
name = "icu_calendar_data" name = "icu_calendar_data"
version = "2.2.0" version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "118577bcf3a0fa7c6ac0a7d6e951814da84ee56b9b1f68fb4d8d10b08cefaf4d" checksum = "527f04223b17edfe0bd43baf14a0cb1b017830db65f3950dc00224860a9a446d"
[[package]] [[package]]
name = "icu_collections" name = "icu_collections"
version = "2.2.0" version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43"
dependencies = [ dependencies = [
"displaydoc", "displaydoc",
"potential_utf", "potential_utf",
"utf8_iter",
"yoke", "yoke",
"zerofrom", "zerofrom",
"zerovec", "zerovec",
@ -124,9 +123,9 @@ dependencies = [
[[package]] [[package]]
name = "icu_locale" name = "icu_locale"
version = "2.2.0" version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5a396343c7208121dc86e35623d3dfe19814a7613cfd14964994cdc9c9a2e26" checksum = "532b11722e350ab6bf916ba6eb0efe3ee54b932666afec989465f9243fe6dd60"
dependencies = [ dependencies = [
"icu_collections", "icu_collections",
"icu_locale_core", "icu_locale_core",
@ -139,9 +138,9 @@ dependencies = [
[[package]] [[package]]
name = "icu_locale_core" name = "icu_locale_core"
version = "2.2.0" version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6"
dependencies = [ dependencies = [
"displaydoc", "displaydoc",
"litemap", "litemap",
@ -153,15 +152,15 @@ dependencies = [
[[package]] [[package]]
name = "icu_locale_data" name = "icu_locale_data"
version = "2.2.0" version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5fdcc9ac77c6d74ff5cf6e65ef3181d6af32003b16fce3a77fb451d2f695993" checksum = "1c5f1d16b4c3a2642d3a719f18f6b06070ab0aef246a6418130c955ae08aa831"
[[package]] [[package]]
name = "icu_provider" name = "icu_provider"
version = "2.2.0" version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614"
dependencies = [ dependencies = [
"displaydoc", "displaydoc",
"icu_locale_core", "icu_locale_core",
@ -317,22 +316,22 @@ dependencies = [
[[package]] [[package]]
name = "temporal_capi" name = "temporal_capi"
version = "0.2.3" version = "0.2.0"
dependencies = [ dependencies = [
"temporal_capi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "temporal_capi 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"temporal_rs", "temporal_rs",
] ]
[[package]] [[package]]
name = "temporal_capi" name = "temporal_capi"
version = "0.2.3" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a2a1f001e756a9f5f2d175a9965c4c0b3a054f09f30de3a75ab49765f2deb36" checksum = "64a85237ba1a9512ac9217a71fdbeed3295bb97e72aa0e3cd005d42dc92eeb55"
dependencies = [ dependencies = [
"diplomat", "diplomat",
"diplomat-runtime", "diplomat-runtime",
"icu_calendar", "icu_calendar",
"icu_locale_core", "icu_locale",
"num-traits", "num-traits",
"temporal_rs", "temporal_rs",
"timezone_provider", "timezone_provider",
@ -341,14 +340,13 @@ dependencies = [
[[package]] [[package]]
name = "temporal_rs" name = "temporal_rs"
version = "0.2.3" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a902a45282e5175186b21d355efc92564601efe6e2d92818dc9e333d50bd4de" checksum = "654b89203889c8b90b96d275d1296c56df5f0ffee127213730c1b9895b69b33e"
dependencies = [ dependencies = [
"calendrical_calculations",
"core_maths", "core_maths",
"icu_calendar", "icu_calendar",
"icu_locale_core", "icu_locale",
"ixdtf", "ixdtf",
"num-traits", "num-traits",
"timezone_provider", "timezone_provider",
@ -358,9 +356,9 @@ dependencies = [
[[package]] [[package]]
name = "timezone_provider" name = "timezone_provider"
version = "0.2.3" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c48f9b04628a2b813051e4dfe97c65281e49625eabd09ec343190e31e399a8c2" checksum = "838a6ce9f08d07a637682a7dda441b97dc34e4aaf0dbfd9ca3d7eaf6fe1e8495"
dependencies = [ dependencies = [
"combine", "combine",
"jiff-tzdb", "jiff-tzdb",
@ -372,9 +370,9 @@ dependencies = [
[[package]] [[package]]
name = "tinystr" name = "tinystr"
version = "0.8.3" version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869"
dependencies = [ dependencies = [
"displaydoc", "displaydoc",
"serde_core", "serde_core",
@ -396,12 +394,6 @@ version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
[[package]]
name = "utf8_iter"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]] [[package]]
name = "writeable" name = "writeable"
version = "0.6.2" version = "0.6.2"
@ -410,9 +402,9 @@ checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9"
[[package]] [[package]]
name = "yoke" name = "yoke"
version = "0.8.2" version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954"
dependencies = [ dependencies = [
"stable_deref_trait", "stable_deref_trait",
"yoke-derive", "yoke-derive",
@ -421,9 +413,9 @@ dependencies = [
[[package]] [[package]]
name = "yoke-derive" name = "yoke-derive"
version = "0.8.2" version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -454,19 +446,18 @@ dependencies = [
[[package]] [[package]]
name = "zerotrie" name = "zerotrie"
version = "0.2.4" version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851"
dependencies = [ dependencies = [
"displaydoc", "displaydoc",
"zerovec",
] ]
[[package]] [[package]]
name = "zerovec" name = "zerovec"
version = "0.11.6" version = "0.11.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002"
dependencies = [ dependencies = [
"serde", "serde",
"yoke", "yoke",
@ -476,9 +467,9 @@ dependencies = [
[[package]] [[package]]
name = "zerovec-derive" name = "zerovec-derive"
version = "0.11.3" version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View file

@ -1,15 +1,15 @@
[package] [package]
name = "temporal_capi" name = "temporal_capi"
version = "0.2.3" version = "0.2.0"
edition = "2024" edition = "2024"
[dependencies.temporal_capi] [dependencies.temporal_capi]
version = "0.2.3" version = "0.2.0"
default-features = false default-features = false
features = ["compiled_data"] features = ["compiled_data"]
[dependencies.temporal_rs] [dependencies.temporal_rs]
version = "0.2.3" version = "0.2.0"
default-features = false default-features = false
features = ["float64_representable_durations"] features = ["float64_representable_durations"]

89
pkg/temporal/build.zig Normal file
View file

@ -0,0 +1,89 @@
const std = @import("std");
pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const force_build_rust = b.option(bool, "build-rust", "Always build Rust library from source") orelse false;
const arch_str = @tagName(target.result.cpu.arch);
const os_str = @tagName(target.result.os.tag);
const abi = target.result.abi;
const target_triple = if (abi == .none)
b.fmt("{s}-{s}", .{ arch_str, os_str })
else
b.fmt("{s}-{s}-{s}", .{ arch_str, os_str, @tagName(abi) });
const lib_name = if (target.result.os.tag == .windows and abi == .msvc)
"temporal_capi.lib"
else
"libtemporal_capi.a";
const prebuilt_lib_path = b.fmt("{s}/{s}", .{ target_triple, lib_name });
// --- Pre-built resolution --- //
var prebuilt_lib_file: ?std.Build.LazyPath = null;
var selected_lib_file: std.Build.LazyPath = undefined;
if (!force_build_rust) {
const libtemporal_dep = b.lazyDependency("libtemporal", .{});
if (libtemporal_dep) |dep| {
const lib_file_candidate = dep.path(prebuilt_lib_path);
const lib_full_path = lib_file_candidate.getPath(b);
if (std.Io.Dir.cwd().openFile(b.graph.io, lib_full_path, .{})) |lib_check_file| {
lib_check_file.close(b.graph.io);
prebuilt_lib_file = lib_file_candidate;
} else |_| {}
}
}
if (prebuilt_lib_file) |plf| {
// std.debug.print("Using pre-built temporal_capi library from downloaded artifact at: {s}\n", .{prebuilt_lib_path});
selected_lib_file = plf;
} else {
// std.debug.print("building from source: {s}\n", .{prebuilt_lib_path});
const build_crab = @import("build_crab");
const build_dir = build_crab.addCargoBuild(
b,
.{
.manifest_path = b.path("Cargo.toml"),
.cargo_args = if (optimize == .Debug) &.{} else &.{"--release"},
},
.{
.target = target,
.optimize = .ReleaseSafe,
},
);
selected_lib_file = build_dir.path(b, lib_name);
}
// --- Install Step (for publishing) --- //
const install_lib = b.addInstallFile(selected_lib_file, b.fmt("lib/{s}/{s}", .{ target_triple, lib_name }));
b.getInstallStep().dependOn(&install_lib.step);
// --- Zig Module --- //
const mod = b.addModule("temporal_rs", .{
.root_source_file = b.path("src/root.zig"),
.target = target,
.optimize = optimize,
});
// Add Headers
const temporal_rs_git = b.dependency("temporal_rs", .{
.target = target,
.optimize = optimize,
});
mod.addIncludePath(temporal_rs_git.path("temporal_capi/bindings/c"));
mod.addIncludePath(b.path("src/stubs/c_headers"));
// Add Object/Library
mod.addObjectFile(selected_lib_file);
// --- Rust Misc Deps --- //
if (target.result.os.tag == .windows) mod.linkSystemLibrary("userenv", .{});
const unwind_stubs = b.addLibrary(.{ .linkage = .static, .name = "unwind_stubs", .root_module = b.createModule(.{
.root_source_file = b.path("src/stubs/unwind.zig"),
.target = target,
.optimize = optimize,
}) });
mod.linkLibrary(unwind_stubs);
}

View file

@ -0,0 +1,26 @@
.{
.name = .temporal,
.version = "0.2.0",
.fingerprint = 0xd5dcf3f41df6b117,
.minimum_zig_version = "0.16.0-dev.2565+684032671",
.dependencies = .{
.temporal_rs = .{
.url = "git+https://github.com/boa-dev/temporal?ref=v0.2.0#ad01ef6f6147345f35a6614bf942a83af14098dd",
.hash = "N-V-__8AAN1tOQBrOGLjyyZop7RoeAqcozA7dKIZKD30hcom",
},
.libtemporal = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.0/libtemporal.tar.gz",
.hash = "N-V-__8AAHgP2AWLC4ZLTr_3hWf6xtgtBI5moBrWDWg5kzSD",
.lazy = true,
},
.build_crab = .{
.url = "git+https://github.com/nurulhudaapon/build.crab?ref=zig-dev#1aabc836472d318e9756a43b17853aadc4599800",
.hash = "build_crab-0.2.1-U0id_2LFAABPaq1t9eBZ3p0aA87c-HkKZPYCrCVcgvt6",
},
},
.paths = .{
"build.zig",
"build.zig.zon",
"src",
},
}

20
pkg/temporal/src/root.zig Normal file
View file

@ -0,0 +1,20 @@
pub const c = @cImport({
@cInclude("AnyCalendarKind.h");
@cInclude("Calendar.h");
@cInclude("Duration.h");
@cInclude("ErrorKind.h");
@cInclude("I128Nanoseconds.h");
@cInclude("Instant.h");
@cInclude("OwnedRelativeTo.h");
@cInclude("ParsedDate.h");
@cInclude("ParsedDateTime.h");
@cInclude("ParsedZonedDateTime.h");
@cInclude("PlainDate.h");
@cInclude("PlainDateTime.h");
@cInclude("PlainMonthDay.h");
@cInclude("PlainTime.h");
@cInclude("PlainYearMonth.h");
@cInclude("RelativeTo.h");
@cInclude("TimeZone.h");
@cInclude("ZonedDateTime.h");
});

View file

@ -8,8 +8,7 @@ const ZonedDateTime = @import("ZonedDateTime.zig");
/// The `Temporal.Duration` object represents a difference between two time points, which can be used in date/time arithmetic. /// The `Temporal.Duration` object represents a difference between two time points, which can be used in date/time arithmetic.
/// It is fundamentally represented as a combination of years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, and nanoseconds values. /// It is fundamentally represented as a combination of years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, and nanoseconds values.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration
/// See: [Temporal.Duration](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration)
const Duration = @This(); const Duration = @This();
_inner: *abi.c.Duration, _inner: *abi.c.Duration,
@ -41,8 +40,7 @@ pub const RoundingOptions = struct {
/// Partial duration specification for creating Duration objects. /// Partial duration specification for creating Duration objects.
/// This is a wrapper around the C API type to avoid exposing C types directly. /// This is a wrapper around the C API type to avoid exposing C types directly.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/from
/// See: [Temporal.Duration.from](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/from)
pub const PartialDuration = struct { pub const PartialDuration = struct {
years: ?i64 = null, years: ?i64 = null,
months: ?i64 = null, months: ?i64 = null,
@ -57,8 +55,7 @@ pub const PartialDuration = struct {
}; };
/// Relative-to context for duration operations, used for balancing and calendar-aware math. /// Relative-to context for duration operations, used for balancing and calendar-aware math.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration#calendar_durations
/// See: [Temporal.Duration#calendar_durations](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration#calendar_durations)
pub const RelativeTo = union(enum) { pub const RelativeTo = union(enum) {
plain_date: PlainDate, plain_date: PlainDate,
plain_date_time: PlainDateTime, plain_date_time: PlainDateTime,
@ -81,8 +78,7 @@ pub const CompareOptions = struct {
/// Construct a Duration from years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, and nanoseconds. /// Construct a Duration from years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, and nanoseconds.
/// Equivalent to `Temporal.Duration()` constructor. /// Equivalent to `Temporal.Duration()` constructor.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/Duration
/// See: [Temporal.Duration](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/Duration)
pub fn init( pub fn init(
years_val: i64, years_val: i64,
months_val: i64, months_val: i64,
@ -168,122 +164,105 @@ fn isTimeWithinRange(self: Duration) bool {
} }
/// Returns the number of years in the duration. /// Returns the number of years in the duration.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/years
/// See: [Temporal.Duration.years](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/years)
pub fn years(self: Duration) i64 { pub fn years(self: Duration) i64 {
return abi.c.temporal_rs_Duration_years(self._inner); return abi.c.temporal_rs_Duration_years(self._inner);
} }
/// Returns the number of months in the duration. /// Returns the number of months in the duration.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/months
/// See: [Temporal.Duration.months](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/months)
pub fn months(self: Duration) i64 { pub fn months(self: Duration) i64 {
return abi.c.temporal_rs_Duration_months(self._inner); return abi.c.temporal_rs_Duration_months(self._inner);
} }
/// Returns the number of weeks in the duration. /// Returns the number of weeks in the duration.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/weeks
/// See: [Temporal.Duration.weeks](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/weeks)
pub fn weeks(self: Duration) i64 { pub fn weeks(self: Duration) i64 {
return abi.c.temporal_rs_Duration_weeks(self._inner); return abi.c.temporal_rs_Duration_weeks(self._inner);
} }
/// Returns the number of days in the duration. /// Returns the number of days in the duration.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/days
/// See: [Temporal.Duration.days](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/days)
pub fn days(self: Duration) i64 { pub fn days(self: Duration) i64 {
return abi.c.temporal_rs_Duration_days(self._inner); return abi.c.temporal_rs_Duration_days(self._inner);
} }
/// Returns the number of hours in the duration. /// Returns the number of hours in the duration.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/hours
/// See: [Temporal.Duration.hours](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/hours)
pub fn hours(self: Duration) i64 { pub fn hours(self: Duration) i64 {
return abi.c.temporal_rs_Duration_hours(self._inner); return abi.c.temporal_rs_Duration_hours(self._inner);
} }
/// Returns the number of minutes in the duration. /// Returns the number of minutes in the duration.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/minutes
/// See: [Temporal.Duration.minutes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/minutes)
pub fn minutes(self: Duration) i64 { pub fn minutes(self: Duration) i64 {
return abi.c.temporal_rs_Duration_minutes(self._inner); return abi.c.temporal_rs_Duration_minutes(self._inner);
} }
/// Returns the number of seconds in the duration. /// Returns the number of seconds in the duration.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/seconds
/// See: [Temporal.Duration.seconds](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/seconds)
pub fn seconds(self: Duration) i64 { pub fn seconds(self: Duration) i64 {
return abi.c.temporal_rs_Duration_seconds(self._inner); return abi.c.temporal_rs_Duration_seconds(self._inner);
} }
/// Returns the number of milliseconds in the duration. /// Returns the number of milliseconds in the duration.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/milliseconds
/// See: [Temporal.Duration.milliseconds](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/milliseconds)
pub fn milliseconds(self: Duration) i64 { pub fn milliseconds(self: Duration) i64 {
return abi.c.temporal_rs_Duration_milliseconds(self._inner); return abi.c.temporal_rs_Duration_milliseconds(self._inner);
} }
/// Returns the number of microseconds in the duration. /// Returns the number of microseconds in the duration.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/microseconds
/// See: [Temporal.Duration.microseconds](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/microseconds)
pub fn microseconds(self: Duration) f64 { pub fn microseconds(self: Duration) f64 {
return abi.c.temporal_rs_Duration_microseconds(self._inner); return abi.c.temporal_rs_Duration_microseconds(self._inner);
} }
/// Returns the number of nanoseconds in the duration. /// Returns the number of nanoseconds in the duration.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/nanoseconds
/// See: [Temporal.Duration.nanoseconds](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/nanoseconds)
pub fn nanoseconds(self: Duration) f64 { pub fn nanoseconds(self: Duration) f64 {
return abi.c.temporal_rs_Duration_nanoseconds(self._inner); return abi.c.temporal_rs_Duration_nanoseconds(self._inner);
} }
/// Returns the sign of the duration: positive (1), zero (0), or negative (-1). /// Returns the sign of the duration: positive (1), zero (0), or negative (-1).
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/sign
/// See: [Temporal.Duration.sign](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/sign)
pub fn sign(self: Duration) Sign { pub fn sign(self: Duration) Sign {
return abi.from.sign(abi.c.temporal_rs_Duration_sign(self._inner)); return abi.from.sign(abi.c.temporal_rs_Duration_sign(self._inner));
} }
/// Returns true if the duration is zero (all fields are zero), false otherwise. /// Returns true if the duration is zero (all fields are zero), false otherwise.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/blank
/// See: [Temporal.Duration.blank](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/blank)
pub fn blank(self: Duration) bool { pub fn blank(self: Duration) bool {
return abi.c.temporal_rs_Duration_is_zero(self._inner); return abi.c.temporal_rs_Duration_is_zero(self._inner);
} }
/// Returns a new Duration with the absolute value (all components positive). /// Returns a new Duration with the absolute value (all components positive).
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/abs
/// See: [Temporal.Duration.abs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/abs)
pub fn abs(self: Duration) Duration { pub fn abs(self: Duration) Duration {
const ptr: *abi.c.Duration = abi.c.temporal_rs_Duration_abs(self._inner) orelse unreachable; const ptr: *abi.c.Duration = abi.c.temporal_rs_Duration_abs(self._inner) orelse unreachable;
return .{ ._inner = ptr }; return .{ ._inner = ptr };
} }
/// Returns a new Duration with all components negated (sign reversed). /// Returns a new Duration with all components negated (sign reversed).
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/negated
/// See: [Temporal.Duration.negated](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/negated)
pub fn negated(self: Duration) Duration { pub fn negated(self: Duration) Duration {
const ptr: *abi.c.Duration = abi.c.temporal_rs_Duration_negated(self._inner) orelse unreachable; const ptr: *abi.c.Duration = abi.c.temporal_rs_Duration_negated(self._inner) orelse unreachable;
return .{ ._inner = ptr }; return .{ ._inner = ptr };
} }
/// Returns a new Duration with the sum of this duration and another (balanced as needed). /// Returns a new Duration with the sum of this duration and another (balanced as needed).
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/add
/// See: [Temporal.Duration.add](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/add)
pub fn add(self: Duration, other: Duration) !Duration { pub fn add(self: Duration, other: Duration) !Duration {
return wrapDuration(abi.c.temporal_rs_Duration_add(self._inner, other._inner)); return wrapDuration(abi.c.temporal_rs_Duration_add(self._inner, other._inner));
} }
/// Returns a new Duration with the difference between this duration and another (balanced as needed). /// Returns a new Duration with the difference between this duration and another (balanced as needed).
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/subtract
/// See: [Temporal.Duration.subtract](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/subtract)
pub fn subtract(self: Duration, other: Duration) !Duration { pub fn subtract(self: Duration, other: Duration) !Duration {
return wrapDuration(abi.c.temporal_rs_Duration_subtract(self._inner, other._inner)); return wrapDuration(abi.c.temporal_rs_Duration_subtract(self._inner, other._inner));
} }
/// Returns a new Duration rounded to the given smallest/largest unit and/or balanced. /// Returns a new Duration rounded to the given smallest/largest unit and/or balanced.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/round
/// See: [Temporal.Duration.round](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/round)
pub fn round(self: Duration, options: RoundingOptions) !Duration { pub fn round(self: Duration, options: RoundingOptions) !Duration {
const rel = if (options.relative_to) |r| abi.to.durRelativeTo(r) else abi.c.RelativeTo{ .date = null, .zoned = null }; const rel = if (options.relative_to) |r| abi.to.durRelativeTo(r) else abi.c.RelativeTo{ .date = null, .zoned = null };
return wrapDuration(abi.c.temporal_rs_Duration_round(self._inner, abi.to.durRoundingOpts(options), rel)); return wrapDuration(abi.c.temporal_rs_Duration_round(self._inner, abi.to.durRoundingOpts(options), rel));
@ -295,8 +274,7 @@ fn roundWithProvider(self: Duration, options: RoundingOptions, relative_to: Rela
} }
/// Compares two durations, returning -1, 0, or 1 if this duration is shorter, equal, or longer than the other. /// Compares two durations, returning -1, 0, or 1 if this duration is shorter, equal, or longer than the other.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/compare
/// See: [Temporal.Duration.compare](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/compare)
pub fn compare(self: Duration, other: Duration, options: CompareOptions) !i8 { pub fn compare(self: Duration, other: Duration, options: CompareOptions) !i8 {
const rel = if (options.relative_to) |r| abi.to.durRelativeTo(r) else abi.c.RelativeTo{ .date = null, .zoned = null }; const rel = if (options.relative_to) |r| abi.to.durRelativeTo(r) else abi.c.RelativeTo{ .date = null, .zoned = null };
const res = abi.c.temporal_rs_Duration_compare(self._inner, other._inner, rel); const res = abi.c.temporal_rs_Duration_compare(self._inner, other._inner, rel);
@ -310,8 +288,7 @@ fn compareWithProvider(self: Duration, other: Duration, relative_to: RelativeTo,
} }
/// Returns the total value of the duration in the specified unit. /// Returns the total value of the duration in the specified unit.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/total
/// See: [Temporal.Duration.total](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/total)
pub fn total(self: Duration, options: TotalOptions) !f64 { pub fn total(self: Duration, options: TotalOptions) !f64 {
const rel = if (options.relative_to) |r| abi.to.durRelativeTo(r) else abi.c.RelativeTo{ .date = null, .zoned = null }; const rel = if (options.relative_to) |r| abi.to.durRelativeTo(r) else abi.c.RelativeTo{ .date = null, .zoned = null };
const res = abi.c.temporal_rs_Duration_total(self._inner, abi.to.unit(options.unit).?, rel); const res = abi.c.temporal_rs_Duration_total(self._inner, abi.to.unit(options.unit).?, rel);
@ -326,8 +303,7 @@ fn totalWithProvider(self: Duration, options: TotalOptions, provider: *const abi
} }
/// Returns a string representing this duration in the ISO 8601 format. /// Returns a string representing this duration in the ISO 8601 format.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/toString
/// See: [Temporal.Duration.toString](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/toString)
pub fn toString(self: Duration, allocator: std.mem.Allocator, options: ToStringRoundingOptions) ![]u8 { pub fn toString(self: Duration, allocator: std.mem.Allocator, options: ToStringRoundingOptions) ![]u8 {
var write = abi.DiplomatWrite.init(allocator); var write = abi.DiplomatWrite.init(allocator);
defer write.deinit(); defer write.deinit();
@ -339,16 +315,13 @@ pub fn toString(self: Duration, allocator: std.mem.Allocator, options: ToStringR
} }
/// Returns a string representing this duration in the ISO 8601 format (same as toString). Intended for JSON serialization. /// Returns a string representing this duration in the ISO 8601 format (same as toString). Intended for JSON serialization.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/toJSON
/// See: [Temporal.Duration.toJSON](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/toJSON)
pub fn toJSON(self: Duration, allocator: std.mem.Allocator) ![]u8 { pub fn toJSON(self: Duration, allocator: std.mem.Allocator) ![]u8 {
return self.toString(allocator, .{}); return self.toString(allocator, .{});
} }
/// Returns a string with a language-sensitive representation of this duration. /// Returns a string with a language-sensitive representation of this duration. Not implemented.
/// Not implemented. /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/toLocaleString
///
/// See: [Temporal.Duration.toLocaleString](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/toLocaleString)
pub fn toLocaleString(self: Duration, allocator: std.mem.Allocator) ![]u8 { pub fn toLocaleString(self: Duration, allocator: std.mem.Allocator) ![]u8 {
_ = self; _ = self;
_ = allocator; _ = allocator;
@ -366,6 +339,8 @@ pub fn deinit(self: Duration) void {
abi.c.temporal_rs_Duration_destroy(self._inner); abi.c.temporal_rs_Duration_destroy(self._inner);
} }
// --- Helpers -----------------------------------------------------------------
inline fn handleVoidResult(res: anytype) !void { inline fn handleVoidResult(res: anytype) !void {
_ = try abi.extractResult(res); _ = try abi.extractResult(res);
} }
@ -376,6 +351,8 @@ fn wrapDuration(res: anytype) !Duration {
return .{ ._inner = ptr.? }; return .{ ._inner = ptr.? };
} }
// --- Aliases and enums ------------------------------------------
const OptionU8 = abi.c.OptionU8; const OptionU8 = abi.c.OptionU8;
const OptionU32 = abi.c.OptionU32; const OptionU32 = abi.c.OptionU32;
const OptionI64 = abi.c.OptionI64; const OptionI64 = abi.c.OptionI64;
@ -384,6 +361,8 @@ const Precision = abi.c.Precision;
const Unit_option = abi.c.Unit_option; const Unit_option = abi.c.Unit_option;
const RoundingMode_option = abi.c.RoundingMode_option; const RoundingMode_option = abi.c.RoundingMode_option;
// --- Tests -------------------------------------------------------------------
test init { test init {
// Create a simple duration: 1 hour, 30 minutes // Create a simple duration: 1 hour, 30 minutes
const dur = try Duration.init(0, 0, 0, 0, 1, 30, 0, 0, 0, 0); const dur = try Duration.init(0, 0, 0, 0, 1, 30, 0, 0, 0, 0);
@ -687,6 +666,7 @@ test nanoseconds {
const ns = dur.nanoseconds(); const ns = dur.nanoseconds();
try std.testing.expect(ns > 499 and ns < 501); try std.testing.expect(ns > 499 and ns < 501);
} }
test sign { test sign {
const pos = try Duration.from("P1Y"); const pos = try Duration.from("P1Y");
defer pos.deinit(); defer pos.deinit();

View file

@ -3,12 +3,10 @@ const abi = @import("abi.zig");
const t = @import("temporal.zig"); const t = @import("temporal.zig");
const Duration = @import("Duration.zig"); const Duration = @import("Duration.zig");
const ZonedDateTime = @import("ZonedDateTime.zig");
/// The `Temporal.Instant` object represents a unique point in time, with nanosecond precision. /// The `Temporal.Instant` object represents a unique point in time, with nanosecond precision.
/// It is fundamentally represented as the number of nanoseconds since the Unix epoch (midnight at the beginning of January 1, 1970, UTC), without any time zone or calendar system. /// It is fundamentally represented as the number of nanoseconds since the Unix epoch (midnight at the beginning of January 1, 1970, UTC), without any time zone or calendar system.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant
/// See: [Temporal.Instant](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant)
const Instant = @This(); const Instant = @This();
_inner: *abi.c.Instant, _inner: *abi.c.Instant,
@ -27,8 +25,7 @@ pub const DifferenceSettings = t.DifferenceSettings;
pub const TimeZone = t.TimeZone; pub const TimeZone = t.TimeZone;
/// Options for Instant.toString(). /// Options for Instant.toString().
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/toString
/// See: [Temporal.Instant.toString](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/toString)
pub const ToStringOptions = struct { pub const ToStringOptions = struct {
/// Either an integer from 0 to 9, or null for "auto". /// Either an integer from 0 to 9, or null for "auto".
/// If null (auto), trailing zeros are removed from the fractional seconds. /// If null (auto), trailing zeros are removed from the fractional seconds.
@ -49,31 +46,26 @@ pub const ToStringOptions = struct {
}; };
/// Construct an Instant from epoch nanoseconds (Temporal.Instant.fromEpochNanoseconds). /// Construct an Instant from epoch nanoseconds (Temporal.Instant.fromEpochNanoseconds).
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/fromEpochNanoseconds
/// See: [Temporal.Instant.fromEpochNanoseconds](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/fromEpochNanoseconds)
pub fn init(epoch_ns: i128) !Instant { pub fn init(epoch_ns: i128) !Instant {
return fromEpochNanoseconds(epoch_ns); return fromEpochNanoseconds(epoch_ns);
} }
/// Construct an Instant from epoch milliseconds (Temporal.Instant.fromEpochMilliseconds). /// Construct an Instant from epoch milliseconds (Temporal.Instant.fromEpochMilliseconds).
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/fromEpochMilliseconds
/// See: [Temporal.Instant.fromEpochMilliseconds](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/fromEpochMilliseconds)
pub fn fromEpochMilliseconds(epoch_ms: i64) !Instant { pub fn fromEpochMilliseconds(epoch_ms: i64) !Instant {
return wrapInstant(abi.c.temporal_rs_Instant_from_epoch_milliseconds(epoch_ms)); return wrapInstant(abi.c.temporal_rs_Instant_from_epoch_milliseconds(epoch_ms));
} }
/// Construct an Instant from epoch nanoseconds (Temporal.Instant.fromEpochNanoseconds). /// Construct an Instant from epoch nanoseconds (Temporal.Instant.fromEpochNanoseconds).
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/fromEpochNanoseconds
/// See: [Temporal.Instant.fromEpochNanoseconds](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/fromEpochNanoseconds)
pub fn fromEpochNanoseconds(epoch_ns: i128) !Instant { pub fn fromEpochNanoseconds(epoch_ns: i128) !Instant {
const parts = abi.toI128Nanoseconds(epoch_ns); const parts = abi.toI128Nanoseconds(epoch_ns);
return wrapInstant(abi.c.temporal_rs_Instant_try_new(parts)); return wrapInstant(abi.c.temporal_rs_Instant_try_new(parts));
} }
/// Parse an RFC 9557 string (Temporal.Instant.from) or from another Temporal.Instant. /// Parse an RFC 9557 string (Temporal.Instant.from) or from another Temporal.Instant.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/from
/// See: [Temporal.Instant.from](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/from)
pub fn from(info: anytype) !Instant { pub fn from(info: anytype) !Instant {
const T = @TypeOf(info); const T = @TypeOf(info);
@ -109,59 +101,51 @@ inline fn fromUtf8(text: []const u8) !Instant {
} }
/// Returns a new Instant representing this instant moved forward by a given Duration. /// Returns a new Instant representing this instant moved forward by a given Duration.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/add
/// See: [Temporal.Instant.add](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/add)
pub fn add(self: Instant, duration: *Duration) !Instant { pub fn add(self: Instant, duration: *Duration) !Instant {
return wrapInstant(abi.c.temporal_rs_Instant_add(self._inner, duration._inner)); return wrapInstant(abi.c.temporal_rs_Instant_add(self._inner, duration._inner));
} }
/// Returns a new Instant representing this instant moved backward by a given Duration. /// Returns a new Instant representing this instant moved backward by a given Duration.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/subtract
/// See: [Temporal.Instant.subtract](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/subtract)
pub fn subtract(self: Instant, duration: *Duration) !Instant { pub fn subtract(self: Instant, duration: *Duration) !Instant {
return wrapInstant(abi.c.temporal_rs_Instant_subtract(self._inner, duration._inner)); return wrapInstant(abi.c.temporal_rs_Instant_subtract(self._inner, duration._inner));
} }
/// Returns a Duration representing the difference from this instant until another instant. /// Returns a Duration representing the difference from this instant until another instant.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/until
/// See: [Temporal.Instant.until](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/until)
pub fn until(self: Instant, other: Instant, settings: DifferenceSettings) !Duration { pub fn until(self: Instant, other: Instant, settings: DifferenceSettings) !Duration {
const ptr = (try abi.extractResult(abi.c.temporal_rs_Instant_until(self._inner, other._inner, abi.to.diffsettings(settings)))) orelse return abi.TemporalError.Generic; const ptr = (try abi.extractResult(abi.c.temporal_rs_Instant_until(self._inner, other._inner, abi.to.diffsettings(settings)))) orelse return abi.TemporalError.Generic;
return .{ ._inner = ptr }; return .{ ._inner = ptr };
} }
/// Returns a Duration representing the difference from another instant until this instant. /// Returns a Duration representing the difference from another instant until this instant.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/since
/// See: [Temporal.Instant.since](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/since)
pub fn since(self: Instant, other: Instant, settings: DifferenceSettings) !Duration { pub fn since(self: Instant, other: Instant, settings: DifferenceSettings) !Duration {
const ptr = (try abi.extractResult(abi.c.temporal_rs_Instant_since(self._inner, other._inner, abi.to.diffsettings(settings)))) orelse return abi.TemporalError.Generic; const ptr = (try abi.extractResult(abi.c.temporal_rs_Instant_since(self._inner, other._inner, abi.to.diffsettings(settings)))) orelse return abi.TemporalError.Generic;
return .{ ._inner = ptr }; return .{ ._inner = ptr };
} }
/// Returns a new Instant rounded to the given unit. /// Returns a new Instant rounded to the given unit.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/round
/// See: [Temporal.Instant.round](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/round)
pub fn round(self: Instant, options: RoundingOptions) !Instant { pub fn round(self: Instant, options: RoundingOptions) !Instant {
return wrapInstant(abi.c.temporal_rs_Instant_round(self._inner, abi.to.roundingOpts(options))); return wrapInstant(abi.c.temporal_rs_Instant_round(self._inner, abi.to.roundingOpts(options)));
} }
/// Compares two Instants, returning -1, 0, or 1 if the first is before, equal, or after the second. /// Compares two Instants, returning -1, 0, or 1 if the first is before, equal, or after the second.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/compare
/// See: [Temporal.Instant.compare](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/compare)
pub fn compare(a: Instant, b: Instant) i8 { pub fn compare(a: Instant, b: Instant) i8 {
return abi.c.temporal_rs_Instant_compare(a._inner, b._inner); return abi.c.temporal_rs_Instant_compare(a._inner, b._inner);
} }
/// Returns true if two Instants are equal (same epoch nanoseconds). /// Returns true if two Instants are equal (same epoch nanoseconds).
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/equals
/// See: [Temporal.Instant.equals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/equals)
pub fn equals(a: Instant, b: Instant) bool { pub fn equals(a: Instant, b: Instant) bool {
return abi.c.temporal_rs_Instant_equals(a._inner, b._inner); return abi.c.temporal_rs_Instant_equals(a._inner, b._inner);
} }
/// Returns a string representing this instant in the RFC 9557 format, optionally using a time zone. /// Returns a string representing this instant in the RFC 9557 format, optionally using a time zone.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/toString
/// See: [Temporal.Instant.toString](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/toString)
pub fn toString(self: Instant, allocator: std.mem.Allocator, opts: ToStringOptions) ![]u8 { pub fn toString(self: Instant, allocator: std.mem.Allocator, opts: ToStringOptions) ![]u8 {
const zone_opt = if (opts.time_zone) |tz| abi.toTimeZoneOption(tz._inner) else abi.toTimeZoneOption(null); const zone_opt = if (opts.time_zone) |tz| abi.toTimeZoneOption(tz._inner) else abi.toTimeZoneOption(null);
const rounding = optsToRounding(opts); const rounding = optsToRounding(opts);
@ -190,22 +174,19 @@ fn toStringWithProvider(self: Instant, allocator: std.mem.Allocator, provider: *
} }
/// Returns a string representing this instant in the RFC 9557 format (same as toString). Intended for JSON serialization. /// Returns a string representing this instant in the RFC 9557 format (same as toString). Intended for JSON serialization.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/toJSON
/// See: [Temporal.Instant.toJSON](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/toJSON)
pub fn toJSON(self: Instant, allocator: std.mem.Allocator) ![]u8 { pub fn toJSON(self: Instant, allocator: std.mem.Allocator) ![]u8 {
return self.toString(allocator, .{}); return self.toString(allocator, .{});
} }
/// Returns a string with a language-sensitive representation of this instant. /// Returns a string with a language-sensitive representation of this instant.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/toLocaleString
/// See: [Temporal.Instant.toLocaleString](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/toLocaleString)
pub fn toLocaleString(self: Instant, allocator: std.mem.Allocator) ![]u8 { pub fn toLocaleString(self: Instant, allocator: std.mem.Allocator) ![]u8 {
return self.toString(allocator, .{}); return self.toString(allocator, .{});
} }
/// Returns a ZonedDateTime representing this instant in the specified time zone using the ISO 8601 calendar system. /// Returns a ZonedDateTime representing this instant in the specified time zone using the ISO 8601 calendar system.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/toZonedDateTimeISO
/// See: [Temporal.Instant.toZonedDateTimeISO](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/toZonedDateTimeISO)
pub fn toZonedDateTimeISO(self: Instant, zone: TimeZone) !ZonedDateTime { pub fn toZonedDateTimeISO(self: Instant, zone: TimeZone) !ZonedDateTime {
const ptr = (try abi.extractResult(abi.c.temporal_rs_Instant_to_zoned_date_time_iso(self._inner, zone._inner))) orelse return abi.TemporalError.Generic; const ptr = (try abi.extractResult(abi.c.temporal_rs_Instant_to_zoned_date_time_iso(self._inner, zone._inner))) orelse return abi.TemporalError.Generic;
return .{ ._inner = ptr }; return .{ ._inner = ptr };
@ -224,15 +205,13 @@ fn clone(self: Instant) Instant {
} }
/// Returns the number of milliseconds since the Unix epoch for this instant. /// Returns the number of milliseconds since the Unix epoch for this instant.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/epochMilliseconds
/// See: [Temporal.Instant.epochMilliseconds](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/epochMilliseconds)
pub fn epochMilliseconds(self: Instant) i64 { pub fn epochMilliseconds(self: Instant) i64 {
return abi.c.temporal_rs_Instant_epoch_milliseconds(self._inner); return abi.c.temporal_rs_Instant_epoch_milliseconds(self._inner);
} }
/// Returns the number of nanoseconds since the Unix epoch for this instant. /// Returns the number of nanoseconds since the Unix epoch for this instant.
/// /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/epochNanoseconds
/// See: [Temporal.Instant.epochNanoseconds](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/epochNanoseconds)
pub fn epochNanoseconds(self: Instant) i128 { pub fn epochNanoseconds(self: Instant) i128 {
return abi.fromI128Nanoseconds(abi.c.temporal_rs_Instant_epoch_nanoseconds(self._inner)); return abi.fromI128Nanoseconds(abi.c.temporal_rs_Instant_epoch_nanoseconds(self._inner));
} }
@ -242,6 +221,8 @@ pub fn deinit(self: Instant) void {
abi.c.temporal_rs_Instant_destroy(self._inner); abi.c.temporal_rs_Instant_destroy(self._inner);
} }
// --- Helpers -----------------------------------------------------------------
fn wrapInstant(res: anytype) !Instant { fn wrapInstant(res: anytype) !Instant {
const ptr = (try abi.extractResult(res)) orelse return abi.TemporalError.Generic; const ptr = (try abi.extractResult(res)) orelse return abi.TemporalError.Generic;
return .{ return .{
@ -279,6 +260,18 @@ fn optsToRounding(opts: ToStringOptions) abi.c.ToStringRoundingOptions {
}; };
} }
// --- Forward declarations -----------------------------------------------------
const ZonedDateTime = struct {
_inner: *abi.c.ZonedDateTime,
pub fn deinit(self: ZonedDateTime) void {
abi.c.temporal_rs_ZonedDateTime_destroy(self._inner);
}
};
// --- Tests -------------------------------------------------------------------
test init { test init {
const epoch_ns: i128 = 1_704_067_200_000_000_000; // 2024-01-01T00:00:00Z const epoch_ns: i128 = 1_704_067_200_000_000_000; // 2024-01-01T00:00:00Z
const inst = try Instant.init(epoch_ns); const inst = try Instant.init(epoch_ns);
@ -526,17 +519,7 @@ test toJSON {
} }
test toZonedDateTimeISO { test toZonedDateTimeISO {
const inst = try Instant.fromEpochMilliseconds(1704067200000); if (true) return error.SkipZigTest;
defer inst.deinit();
const zdt = try inst.toZonedDateTimeISO(try TimeZone.init("UTC"));
defer zdt.deinit();
try std.testing.expectEqual(@as(i32, 2024), zdt.year());
try std.testing.expectEqual(@as(u8, 1), zdt.month());
try std.testing.expectEqual(@as(u8, 1), zdt.day());
try std.testing.expectEqual(@as(u8, 0), zdt.hour());
try std.testing.expectEqual(@as(i128, 1_704_067_200_000_000_000), zdt.epochNanoseconds());
} }
test epochMilliseconds { test epochMilliseconds {

View file

@ -3,15 +3,13 @@ const Instant = @import("Instant.zig");
const PlainDate = @import("PlainDate.zig"); const PlainDate = @import("PlainDate.zig");
const PlainDateTime = @import("PlainDateTime.zig"); const PlainDateTime = @import("PlainDateTime.zig");
const PlainTime = @import("PlainTime.zig"); const PlainTime = @import("PlainTime.zig");
const SystemTimeZone = @import("SystemTimeZone.zig");
const ZonedDateTime = @import("ZonedDateTime.zig"); const ZonedDateTime = @import("ZonedDateTime.zig");
const abi = @import("abi.zig");
/// # Temporal.Now /// # Temporal.Now
/// ///
/// The `Temporal.Now` namespace object contains static methods for getting the current time in various formats. /// The `Temporal.Now` namespace object contains static methods for getting the current time in various formats.
/// ///
/// See: [Temporal.Now](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now) /// - [MDN Temporal.Now](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now)
/// ///
/// ## Description /// ## Description
/// ///
@ -31,7 +29,7 @@ const Now = @This();
/// Returns the current time as a [`Temporal.Instant`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant) object. /// Returns the current time as a [`Temporal.Instant`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant) object.
/// ///
/// See: [Temporal.Now.instant](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now/instant) /// See: [MDN Temporal.Now.instant](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now/instant)
pub fn instant(io: std.Io) !Instant { pub fn instant(io: std.Io) !Instant {
const ns = std.Io.Timestamp.now(io, .real).nanoseconds; const ns = std.Io.Timestamp.now(io, .real).nanoseconds;
return Instant.fromEpochNanoseconds(ns); return Instant.fromEpochNanoseconds(ns);
@ -39,80 +37,102 @@ pub fn instant(io: std.Io) !Instant {
/// Returns the current date as a [`Temporal.PlainDate`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainDate) object, in the ISO 8601 calendar and the specified time zone. /// Returns the current date as a [`Temporal.PlainDate`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainDate) object, in the ISO 8601 calendar and the specified time zone.
/// ///
/// When `time_zone_like` is null, the system time zone is used. /// See: [MDN Temporal.Now.plainDateISO](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now/plainDateISO)
/// pub fn plainDateISO(io: std.Io) !PlainDate {
/// See: [Temporal.Now.plainDateISO](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now/plainDateISO) const now = currentParts(io);
pub fn plainDateISO(allocator: std.mem.Allocator, io: std.Io, time_zone_like: ?[]const u8) !PlainDate { return PlainDate.init(now.year, now.month, now.day);
const time_zone = try resolveTimeZone(allocator, io, time_zone_like);
const now = try instant(io);
defer now.deinit();
const ptr = (try abi.extractResult(abi.c.temporal_rs_PlainDate_from_epoch_nanoseconds(
abi.toI128Nanoseconds(now.epochNanoseconds()),
abi.to.toTimeZone(time_zone),
))) orelse return abi.TemporalError.Generic;
return .{ ._inner = ptr };
} }
/// Returns the current date and time as a [`Temporal.PlainDateTime`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainDateTime) object, in the ISO 8601 calendar and the specified time zone. /// Returns the current date and time as a [`Temporal.PlainDateTime`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainDateTime) object, in the ISO 8601 calendar and the specified time zone.
/// ///
/// When `time_zone_like` is null, the system time zone is used. /// See: [MDN Temporal.Now.plainDateTimeISO](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now/plainDateTimeISO)
/// pub fn plainDateTimeISO(io: std.Io) !PlainDateTime {
/// See: [Temporal.Now.plainDateTimeISO](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now/plainDateTimeISO) const now = currentParts(io);
pub fn plainDateTimeISO(allocator: std.mem.Allocator, io: std.Io, time_zone_like: ?[]const u8) !PlainDateTime { return PlainDateTime.init(
const time_zone = try resolveTimeZone(allocator, io, time_zone_like); now.year,
const now = try instant(io); now.month,
defer now.deinit(); now.day,
now.hour,
const ptr = (try abi.extractResult(abi.c.temporal_rs_PlainDateTime_from_epoch_nanoseconds( now.minute,
abi.toI128Nanoseconds(now.epochNanoseconds()), now.second,
abi.to.toTimeZone(time_zone), now.millisecond,
))) orelse return abi.TemporalError.Generic; now.microsecond,
return .{ ._inner = ptr }; now.nanosecond,
);
} }
/// Returns the current time as a [`Temporal.PlainTime`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime) object, in the specified time zone. /// Returns the current time as a [`Temporal.PlainTime`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime) object, in the specified time zone.
/// ///
/// When `time_zone_like` is null, the system time zone is used. /// See: [MDN Temporal.Now.plainTimeISO](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now/plainTimeISO)
/// pub fn plainTimeISO(io: std.Io) !PlainTime {
/// See: [Temporal.Now.plainTimeISO](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now/plainTimeISO) const now = currentParts(io);
pub fn plainTimeISO(allocator: std.mem.Allocator, io: std.Io, time_zone_like: ?[]const u8) !PlainTime { return PlainTime.init(
const zdt = try zonedDateTimeISO(allocator, io, time_zone_like); now.hour,
defer zdt.deinit(); now.minute,
return zdt.toPlainTime(); now.second,
now.millisecond,
now.microsecond,
now.nanosecond,
);
} }
/// Returns a time zone identifier representing the system's current time zone. /// Returns a time zone identifier representing the system's current time zone.
/// ///
/// The caller owns the returned slice and must free it with `allocator`. /// See: [MDN Temporal.Now.timeZoneId](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now/timeZoneId)
/// pub fn timeZoneId() []const u8 {
/// See: [Temporal.Now.timeZoneId](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now/timeZoneId) return "UTC";
pub fn timeZoneId(allocator: std.mem.Allocator, io: std.Io) ![]const u8 {
const time_zone = try SystemTimeZone.timeZone(allocator, io);
var write = abi.DiplomatWrite.init(allocator);
defer write.deinit();
abi.c.temporal_rs_TimeZone_identifier(time_zone._inner, &write.inner);
return try write.toOwnedSlice();
} }
/// Returns the current date and time as a [`Temporal.ZonedDateTime`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime) object, in the ISO 8601 calendar and the specified time zone. /// Returns the current date and time as a [`Temporal.ZonedDateTime`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime) object, in the ISO 8601 calendar and the specified time zone.
/// ///
/// When `time_zone_like` is null, the system time zone is used. /// See: [MDN Temporal.Now.zonedDateTimeISO](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now/zonedDateTimeISO)
/// pub fn zonedDateTimeISO() !ZonedDateTime {
/// See: [Temporal.Now.zonedDateTimeISO](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now/zonedDateTimeISO) return error.TemporalNotImplemented;
pub fn zonedDateTimeISO(allocator: std.mem.Allocator, io: std.Io, time_zone_like: ?[]const u8) !ZonedDateTime {
const now = try instant(io);
defer now.deinit();
const time_zone = try resolveTimeZone(allocator, io, time_zone_like);
return ZonedDateTime.fromEpochNanoseconds(now.epochNanoseconds(), time_zone);
} }
fn resolveTimeZone(allocator: std.mem.Allocator, io: std.Io, time_zone_like: ?[]const u8) !ZonedDateTime.TimeZone { const CurrentParts = struct {
if (time_zone_like) |id| return ZonedDateTime.TimeZone.init(id); year: i32,
return SystemTimeZone.timeZone(allocator, io); month: u8,
day: u8,
hour: u8,
minute: u8,
second: u8,
millisecond: u16,
microsecond: u16,
nanosecond: u16,
};
fn currentParts(io: std.Io) CurrentParts {
const ns = std.Io.Timestamp.now(io, .real).nanoseconds;
const seconds: i64 = @intCast(@divTrunc(ns, 1_000_000_000));
const subsec_nanos_u64: u64 = @intCast(@rem(ns, 1_000_000_000));
const days_since_epoch: u64 = @intCast(@divTrunc(seconds, std.time.epoch.secs_per_day));
const secs_of_day: u64 = @intCast(@mod(seconds, std.time.epoch.secs_per_day));
const epoch_day = std.time.epoch.EpochDay{ .day = @intCast(days_since_epoch) };
const year_day = epoch_day.calculateYearDay();
const month_day = year_day.calculateMonthDay();
const day_seconds = std.time.epoch.DaySeconds{ .secs = @intCast(secs_of_day) };
const millisecond: u16 = @intCast(subsec_nanos_u64 / 1_000_000);
const microsecond: u16 = @intCast((subsec_nanos_u64 / 1_000) % 1_000);
const nanosecond: u16 = @intCast(subsec_nanos_u64 % 1_000);
return .{
.year = @intCast(year_day.year),
.month = @intCast(month_day.month.numeric()),
.day = @intCast(month_day.day_index + 1),
.hour = @intCast(day_seconds.getHoursIntoDay()),
.minute = @intCast(day_seconds.getMinutesIntoHour()),
.second = @intCast(day_seconds.getSecondsIntoMinute()),
.millisecond = millisecond,
.microsecond = microsecond,
.nanosecond = nanosecond,
};
} }
// ---------- Tests ---------------------
test instant { test instant {
const io = std.testing.io; const io = std.testing.io;
const inst = try instant(io); const inst = try instant(io);
@ -122,62 +142,31 @@ test instant {
test plainDateISO { test plainDateISO {
const io = std.testing.io; const io = std.testing.io;
const date = try plainDateISO(std.testing.allocator, io, null); const date = try plainDateISO(io);
defer date.deinit();
try std.testing.expect(date.year() >= 1970); try std.testing.expect(date.year() >= 1970);
try std.testing.expect(date.month() >= 1 and date.month() <= 12); try std.testing.expect(date.month() >= 1 and date.month() <= 12);
try std.testing.expect(date.day() >= 1 and date.day() <= 31); try std.testing.expect(date.day() >= 1 and date.day() <= 31);
} }
test plainDateTimeISO { test plainDateTimeISO {
const io = std.testing.io; const io = std.testing.io;
var dt = try plainDateTimeISO(std.testing.allocator, io, null); const dt = try plainDateTimeISO(io);
defer dt.deinit();
try std.testing.expect(dt.year() >= 1970); try std.testing.expect(dt.year() >= 1970);
try std.testing.expect(dt.month() >= 1 and dt.month() <= 12); try std.testing.expect(dt.month() >= 1 and dt.month() <= 12);
try std.testing.expect(dt.day() >= 1 and dt.day() <= 31); try std.testing.expect(dt.day() >= 1 and dt.day() <= 31);
try std.testing.expect(dt.hour() < 24); try std.testing.expect(dt.hour() < 24);
try std.testing.expect(dt.minute() < 60); try std.testing.expect(dt.minute() < 60);
} }
test plainTimeISO { test plainTimeISO {
const io = std.testing.io; const io = std.testing.io;
const t = try plainTimeISO(std.testing.allocator, io, null); const t = try plainTimeISO(io);
try std.testing.expect(t.hour() < 24); try std.testing.expect(t.hour() < 24);
try std.testing.expect(t.minute() < 60); try std.testing.expect(t.minute() < 60);
try std.testing.expect(t.second() < 60); try std.testing.expect(t.second() < 60);
} }
test timeZoneId { test timeZoneId {
const io = std.testing.io; const tz = timeZoneId();
const tz = try timeZoneId(std.testing.allocator, io); try std.testing.expectEqualStrings("UTC", tz);
defer std.testing.allocator.free(tz);
try std.testing.expect(tz.len > 0);
_ = try ZonedDateTime.TimeZone.init(tz);
} }
test zonedDateTimeISO { test zonedDateTimeISO {
const io = std.testing.io; try std.testing.expectError(error.TemporalNotImplemented, zonedDateTimeISO());
const zdt = try zonedDateTimeISO(std.testing.allocator, io, null);
defer zdt.deinit();
try std.testing.expect(zdt.epochNanoseconds() > 0);
const tz = try zdt.timeZoneId(std.testing.allocator);
defer std.testing.allocator.free(tz);
const expected_tz = try timeZoneId(std.testing.allocator, io);
defer std.testing.allocator.free(expected_tz);
try std.testing.expectEqualStrings(expected_tz, tz);
}
test "plainDateISO with explicit time zone" {
const io = std.testing.io;
const date = try plainDateISO(std.testing.allocator, io, "UTC");
defer date.deinit();
const zdt = try zonedDateTimeISO(std.testing.allocator, io, "UTC");
defer zdt.deinit();
const plain = try zdt.toPlainDate();
defer plain.deinit();
try std.testing.expect(date.equals(plain));
} }

View file

@ -13,7 +13,8 @@ const Duration = @import("Duration.zig");
/// ///
/// The `Temporal.PlainDate` object represents a calendar date (year, month, day) with no time or time zone. /// The `Temporal.PlainDate` object represents a calendar date (year, month, day) with no time or time zone.
/// ///
/// See: [Temporal.PlainDate](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainDate) /// The `Temporal.PlainDate` object represents a calendar date (year, month, day) with no time or time zone.
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainDate
const PlainDate = @This(); const PlainDate = @This();
/// Internal pointer to the underlying C PlainDate object. /// Internal pointer to the underlying C PlainDate object.
@ -54,22 +55,6 @@ pub const ToZonedDateTimeOptions = struct {
plain_time: ?PlainTime = null, plain_time: ?PlainTime = null,
}; };
/// Options for `with()` method.
pub const WithOptions = struct {
/// Year value to override.
year: ?i32 = null,
/// Month value to override.
month: ?u8 = null,
/// Calendar-specific month code to override.
month_code: ?[]const u8 = null,
/// Day value to override.
day: ?u8 = null,
/// Era value to override.
era: ?[]const u8 = null,
/// Era year value to override.
era_year: ?i32 = null,
};
/// Creates a new PlainDate from the given ISO year, month, and day. /// Creates a new PlainDate from the given ISO year, month, and day.
pub fn init(year_val: i32, month_val: u8, day_val: u8) !PlainDate { pub fn init(year_val: i32, month_val: u8, day_val: u8) !PlainDate {
return calInit(year_val, month_val, day_val, "iso8601"); return calInit(year_val, month_val, day_val, "iso8601");
@ -152,28 +137,11 @@ pub fn since(self: PlainDate, other: PlainDate, settings: DifferenceSettings) !D
return .{ ._inner = ptr }; return .{ ._inner = ptr };
} }
/// Returns a new PlainDate with some fields replaced. /// Returns a new PlainDate with some fields replaced (not implemented).
pub fn with(self: PlainDate, fields: WithOptions) !PlainDate { pub fn with(self: PlainDate, fields: anytype) !PlainDate {
const partial_date = abi.c.PartialDate{ _ = self;
.year = if (fields.year) |y| abi.toOption(abi.c.OptionI32, y) else .{ .is_ok = false }, _ = fields;
.month = if (fields.month) |m| abi.toOption(abi.c.OptionU8, m) else .{ .is_ok = false }, return error.TemporalNotImplemented;
.day = if (fields.day) |d| abi.toOption(abi.c.OptionU8, d) else .{ .is_ok = false },
.month_code = if (fields.month_code) |mc| abi.toDiplomatStringView(mc) else .{ .data = null, .len = 0 },
.era = if (fields.era) |e| abi.toDiplomatStringView(e) else .{ .data = null, .len = 0 },
.era_year = if (fields.era_year) |ey| abi.toOption(abi.c.OptionI32, ey) else .{ .is_ok = false },
.calendar = abi.c.AnyCalendarKind_Iso,
};
const overflow = abi.c.ArithmeticOverflow_option{
.is_ok = true,
.unnamed_0 = .{ .ok = abi.c.ArithmeticOverflow_Constrain },
};
return wrapPlainDate(abi.c.temporal_rs_PlainDate_with(
self._inner,
partial_date,
overflow,
));
} }
/// Returns a new PlainDate with a different calendar. /// Returns a new PlainDate with a different calendar.
@ -558,13 +526,7 @@ test with {
const date = try PlainDate.init(2024, 3, 15); const date = try PlainDate.init(2024, 3, 15);
defer date.deinit(); defer date.deinit();
try std.testing.expectError(error.TypeError, date.with(.{})); try std.testing.expectError(error.TemporalNotImplemented, date.with(.{}));
const changed = try date.with(.{ .year = 2025, .month = 4, .day = 16 });
defer changed.deinit();
try std.testing.expectEqual(@as(i32, 2025), changed.year());
try std.testing.expectEqual(@as(u8, 4), changed.month());
try std.testing.expectEqual(@as(u8, 16), changed.day());
} }
test withCalendar { test withCalendar {

View file

@ -11,7 +11,9 @@ const Duration = @import("Duration.zig");
/// ///
/// The `Temporal.PlainDateTime` object represents a calendar date and wall-clock time, but no time zone or offset. /// The `Temporal.PlainDateTime` object represents a calendar date and wall-clock time, but no time zone or offset.
/// ///
/// See: [Temporal.PlainDateTime](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainDateTime) /// - [MDN Temporal.PlainDateTime](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainDateTime)
/// The `Temporal.PlainDateTime` object represents a calendar date and wall-clock time, but no time zone or offset.
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainDateTime
const PlainDateTime = @This(); const PlainDateTime = @This();
/// Internal pointer to the underlying C PlainDateTime object. /// Internal pointer to the underlying C PlainDateTime object.
@ -545,6 +547,7 @@ fn wrapPlainDateTime(res: anytype) !PlainDateTime {
return .{ ._inner = ptr }; return .{ ._inner = ptr };
} }
// ---------- Tests ---------------------
test init { test init {
const dt = try PlainDateTime.init(2024, 1, 15, 14, 30, 45, 123, 456, 789); const dt = try PlainDateTime.init(2024, 1, 15, 14, 30, 45, 123, 456, 789);
try std.testing.expectEqual(@as(i32, 2024), dt.year()); try std.testing.expectEqual(@as(i32, 2024), dt.year());

View file

@ -8,7 +8,7 @@ const PlainDate = @import("PlainDate.zig");
/// ///
/// The `Temporal.PlainMonthDay` object represents a month and day in a calendar, with no year or time. /// The `Temporal.PlainMonthDay` object represents a month and day in a calendar, with no year or time.
/// ///
/// See: [Temporal.PlainMonthDay](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay) /// - [MDN Temporal.PlainMonthDay](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay)
const PlainMonthDay = @This(); const PlainMonthDay = @This();
_inner: *abi.c.PlainMonthDay, _inner: *abi.c.PlainMonthDay,
@ -39,8 +39,7 @@ fn wrapPlainMonthDay(result: anytype) !PlainMonthDay {
/// Creates a new PlainMonthDay from the given month, day, and optional calendar. /// Creates a new PlainMonthDay from the given month, day, and optional calendar.
/// Equivalent to the Temporal.PlainMonthDay constructor. /// Equivalent to the Temporal.PlainMonthDay constructor.
/// /// See [MDN Temporal.PlainMonthDay() constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay/PlainMonthDay)
/// See: [Temporal.PlainMonthDay](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay/PlainMonthDay)
pub fn init(month_val: u8, day_val: u8, calendar: ?[]const u8) !PlainMonthDay { pub fn init(month_val: u8, day_val: u8, calendar: ?[]const u8) !PlainMonthDay {
const cal_kind = if (calendar) |cal| blk: { const cal_kind = if (calendar) |cal| blk: {
const cal_view = abi.toDiplomatStringView(cal); const cal_view = abi.toDiplomatStringView(cal);
@ -61,8 +60,7 @@ pub fn init(month_val: u8, day_val: u8, calendar: ?[]const u8) !PlainMonthDay {
} }
/// Parses a PlainMonthDay from a string. /// Parses a PlainMonthDay from a string.
/// /// See [MDN Temporal.PlainMonthDay.from()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay/from)
/// See: [Temporal.PlainMonthDay.from](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay/from)
pub fn from(s: []const u8) !PlainMonthDay { pub fn from(s: []const u8) !PlainMonthDay {
return fromUtf8(s); return fromUtf8(s);
} }
@ -79,16 +77,14 @@ fn fromUtf16(utf16: []const u16) !PlainMonthDay {
// Comparison // Comparison
/// Returns true if this PlainMonthDay is equal to another (same date and calendar). /// Returns true if this PlainMonthDay is equal to another (same date and calendar).
/// /// See [MDN Temporal.PlainMonthDay.prototype.equals()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay/equals)
/// See: [Temporal.PlainMonthDay.equals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay/equals)
pub fn equals(self: PlainMonthDay, other: PlainMonthDay) bool { pub fn equals(self: PlainMonthDay, other: PlainMonthDay) bool {
return abi.c.temporal_rs_PlainMonthDay_equals(self._inner, other._inner); return abi.c.temporal_rs_PlainMonthDay_equals(self._inner, other._inner);
} }
// Property accessors // Property accessors
/// Returns the calendar identifier used to interpret the internal ISO 8601 date. /// Returns the calendar identifier used to interpret the internal ISO 8601 date.
/// /// See [MDN Temporal.PlainMonthDay.prototype.calendarId](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay/calendarId)
/// See: [Temporal.PlainMonthDay.calendarId](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay/calendarId)
pub fn calendarId(self: PlainMonthDay, allocator: std.mem.Allocator) ![]u8 { pub fn calendarId(self: PlainMonthDay, allocator: std.mem.Allocator) ![]u8 {
const calendar_ptr = abi.c.temporal_rs_PlainMonthDay_calendar(self._inner) orelse return error.TemporalError; const calendar_ptr = abi.c.temporal_rs_PlainMonthDay_calendar(self._inner) orelse return error.TemporalError;
const cal_id_view = abi.c.temporal_rs_Calendar_identifier(calendar_ptr); const cal_id_view = abi.c.temporal_rs_Calendar_identifier(calendar_ptr);
@ -96,15 +92,13 @@ pub fn calendarId(self: PlainMonthDay, allocator: std.mem.Allocator) ![]u8 {
} }
/// Returns the 1-based day index in the month of this date. /// Returns the 1-based day index in the month of this date.
/// /// See [MDN Temporal.PlainMonthDay.prototype.day](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay/day)
/// See: [Temporal.PlainMonthDay.day](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay/day)
pub fn day(self: PlainMonthDay) u8 { pub fn day(self: PlainMonthDay) u8 {
return abi.c.temporal_rs_PlainMonthDay_day(self._inner); return abi.c.temporal_rs_PlainMonthDay_day(self._inner);
} }
/// Returns the calendar-specific string representing the month of this date. /// Returns the calendar-specific string representing the month of this date.
/// /// See [MDN Temporal.PlainMonthDay.prototype.monthCode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay/monthCode)
/// See: [Temporal.PlainMonthDay.monthCode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay/monthCode)
pub fn monthCode(self: PlainMonthDay, allocator: std.mem.Allocator) ![]const u8 { pub fn monthCode(self: PlainMonthDay, allocator: std.mem.Allocator) ![]const u8 {
var write = abi.DiplomatWrite.init(allocator); var write = abi.DiplomatWrite.init(allocator);
defer write.deinit(); defer write.deinit();
@ -115,8 +109,7 @@ pub fn monthCode(self: PlainMonthDay, allocator: std.mem.Allocator) ![]const u8
// Modification // Modification
/// Returns a new PlainMonthDay with some fields replaced by new values. /// Returns a new PlainMonthDay with some fields replaced by new values.
/// /// See [MDN Temporal.PlainMonthDay.prototype.with()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay/with)
/// See: [Temporal.PlainMonthDay.with](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay/with)
pub fn with(self: PlainMonthDay, options: WithOptions) !PlainMonthDay { pub fn with(self: PlainMonthDay, options: WithOptions) !PlainMonthDay {
// Build month_code view // Build month_code view
const month_code_view = if (options.month_code) |mc| const month_code_view = if (options.month_code) |mc|
@ -149,8 +142,7 @@ pub fn with(self: PlainMonthDay, options: WithOptions) !PlainMonthDay {
// Conversion // Conversion
/// Returns a PlainDate representing this month-day and a supplied year in the same calendar system. /// Returns a PlainDate representing this month-day and a supplied year in the same calendar system.
/// /// See [MDN Temporal.PlainMonthDay.prototype.toPlainDate()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay/toPlainDate)
/// See: [Temporal.PlainMonthDay.toPlainDate](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay/toPlainDate)
pub fn toPlainDate(self: PlainMonthDay, year: i32) !PlainDate { pub fn toPlainDate(self: PlainMonthDay, year: i32) !PlainDate {
const partial_date = abi.c.PartialDate_option{ const partial_date = abi.c.PartialDate_option{
.is_ok = true, .is_ok = true,
@ -175,8 +167,7 @@ pub fn toPlainDate(self: PlainMonthDay, year: i32) !PlainDate {
// String conversions // String conversions
/// Returns a string representing this month-day in RFC 9557 format. /// Returns a string representing this month-day in RFC 9557 format.
/// /// See [MDN Temporal.PlainMonthDay.prototype.toString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay/toString)
/// See: [Temporal.PlainMonthDay.toString](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay/toString)
pub fn toString(self: PlainMonthDay, allocator: std.mem.Allocator) ![]u8 { pub fn toString(self: PlainMonthDay, allocator: std.mem.Allocator) ![]u8 {
return toStringWithOptions(self, allocator, .{}); return toStringWithOptions(self, allocator, .{});
} }
@ -193,27 +184,26 @@ fn toStringWithOptions(self: PlainMonthDay, allocator: std.mem.Allocator, option
} }
/// Returns a string representing this month-day in RFC 9557 format (ISO 8601). /// Returns a string representing this month-day in RFC 9557 format (ISO 8601).
/// /// See [MDN Temporal.PlainMonthDay.prototype.toJSON()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay/toJSON)
/// See: [Temporal.PlainMonthDay.toJSON](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay/toJSON)
pub fn toJSON(self: PlainMonthDay, allocator: std.mem.Allocator) ![]u8 { pub fn toJSON(self: PlainMonthDay, allocator: std.mem.Allocator) ![]u8 {
return toString(self, allocator); return toString(self, allocator);
} }
/// Returns a language-sensitive string representation of this month-day. /// Returns a language-sensitive string representation of this month-day.
/// /// See [MDN Temporal.PlainMonthDay.prototype.toLocaleString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay/toLocaleString)
/// See: [Temporal.PlainMonthDay.toLocaleString](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay/toLocaleString)
pub fn toLocaleString(self: PlainMonthDay, allocator: std.mem.Allocator) ![]u8 { pub fn toLocaleString(self: PlainMonthDay, allocator: std.mem.Allocator) ![]u8 {
return toString(self, allocator); return toString(self, allocator);
} }
/// Throws an error; valueOf() is not supported for PlainMonthDay. /// Throws an error; valueOf() is not supported for PlainMonthDay.
/// /// See [MDN Temporal.PlainMonthDay.prototype.valueOf()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay/valueOf)
/// See: [Temporal.PlainMonthDay.valueOf](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay/valueOf)
pub fn valueOf(self: PlainMonthDay) !void { pub fn valueOf(self: PlainMonthDay) !void {
_ = self; _ = self;
return error.ValueError; return error.ValueError;
} }
// ---------- Tests ---------------------
test init { test init {
const md = try init(12, 25, null); const md = try init(12, 25, null);
try std.testing.expectEqual(@as(u8, 25), md.day()); try std.testing.expectEqual(@as(u8, 25), md.day());

View file

@ -8,7 +8,7 @@ const Duration = @import("Duration.zig");
/// ///
/// The `Temporal.PlainTime` object represents a wall-clock time, with no date or time zone. /// The `Temporal.PlainTime` object represents a wall-clock time, with no date or time zone.
/// ///
/// See: [Temporal.PlainTime](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime) /// - [MDN Temporal.PlainTime](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime)
const PlainTime = @This(); const PlainTime = @This();
_inner: *abi.c.PlainTime, _inner: *abi.c.PlainTime,
@ -45,26 +45,18 @@ pub fn init(
microsecond_val: u16, microsecond_val: u16,
nanosecond_val: u16, nanosecond_val: u16,
) !PlainTime { ) !PlainTime {
if (hour_val > 23 or minute_val > 59 or second_val > 59 or return wrapPlainTime(abi.c.temporal_rs_PlainTime_try_new(
millisecond_val > 999 or microsecond_val > 999 or nanosecond_val > 999)
{
return abi.TemporalError.RangeError;
}
var buf: [18]u8 = undefined;
const s = std.fmt.bufPrint(&buf, "{d:0>2}:{d:0>2}:{d:0>2}.{d:0>3}{d:0>3}{d:0>3}", .{
hour_val, hour_val,
minute_val, minute_val,
second_val, second_val,
millisecond_val, millisecond_val,
microsecond_val, microsecond_val,
nanosecond_val, nanosecond_val,
}) catch unreachable; ));
return from(s);
} }
/// Parses a PlainTime from a string. /// Parses a PlainTime from a string.
/// /// See [MDN Temporal.PlainTime.from()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/from)
/// See: [Temporal.PlainTime.from](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/from)
pub fn from(s: []const u8) !PlainTime { pub fn from(s: []const u8) !PlainTime {
return fromUtf8(s); return fromUtf8(s);
} }
@ -81,36 +73,31 @@ fn fromUtf16(utf16: []const u16) !PlainTime {
/// Compares two PlainTime instances by their time values. /// Compares two PlainTime instances by their time values.
/// Returns -1, 0, or 1 if the first is before, equal, or after the second. /// Returns -1, 0, or 1 if the first is before, equal, or after the second.
/// /// See [MDN Temporal.PlainTime.compare()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/compare)
/// See: [Temporal.PlainTime.compare](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/compare)
pub fn compare(a: PlainTime, b: PlainTime) i8 { pub fn compare(a: PlainTime, b: PlainTime) i8 {
return abi.c.temporal_rs_PlainTime_compare(a._inner, b._inner); return abi.c.temporal_rs_PlainTime_compare(a._inner, b._inner);
} }
/// Returns true if this PlainTime is equal to another (same time values). /// Returns true if this PlainTime is equal to another (same time values).
/// /// See [MDN Temporal.PlainTime.prototype.equals()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/equals)
/// See: [Temporal.PlainTime.equals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/equals)
pub fn equals(self: PlainTime, other: PlainTime) bool { pub fn equals(self: PlainTime, other: PlainTime) bool {
return abi.c.temporal_rs_PlainTime_equals(self._inner, other._inner); return abi.c.temporal_rs_PlainTime_equals(self._inner, other._inner);
} }
/// Returns a new PlainTime moved forward by the given duration, wrapping around the clock if necessary. /// Returns a new PlainTime moved forward by the given duration, wrapping around the clock if necessary.
/// /// See [MDN Temporal.PlainTime.prototype.add()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/add)
/// See: [Temporal.PlainTime.add](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/add)
pub fn add(self: PlainTime, duration: Duration) !PlainTime { pub fn add(self: PlainTime, duration: Duration) !PlainTime {
return wrapPlainTime(abi.c.temporal_rs_PlainTime_add(self._inner, duration._inner)); return wrapPlainTime(abi.c.temporal_rs_PlainTime_add(self._inner, duration._inner));
} }
/// Returns a new PlainTime moved backward by the given duration, wrapping around the clock if necessary. /// Returns a new PlainTime moved backward by the given duration, wrapping around the clock if necessary.
/// /// See [MDN Temporal.PlainTime.prototype.subtract()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/subtract)
/// See: [Temporal.PlainTime.subtract](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/subtract)
pub fn subtract(self: PlainTime, duration: Duration) !PlainTime { pub fn subtract(self: PlainTime, duration: Duration) !PlainTime {
return wrapPlainTime(abi.c.temporal_rs_PlainTime_subtract(self._inner, duration._inner)); return wrapPlainTime(abi.c.temporal_rs_PlainTime_subtract(self._inner, duration._inner));
} }
/// Returns the duration from this PlainTime to another. /// Returns the duration from this PlainTime to another.
/// /// See [MDN Temporal.PlainTime.prototype.until()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/until)
/// See: [Temporal.PlainTime.until](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/until)
pub fn until(self: PlainTime, other: PlainTime, options: DifferenceSettings) !Duration { pub fn until(self: PlainTime, other: PlainTime, options: DifferenceSettings) !Duration {
const settings = abi.to.diffsettings(options); const settings = abi.to.diffsettings(options);
const result = abi.c.temporal_rs_PlainTime_until(self._inner, other._inner, settings); const result = abi.c.temporal_rs_PlainTime_until(self._inner, other._inner, settings);
@ -119,8 +106,7 @@ pub fn until(self: PlainTime, other: PlainTime, options: DifferenceSettings) !Du
} }
/// Returns the duration from another PlainTime to this one. /// Returns the duration from another PlainTime to this one.
/// /// See [MDN Temporal.PlainTime.prototype.since()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/since)
/// See: [Temporal.PlainTime.since](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/since)
pub fn since(self: PlainTime, other: PlainTime, options: DifferenceSettings) !Duration { pub fn since(self: PlainTime, other: PlainTime, options: DifferenceSettings) !Duration {
const settings = abi.to.diffsettings(options); const settings = abi.to.diffsettings(options);
const result = abi.c.temporal_rs_PlainTime_since(self._inner, other._inner, settings); const result = abi.c.temporal_rs_PlainTime_since(self._inner, other._inner, settings);
@ -130,59 +116,51 @@ pub fn since(self: PlainTime, other: PlainTime, options: DifferenceSettings) !Du
// Rounding // Rounding
/// Returns a new PlainTime rounded to the given unit and options. /// Returns a new PlainTime rounded to the given unit and options.
/// /// See [MDN Temporal.PlainTime.prototype.round()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/round)
/// See: [Temporal.PlainTime.round](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/round)
pub fn round(self: PlainTime, options: RoundOptions) !PlainTime { pub fn round(self: PlainTime, options: RoundOptions) !PlainTime {
return wrapPlainTime(abi.c.temporal_rs_PlainTime_round(self._inner, abi.to.roundingOpts(options))); return wrapPlainTime(abi.c.temporal_rs_PlainTime_round(self._inner, abi.to.roundingOpts(options)));
} }
// Property accessors // Property accessors
/// Returns the hour component of this time (0-23). /// Returns the hour component of this time (0-23).
/// /// See [MDN Temporal.PlainTime.prototype.hour](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/hour)
/// See: [Temporal.PlainTime.hour](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/hour)
pub fn hour(self: PlainTime) u8 { pub fn hour(self: PlainTime) u8 {
return abi.c.temporal_rs_PlainTime_hour(self._inner); return abi.c.temporal_rs_PlainTime_hour(self._inner);
} }
/// Returns the minute component of this time (0-59). /// Returns the minute component of this time (0-59).
/// /// See [MDN Temporal.PlainTime.prototype.minute](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/minute)
/// See: [Temporal.PlainTime.minute](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/minute)
pub fn minute(self: PlainTime) u8 { pub fn minute(self: PlainTime) u8 {
return abi.c.temporal_rs_PlainTime_minute(self._inner); return abi.c.temporal_rs_PlainTime_minute(self._inner);
} }
/// Returns the second component of this time (0-59). /// Returns the second component of this time (0-59).
/// /// See [MDN Temporal.PlainTime.prototype.second](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/second)
/// See: [Temporal.PlainTime.second](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/second)
pub fn second(self: PlainTime) u8 { pub fn second(self: PlainTime) u8 {
return abi.c.temporal_rs_PlainTime_second(self._inner); return abi.c.temporal_rs_PlainTime_second(self._inner);
} }
/// Returns the millisecond component of this time (0-999). /// Returns the millisecond component of this time (0-999).
/// /// See [MDN Temporal.PlainTime.prototype.millisecond](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/millisecond)
/// See: [Temporal.PlainTime.millisecond](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/millisecond)
pub fn millisecond(self: PlainTime) u16 { pub fn millisecond(self: PlainTime) u16 {
return abi.c.temporal_rs_PlainTime_millisecond(self._inner); return abi.c.temporal_rs_PlainTime_millisecond(self._inner);
} }
/// Returns the microsecond component of this time (0-999). /// Returns the microsecond component of this time (0-999).
/// /// See [MDN Temporal.PlainTime.prototype.microsecond](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/microsecond)
/// See: [Temporal.PlainTime.microsecond](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/microsecond)
pub fn microsecond(self: PlainTime) u16 { pub fn microsecond(self: PlainTime) u16 {
return abi.c.temporal_rs_PlainTime_microsecond(self._inner); return abi.c.temporal_rs_PlainTime_microsecond(self._inner);
} }
/// Returns the nanosecond component of this time (0-999). /// Returns the nanosecond component of this time (0-999).
/// /// See [MDN Temporal.PlainTime.prototype.nanosecond](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/nanosecond)
/// See: [Temporal.PlainTime.nanosecond](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/nanosecond)
pub fn nanosecond(self: PlainTime) u16 { pub fn nanosecond(self: PlainTime) u16 {
return abi.c.temporal_rs_PlainTime_nanosecond(self._inner); return abi.c.temporal_rs_PlainTime_nanosecond(self._inner);
} }
// Modification // Modification
/// Returns a new PlainTime with some fields replaced by new values. /// Returns a new PlainTime with some fields replaced by new values.
/// /// See [MDN Temporal.PlainTime.prototype.with()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/with)
/// See: [Temporal.PlainTime.with](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/with)
pub fn with(self: PlainTime, options: WithOptions) !PlainTime { pub fn with(self: PlainTime, options: WithOptions) !PlainTime {
const partial = abi.c.PartialTime{ const partial = abi.c.PartialTime{
.hour = abi.toOption(abi.c.OptionU8, options.hour), .hour = abi.toOption(abi.c.OptionU8, options.hour),
@ -201,8 +179,7 @@ pub fn with(self: PlainTime, options: WithOptions) !PlainTime {
// String conversions // String conversions
/// Returns a string representing this PlainTime in RFC 9557 format. /// Returns a string representing this PlainTime in RFC 9557 format.
/// /// See [MDN Temporal.PlainTime.prototype.toString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/toString)
/// See: [Temporal.PlainTime.toString](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/toString)
pub fn toString(self: PlainTime, allocator: std.mem.Allocator) ![]u8 { pub fn toString(self: PlainTime, allocator: std.mem.Allocator) ![]u8 {
return toStringWithOptions(self, allocator, .{}); return toStringWithOptions(self, allocator, .{});
} }
@ -224,29 +201,28 @@ fn toStringWithOptions(self: PlainTime, allocator: std.mem.Allocator, options: t
} }
/// Returns a string representing this PlainTime in RFC 9557 format (ISO 8601). /// Returns a string representing this PlainTime in RFC 9557 format (ISO 8601).
/// /// See [MDN Temporal.PlainTime.prototype.toJSON()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/toJSON)
/// See: [Temporal.PlainTime.toJSON](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/toJSON)
pub fn toJSON(self: PlainTime, allocator: std.mem.Allocator) ![]u8 { pub fn toJSON(self: PlainTime, allocator: std.mem.Allocator) ![]u8 {
return toString(self, allocator); return toString(self, allocator);
} }
/// Returns a language-sensitive string representation of this PlainTime. /// Returns a language-sensitive string representation of this PlainTime.
/// /// See [MDN Temporal.PlainTime.prototype.toLocaleString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/toLocaleString)
/// See: [Temporal.PlainTime.toLocaleString](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/toLocaleString)
pub fn toLocaleString(self: PlainTime, allocator: std.mem.Allocator) ![]u8 { pub fn toLocaleString(self: PlainTime, allocator: std.mem.Allocator) ![]u8 {
// For now, just use toString - locale-specific formatting would require more work // For now, just use toString - locale-specific formatting would require more work
return toString(self, allocator); return toString(self, allocator);
} }
/// Throws an error; valueOf() is not supported for PlainTime. /// Throws an error; valueOf() is not supported for PlainTime.
/// /// See [MDN Temporal.PlainTime.prototype.valueOf()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/valueOf)
/// See: [Temporal.PlainTime.valueOf](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime/valueOf)
pub fn valueOf(self: PlainTime) !void { pub fn valueOf(self: PlainTime) !void {
_ = self; _ = self;
// PlainTime should not be used in arithmetic/comparison operations implicitly // PlainTime should not be used in arithmetic/comparison operations implicitly
return error.ValueError; return error.ValueError;
} }
// ---------- Tests ---------------------
test init { test init {
{ {
const time = try init(14, 30, 45, 123, 456, 789); const time = try init(14, 30, 45, 123, 456, 789);

View file

@ -9,7 +9,7 @@ const Duration = @import("Duration.zig");
/// ///
/// The `Temporal.PlainYearMonth` object represents a particular month in a specific year, with no day or time. /// The `Temporal.PlainYearMonth` object represents a particular month in a specific year, with no day or time.
/// ///
/// See: [Temporal.PlainYearMonth](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth) /// - [MDN Temporal.PlainYearMonth](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth)
const PlainYearMonth = @This(); const PlainYearMonth = @This();
_inner: *abi.c.PlainYearMonth, _inner: *abi.c.PlainYearMonth,
@ -47,8 +47,7 @@ fn wrapPlainYearMonth(result: anytype) !PlainYearMonth {
/// Creates a new PlainYearMonth from the given year, month, and optional calendar. /// Creates a new PlainYearMonth from the given year, month, and optional calendar.
/// Equivalent to the Temporal.PlainYearMonth constructor. /// Equivalent to the Temporal.PlainYearMonth constructor.
/// /// See [MDN Temporal.PlainYearMonth() constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/PlainYearMonth)
/// See: [Temporal.PlainYearMonth](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/PlainYearMonth)
pub fn init(year_val: i32, month_val: u8, calendar: ?[]const u8) !PlainYearMonth { pub fn init(year_val: i32, month_val: u8, calendar: ?[]const u8) !PlainYearMonth {
const cal_kind = if (calendar) |cal| blk: { const cal_kind = if (calendar) |cal| blk: {
const cal_view = abi.toDiplomatStringView(cal); const cal_view = abi.toDiplomatStringView(cal);
@ -69,8 +68,7 @@ pub fn init(year_val: i32, month_val: u8, calendar: ?[]const u8) !PlainYearMonth
} }
/// Parses a PlainYearMonth from a string. /// Parses a PlainYearMonth from a string.
/// /// See [MDN Temporal.PlainYearMonth.from()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/from)
/// See: [Temporal.PlainYearMonth.from](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/from)
pub fn from(s: []const u8) !PlainYearMonth { pub fn from(s: []const u8) !PlainYearMonth {
return fromUtf8(s); return fromUtf8(s);
} }
@ -88,39 +86,34 @@ fn fromUtf16(utf16: []const u16) !PlainYearMonth {
// Comparison // Comparison
/// Compares two PlainYearMonth instances by their ISO date values. /// Compares two PlainYearMonth instances by their ISO date values.
/// Returns -1, 0, or 1 if the first is before, equal, or after the second. /// Returns -1, 0, or 1 if the first is before, equal, or after the second.
/// /// See [MDN Temporal.PlainYearMonth.compare()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/compare)
/// See: [Temporal.PlainYearMonth.compare](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/compare)
pub fn compare(a: PlainYearMonth, b: PlainYearMonth) i8 { pub fn compare(a: PlainYearMonth, b: PlainYearMonth) i8 {
return abi.c.temporal_rs_PlainYearMonth_compare(a._inner, b._inner); return abi.c.temporal_rs_PlainYearMonth_compare(a._inner, b._inner);
} }
/// Returns true if this PlainYearMonth is equal to another (same ISO date and calendar). /// Returns true if this PlainYearMonth is equal to another (same ISO date and calendar).
/// /// See [MDN Temporal.PlainYearMonth.prototype.equals()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/equals)
/// See: [Temporal.PlainYearMonth.equals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/equals)
pub fn equals(self: PlainYearMonth, other: PlainYearMonth) bool { pub fn equals(self: PlainYearMonth, other: PlainYearMonth) bool {
return abi.c.temporal_rs_PlainYearMonth_equals(self._inner, other._inner); return abi.c.temporal_rs_PlainYearMonth_equals(self._inner, other._inner);
} }
// Arithmetic // Arithmetic
/// Returns a new PlainYearMonth moved forward by the given duration. /// Returns a new PlainYearMonth moved forward by the given duration.
/// /// See [MDN Temporal.PlainYearMonth.prototype.add()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/add)
/// See: [Temporal.PlainYearMonth.add](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/add)
pub fn add(self: PlainYearMonth, duration: Duration) !PlainYearMonth { pub fn add(self: PlainYearMonth, duration: Duration) !PlainYearMonth {
const overflow = abi.c.ArithmeticOverflow_Constrain; const overflow = abi.c.ArithmeticOverflow_Constrain;
return wrapPlainYearMonth(abi.c.temporal_rs_PlainYearMonth_add(self._inner, duration._inner, overflow)); return wrapPlainYearMonth(abi.c.temporal_rs_PlainYearMonth_add(self._inner, duration._inner, overflow));
} }
/// Returns a new PlainYearMonth moved backward by the given duration. /// Returns a new PlainYearMonth moved backward by the given duration.
/// /// See [MDN Temporal.PlainYearMonth.prototype.subtract()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/subtract)
/// See: [Temporal.PlainYearMonth.subtract](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/subtract)
pub fn subtract(self: PlainYearMonth, duration: Duration) !PlainYearMonth { pub fn subtract(self: PlainYearMonth, duration: Duration) !PlainYearMonth {
const overflow = abi.c.ArithmeticOverflow_Constrain; const overflow = abi.c.ArithmeticOverflow_Constrain;
return wrapPlainYearMonth(abi.c.temporal_rs_PlainYearMonth_subtract(self._inner, duration._inner, overflow)); return wrapPlainYearMonth(abi.c.temporal_rs_PlainYearMonth_subtract(self._inner, duration._inner, overflow));
} }
/// Returns the duration from this PlainYearMonth to another. /// Returns the duration from this PlainYearMonth to another.
/// /// See [MDN Temporal.PlainYearMonth.prototype.until()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/until)
/// See: [Temporal.PlainYearMonth.until](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/until)
pub fn until(self: PlainYearMonth, other: PlainYearMonth, options: DifferenceSettings) !Duration { pub fn until(self: PlainYearMonth, other: PlainYearMonth, options: DifferenceSettings) !Duration {
const settings = abi.to.diffsettings(options); const settings = abi.to.diffsettings(options);
const result = abi.c.temporal_rs_PlainYearMonth_until(self._inner, other._inner, settings); const result = abi.c.temporal_rs_PlainYearMonth_until(self._inner, other._inner, settings);
@ -129,8 +122,7 @@ pub fn until(self: PlainYearMonth, other: PlainYearMonth, options: DifferenceSet
} }
/// Returns the duration from another PlainYearMonth to this one. /// Returns the duration from another PlainYearMonth to this one.
/// /// See [MDN Temporal.PlainYearMonth.prototype.since()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/since)
/// See: [Temporal.PlainYearMonth.since](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/since)
pub fn since(self: PlainYearMonth, other: PlainYearMonth, options: DifferenceSettings) !Duration { pub fn since(self: PlainYearMonth, other: PlainYearMonth, options: DifferenceSettings) !Duration {
const settings = abi.to.diffsettings(options); const settings = abi.to.diffsettings(options);
const result = abi.c.temporal_rs_PlainYearMonth_since(self._inner, other._inner, settings); const result = abi.c.temporal_rs_PlainYearMonth_since(self._inner, other._inner, settings);
@ -140,8 +132,7 @@ pub fn since(self: PlainYearMonth, other: PlainYearMonth, options: DifferenceSet
// Property accessors // Property accessors
/// Returns the calendar identifier used to interpret the internal ISO 8601 date. /// Returns the calendar identifier used to interpret the internal ISO 8601 date.
/// /// See [MDN Temporal.PlainYearMonth.prototype.calendarId](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/calendarId)
/// See: [Temporal.PlainYearMonth.calendarId](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/calendarId)
pub fn calendarId(self: PlainYearMonth, allocator: std.mem.Allocator) ![]u8 { pub fn calendarId(self: PlainYearMonth, allocator: std.mem.Allocator) ![]u8 {
const calendar_ptr = abi.c.temporal_rs_PlainYearMonth_calendar(self._inner) orelse return error.TemporalError; const calendar_ptr = abi.c.temporal_rs_PlainYearMonth_calendar(self._inner) orelse return error.TemporalError;
const cal_id_view = abi.c.temporal_rs_Calendar_identifier(calendar_ptr); const cal_id_view = abi.c.temporal_rs_Calendar_identifier(calendar_ptr);
@ -149,22 +140,19 @@ pub fn calendarId(self: PlainYearMonth, allocator: std.mem.Allocator) ![]u8 {
} }
/// Returns the year of this year-month relative to the calendar's epoch. /// Returns the year of this year-month relative to the calendar's epoch.
/// /// See [MDN Temporal.PlainYearMonth.prototype.year](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/year)
/// See: [Temporal.PlainYearMonth.year](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/year)
pub fn year(self: PlainYearMonth) i32 { pub fn year(self: PlainYearMonth) i32 {
return abi.c.temporal_rs_PlainYearMonth_year(self._inner); return abi.c.temporal_rs_PlainYearMonth_year(self._inner);
} }
/// Returns the 1-based month index in the year of this year-month. /// Returns the 1-based month index in the year of this year-month.
/// /// See [MDN Temporal.PlainYearMonth.prototype.month](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/month)
/// See: [Temporal.PlainYearMonth.month](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/month)
pub fn month(self: PlainYearMonth) u8 { pub fn month(self: PlainYearMonth) u8 {
return abi.c.temporal_rs_PlainYearMonth_month(self._inner); return abi.c.temporal_rs_PlainYearMonth_month(self._inner);
} }
/// Returns the calendar-specific string representing the month of this year-month. /// Returns the calendar-specific string representing the month of this year-month.
/// /// See [MDN Temporal.PlainYearMonth.prototype.monthCode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/monthCode)
/// See: [Temporal.PlainYearMonth.monthCode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/monthCode)
pub fn monthCode(self: PlainYearMonth, allocator: std.mem.Allocator) ![]const u8 { pub fn monthCode(self: PlainYearMonth, allocator: std.mem.Allocator) ![]const u8 {
var write = abi.DiplomatWrite.init(allocator); var write = abi.DiplomatWrite.init(allocator);
defer write.deinit(); defer write.deinit();
@ -174,36 +162,31 @@ pub fn monthCode(self: PlainYearMonth, allocator: std.mem.Allocator) ![]const u8
} }
/// Returns the number of days in the month of this year-month. /// Returns the number of days in the month of this year-month.
/// /// See [MDN Temporal.PlainYearMonth.prototype.daysInMonth](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/daysInMonth)
/// See: [Temporal.PlainYearMonth.daysInMonth](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/daysInMonth)
pub fn daysInMonth(self: PlainYearMonth) u16 { pub fn daysInMonth(self: PlainYearMonth) u16 {
return abi.c.temporal_rs_PlainYearMonth_days_in_month(self._inner); return abi.c.temporal_rs_PlainYearMonth_days_in_month(self._inner);
} }
/// Returns the number of days in the year of this year-month. /// Returns the number of days in the year of this year-month.
/// /// See [MDN Temporal.PlainYearMonth.prototype.daysInYear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/daysInYear)
/// See: [Temporal.PlainYearMonth.daysInYear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/daysInYear)
pub fn daysInYear(self: PlainYearMonth) u16 { pub fn daysInYear(self: PlainYearMonth) u16 {
return abi.c.temporal_rs_PlainYearMonth_days_in_year(self._inner); return abi.c.temporal_rs_PlainYearMonth_days_in_year(self._inner);
} }
/// Returns the number of months in the year of this year-month. /// Returns the number of months in the year of this year-month.
/// /// See [MDN Temporal.PlainYearMonth.prototype.monthsInYear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/monthsInYear)
/// See: [Temporal.PlainYearMonth.monthsInYear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/monthsInYear)
pub fn monthsInYear(self: PlainYearMonth) u16 { pub fn monthsInYear(self: PlainYearMonth) u16 {
return abi.c.temporal_rs_PlainYearMonth_months_in_year(self._inner); return abi.c.temporal_rs_PlainYearMonth_months_in_year(self._inner);
} }
/// Returns true if this year-month is in a leap year. /// Returns true if this year-month is in a leap year.
/// /// See [MDN Temporal.PlainYearMonth.prototype.inLeapYear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/inLeapYear)
/// See: [Temporal.PlainYearMonth.inLeapYear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/inLeapYear)
pub fn inLeapYear(self: PlainYearMonth) bool { pub fn inLeapYear(self: PlainYearMonth) bool {
return abi.c.temporal_rs_PlainYearMonth_in_leap_year(self._inner); return abi.c.temporal_rs_PlainYearMonth_in_leap_year(self._inner);
} }
/// Returns the calendar-specific era of this year-month, or null if not applicable. /// Returns the calendar-specific era of this year-month, or null if not applicable.
/// /// See [MDN Temporal.PlainYearMonth.prototype.era](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/era)
/// See: [Temporal.PlainYearMonth.era](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/era)
pub fn era(self: PlainYearMonth, allocator: std.mem.Allocator) !?[]const u8 { pub fn era(self: PlainYearMonth, allocator: std.mem.Allocator) !?[]const u8 {
var write = abi.DiplomatWrite.init(allocator); var write = abi.DiplomatWrite.init(allocator);
defer write.deinit(); defer write.deinit();
@ -215,8 +198,7 @@ pub fn era(self: PlainYearMonth, allocator: std.mem.Allocator) !?[]const u8 {
} }
/// Returns the year of this year-month within the era, or null if not applicable. /// Returns the year of this year-month within the era, or null if not applicable.
/// /// See [MDN Temporal.PlainYearMonth.prototype.eraYear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/eraYear)
/// See: [Temporal.PlainYearMonth.eraYear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/eraYear)
pub fn eraYear(self: PlainYearMonth) ?i32 { pub fn eraYear(self: PlainYearMonth) ?i32 {
const result = abi.c.temporal_rs_PlainYearMonth_era_year(self._inner); const result = abi.c.temporal_rs_PlainYearMonth_era_year(self._inner);
if (!result.is_ok) return null; if (!result.is_ok) return null;
@ -225,8 +207,7 @@ pub fn eraYear(self: PlainYearMonth) ?i32 {
// Modification // Modification
/// Returns a new PlainYearMonth with some fields replaced by new values. /// Returns a new PlainYearMonth with some fields replaced by new values.
/// /// See [MDN Temporal.PlainYearMonth.prototype.with()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/with)
/// See: [Temporal.PlainYearMonth.with](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/with)
pub fn with(self: PlainYearMonth, options: WithOptions) !PlainYearMonth { pub fn with(self: PlainYearMonth, options: WithOptions) !PlainYearMonth {
// Build month_code view // Build month_code view
const month_code_view = if (options.month_code) |mc| const month_code_view = if (options.month_code) |mc|
@ -259,8 +240,7 @@ pub fn with(self: PlainYearMonth, options: WithOptions) !PlainYearMonth {
// Conversion // Conversion
/// Returns a PlainDate representing this year-month and a supplied day in the same calendar system. /// Returns a PlainDate representing this year-month and a supplied day in the same calendar system.
/// /// See [MDN Temporal.PlainYearMonth.prototype.toPlainDate()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/toPlainDate)
/// See: [Temporal.PlainYearMonth.toPlainDate](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/toPlainDate)
pub fn toPlainDate(self: PlainYearMonth, day: u8) !PlainDate { pub fn toPlainDate(self: PlainYearMonth, day: u8) !PlainDate {
const partial_date = abi.c.PartialDate_option{ const partial_date = abi.c.PartialDate_option{
.is_ok = true, .is_ok = true,
@ -285,8 +265,7 @@ pub fn toPlainDate(self: PlainYearMonth, day: u8) !PlainDate {
// String conversions // String conversions
/// Returns a string representing this year-month in RFC 9557 format. /// Returns a string representing this year-month in RFC 9557 format.
/// /// See [MDN Temporal.PlainYearMonth.prototype.toString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/toString)
/// See: [Temporal.PlainYearMonth.toString](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/toString)
pub fn toString(self: PlainYearMonth, allocator: std.mem.Allocator) ![]u8 { pub fn toString(self: PlainYearMonth, allocator: std.mem.Allocator) ![]u8 {
return toStringWithOptions(self, allocator, .{}); return toStringWithOptions(self, allocator, .{});
} }
@ -303,27 +282,26 @@ fn toStringWithOptions(self: PlainYearMonth, allocator: std.mem.Allocator, optio
} }
/// Returns a JSON string representing this year-month. /// Returns a JSON string representing this year-month.
/// /// See [MDN Temporal.PlainYearMonth.prototype.toJSON()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/toJSON)
/// See: [Temporal.PlainYearMonth.toJSON](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/toJSON)
pub fn toJSON(self: PlainYearMonth, allocator: std.mem.Allocator) ![]u8 { pub fn toJSON(self: PlainYearMonth, allocator: std.mem.Allocator) ![]u8 {
return toString(self, allocator); return toString(self, allocator);
} }
/// Returns a locale-sensitive string representing this year-month. /// Returns a locale-sensitive string representing this year-month.
/// /// See [MDN Temporal.PlainYearMonth.prototype.toLocaleString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/toLocaleString)
/// See: [Temporal.PlainYearMonth.toLocaleString](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/toLocaleString)
pub fn toLocaleString(self: PlainYearMonth, allocator: std.mem.Allocator) ![]u8 { pub fn toLocaleString(self: PlainYearMonth, allocator: std.mem.Allocator) ![]u8 {
return toString(self, allocator); return toString(self, allocator);
} }
/// Throws a TypeError, as PlainYearMonth objects cannot be converted to primitive values. /// Throws a TypeError, as PlainYearMonth objects cannot be converted to primitive values.
/// /// See [MDN Temporal.PlainYearMonth.prototype.valueOf()](https://developer.mozilla
/// See: [Temporal.PlainYearMonth.valueOf](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/valueOf)
pub fn valueOf(self: PlainYearMonth) !void { pub fn valueOf(self: PlainYearMonth) !void {
_ = self; _ = self;
return error.ValueError; return error.ValueError;
} }
// ---------- Tests ---------------------
test init { test init {
const ym = try init(2024, 12, null); const ym = try init(2024, 12, null);
try std.testing.expectEqual(@as(i32, 2024), ym.year()); try std.testing.expectEqual(@as(i32, 2024), ym.year());
@ -452,43 +430,6 @@ test until {
try std.testing.expectEqual(@as(i64, 6), dur.months()); try std.testing.expectEqual(@as(i64, 6), dur.months());
} }
test calendarId {
const ym = try from("2021-07-01[u-ca=gregory]");
const cal_id = try ym.calendarId(std.testing.allocator);
defer std.testing.allocator.free(cal_id);
try std.testing.expectEqualStrings("gregory", cal_id);
}
test year {
const ym = try from("2021-07");
try std.testing.expectEqual(@as(i32, 2021), ym.year());
}
test month {
const ym = try from("2021-07");
try std.testing.expectEqual(@as(u8, 7), ym.month());
}
test monthCode {
const ym = try from("2021-07");
const month_code = try ym.monthCode(std.testing.allocator);
defer std.testing.allocator.free(month_code);
try std.testing.expectEqualStrings("M07", month_code);
}
test era {
const ym = try from("2021-07-01[u-ca=gregory]");
const maybe_era = try ym.era(std.testing.allocator);
const era_value = maybe_era orelse return error.TestUnexpectedResult;
defer std.testing.allocator.free(era_value);
try std.testing.expectEqualStrings("ce", era_value);
}
test eraYear {
const ym = try from("2021-07-01[u-ca=gregory]");
try std.testing.expectEqual(@as(?i32, 2021), ym.eraYear());
}
test with { test with {
// Test modifying year // Test modifying year
const ym1 = try init(2024, 6, null); const ym1 = try init(2024, 6, null);

View file

@ -1,68 +0,0 @@
const builtin = @import("builtin");
const std = @import("std");
const ZonedDateTime = @import("ZonedDateTime.zig");
const zoneinfo_marker = "zoneinfo/";
/// Returns the host environment's current time zone identifier.
///
/// Resolution order:
/// 1. `TZ` environment variable (when set and non-empty)
/// 2. Unix: `/etc/localtime` symlink target under `zoneinfo/`
/// 3. `"UTC"`
///
/// The caller owns the returned slice.
pub fn identifier(allocator: std.mem.Allocator, io: std.Io) ![]const u8 {
if (tzFromEnv(allocator)) |tz| return tz;
if (detectFromPlatform(allocator, io)) |tz| return tz;
return try allocator.dupe(u8, "UTC");
}
/// Returns a `TimeZone` for the host environment's current time zone.
pub fn timeZone(allocator: std.mem.Allocator, io: std.Io) !ZonedDateTime.TimeZone {
const id = try identifier(allocator, io);
defer allocator.free(id);
return ZonedDateTime.TimeZone.init(id);
}
fn tzFromEnv(allocator: std.mem.Allocator) ?[]const u8 {
if (!builtin.link_libc) return null;
const value = std.c.getenv("TZ") orelse return null;
const tz = std.mem.span(value);
if (tz.len == 0) return null;
return allocator.dupe(u8, tz) catch null;
}
fn detectFromPlatform(allocator: std.mem.Allocator, io: std.Io) ?[]const u8 {
return switch (builtin.os.tag) {
.linux, .macos, .freebsd, .openbsd, .netbsd, .dragonfly => detectFromEtcLocaltime(allocator, io) catch null,
else => null,
};
}
fn detectFromEtcLocaltime(allocator: std.mem.Allocator, io: std.Io) ![]const u8 {
var target_buf: [std.fs.max_path_bytes]u8 = undefined;
const len = std.Io.Dir.readLinkAbsolute(io, "/etc/localtime", &target_buf) catch return error.NotFound;
const target = target_buf[0..len];
const idx = std.mem.lastIndexOf(u8, target, zoneinfo_marker) orelse return error.NotFound;
return try allocator.dupe(u8, target[idx + zoneinfo_marker.len ..]);
}
test identifier {
const io = std.testing.io;
const tz = try identifier(std.testing.allocator, io);
defer std.testing.allocator.free(tz);
try std.testing.expect(tz.len > 0);
_ = try ZonedDateTime.TimeZone.init(tz);
}
test timeZone {
const io = std.testing.io;
_ = try timeZone(std.testing.allocator, io);
}

View file

@ -13,21 +13,27 @@ const ZonedDateTime = @This();
_inner: *abi.c.ZonedDateTime, _inner: *abi.c.ZonedDateTime,
/// The unit of time used for rounding and difference calculations. /// The unit of time used for rounding and difference calculations.
/// See [MDN Temporal.ZonedDateTime](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime) for details.
pub const Unit = t.Unit; pub const Unit = t.Unit;
/// The rounding mode used for rounding operations. /// The rounding mode used for rounding operations.
/// See [MDN Temporal.ZonedDateTime](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime) for details.
pub const RoundingMode = t.RoundingMode; pub const RoundingMode = t.RoundingMode;
/// The sign of a duration or difference. /// The sign of a duration or difference.
/// See [MDN Temporal.ZonedDateTime](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime) for details.
pub const Sign = t.Sign; pub const Sign = t.Sign;
/// Options for difference calculations between ZonedDateTime instances. /// Options for difference calculations between ZonedDateTime instances.
/// See [MDN Temporal.ZonedDateTime#instance_methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime#instance_methods) for details.
pub const DifferenceSettings = t.DifferenceSettings; pub const DifferenceSettings = t.DifferenceSettings;
/// Options for rounding ZonedDateTime instances. /// Options for rounding ZonedDateTime instances.
/// See [MDN Temporal.ZonedDateTime#instance_methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime#instance_methods) for details.
pub const RoundOptions = t.RoundingOptions; pub const RoundOptions = t.RoundingOptions;
/// Represents a time zone, identified by an IANA time zone identifier or a fixed offset. /// Represents a time zone, identified by an IANA time zone identifier or a fixed offset.
/// See [MDN Temporal.ZonedDateTime#time-zones-and-offsets](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime#time-zones-and-offsets).
pub const TimeZone = struct { pub const TimeZone = struct {
_inner: abi.c.TimeZone, _inner: abi.c.TimeZone,
@ -41,6 +47,7 @@ pub const TimeZone = struct {
}; };
/// Disambiguation options for resolving ambiguous local times (e.g., during DST transitions). /// Disambiguation options for resolving ambiguous local times (e.g., during DST transitions).
/// See [MDN Temporal.ZonedDateTime#ambiguity-and-gaps-from-local-time-to-utc-time](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime#ambiguity-and-gaps-from-local-time-to-utc-time).
pub const Disambiguation = enum { pub const Disambiguation = enum {
compatible, compatible,
earlier, earlier,
@ -49,6 +56,7 @@ pub const Disambiguation = enum {
}; };
/// Options for resolving offset ambiguity when parsing ZonedDateTime from a string. /// Options for resolving offset ambiguity when parsing ZonedDateTime from a string.
/// See [MDN Temporal.ZonedDateTime#offset-ambiguity](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime#offset-ambiguity).
pub const OffsetDisambiguation = enum { pub const OffsetDisambiguation = enum {
use_offset, use_offset,
prefer_offset, prefer_offset,
@ -57,6 +65,7 @@ pub const OffsetDisambiguation = enum {
}; };
/// Controls how the calendar is displayed in string output. /// Controls how the calendar is displayed in string output.
/// See [MDN Temporal.ZonedDateTime#rfc-9557-format](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime#rfc-9557-format).
pub const CalendarDisplay = enum { pub const CalendarDisplay = enum {
auto, auto,
always, always,
@ -65,12 +74,14 @@ pub const CalendarDisplay = enum {
}; };
/// Controls how the offset is displayed in string output. /// Controls how the offset is displayed in string output.
/// See [MDN Temporal.ZonedDateTime#rfc-9557-format](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime#rfc-9557-format).
pub const DisplayOffset = enum { pub const DisplayOffset = enum {
auto, auto,
never, never,
}; };
/// Controls how the time zone is displayed in string output. /// Controls how the time zone is displayed in string output.
/// See [MDN Temporal.ZonedDateTime#rfc-9557-format](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime#rfc-9557-format).
pub const DisplayTimeZone = enum { pub const DisplayTimeZone = enum {
auto, auto,
never, never,
@ -78,8 +89,7 @@ pub const DisplayTimeZone = enum {
}; };
/// Options for formatting ZonedDateTime as a string. /// Options for formatting ZonedDateTime as a string.
/// /// See [MDN Temporal.ZonedDateTime#rfc-9557-format](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime#rfc-9557-format).
/// See: [Temporal.ZonedDateTime.toString](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/toString#parameters)
pub const ToStringOptions = struct { pub const ToStringOptions = struct {
fractional_second_digits: ?u8 = null, fractional_second_digits: ?u8 = null,
smallest_unit: ?Unit = null, smallest_unit: ?Unit = null,
@ -89,49 +99,35 @@ pub const ToStringOptions = struct {
time_zone_name: DisplayTimeZone = .auto, time_zone_name: DisplayTimeZone = .auto,
}; };
/// Options for `with()` method. /// Helper function to wrap a C API result into a ZonedDateTime
/// fn wrapZonedDateTime(result: anytype) !ZonedDateTime {
/// See: [Temporal.ZonedDateTime.with](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/with#parameters) const ptr = (try abi.extractResult(result)) orelse return abi.TemporalError.Generic;
pub const WithOptions = struct { return .{ ._inner = ptr };
year: ?i32 = null, }
month: ?u8 = null,
month_code: ?[]const u8 = null,
day: ?u8 = null,
era: ?[]const u8 = null,
era_year: ?i32 = null,
hour: ?u8 = null,
minute: ?u8 = null,
second: ?u8 = null,
millisecond: ?u16 = null,
microsecond: ?u16 = null,
nanosecond: ?u16 = null,
offset: ?[]const u8 = null,
time_zone: ?TimeZone = null,
};
/// Creates a new ZonedDateTime from the given epoch nanoseconds and time zone. /// Creates a new ZonedDateTime from the given epoch nanoseconds and time zone.
/// Equivalent to the Temporal.ZonedDateTime constructor. /// Equivalent to the Temporal.ZonedDateTime constructor.
/// /// See [MDN Temporal.ZonedDateTime() constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/ZonedDateTime)
/// See: [Temporal.ZonedDateTime](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/ZonedDateTime)
pub fn init(epoch_ns: i128, time_zone: TimeZone) !ZonedDateTime { pub fn init(epoch_ns: i128, time_zone: TimeZone) !ZonedDateTime {
const ns_parts = abi.toI128Nanoseconds(epoch_ns); const ns_parts = abi.toI128Nanoseconds(epoch_ns);
return wrapZonedDateTime(abi.c.temporal_rs_ZonedDateTime_from_epoch_nanoseconds(ns_parts, abi.to.toTimeZone(time_zone))); return wrapZonedDateTime(abi.c.temporal_rs_ZonedDateTime_from_epoch_nanoseconds(ns_parts, abi.to.toTimeZone(time_zone)));
} }
/// Creates a new ZonedDateTime from the given epoch milliseconds and time zone. /// Creates a new ZonedDateTime from the given epoch milliseconds and time zone.
/// See [MDN Temporal.ZonedDateTime](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime)
pub fn fromEpochMilliseconds(epoch_ms: i64, time_zone: TimeZone) !ZonedDateTime { pub fn fromEpochMilliseconds(epoch_ms: i64, time_zone: TimeZone) !ZonedDateTime {
return wrapZonedDateTime(abi.c.temporal_rs_ZonedDateTime_from_epoch_milliseconds(epoch_ms, abi.to.toTimeZone(time_zone))); return wrapZonedDateTime(abi.c.temporal_rs_ZonedDateTime_from_epoch_milliseconds(epoch_ms, abi.to.toTimeZone(time_zone)));
} }
/// Creates a new ZonedDateTime from the given epoch nanoseconds and time zone. /// Creates a new ZonedDateTime from the given epoch nanoseconds and time zone.
/// See [MDN Temporal.ZonedDateTime](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime)
pub fn fromEpochNanoseconds(epoch_ns: i128, time_zone: TimeZone) !ZonedDateTime { pub fn fromEpochNanoseconds(epoch_ns: i128, time_zone: TimeZone) !ZonedDateTime {
const ns_parts = abi.toI128Nanoseconds(epoch_ns); const ns_parts = abi.toI128Nanoseconds(epoch_ns);
return wrapZonedDateTime(abi.c.temporal_rs_ZonedDateTime_from_epoch_nanoseconds(ns_parts, abi.to.toTimeZone(time_zone))); return wrapZonedDateTime(abi.c.temporal_rs_ZonedDateTime_from_epoch_nanoseconds(ns_parts, abi.to.toTimeZone(time_zone)));
} }
/// Parses a ZonedDateTime from a string, with optional disambiguation and offset options. /// Parses a ZonedDateTime from a string, with optional disambiguation and offset options.
/// /// See [MDN Temporal.ZonedDateTime.from()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/from)
/// See: [Temporal.ZonedDateTime.from](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/from)
pub fn from(s: []const u8, time_zone: ?TimeZone, disambiguation: Disambiguation, offset_disambiguation: OffsetDisambiguation) !ZonedDateTime { pub fn from(s: []const u8, time_zone: ?TimeZone, disambiguation: Disambiguation, offset_disambiguation: OffsetDisambiguation) !ZonedDateTime {
_ = time_zone; // The time zone is parsed from the string _ = time_zone; // The time zone is parsed from the string
const view = abi.toDiplomatStringView(s); const view = abi.toDiplomatStringView(s);
@ -140,30 +136,26 @@ pub fn from(s: []const u8, time_zone: ?TimeZone, disambiguation: Disambiguation,
/// Compares two ZonedDateTime instances by their instant values. /// Compares two ZonedDateTime instances by their instant values.
/// Returns -1, 0, or 1 if the first is before, equal, or after the second. /// Returns -1, 0, or 1 if the first is before, equal, or after the second.
/// /// See [MDN Temporal.ZonedDateTime.compare()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/compare)
/// See: [Temporal.ZonedDateTime.compare](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/compare)
pub fn compare(a: ZonedDateTime, b: ZonedDateTime) i8 { pub fn compare(a: ZonedDateTime, b: ZonedDateTime) i8 {
return abi.c.temporal_rs_ZonedDateTime_compare_instant(a._inner, b._inner); return abi.c.temporal_rs_ZonedDateTime_compare_instant(a._inner, b._inner);
} }
/// Returns a new ZonedDateTime moved forward by the given duration. /// Returns a new ZonedDateTime moved forward by the given duration.
/// /// See [MDN Temporal.ZonedDateTime.prototype.add()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/add)
/// See: [Temporal.ZonedDateTime.add](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/add)
pub fn add(self: ZonedDateTime, duration: Duration) !ZonedDateTime { pub fn add(self: ZonedDateTime, duration: Duration) !ZonedDateTime {
const overflow_opt = abi.toOption(abi.c.ArithmeticOverflow_option, null); const overflow_opt = abi.toOption(abi.c.ArithmeticOverflow_option, null);
return wrapZonedDateTime(abi.c.temporal_rs_ZonedDateTime_add(self._inner, duration._inner, overflow_opt)); return wrapZonedDateTime(abi.c.temporal_rs_ZonedDateTime_add(self._inner, duration._inner, overflow_opt));
} }
/// Returns true if this ZonedDateTime is equal to another (same instant, time zone, and calendar). /// Returns true if this ZonedDateTime is equal to another (same instant, time zone, and calendar).
/// /// See [MDN Temporal.ZonedDateTime.prototype.equals()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/equals)
/// See: [Temporal.ZonedDateTime.equals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/equals)
pub fn equals(self: ZonedDateTime, other: ZonedDateTime) bool { pub fn equals(self: ZonedDateTime, other: ZonedDateTime) bool {
return abi.c.temporal_rs_ZonedDateTime_equals(self._inner, other._inner); return abi.c.temporal_rs_ZonedDateTime_equals(self._inner, other._inner);
} }
/// Returns the first instant after or before this instant at which the time zone's UTC offset changes, or null if none. /// Returns the first instant after or before this instant at which the time zone's UTC offset changes, or null if none.
/// /// See [MDN Temporal.ZonedDateTime.prototype.getTimeZoneTransition()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/getTimeZoneTransition)
/// See: [Temporal.ZonedDateTime.getTimeZoneTransition](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/getTimeZoneTransition)
pub fn getTimeZoneTransition(self: ZonedDateTime, direction: enum { next, previous }) !?ZonedDateTime { pub fn getTimeZoneTransition(self: ZonedDateTime, direction: enum { next, previous }) !?ZonedDateTime {
const dir = switch (direction) { const dir = switch (direction) {
.next => abi.c.TransitionDirection_Next, .next => abi.c.TransitionDirection_Next,
@ -178,15 +170,13 @@ pub fn getTimeZoneTransition(self: ZonedDateTime, direction: enum { next, previo
} }
/// Returns a new ZonedDateTime rounded to the given unit and options. /// Returns a new ZonedDateTime rounded to the given unit and options.
/// /// See [MDN Temporal.ZonedDateTime.prototype.round()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/round)
/// See: [Temporal.ZonedDateTime.round](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/round)
pub fn round(self: ZonedDateTime, options: RoundOptions) !ZonedDateTime { pub fn round(self: ZonedDateTime, options: RoundOptions) !ZonedDateTime {
return wrapZonedDateTime(abi.c.temporal_rs_ZonedDateTime_round(self._inner, abi.to.roundingOpts(options))); return wrapZonedDateTime(abi.c.temporal_rs_ZonedDateTime_round(self._inner, abi.to.roundingOpts(options)));
} }
/// Returns the duration from another ZonedDateTime to this one. /// Returns the duration from another ZonedDateTime to this one.
/// /// See [MDN Temporal.ZonedDateTime.prototype.since()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/since)
/// See: [Temporal.ZonedDateTime.since](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/since)
pub fn since(self: ZonedDateTime, other: ZonedDateTime, settings: DifferenceSettings) !Duration { pub fn since(self: ZonedDateTime, other: ZonedDateTime, settings: DifferenceSettings) !Duration {
const ptr = try abi.extractResult(abi.c.temporal_rs_ZonedDateTime_since(self._inner, other._inner, abi.to.diffsettings(settings))); const ptr = try abi.extractResult(abi.c.temporal_rs_ZonedDateTime_since(self._inner, other._inner, abi.to.diffsettings(settings)));
if (ptr == null) return error.TemporalError; if (ptr == null) return error.TemporalError;
@ -194,69 +184,60 @@ pub fn since(self: ZonedDateTime, other: ZonedDateTime, settings: DifferenceSett
} }
/// Returns a ZonedDateTime representing the start of the day in the time zone. /// Returns a ZonedDateTime representing the start of the day in the time zone.
/// /// See [MDN Temporal.ZonedDateTime.prototype.startOfDay()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/startOfDay)
/// See: [Temporal.ZonedDateTime.startOfDay](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/startOfDay)
pub fn startOfDay(self: ZonedDateTime) !ZonedDateTime { pub fn startOfDay(self: ZonedDateTime) !ZonedDateTime {
return wrapZonedDateTime(abi.c.temporal_rs_ZonedDateTime_start_of_day(self._inner)); return wrapZonedDateTime(abi.c.temporal_rs_ZonedDateTime_start_of_day(self._inner));
} }
/// Returns a new ZonedDateTime moved backward by the given duration. /// Returns a new ZonedDateTime moved backward by the given duration.
/// /// See [MDN Temporal.ZonedDateTime.prototype.subtract()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/subtract)
/// See: [Temporal.ZonedDateTime.subtract](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/subtract)
pub fn subtract(self: ZonedDateTime, duration: Duration) !ZonedDateTime { pub fn subtract(self: ZonedDateTime, duration: Duration) !ZonedDateTime {
const overflow_opt = abi.toOption(abi.c.ArithmeticOverflow_option, null); const overflow_opt = abi.toOption(abi.c.ArithmeticOverflow_option, null);
return wrapZonedDateTime(abi.c.temporal_rs_ZonedDateTime_subtract(self._inner, duration._inner, overflow_opt)); return wrapZonedDateTime(abi.c.temporal_rs_ZonedDateTime_subtract(self._inner, duration._inner, overflow_opt));
} }
/// Returns a new Instant representing the same instant as this ZonedDateTime. /// Returns a new Instant representing the same instant as this ZonedDateTime.
/// /// See [MDN Temporal.ZonedDateTime.prototype.toInstant()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/toInstant)
/// See: [Temporal.ZonedDateTime.toInstant](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/toInstant)
pub fn toInstant(self: ZonedDateTime) !Instant { pub fn toInstant(self: ZonedDateTime) !Instant {
const instant_ptr = abi.c.temporal_rs_ZonedDateTime_to_instant(self._inner) orelse return error.TemporalError; const instant_ptr = abi.c.temporal_rs_ZonedDateTime_to_instant(self._inner) orelse return error.TemporalError;
return .{ ._inner = instant_ptr }; return .{ ._inner = instant_ptr };
} }
/// Returns a string representing this ZonedDateTime in RFC 9557 format (ISO 8601 with time zone). /// Returns a string representing this ZonedDateTime in RFC 9557 format (ISO 8601 with time zone).
/// /// See [MDN Temporal.ZonedDateTime.prototype.toJSON()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/toJSON)
/// See: [Temporal.ZonedDateTime.toJSON](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/toJSON)
pub fn toJSON(self: ZonedDateTime, allocator: std.mem.Allocator) ![]u8 { pub fn toJSON(self: ZonedDateTime, allocator: std.mem.Allocator) ![]u8 {
return self.toString(allocator, .{}); return self.toString(allocator, .{});
} }
/// Returns a language-sensitive string representation of this ZonedDateTime. /// Returns a language-sensitive string representation of this ZonedDateTime.
/// /// See [MDN Temporal.ZonedDateTime.prototype.toLocaleString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/toLocaleString)
/// See: [Temporal.ZonedDateTime.toLocaleString](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/toLocaleString)
pub fn toLocaleString(self: ZonedDateTime, allocator: std.mem.Allocator) ![]u8 { pub fn toLocaleString(self: ZonedDateTime, allocator: std.mem.Allocator) ![]u8 {
return self.toString(allocator, .{}); return self.toString(allocator, .{});
} }
/// Returns a PlainDate representing the date portion of this ZonedDateTime. /// Returns a PlainDate representing the date portion of this ZonedDateTime.
/// /// See [MDN Temporal.ZonedDateTime.prototype.toPlainDate()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/toPlainDate)
/// See: [Temporal.ZonedDateTime.toPlainDate](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/toPlainDate)
pub fn toPlainDate(self: ZonedDateTime) !PlainDate { pub fn toPlainDate(self: ZonedDateTime) !PlainDate {
const ptr = abi.c.temporal_rs_ZonedDateTime_to_plain_date(self._inner) orelse return error.TemporalError; const ptr = abi.c.temporal_rs_ZonedDateTime_to_plain_date(self._inner) orelse return error.TemporalError;
return .{ ._inner = ptr }; return .{ ._inner = ptr };
} }
/// Returns a PlainDateTime representing the date and time portions of this ZonedDateTime. /// Returns a PlainDateTime representing the date and time portions of this ZonedDateTime.
/// /// See [MDN Temporal.ZonedDateTime.prototype.toPlainDateTime()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/toPlainDateTime)
/// See: [Temporal.ZonedDateTime.toPlainDateTime](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/toPlainDateTime)
pub fn toPlainDateTime(self: ZonedDateTime) !PlainDateTime { pub fn toPlainDateTime(self: ZonedDateTime) !PlainDateTime {
const ptr = abi.c.temporal_rs_ZonedDateTime_to_plain_datetime(self._inner) orelse return error.TemporalError; const ptr = abi.c.temporal_rs_ZonedDateTime_to_plain_datetime(self._inner) orelse return error.TemporalError;
return .{ ._inner = ptr }; return .{ ._inner = ptr };
} }
/// Returns a PlainTime representing the time portion of this ZonedDateTime. /// Returns a PlainTime representing the time portion of this ZonedDateTime.
/// /// See [MDN Temporal.ZonedDateTime.prototype.toPlainTime()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/toPlainTime)
/// See: [Temporal.ZonedDateTime.toPlainTime](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/toPlainTime)
pub fn toPlainTime(self: ZonedDateTime) !PlainTime { pub fn toPlainTime(self: ZonedDateTime) !PlainTime {
const ptr = abi.c.temporal_rs_ZonedDateTime_to_plain_time(self._inner) orelse return error.TemporalError; const ptr = abi.c.temporal_rs_ZonedDateTime_to_plain_time(self._inner) orelse return error.TemporalError;
return .{ ._inner = ptr }; return .{ ._inner = ptr };
} }
/// Returns a string representing this ZonedDateTime in RFC 9557 format, with options for formatting. /// Returns a string representing this ZonedDateTime in RFC 9557 format, with options for formatting.
/// /// See [MDN Temporal.ZonedDateTime.prototype.toString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/toString)
/// See: [Temporal.ZonedDateTime.toString](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/toString)
pub fn toString(self: ZonedDateTime, allocator: std.mem.Allocator, opts: ToStringOptions) ![]u8 { pub fn toString(self: ZonedDateTime, allocator: std.mem.Allocator, opts: ToStringOptions) ![]u8 {
var write = abi.DiplomatWrite.init(allocator); var write = abi.DiplomatWrite.init(allocator);
defer write.deinit(); defer write.deinit();
@ -275,8 +256,7 @@ pub fn toString(self: ZonedDateTime, allocator: std.mem.Allocator, opts: ToStrin
} }
/// Returns the duration from this ZonedDateTime to another. /// Returns the duration from this ZonedDateTime to another.
/// /// See [MDN Temporal.ZonedDateTime.prototype.until()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/until)
/// See: [Temporal.ZonedDateTime.until](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/until)
pub fn until(self: ZonedDateTime, other: ZonedDateTime, settings: DifferenceSettings) !Duration { pub fn until(self: ZonedDateTime, other: ZonedDateTime, settings: DifferenceSettings) !Duration {
const ptr = try abi.extractResult(abi.c.temporal_rs_ZonedDateTime_until(self._inner, other._inner, abi.to.diffsettings(settings))); const ptr = try abi.extractResult(abi.c.temporal_rs_ZonedDateTime_until(self._inner, other._inner, abi.to.diffsettings(settings)));
if (ptr == null) return error.TemporalError; if (ptr == null) return error.TemporalError;
@ -284,8 +264,7 @@ pub fn until(self: ZonedDateTime, other: ZonedDateTime, settings: DifferenceSett
} }
/// Throws an error; valueOf() is not supported for ZonedDateTime. /// Throws an error; valueOf() is not supported for ZonedDateTime.
/// /// See [MDN Temporal.ZonedDateTime.prototype.valueOf()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/valueOf)
/// See: [Temporal.ZonedDateTime.valueOf](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/valueOf)
pub fn valueOf(_: ZonedDateTime) !void { pub fn valueOf(_: ZonedDateTime) !void {
return error.ValueOfNotSupported; return error.ValueOfNotSupported;
} }
@ -294,26 +273,13 @@ pub fn valueOf(_: ZonedDateTime) !void {
/// See [MDN Temporal.ZonedDateTime.prototype.with()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/with) /// See [MDN Temporal.ZonedDateTime.prototype.with()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/with)
pub fn with(self: ZonedDateTime, allocator: std.mem.Allocator, fields: anytype) !ZonedDateTime { pub fn with(self: ZonedDateTime, allocator: std.mem.Allocator, fields: anytype) !ZonedDateTime {
_ = allocator; _ = allocator;
const partial = abi.toPartialZonedDateTime(fields); _ = fields;
const disambiguation = abi.toOption(abi.c.Disambiguation_option, abi.to.toDisambiguation(Disambiguation.compatible)); _ = self;
const offset_option = abi.toOption(abi.c.OffsetDisambiguation_option, abi.to.toOffsetDisambiguation(OffsetDisambiguation.prefer_offset)); return error.TemporalNoteImplemented; // Need PartialZonedDateTime mapping
const overflow = abi.c.ArithmeticOverflow_option{
.is_ok = true,
.unnamed_0 = .{ .ok = abi.c.ArithmeticOverflow_Constrain },
};
return wrapZonedDateTime(abi.c.temporal_rs_ZonedDateTime_with(
self._inner,
partial,
disambiguation,
offset_option,
overflow,
));
} }
/// Returns a new ZonedDateTime interpreted in the new calendar system. /// Returns a new ZonedDateTime interpreted in the new calendar system.
/// /// See [MDN Temporal.ZonedDateTime.prototype.withCalendar()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/withCalendar)
/// See: [Temporal.ZonedDateTime.withCalendar](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/withCalendar)
pub fn withCalendar(self: ZonedDateTime, calendar: []const u8) !ZonedDateTime { pub fn withCalendar(self: ZonedDateTime, calendar: []const u8) !ZonedDateTime {
const cal_view = abi.toDiplomatStringView(calendar); const cal_view = abi.toDiplomatStringView(calendar);
const cal_result = abi.c.temporal_rs_AnyCalendarKind_parse_temporal_calendar_string(cal_view); const cal_result = abi.c.temporal_rs_AnyCalendarKind_parse_temporal_calendar_string(cal_view);
@ -324,24 +290,21 @@ pub fn withCalendar(self: ZonedDateTime, calendar: []const u8) !ZonedDateTime {
} }
/// Returns a new ZonedDateTime with the time part replaced by the new time. /// Returns a new ZonedDateTime with the time part replaced by the new time.
/// /// See [MDN Temporal.ZonedDateTime.prototype.withPlainTime()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/withPlainTime)
/// See: [Temporal.ZonedDateTime.withPlainTime](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/withPlainTime)
pub fn withPlainTime(self: ZonedDateTime, time: ?PlainTime) !ZonedDateTime { pub fn withPlainTime(self: ZonedDateTime, time: ?PlainTime) !ZonedDateTime {
const time_ptr = if (time) |tt| tt._inner else null; const time_ptr = if (time) |tt| tt._inner else null;
return wrapZonedDateTime(abi.c.temporal_rs_ZonedDateTime_with_plain_time(self._inner, time_ptr)); return wrapZonedDateTime(abi.c.temporal_rs_ZonedDateTime_with_plain_time(self._inner, time_ptr));
} }
/// Returns a new ZonedDateTime representing the same instant in a new time zone. /// Returns a new ZonedDateTime representing the same instant in a new time zone.
/// /// See [MDN Temporal.ZonedDateTime.prototype.withTimeZone()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/withTimeZone)
/// See: [Temporal.ZonedDateTime.withTimeZone](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/withTimeZone)
pub fn withTimeZone(self: ZonedDateTime, time_zone: TimeZone) !ZonedDateTime { pub fn withTimeZone(self: ZonedDateTime, time_zone: TimeZone) !ZonedDateTime {
return wrapZonedDateTime(abi.c.temporal_rs_ZonedDateTime_with_timezone(self._inner, abi.to.toTimeZone(time_zone))); return wrapZonedDateTime(abi.c.temporal_rs_ZonedDateTime_with_timezone(self._inner, abi.to.toTimeZone(time_zone)));
} }
// Property accessors // Property accessors
/// Returns the calendar identifier used to interpret the internal ISO 8601 date. /// Returns the calendar identifier used to interpret the internal ISO 8601 date.
/// /// See [MDN Temporal.ZonedDateTime.prototype.calendarId](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/calendarId)
/// See: [Temporal.ZonedDateTime.calendarId](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/calendarId)
pub fn calendarId(self: ZonedDateTime, allocator: std.mem.Allocator) ![]u8 { pub fn calendarId(self: ZonedDateTime, allocator: std.mem.Allocator) ![]u8 {
const calendar_ptr = abi.c.temporal_rs_ZonedDateTime_calendar(self._inner) orelse return error.TemporalError; const calendar_ptr = abi.c.temporal_rs_ZonedDateTime_calendar(self._inner) orelse return error.TemporalError;
const cal_id_view = abi.c.temporal_rs_Calendar_identifier(calendar_ptr); const cal_id_view = abi.c.temporal_rs_Calendar_identifier(calendar_ptr);
@ -349,65 +312,56 @@ pub fn calendarId(self: ZonedDateTime, allocator: std.mem.Allocator) ![]u8 {
} }
/// Returns the 1-based day index in the month of this date. /// Returns the 1-based day index in the month of this date.
/// /// See [MDN Temporal.ZonedDateTime.prototype.day](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/day)
/// See: [Temporal.ZonedDateTime.day](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/day)
pub fn day(self: ZonedDateTime) u8 { pub fn day(self: ZonedDateTime) u8 {
return abi.c.temporal_rs_ZonedDateTime_day(self._inner); return abi.c.temporal_rs_ZonedDateTime_day(self._inner);
} }
/// Returns the 1-based day index in the week of this date. /// Returns the 1-based day index in the week of this date.
/// /// See [MDN Temporal.ZonedDateTime.prototype.dayOfWeek](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/dayOfWeek)
/// See: [Temporal.ZonedDateTime.dayOfWeek](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/dayOfWeek)
pub fn dayOfWeek(self: ZonedDateTime) u16 { pub fn dayOfWeek(self: ZonedDateTime) u16 {
return abi.c.temporal_rs_ZonedDateTime_day_of_week(self._inner); return abi.c.temporal_rs_ZonedDateTime_day_of_week(self._inner);
} }
/// Returns the 1-based day index in the year of this date. /// Returns the 1-based day index in the year of this date.
/// /// See [MDN Temporal.ZonedDateTime.prototype.dayOfYear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/dayOfYear)
/// See: [Temporal.ZonedDateTime.dayOfYear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/dayOfYear)
pub fn dayOfYear(self: ZonedDateTime) u16 { pub fn dayOfYear(self: ZonedDateTime) u16 {
return abi.c.temporal_rs_ZonedDateTime_day_of_year(self._inner); return abi.c.temporal_rs_ZonedDateTime_day_of_year(self._inner);
} }
/// Returns the number of days in the month of this date. /// Returns the number of days in the month of this date.
/// /// See [MDN Temporal.ZonedDateTime.prototype.daysInMonth](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/daysInMonth)
/// See: [Temporal.ZonedDateTime.daysInMonth](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/daysInMonth)
pub fn daysInMonth(self: ZonedDateTime) u16 { pub fn daysInMonth(self: ZonedDateTime) u16 {
return abi.c.temporal_rs_ZonedDateTime_days_in_month(self._inner); return abi.c.temporal_rs_ZonedDateTime_days_in_month(self._inner);
} }
/// Returns the number of days in the week of this date. /// Returns the number of days in the week of this date.
/// /// See [MDN Temporal.ZonedDateTime.prototype.daysInWeek](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/daysInWeek)
/// See: [Temporal.ZonedDateTime.daysInWeek](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/daysInWeek)
pub fn daysInWeek(self: ZonedDateTime) u16 { pub fn daysInWeek(self: ZonedDateTime) u16 {
return abi.c.temporal_rs_ZonedDateTime_days_in_week(self._inner); return abi.c.temporal_rs_ZonedDateTime_days_in_week(self._inner);
} }
/// Returns the number of days in the year of this date. /// Returns the number of days in the year of this date.
/// /// See [MDN Temporal.ZonedDateTime.prototype.daysInYear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/daysInYear)
/// See: [Temporal.ZonedDateTime.daysInYear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/daysInYear)
pub fn daysInYear(self: ZonedDateTime) u16 { pub fn daysInYear(self: ZonedDateTime) u16 {
return abi.c.temporal_rs_ZonedDateTime_days_in_year(self._inner); return abi.c.temporal_rs_ZonedDateTime_days_in_year(self._inner);
} }
/// Returns the number of milliseconds since the Unix epoch to this instant. /// Returns the number of milliseconds since the Unix epoch to this instant.
/// /// See [MDN Temporal.ZonedDateTime.prototype.epochMilliseconds](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/epochMilliseconds)
/// See: [Temporal.ZonedDateTime.epochMilliseconds](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/epochMilliseconds)
pub fn epochMilliseconds(self: ZonedDateTime) i64 { pub fn epochMilliseconds(self: ZonedDateTime) i64 {
return abi.c.temporal_rs_ZonedDateTime_epoch_milliseconds(self._inner); return abi.c.temporal_rs_ZonedDateTime_epoch_milliseconds(self._inner);
} }
/// Returns the number of nanoseconds since the Unix epoch to this instant. /// Returns the number of nanoseconds since the Unix epoch to this instant.
/// /// See [MDN Temporal.ZonedDateTime.prototype.epochNanoseconds](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/epochNanoseconds)
/// See: [Temporal.ZonedDateTime.epochNanoseconds](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/epochNanoseconds)
pub fn epochNanoseconds(self: ZonedDateTime) i128 { pub fn epochNanoseconds(self: ZonedDateTime) i128 {
const parts = abi.c.temporal_rs_ZonedDateTime_epoch_nanoseconds(self._inner); const parts = abi.c.temporal_rs_ZonedDateTime_epoch_nanoseconds(self._inner);
return abi.fromI128Nanoseconds(parts); return abi.fromI128Nanoseconds(parts);
} }
/// Returns the calendar-specific era of this date, or null if not applicable. /// Returns the calendar-specific era of this date, or null if not applicable.
/// /// See [MDN Temporal.ZonedDateTime.prototype.era](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/era)
/// See: [Temporal.ZonedDateTime.era](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/era)
pub fn era(self: ZonedDateTime, allocator: std.mem.Allocator) !?[]u8 { pub fn era(self: ZonedDateTime, allocator: std.mem.Allocator) !?[]u8 {
var write = abi.DiplomatWrite.init(allocator); var write = abi.DiplomatWrite.init(allocator);
defer write.deinit(); defer write.deinit();
@ -421,66 +375,57 @@ pub fn era(self: ZonedDateTime, allocator: std.mem.Allocator) !?[]u8 {
} }
/// Returns the year of this date within the era, or null if not applicable. /// Returns the year of this date within the era, or null if not applicable.
/// /// See [MDN Temporal.ZonedDateTime.prototype.eraYear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/eraYear)
/// See: [Temporal.ZonedDateTime.eraYear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/eraYear)
pub fn eraYear(self: ZonedDateTime) ?i32 { pub fn eraYear(self: ZonedDateTime) ?i32 {
const result = abi.c.temporal_rs_ZonedDateTime_era_year(self._inner); const result = abi.c.temporal_rs_ZonedDateTime_era_year(self._inner);
return abi.fromOption(result); return abi.fromOption(result);
} }
/// Returns the hour component of this time (0-23). /// Returns the hour component of this time (0-23).
/// /// See [MDN Temporal.ZonedDateTime.prototype.hour](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/hour)
/// See: [Temporal.ZonedDateTime.hour](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/hour)
pub fn hour(self: ZonedDateTime) u8 { pub fn hour(self: ZonedDateTime) u8 {
return abi.c.temporal_rs_ZonedDateTime_hour(self._inner); return abi.c.temporal_rs_ZonedDateTime_hour(self._inner);
} }
/// Returns the number of hours in the day of this date in the time zone. /// Returns the number of hours in the day of this date in the time zone.
/// /// See [MDN Temporal.ZonedDateTime.prototype.hoursInDay](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/hoursInDay)
/// See: [Temporal.ZonedDateTime.hoursInDay](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/hoursInDay)
pub fn hoursInDay(self: ZonedDateTime) !f64 { pub fn hoursInDay(self: ZonedDateTime) !f64 {
const result = abi.c.temporal_rs_ZonedDateTime_hours_in_day(self._inner); const result = abi.c.temporal_rs_ZonedDateTime_hours_in_day(self._inner);
return try abi.extractResult(result); return try abi.extractResult(result);
} }
/// Returns true if this date is in a leap year. /// Returns true if this date is in a leap year.
/// /// See [MDN Temporal.ZonedDateTime.prototype.inLeapYear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/inLeapYear)
/// See: [Temporal.ZonedDateTime.inLeapYear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/inLeapYear)
pub fn inLeapYear(self: ZonedDateTime) bool { pub fn inLeapYear(self: ZonedDateTime) bool {
return abi.c.temporal_rs_ZonedDateTime_in_leap_year(self._inner); return abi.c.temporal_rs_ZonedDateTime_in_leap_year(self._inner);
} }
/// Returns the microsecond component of this time (0-999). /// Returns the microsecond component of this time (0-999).
/// /// See [MDN Temporal.ZonedDateTime.prototype.microsecond](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/microsecond)
/// See: [Temporal.ZonedDateTime.microsecond](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/microsecond)
pub fn microsecond(self: ZonedDateTime) u16 { pub fn microsecond(self: ZonedDateTime) u16 {
return abi.c.temporal_rs_ZonedDateTime_microsecond(self._inner); return abi.c.temporal_rs_ZonedDateTime_microsecond(self._inner);
} }
/// Returns the millisecond component of this time (0-999). /// Returns the millisecond component of this time (0-999).
/// /// See [MDN Temporal.ZonedDateTime.prototype.millisecond](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/millisecond)
/// See: [Temporal.ZonedDateTime.millisecond](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/millisecond)
pub fn millisecond(self: ZonedDateTime) u16 { pub fn millisecond(self: ZonedDateTime) u16 {
return abi.c.temporal_rs_ZonedDateTime_millisecond(self._inner); return abi.c.temporal_rs_ZonedDateTime_millisecond(self._inner);
} }
/// Returns the minute component of this time (0-59). /// Returns the minute component of this time (0-59).
/// /// See [MDN Temporal.ZonedDateTime.prototype.minute](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/minute)
/// See: [Temporal.ZonedDateTime.minute](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/minute)
pub fn minute(self: ZonedDateTime) u8 { pub fn minute(self: ZonedDateTime) u8 {
return abi.c.temporal_rs_ZonedDateTime_minute(self._inner); return abi.c.temporal_rs_ZonedDateTime_minute(self._inner);
} }
/// Returns the 1-based month index in the year of this date. /// Returns the 1-based month index in the year of this date.
/// /// See [MDN Temporal.ZonedDateTime.prototype.month](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/month)
/// See: [Temporal.ZonedDateTime.month](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/month)
pub fn month(self: ZonedDateTime) u8 { pub fn month(self: ZonedDateTime) u8 {
return abi.c.temporal_rs_ZonedDateTime_month(self._inner); return abi.c.temporal_rs_ZonedDateTime_month(self._inner);
} }
/// Returns the calendar-specific string representing the month of this date. /// Returns the calendar-specific string representing the month of this date.
/// /// See [MDN Temporal.ZonedDateTime.prototype.monthCode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/monthCode)
/// See: [Temporal.ZonedDateTime.monthCode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/monthCode)
pub fn monthCode(self: ZonedDateTime, allocator: std.mem.Allocator) ![]u8 { pub fn monthCode(self: ZonedDateTime, allocator: std.mem.Allocator) ![]u8 {
var write = abi.DiplomatWrite.init(allocator); var write = abi.DiplomatWrite.init(allocator);
defer write.deinit(); defer write.deinit();
@ -489,22 +434,19 @@ pub fn monthCode(self: ZonedDateTime, allocator: std.mem.Allocator) ![]u8 {
} }
/// Returns the number of months in the year of this date. /// Returns the number of months in the year of this date.
/// /// See [MDN Temporal.ZonedDateTime.prototype.monthsInYear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/monthsInYear)
/// See: [Temporal.ZonedDateTime.monthsInYear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/monthsInYear)
pub fn monthsInYear(self: ZonedDateTime) u16 { pub fn monthsInYear(self: ZonedDateTime) u16 {
return abi.c.temporal_rs_ZonedDateTime_months_in_year(self._inner); return abi.c.temporal_rs_ZonedDateTime_months_in_year(self._inner);
} }
/// Returns the nanosecond component of this time (0-999). /// Returns the nanosecond component of this time (0-999).
/// /// See [MDN Temporal.ZonedDateTime.prototype.nanosecond](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/nanosecond)
/// See: [Temporal.ZonedDateTime.nanosecond](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/nanosecond)
pub fn nanosecond(self: ZonedDateTime) u16 { pub fn nanosecond(self: ZonedDateTime) u16 {
return abi.c.temporal_rs_ZonedDateTime_nanosecond(self._inner); return abi.c.temporal_rs_ZonedDateTime_nanosecond(self._inner);
} }
/// Returns the offset used to interpret the internal instant, as a string (±HH:mm). /// Returns the offset used to interpret the internal instant, as a string (±HH:mm).
/// /// See [MDN Temporal.ZonedDateTime.prototype.offset](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/offset)
/// See: [Temporal.ZonedDateTime.offset](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/offset)
pub fn offset(self: ZonedDateTime, allocator: std.mem.Allocator) ![]u8 { pub fn offset(self: ZonedDateTime, allocator: std.mem.Allocator) ![]u8 {
var write = abi.DiplomatWrite.init(allocator); var write = abi.DiplomatWrite.init(allocator);
defer write.deinit(); defer write.deinit();
@ -514,22 +456,19 @@ pub fn offset(self: ZonedDateTime, allocator: std.mem.Allocator) ![]u8 {
} }
/// Returns the offset used to interpret the internal instant, as a number of nanoseconds. /// Returns the offset used to interpret the internal instant, as a number of nanoseconds.
/// /// See [MDN Temporal.ZonedDateTime.prototype.offsetNanoseconds](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/offsetNanoseconds)
/// See: [Temporal.ZonedDateTime.offsetNanoseconds](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/offsetNanoseconds)
pub fn offsetNanoseconds(self: ZonedDateTime) i64 { pub fn offsetNanoseconds(self: ZonedDateTime) i64 {
return abi.c.temporal_rs_ZonedDateTime_offset_nanoseconds(self._inner); return abi.c.temporal_rs_ZonedDateTime_offset_nanoseconds(self._inner);
} }
/// Returns the second component of this time (0-59). /// Returns the second component of this time (0-59).
/// /// See [MDN Temporal.ZonedDateTime.prototype.second](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/second)
/// See: [Temporal.ZonedDateTime.second](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/second)
pub fn second(self: ZonedDateTime) u8 { pub fn second(self: ZonedDateTime) u8 {
return abi.c.temporal_rs_ZonedDateTime_second(self._inner); return abi.c.temporal_rs_ZonedDateTime_second(self._inner);
} }
/// Returns the time zone identifier used to interpret the internal instant. /// Returns the time zone identifier used to interpret the internal instant.
/// /// See [MDN Temporal.ZonedDateTime.prototype.timeZoneId](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/timeZoneId)
/// See: [Temporal.ZonedDateTime.timeZoneId](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/timeZoneId)
pub fn timeZoneId(self: ZonedDateTime, allocator: std.mem.Allocator) ![]u8 { pub fn timeZoneId(self: ZonedDateTime, allocator: std.mem.Allocator) ![]u8 {
const tz = abi.c.temporal_rs_ZonedDateTime_timezone(self._inner); const tz = abi.c.temporal_rs_ZonedDateTime_timezone(self._inner);
var write = abi.DiplomatWrite.init(allocator); var write = abi.DiplomatWrite.init(allocator);
@ -541,23 +480,20 @@ pub fn timeZoneId(self: ZonedDateTime, allocator: std.mem.Allocator) ![]u8 {
} }
/// Returns the 1-based week index in the year of this date, or null if not defined. /// Returns the 1-based week index in the year of this date, or null if not defined.
/// /// See [MDN Temporal.ZonedDateTime.prototype.weekOfYear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/weekOfYear)
/// See: [Temporal.ZonedDateTime.weekOfYear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/weekOfYear)
pub fn weekOfYear(self: ZonedDateTime) ?u8 { pub fn weekOfYear(self: ZonedDateTime) ?u8 {
const result = abi.c.temporal_rs_ZonedDateTime_week_of_year(self._inner); const result = abi.c.temporal_rs_ZonedDateTime_week_of_year(self._inner);
return abi.fromOption(result); return abi.fromOption(result);
} }
/// Returns the year of this date relative to the calendar's epoch. /// Returns the year of this date relative to the calendar's epoch.
/// /// See [MDN Temporal.ZonedDateTime.prototype.year](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/year)
/// See: [Temporal.ZonedDateTime.year](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/year)
pub fn year(self: ZonedDateTime) i32 { pub fn year(self: ZonedDateTime) i32 {
return abi.c.temporal_rs_ZonedDateTime_year(self._inner); return abi.c.temporal_rs_ZonedDateTime_year(self._inner);
} }
/// Returns the year to be paired with the weekOfYear of this date, or null if not defined. /// Returns the year to be paired with the weekOfYear of this date, or null if not defined.
/// /// See [MDN Temporal.ZonedDateTime.prototype.yearOfWeek](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/yearOfWeek)
/// See: [Temporal.ZonedDateTime.yearOfWeek](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/yearOfWeek)
pub fn yearOfWeek(self: ZonedDateTime) ?i32 { pub fn yearOfWeek(self: ZonedDateTime) ?i32 {
const result = abi.c.temporal_rs_ZonedDateTime_year_of_week(self._inner); const result = abi.c.temporal_rs_ZonedDateTime_year_of_week(self._inner);
return abi.fromOption(result); return abi.fromOption(result);
@ -574,12 +510,7 @@ pub fn deinit(self: ZonedDateTime) void {
abi.c.temporal_rs_ZonedDateTime_destroy(self._inner); abi.c.temporal_rs_ZonedDateTime_destroy(self._inner);
} }
/// Helper function to wrap a C API result into a ZonedDateTime // ---------- Tests ---------------------
fn wrapZonedDateTime(result: anytype) !ZonedDateTime {
const ptr = (try abi.extractResult(result)) orelse return abi.TemporalError.Generic;
return .{ ._inner = ptr };
}
test init { test init {
const tz = try TimeZone.init("America/New_York"); const tz = try TimeZone.init("America/New_York");
const zdt = try init(0, tz); const zdt = try init(0, tz);
@ -731,11 +662,7 @@ test add {
} }
test getTimeZoneTransition { test getTimeZoneTransition {
const zdt = try from("2021-01-01T12:00:00+00:00[UTC]", null, .compatible, .reject); if (true) return error.SkipZigTest; // getTimeZoneTransition() not properly implemented in underlying library
defer zdt.deinit();
try std.testing.expectEqual(@as(?ZonedDateTime, null), try zdt.getTimeZoneTransition(.next));
try std.testing.expectEqual(@as(?ZonedDateTime, null), try zdt.getTimeZoneTransition(.previous));
} }
test round { test round {
@ -829,14 +756,7 @@ test valueOf {
test with { test with {
const zdt = try from("2021-01-01T12:00:00+00:00[UTC]", null, .compatible, .reject); const zdt = try from("2021-01-01T12:00:00+00:00[UTC]", null, .compatible, .reject);
defer zdt.deinit(); defer zdt.deinit();
try std.testing.expectError(error.TemporalNoteImplemented, zdt.with(std.testing.allocator, .{}));
const result = try zdt.with(std.testing.allocator, .{ .year = 2022, .month = 2, .day = 3, .hour = 4 });
defer result.deinit();
try std.testing.expectEqual(@as(i32, 2022), result.year());
try std.testing.expectEqual(@as(u8, 2), result.month());
try std.testing.expectEqual(@as(u8, 3), result.day());
try std.testing.expectEqual(@as(u8, 4), result.hour());
} }
test withCalendar { test withCalendar {
@ -881,12 +801,6 @@ test calendarId {
try std.testing.expect(cal_id.len > 0); try std.testing.expect(cal_id.len > 0);
} }
test day {
const zdt = try from("2021-01-02T12:00:00+00:00[UTC]", null, .compatible, .reject);
defer zdt.deinit();
try std.testing.expectEqual(@as(u8, 2), zdt.day());
}
test dayOfWeek { test dayOfWeek {
const zdt = try from("2021-01-01T12:00:00+00:00[UTC]", null, .compatible, .reject); const zdt = try from("2021-01-01T12:00:00+00:00[UTC]", null, .compatible, .reject);
defer zdt.deinit(); defer zdt.deinit();
@ -954,12 +868,6 @@ test eraYear {
} }
} }
test hour {
const zdt = try from("2021-01-01T12:00:00+00:00[UTC]", null, .compatible, .reject);
defer zdt.deinit();
try std.testing.expectEqual(@as(u8, 12), zdt.hour());
}
test hoursInDay { test hoursInDay {
const zdt = try from("2021-01-01T12:00:00+00:00[UTC]", null, .compatible, .reject); const zdt = try from("2021-01-01T12:00:00+00:00[UTC]", null, .compatible, .reject);
defer zdt.deinit(); defer zdt.deinit();
@ -984,24 +892,6 @@ test microsecond {
try std.testing.expect(us >= 0 and us < 1000); try std.testing.expect(us >= 0 and us < 1000);
} }
test millisecond {
const zdt = try from("2021-01-01T12:00:00.123456789+00:00[UTC]", null, .compatible, .reject);
defer zdt.deinit();
try std.testing.expectEqual(@as(u16, 123), zdt.millisecond());
}
test minute {
const zdt = try from("2021-01-01T12:34:00+00:00[UTC]", null, .compatible, .reject);
defer zdt.deinit();
try std.testing.expectEqual(@as(u8, 34), zdt.minute());
}
test month {
const zdt = try from("2021-07-01T12:00:00+00:00[UTC]", null, .compatible, .reject);
defer zdt.deinit();
try std.testing.expectEqual(@as(u8, 7), zdt.month());
}
test monthCode { test monthCode {
const zdt = try from("2021-01-01T12:00:00+00:00[UTC]", null, .compatible, .reject); const zdt = try from("2021-01-01T12:00:00+00:00[UTC]", null, .compatible, .reject);
defer zdt.deinit(); defer zdt.deinit();
@ -1024,12 +914,7 @@ test nanosecond {
} }
test offset { test offset {
const zdt = try from("2021-01-01T12:00:00+00:00[UTC]", null, .compatible, .reject); if (true) return error.SkipZigTest; // offset() throws RangeError with UTC timezone
defer zdt.deinit();
const off = try zdt.offset(std.testing.allocator);
defer std.testing.allocator.free(off);
try std.testing.expectEqualStrings("+00:00", off);
} }
test offsetNanoseconds { test offsetNanoseconds {
@ -1039,21 +924,6 @@ test offsetNanoseconds {
try std.testing.expectEqual(@as(i64, 0), off_ns); try std.testing.expectEqual(@as(i64, 0), off_ns);
} }
test second {
const zdt = try from("2021-01-01T12:34:56+00:00[UTC]", null, .compatible, .reject);
defer zdt.deinit();
try std.testing.expectEqual(@as(u8, 56), zdt.second());
}
test timeZoneId {
const zdt = try from("2021-01-01T12:00:00+00:00[UTC]", null, .compatible, .reject);
defer zdt.deinit();
const id = try zdt.timeZoneId(std.testing.allocator);
defer std.testing.allocator.free(id);
try std.testing.expectEqualStrings("UTC", id);
}
test weekOfYear { test weekOfYear {
const zdt = try from("2021-01-01T12:00:00+00:00[UTC]", null, .compatible, .reject); const zdt = try from("2021-01-01T12:00:00+00:00[UTC]", null, .compatible, .reject);
defer zdt.deinit(); defer zdt.deinit();
@ -1063,12 +933,6 @@ test weekOfYear {
} }
} }
test year {
const zdt = try from("2021-01-01T12:00:00+00:00[UTC]", null, .compatible, .reject);
defer zdt.deinit();
try std.testing.expectEqual(@as(i32, 2021), zdt.year());
}
test yearOfWeek { test yearOfWeek {
const zdt = try from("2021-01-01T12:00:00+00:00[UTC]", null, .compatible, .reject); const zdt = try from("2021-01-01T12:00:00+00:00[UTC]", null, .compatible, .reject);
defer zdt.deinit(); defer zdt.deinit();

View file

@ -1,6 +1,6 @@
const std = @import("std"); const std = @import("std");
pub const c = @import("libtemporal").c; pub const c = @import("temporal_rs").c;
pub const to_string_rounding_options_auto: c.ToStringRoundingOptions = .{ pub const to_string_rounding_options_auto: c.ToStringRoundingOptions = .{
.precision = .{ .is_minute = false, .precision = toOption(c.OptionU8, null) }, .precision = .{ .is_minute = false, .precision = toOption(c.OptionU8, null) },
@ -90,85 +90,6 @@ pub fn toTimeZoneOption(maybe_value: ?c.TimeZone) c.TimeZone_option {
return toOption(c.TimeZone_option, maybe_value); return toOption(c.TimeZone_option, maybe_value);
} }
pub fn toPartialZonedDateTime(fields: anytype) c.PartialZonedDateTime {
return .{
.date = .{
.year = toI32OptionField(fields, "year"),
.month = toU8OptionField(fields, "month"),
.month_code = toStringViewField(fields, "month_code"),
.day = toU8OptionField(fields, "day"),
.era = toStringViewField(fields, "era"),
.era_year = toI32OptionField(fields, "era_year"),
.calendar = c.AnyCalendarKind_Iso,
},
.time = .{
.hour = toU8OptionField(fields, "hour"),
.minute = toU8OptionField(fields, "minute"),
.second = toU8OptionField(fields, "second"),
.millisecond = toU16OptionField(fields, "millisecond"),
.microsecond = toU16OptionField(fields, "microsecond"),
.nanosecond = toU16OptionField(fields, "nanosecond"),
},
.offset = toOptionStringViewField(fields, "offset"),
.timezone = toTimeZoneOptionField(fields, "time_zone"),
};
}
fn toI32OptionField(fields: anytype, comptime name: []const u8) c.OptionI32 {
return toOption(c.OptionI32, intField(i32, fields, name));
}
fn toU8OptionField(fields: anytype, comptime name: []const u8) c.OptionU8 {
return toOption(c.OptionU8, intField(u8, fields, name));
}
fn toU16OptionField(fields: anytype, comptime name: []const u8) c.OptionU16 {
return toOption(c.OptionU16, intField(u16, fields, name));
}
fn intField(comptime Int: type, fields: anytype, comptime name: []const u8) ?Int {
if (!@hasField(@TypeOf(fields), name)) return null;
const value = @field(fields, name);
return switch (@typeInfo(@TypeOf(value))) {
.optional => if (value) |payload| @as(Int, @intCast(payload)) else null,
else => @as(Int, @intCast(value)),
};
}
fn toStringViewField(fields: anytype, comptime name: []const u8) c.DiplomatStringView {
if (stringField(fields, name)) |value| return toDiplomatStringView(value);
return .{ .data = null, .len = 0 };
}
fn toOptionStringViewField(fields: anytype, comptime name: []const u8) c.OptionStringView {
if (stringField(fields, name)) |value| {
return .{ .is_ok = true, .unnamed_0 = .{ .ok = toDiplomatStringView(value) } };
}
return .{ .is_ok = false };
}
fn stringField(fields: anytype, comptime name: []const u8) ?[]const u8 {
if (!@hasField(@TypeOf(fields), name)) return null;
const value = @field(fields, name);
return switch (@typeInfo(@TypeOf(value))) {
.optional => value,
else => value,
};
}
fn toTimeZoneOptionField(fields: anytype, comptime name: []const u8) c.TimeZone_option {
if (!@hasField(@TypeOf(fields), name)) return .{ .is_ok = false };
const value = @field(fields, name);
const maybe_time_zone = switch (@typeInfo(@TypeOf(value))) {
.optional => if (value) |payload| payload._inner else null,
else => value._inner,
};
return toOption(c.TimeZone_option, maybe_time_zone);
}
/// Convert a Zig `?Unit` to a Rust `Option<Unit>`. /// Convert a Zig `?Unit` to a Rust `Option<Unit>`.
pub fn toUnitOption(maybe_value: ?c.Unit) c.Unit_option { pub fn toUnitOption(maybe_value: ?c.Unit) c.Unit_option {
return toOption(c.Unit_option, maybe_value); return toOption(c.Unit_option, maybe_value);

View file

@ -4,49 +4,49 @@ const Temporal = @This();
/// The `Temporal.Duration` object represents a difference between two time points, which can be used in date/time arithmetic. /// The `Temporal.Duration` object represents a difference between two time points, which can be used in date/time arithmetic.
/// It is fundamentally represented as a combination of years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, and nanoseconds values. /// It is fundamentally represented as a combination of years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, and nanoseconds values.
/// ///
/// See: [Temporal.Duration](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration) /// - [MDN Temporal.Duration](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration)
pub const Duration = @import("Duration.zig"); pub const Duration = @import("Duration.zig");
/// The `Temporal.Instant` object represents a unique point in time, with nanosecond precision. /// The `Temporal.Instant` object represents a unique point in time, with nanosecond precision.
/// It is fundamentally represented as the number of nanoseconds since the Unix epoch (midnight at the beginning of January 1, 1970, UTC), without any time zone or calendar system. /// It is fundamentally represented as the number of nanoseconds since the Unix epoch (midnight at the beginning of January 1, 1970, UTC), without any time zone or calendar system.
/// ///
/// See: [Temporal.Instant](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant) /// - [MDN Temporal.Instant](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant)
pub const Instant = @import("Instant.zig"); pub const Instant = @import("Instant.zig");
/// The `Temporal.Now` namespace object contains static methods for getting the current time in various formats. /// The `Temporal.Now` namespace object contains static methods for getting the current time in various formats.
/// All properties and methods are static. /// All properties and methods are static.
/// ///
/// See: [Temporal.Now](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now) /// - [MDN Temporal.Now](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now)
pub const Now = @import("Now.zig"); pub const Now = @import("Now.zig");
/// The `Temporal.PlainDate` object represents a calendar date (year, month, day) with no time or time zone. /// The `Temporal.PlainDate` object represents a calendar date (year, month, day) with no time or time zone.
/// ///
/// See: [Temporal.PlainDate](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainDate) /// - [MDN Temporal.PlainDate](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainDate)
pub const PlainDate = @import("PlainDate.zig"); pub const PlainDate = @import("PlainDate.zig");
/// The `Temporal.PlainDateTime` object represents a calendar date and wall-clock time, but no time zone or offset. /// The `Temporal.PlainDateTime` object represents a calendar date and wall-clock time, but no time zone or offset.
/// ///
/// See: [Temporal.PlainDateTime](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainDateTime) /// - [MDN Temporal.PlainDateTime](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainDateTime)
pub const PlainDateTime = @import("PlainDateTime.zig"); pub const PlainDateTime = @import("PlainDateTime.zig");
/// The `Temporal.PlainMonthDay` object represents a month and day in a calendar, with no year or time. /// The `Temporal.PlainMonthDay` object represents a month and day in a calendar, with no year or time.
/// ///
/// See: [Temporal.PlainMonthDay](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay) /// - [MDN Temporal.PlainMonthDay](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainMonthDay)
pub const PlainMonthDay = @import("PlainMonthDay.zig"); pub const PlainMonthDay = @import("PlainMonthDay.zig");
/// The `Temporal.PlainTime` object represents a wall-clock time, with no date or time zone. /// The `Temporal.PlainTime` object represents a wall-clock time, with no date or time zone.
/// ///
/// See: [Temporal.PlainTime](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime) /// - [MDN Temporal.PlainTime](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime)
pub const PlainTime = @import("PlainTime.zig"); pub const PlainTime = @import("PlainTime.zig");
/// The `Temporal.PlainYearMonth` object represents a particular month in a specific year, with no day or time. /// The `Temporal.PlainYearMonth` object represents a particular month in a specific year, with no day or time.
/// ///
/// See: [Temporal.PlainYearMonth](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth) /// - [MDN Temporal.PlainYearMonth](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth)
pub const PlainYearMonth = @import("PlainYearMonth.zig"); pub const PlainYearMonth = @import("PlainYearMonth.zig");
/// The `Temporal.ZonedDateTime` object represents an exact time, including a time zone and calendar. /// The `Temporal.ZonedDateTime` object represents an exact time, including a time zone and calendar.
/// ///
/// See: [Temporal.ZonedDateTime](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime) /// - [MDN Temporal.ZonedDateTime](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime)
pub const ZonedDateTime = @import("ZonedDateTime.zig"); pub const ZonedDateTime = @import("ZonedDateTime.zig");
test Temporal { test Temporal {
@ -227,7 +227,6 @@ test PlainDate {
"ToStringOptions", "ToStringOptions",
"CalendarDisplay", "CalendarDisplay",
"ToZonedDateTimeOptions", "ToZonedDateTimeOptions",
"WithOptions",
"Unit", "Unit",
"RoundingMode", "RoundingMode",
"Sign", "Sign",
@ -502,7 +501,6 @@ test ZonedDateTime {
"DisplayOffset", "DisplayOffset",
"DisplayTimeZone", "DisplayTimeZone",
"ToStringOptions", "ToStringOptions",
"WithOptions",
}; };
try assertDecls(ZonedDateTime, checks); try assertDecls(ZonedDateTime, checks);
@ -526,10 +524,10 @@ fn assertDecls(comptime T: type, checks: anytype) !void {
var hasField = false; var hasField = false;
if (typeInfo == .@"struct") { if (typeInfo == .@"struct") {
const struct_info = typeInfo.@"struct"; const struct_info = typeInfo.@"struct";
inline for (struct_info.field_names) |field_name| { inline for (struct_info.fields) |field| {
// Check both camelCase and snake_case // Check both camelCase and snake_case
if (std.mem.eql(u8, field_name, check) or if (std.mem.eql(u8, field.name, check) or
std.mem.eql(u8, field_name, camelToSnakeCase(check))) std.mem.eql(u8, field.name, camelToSnakeCase(check)))
{ {
hasField = true; hasField = true;
break; break;
@ -548,39 +546,39 @@ fn assertDecls(comptime T: type, checks: anytype) !void {
const struct_info = typeInfo.@"struct"; const struct_info = typeInfo.@"struct";
// Check declarations // Check declarations
inline for (struct_info.decl_names) |decl_name| { inline for (struct_info.decls) |decl| {
// Allow deinit as extraneous // Allow deinit as extraneous
if (comptime std.mem.eql(u8, decl_name, "deinit")) continue; if (comptime std.mem.eql(u8, decl.name, "deinit")) continue;
var found = false; var found = false;
inline for (checks) |check| { inline for (checks) |check| {
if (std.mem.eql(u8, decl_name, check)) { if (std.mem.eql(u8, decl.name, check)) {
found = true; found = true;
break; break;
} }
} }
if (!found) { if (!found) {
std.log.err("Extraneous {s} decl: {s}", .{ @typeName(T), decl_name }); std.log.err("Extraneous {s} decl: {s}", .{ @typeName(T), decl.name });
try std.testing.expect(false); try std.testing.expect(false);
} }
} }
// Check fields (properties) // Check fields (properties)
inline for (struct_info.field_names) |field_name| { inline for (struct_info.fields) |field| {
// Allow internal fields (starting with underscore) // Allow internal fields (starting with underscore)
if (comptime std.mem.startsWith(u8, field_name, "_")) continue; if (comptime std.mem.startsWith(u8, field.name, "_")) continue;
var found = false; var found = false;
inline for (checks) |check| { inline for (checks) |check| {
if (std.mem.eql(u8, field_name, camelToSnakeCase(check))) { if (std.mem.eql(u8, field.name, camelToSnakeCase(check))) {
found = true; found = true;
break; break;
} }
} }
if (!found) { if (!found) {
std.log.err("Extraneous {s} field: {s}", .{ @typeName(T), field_name }); std.log.err("Extraneous {s} field: {s}", .{ @typeName(T), field.name });
try std.testing.expect(false); try std.testing.expect(false);
} }
} }

View file

@ -1,4 +1,11 @@
/// # Temporal Types and Utilities
///
/// This file defines core types and options used throughout the Temporal API implementation.
///
/// - [MDN Temporal](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal)
/// ## Unit
/// Time unit for Temporal operations (e.g., nanosecond, second, day, year). /// Time unit for Temporal operations (e.g., nanosecond, second, day, year).
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal
pub const Unit = enum { pub const Unit = enum {
auto, auto,
nanosecond, nanosecond,
@ -83,11 +90,9 @@ pub const TimeZone = struct {
_inner: abi.c.TimeZone, _inner: abi.c.TimeZone,
/// Initialize a TimeZone from an identifier string. /// Initialize a TimeZone from an identifier string.
pub fn init(id: []const u8) !TimeZone { pub fn init(id: []const u8) TimeZone {
const view = abi.toDiplomatStringView(id); const view = abi.toDiplomatStringView(id);
const result = abi.c.temporal_rs_TimeZone_try_from_str(view); return .{ ._inner = .{ .id = view } };
const time_zone = try abi.extractResult(result);
return .{ ._inner = time_zone };
} }
}; };

View file

@ -20,7 +20,7 @@ pub const std_options = std.Options{
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
const BORDER: [80]u8 = @splat('='); const BORDER = "=" ** 80;
// use in custom panic handler // use in custom panic handler
var current_test: ?[]const u8 = null; var current_test: ?[]const u8 = null;
@ -31,7 +31,6 @@ pub fn main(init: std.process.Init) !void {
const env = Env.init(allocator, init.minimal.environ); const env = Env.init(allocator, init.minimal.environ);
defer env.deinit(allocator); defer env.deinit(allocator);
std.testing.environ = env.environ;
var slowest = SlowTracker.init(allocator, io, 15); var slowest = SlowTracker.init(allocator, io, 15);
defer slowest.deinit(allocator); defer slowest.deinit(allocator);
@ -100,13 +99,13 @@ pub fn main(init: std.process.Init) !void {
while (attempt < max_attempts) : (attempt += 1) { while (attempt < max_attempts) : (attempt += 1) {
current_test = friendly_name; current_test = friendly_name;
std.testing.allocator_instance = .init(std.heap.page_allocator, .{}); std.testing.allocator_instance = .{};
final_result = t.func(); final_result = t.func();
current_test = null; current_test = null;
final_ns_taken = slowest.endTiming(allocator, scope_name, friendly_name); final_ns_taken = slowest.endTiming(allocator, scope_name, friendly_name);
if (std.testing.allocator_instance.deinit() > 0) { if (std.testing.allocator_instance.deinit() == .leak) {
leak += 1; leak += 1;
Printer.status(.fail, "\n{s}\n\"{s}\" - Memory Leak\n{s}\n", .{ BORDER, friendly_name, BORDER }); Printer.status(.fail, "\n{s}\n\"{s}\" - Memory Leak\n{s}\n", .{ BORDER, friendly_name, BORDER });
} }
@ -150,7 +149,7 @@ pub fn main(init: std.process.Init) !void {
Printer.status(.fail, "\n{s}\n\"{s}\" - {s}\n{s}\n", .{ BORDER, friendly_name, @errorName(err), BORDER }); Printer.status(.fail, "\n{s}\n\"{s}\" - {s}\n{s}\n", .{ BORDER, friendly_name, @errorName(err), BORDER });
} }
if (@errorReturnTrace()) |trace| { if (@errorReturnTrace()) |trace| {
std.debug.dumpErrorReturnTrace(trace); std.debug.dumpStackTrace(trace);
} }
if (env.fail_first) { if (env.fail_first) {
break; break;
@ -273,9 +272,8 @@ const SlowTracker = struct {
name: []const u8, name: []const u8,
}; };
fn deinit(self: *SlowTracker, allocator: Allocator) void { fn deinit(self: SlowTracker, allocator: Allocator) void {
var slowest = &self.slowest; self.slowest.deinit(allocator);
slowest.deinit(allocator);
} }
fn startTiming(self: *SlowTracker) void { fn startTiming(self: *SlowTracker) void {

View file

@ -1,17 +0,0 @@
import { readFile } from "fs/promises";
let memory = null;
const buffer = await readFile("zig-out/bin/temporalz.wasm");
const temporalz = await WebAssembly.instantiate(buffer, {
env: {
console(ptr, len) {
const bytes = new Uint8Array(memory.buffer, ptr, len);
const message = new TextDecoder().decode(bytes);
console.log(message);
},
},
});
memory = temporalz.instance.exports.memory;
temporalz.instance.exports._start();

View file

@ -1,24 +0,0 @@
const std = @import("std");
const builtin = @import("builtin");
const program = @import("root.zig");
const freestanding = builtin.os.tag == .freestanding;
pub fn main(init: Init) !void {
const allocator = std.heap.page_allocator;
const io = if (freestanding) null else init.io;
try program.run(allocator, io);
}
// -- //
const Init = if (freestanding) std.process.Init.Minimal else std.process.Init;
pub const std_options: std.Options = .{
.logFn = if (freestanding) logFn else std.log.defaultLog,
};
extern fn console(ptr: [*]u8, len: u32) void;
fn logFn(comptime _: anytype, comptime _: anytype, comptime format: []const u8, args: anytype) void {
const formatted = std.fmt.allocPrint(std.heap.wasm_allocator, format, args) catch return;
console(formatted.ptr, formatted.len);
}

View file

@ -1,913 +0,0 @@
const std = @import("std");
const builtin = @import("builtin");
const Temporal = @import("temporalz");
pub fn run(allocator: std.mem.Allocator, io_optional: ?std.Io) !void {
// --- Instant --- //
const instant = try Temporal.Instant.init(1_704_067_200_000_000_000); // 2024-01-01 00:00:00 UTC
defer instant.deinit();
std.log.info(
\\Instant
\\ - milliseconds: {}
\\ - nanoseconds: {}
\\ - toString(): {s}
\\
\\
, .{
instant.epochMilliseconds(),
instant.epochNanoseconds(),
try instant.toString(allocator, .{}),
});
// --- Duration --- //
const dur = try Temporal.Duration.from("PT1H");
defer dur.deinit();
std.log.info(
\\Duration
\\ - nanoseconds: {}
\\ - milliseconds: {}
\\ - seconds: {}
\\ - minutes: {}
\\ - hours: {}
\\ - days: {}
\\ - weeks: {}
\\ - months: {}
\\ - years: {}
\\ - toString(): {s}
\\
\\
, .{
dur.nanoseconds(),
dur.milliseconds(),
dur.seconds(),
dur.minutes(),
dur.hours(),
dur.days(),
dur.weeks(),
dur.months(),
dur.years(),
try dur.toString(allocator, .{}),
});
// --- Now --- //
if (io_optional) |io| {
const now_instant = try Temporal.Now.instant(io);
defer now_instant.deinit();
const now_date = try Temporal.Now.plainDateISO(allocator, io, null);
defer now_date.deinit();
const now_datetime = try Temporal.Now.plainDateTimeISO(allocator, io, null);
const now_time = try Temporal.Now.plainTimeISO(allocator, io, null);
std.log.info(
\\Now
\\ - instant: {s}
\\ - date: {s}
\\ - datetime: {s}
\\ - time: {s}
\\
\\
, .{
try now_instant.toString(allocator, .{}),
try now_date.toString(allocator, .{}),
try now_datetime.toString(allocator, .{}),
try now_time.toString(allocator),
});
}
// --- PlainDate --- //
const date = try Temporal.PlainDate.init(2024, 2, 2);
defer date.deinit();
std.log.info(
\\PlainDate
\\ - year: {}
\\ - month: {}
\\ - day: {}
\\ - toString(): {s}
\\
\\
, .{
date.year(),
date.month(),
date.day(),
try date.toString(allocator, .{}),
});
// --- PlainDateTime --- //
const dt = try Temporal.PlainDateTime.init(2024, 2, 2, 13, 45, 30, 123, 456, 789);
std.log.info(
\\PlainDateTime
\\ - year: {}
\\ - month: {}
\\ - day: {}
\\ - hour: {}
\\ - minute: {}
\\ - second: {}
\\ - toString(): {s}
\\
\\
, .{
dt.year(),
dt.month(),
dt.day(),
dt.hour(),
dt.minute(),
dt.second(),
try dt.toString(allocator, .{}),
});
// --- PlainMonthDay --- //
const md = try Temporal.PlainMonthDay.init(2, 2, null);
std.log.info(
\\PlainMonthDay
\\ - monthCode: {s}
\\ - day: {}
\\ - toString(): {s}
\\
\\
, .{
try md.monthCode(allocator),
md.day(),
try md.toString(allocator),
});
// --- PlainTime --- //
const tm = try Temporal.PlainTime.init(13, 45, 30, 123, 456, 789);
std.log.info(
\\PlainTime
\\ - hour: {}
\\ - minute: {}
\\ - second: {}
\\ - toString(): {s}
\\
\\
, .{
tm.hour(),
tm.minute(),
tm.second(),
try tm.toString(allocator),
});
// --- PlainYearMonth --- //
const ym = try Temporal.PlainYearMonth.init(2024, 2, null);
std.log.info(
\\PlainYearMonth
\\ - year: {}
\\ - month: {}
\\ - toString(): {s}
\\
\\
, .{ ym.year(), ym.month(), try ym.toString(allocator) });
// --- ZonedDateTime --- //
const tz = try Temporal.ZonedDateTime.TimeZone.init("UTC");
// Example: 2024-02-02T13:45:30.123456789Z in nanoseconds since epoch
const zdt_epoch_ns: i128 = 1706881530123456789;
const zdt = try Temporal.ZonedDateTime.fromEpochNanoseconds(zdt_epoch_ns, tz);
defer zdt.deinit();
std.log.info(
\\ZonedDateTime
\\ - year: {}
\\ - month: {}
\\ - day: {}
\\ - hour: {}
\\ - minute: {}
\\ - second: {}
\\ - timeZone: {s}
\\ - toString(): {s}
\\
\\
, .{
zdt.year(),
zdt.month(),
zdt.day(),
zdt.hour(),
zdt.minute(),
zdt.second(),
try zdt.timeZoneId(allocator),
try zdt.toString(allocator, .{}),
});
try runTimeZoneExamples(allocator, io_optional, null);
// ----
// More complex Temporal API examples
// ----
// Duration arithmetic
const dur1 = try Temporal.Duration.from("P1DT2H");
const dur2 = try Temporal.Duration.from("PT30M");
const dur_sum = try dur1.add(dur2);
std.log.info(
\\Duration Arithmetic
\\ - dur1: {s}
\\ - dur2: {s}
\\ - dur1 + dur2: {s}
\\
\\
, .{
try dur1.toString(allocator, .{}),
try dur2.toString(allocator, .{}),
try dur_sum.toString(allocator, .{}),
});
// Instant comparison and arithmetic
const inst1 = try Temporal.Instant.init(1_704_067_200_000_000_000);
const inst2 = try Temporal.Instant.init(1_704_153_600_000_000_000); // +1 day
const inst_diff = try inst2.since(inst1, Temporal.Instant.DifferenceSettings{});
std.log.info(
\\Instant Comparison
\\ - inst1: {s}
\\ - inst2: {s}
\\ - inst2.since(inst1): {s}
\\
\\
, .{
try inst1.toString(allocator, .{}),
try inst2.toString(allocator, .{}),
try inst_diff.toString(allocator, .{}),
});
// PlainDate to PlainDateTime and back
const pd = try Temporal.PlainDate.init(2024, 2, 2);
const pdt = try pd.toPlainDateTime(try Temporal.PlainTime.init(12, 0, 0, 0, 0, 0));
std.log.info(
\\PlainDate/PlainDateTime Conversion
\\ - PlainDate: {s}
\\ - toPlainDateTime(12:00): {s}
\\ - toPlainDate(): {s}
\\
\\
, .{
try pd.toString(allocator, .{}),
try pdt.toString(allocator, .{}),
try (try pdt.toPlainDate()).toString(allocator, .{}),
});
// ZonedDateTime to Instant and back
const zdt2 = try Temporal.ZonedDateTime.fromEpochNanoseconds(1706881530123456789, tz);
const zdt2_inst = try zdt2.toInstant();
const zdt2_from_inst = try Temporal.ZonedDateTime.fromEpochNanoseconds(zdt2_inst.epochNanoseconds(), tz);
std.log.info(
\\ZonedDateTime/Instant Conversion
\\ - ZonedDateTime: {s}
\\ - toInstant(): {s}
\\ - fromEpochNanoseconds(instant): {s}
\\
\\
, .{
try zdt2.toString(allocator, .{}),
try zdt2_inst.toString(allocator, .{}),
try zdt2_from_inst.toString(allocator, .{}),
});
// ----
// Further more complex examples covering more methods
// ----
// Duration: abs, negated, round, subtract, total, valueOf
const dur_neg = dur.negated();
const dur_abs = dur_neg.abs();
const dur_sub = try dur.subtract(dur2);
const dur_rounded = try dur.round(.{ .smallest_unit = Temporal.Duration.Unit.hour });
const dur_total_hours = try dur.total(.{ .unit = Temporal.Duration.Unit.hour });
std.log.info(
\\Duration Advanced
\\ - negated: {s}
\\ - abs: {s}
\\ - subtract dur2: {s}
\\ - round to hour: {s}
\\ - total hours: {d}
\\
\\
, .{
try dur_neg.toString(allocator, .{}),
try dur_abs.toString(allocator, .{}),
try dur_sub.toString(allocator, .{}),
try dur_rounded.toString(allocator, .{}),
dur_total_hours,
});
// Instant: add, subtract, round, equals, valueOf
const inst_add = try inst1.add(@constCast(&dur));
const inst_sub = try inst2.subtract(@constCast(&dur));
const inst_rounded = try inst1.round(.{ .smallest_unit = Temporal.Instant.Unit.second });
const inst_eq = Temporal.Instant.compare(inst1, inst1) == 0;
std.log.info(
\\Instant Advanced
\\ - add duration: {s}
\\ - subtract duration: {s}
\\ - round to second: {s}
\\ - inst1 equals inst1: {}
\\
\\
, .{
try inst_add.toString(allocator, .{}),
try inst_sub.toString(allocator, .{}),
try inst_rounded.toString(allocator, .{}),
inst_eq,
});
// PlainDate: add, subtract, with, equals, since, until, withCalendar
const date_added = try date.add(dur);
const date_sub = try date.subtract(dur);
const date_with = try date.with(.{ .year = 2025 });
const date_eq = date.equals(date);
const date_since = try date.since(date, Temporal.PlainDate.DifferenceSettings{});
const date_until = try date.until(date, Temporal.PlainDate.DifferenceSettings{});
const date_with_cal = try date.withCalendar("iso8601");
std.log.info(
\\PlainDate Advanced
\\ - equals self: {}
\\ - add duration: {s}
\\ - subtract duration: {s}
\\ - since self: {s}
\\ - until self: {s}
\\ - withCalendar: {s}
\\ - with year=2025: {s}
\\
\\
,
.{
date_eq,
try date_added.toString(allocator, .{}),
try date_sub.toString(allocator, .{}),
try date_since.toString(allocator, .{}),
try date_until.toString(allocator, .{}),
try date_with_cal.toString(allocator, .{}),
try date_with.toString(allocator, .{}),
},
);
// PlainDateTime: add, subtract, round, with, equals, since, until, withCalendar, withPlainTime
const dt_added = try dt.add(dur);
const dt_sub = try dt.subtract(dur);
const dt_rounded = try dt.round(.{ .smallest_unit = Temporal.PlainDateTime.Unit.minute });
const dt_with = try dt.with(.{ .year = 2025 });
const dt_eq = dt.equals(dt);
const dt_since = try dt.since(dt, Temporal.PlainDateTime.DifferenceSettings{});
const dt_until = try dt.until(dt, Temporal.PlainDateTime.DifferenceSettings{});
const dt_with_cal = try dt.withCalendar("iso8601");
const dt_with_time = try dt.withPlainTime(try Temporal.PlainTime.init(1, 2, 3, 4, 5, 6));
std.log.info(
\\PlainDateTime Advanced
\\ - add duration: {s}
\\ - subtract duration: {s}
\\ - round to minute: {s}
\\ - with year=2025: {s}
\\ - equals self: {}
\\ - since self: {s}
\\ - until self: {s}
\\ - withCalendar: {s}
\\ - withPlainTime: {s}
\\
\\
, .{
try dt_added.toString(allocator, .{}),
try dt_sub.toString(allocator, .{}),
try dt_rounded.toString(allocator, .{}),
try dt_with.toString(allocator, .{}),
dt_eq,
try dt_since.toString(allocator, .{}),
try dt_until.toString(allocator, .{}),
try dt_with_cal.toString(allocator, .{}),
try dt_with_time.toString(allocator, .{}),
});
// PlainTime: add, subtract, round, with, equals, since, until
const tm_added = try tm.add(dur);
const tm_sub = try tm.subtract(dur);
const tm_rounded = try tm.round(.{ .smallest_unit = Temporal.PlainTime.Unit.second });
const tm_with = try tm.with(.{ .hour = 1 });
const tm_eq = tm.equals(tm);
const tm_since = try tm.since(tm, Temporal.PlainTime.DifferenceSettings{});
const tm_until = try tm.until(tm, Temporal.PlainTime.DifferenceSettings{});
std.log.info(
\\PlainTime Advanced
\\ - add duration: {s}
\\ - subtract duration: {s}
\\ - round to second: {s}
\\ - with hour=1: {s}
\\ - equals self: {}
\\ - since self: {s}
\\ - until self: {s}
\\
\\
, .{
try tm_added.toString(allocator),
try tm_sub.toString(allocator),
try tm_rounded.toString(allocator),
try tm_with.toString(allocator),
tm_eq,
try tm_since.toString(allocator, .{}),
try tm_until.toString(allocator, .{}),
});
// PlainYearMonth: add, subtract, with, equals, since, until
const dur_ym = try Temporal.Duration.from("P1M");
defer dur_ym.deinit();
const ym_added = try ym.add(dur_ym);
const ym_sub = try ym.subtract(dur_ym);
const ym_with = try ym.with(.{ .year = 2025 });
const ym_eq = ym.equals(ym);
const ym_since = try ym.since(ym, Temporal.PlainYearMonth.DifferenceSettings{});
const ym_until = try ym.until(ym, Temporal.PlainYearMonth.DifferenceSettings{});
std.log.info(
\\PlainYearMonth Advanced
\\ - add duration: {s}
\\ - subtract duration: {s}
\\ - with year=2025: {s}
\\ - equals self: {}
\\ - since self: {s}
\\ - until self: {s}
\\
\\
, .{
try ym_added.toString(allocator),
try ym_sub.toString(allocator),
try ym_with.toString(allocator),
ym_eq,
try ym_since.toString(allocator, .{}),
try ym_until.toString(allocator, .{}),
});
// ZonedDateTime: add, subtract, round, equals, since, until, withCalendar, withPlainTime, withTimeZone
const zdt_added = try zdt.add(dur);
const zdt_sub = try zdt.subtract(dur);
const zdt_rounded = try zdt.round(.{ .smallest_unit = Temporal.ZonedDateTime.Unit.hour });
const zdt_eq = zdt.equals(zdt);
const zdt_since = try zdt.since(zdt, Temporal.ZonedDateTime.DifferenceSettings{});
const zdt_until = try zdt.until(zdt, Temporal.ZonedDateTime.DifferenceSettings{});
const zdt_with_cal = try zdt.withCalendar("iso8601");
const zdt_with_time = try zdt.withPlainTime(try Temporal.PlainTime.init(1, 2, 3, 4, 5, 6));
const zdt_with_tz = try zdt.withTimeZone(tz);
std.log.info(
\\ZonedDateTime Advanced
\\ - add duration: {s}
\\ - subtract duration: {s}
\\ - round to hour: {s}
\\ - equals self: {}
\\ - since self: {s}
\\ - until self: {s}
\\ - withCalendar: {s}
\\ - withPlainTime: {s}
\\ - withTimeZone: {s}
\\
\\
, .{
try zdt_added.toString(allocator, .{}),
try zdt_sub.toString(allocator, .{}),
try zdt_rounded.toString(allocator, .{}),
zdt_eq,
try zdt_since.toString(allocator, .{}),
try zdt_until.toString(allocator, .{}),
try zdt_with_cal.toString(allocator, .{}),
try zdt_with_time.toString(allocator, .{}),
try zdt_with_tz.toString(allocator, .{}),
});
// ----
// API coverage examples for the remaining public methods
// ----
const dur_init = try Temporal.Duration.init(0, 1, 0, 2, 3, 4, 5, 6, 7, 8);
const dur_from_partial = try Temporal.Duration.from(Temporal.Duration.PartialDuration{ .minutes = 90 });
const dur_compare = try dur.compare(dur2, .{});
const dur_locale_supported = dur.toLocaleString(allocator) != error.TemporalNotImplemented;
std.log.info(
\\Duration Coverage
\\ - init: {s}
\\ - from partial: {s}
\\ - compare(dur, dur2): {}
\\ - sign: {s}
\\ - blank: {}
\\ - microseconds: {d}
\\ - toJSON(): {s}
\\ - toLocaleString supported: {}
\\
\\
, .{
try dur_init.toString(allocator, .{}),
try dur_from_partial.toString(allocator, .{}),
dur_compare,
@tagName(dur.sign()),
dur.blank(),
dur.microseconds(),
try dur.toJSON(allocator),
dur_locale_supported,
});
const instant_from_ms = try Temporal.Instant.fromEpochMilliseconds(1_704_067_200_000);
const instant_from_ns = try Temporal.Instant.fromEpochNanoseconds(1_704_067_200_000_000_000);
const instant_from_str = try Temporal.Instant.from("2024-01-01T00:00:00Z");
const instant_until = try inst1.until(inst2, Temporal.Instant.DifferenceSettings{});
const instant_zdt = try inst1.toZonedDateTimeISO(try Temporal.Instant.TimeZone.init("UTC"));
defer instant_zdt.deinit();
std.log.info(
\\Instant Coverage
\\ - fromEpochMilliseconds: {s}
\\ - fromEpochNanoseconds: {s}
\\ - from string: {s}
\\ - equals(from ms, from ns): {}
\\ - until inst2: {s}
\\ - toJSON(): {s}
\\ - toLocaleString(): {s}
\\ - toZonedDateTimeISO(): {s}
\\
\\
, .{
try instant_from_ms.toString(allocator, .{}),
try instant_from_ns.toString(allocator, .{}),
try instant_from_str.toString(allocator, .{}),
Temporal.Instant.equals(instant_from_ms, instant_from_ns),
try instant_until.toString(allocator, .{}),
try inst1.toJSON(allocator),
try inst1.toLocaleString(allocator),
try instant_zdt.toString(allocator, .{}),
});
if (io_optional) |io| {
const now_zdt = try Temporal.Now.zonedDateTimeISO(allocator, io, null);
defer now_zdt.deinit();
const now_tz_id = try Temporal.Now.timeZoneId(allocator, io);
defer allocator.free(now_tz_id);
std.log.info(
\\Now Coverage
\\ - timeZoneId(): {s}
\\ - zonedDateTimeISO(): {s}
\\
\\
, .{
now_tz_id,
try now_zdt.toString(allocator, .{}),
});
}
const date_cal = try Temporal.PlainDate.calInit(2024, 2, 2, "iso8601");
const date_from = try Temporal.PlainDate.from("2024-02-02");
const date_md = try date.toPlainMonthDay();
const date_ym = try date.toPlainYearMonth();
const date_zdt = try date.toZonedDateTime(.{ .time_zone = "UTC", .plain_time = tm });
const date_locale_supported = date.toLocaleString(allocator) != error.TemporalNotImplemented;
const date_valueof_supported = date.valueOf() != error.TemporalValueOfNotSupported;
const date_with_coverage = try date.with(.{ .year = 2025, .month = 3, .day = 4 });
std.log.info(
\\PlainDate Coverage
\\ - calInit: {s}
\\ - from string: {s}
\\ - compare(date, from): {}
\\ - calendarId: {s}
\\ - dayOfWeek/dayOfYear: {}/{}
\\ - daysInWeek/daysInMonth/daysInYear: {}/{}/{}
\\ - monthCode/monthsInYear: {s}/{}
\\ - inLeapYear: {}
\\ - era/eraYear: {any}/{?}
\\ - weekOfYear/yearOfWeek: {?}/{?}
\\ - toPlainMonthDay: {s}
\\ - toPlainYearMonth: {s}
\\ - toZonedDateTime: {s}
\\ - toJSON(): {s}
\\ - toLocaleString supported: {}
\\ - valueOf supported: {}
\\ - with year/month/day: {s}
\\
\\
, .{
try date_cal.toString(allocator, .{}),
try date_from.toString(allocator, .{}),
Temporal.PlainDate.compare(date, date_from),
try date.calendarId(allocator),
date.dayOfWeek(),
date.dayOfYear(),
date.daysInWeek(),
date.daysInMonth(),
date.daysInYear(),
try date.monthCode(allocator),
date.monthsInYear(),
date.inLeapYear(),
try date.era(allocator),
date.eraYear(),
date.weekOfYear(),
date.yearOfWeek(),
try date_md.toString(allocator),
try date_ym.toString(allocator),
try date_zdt.toString(allocator, .{}),
try date.toJSON(allocator),
date_locale_supported,
date_valueof_supported,
try date_with_coverage.toString(allocator, .{}),
});
const dt_cal = try Temporal.PlainDateTime.calInit(2024, 2, 2, 13, 45, 30, 123, 456, 789, "iso8601");
const dt_from = try Temporal.PlainDateTime.from("2024-02-02T13:45:30.123456789", .{});
const dt_plain_time = try dt.toPlainTime();
const dt_zdt = try dt.toZonedDateTime(.{ .timeZone = "UTC" });
const dt_valueof_supported = dt.valueOf() != error.ComparisonNotSupported;
std.log.info(
\\PlainDateTime Coverage
\\ - calInit: {s}
\\ - from string: {s}
\\ - compare(dt, from): {}
\\ - calendarId: {s}
\\ - dayOfWeek/dayOfYear: {}/{}
\\ - daysInWeek/daysInMonth/daysInYear: {}/{}/{}
\\ - monthCode/monthsInYear: {s}/{}
\\ - inLeapYear: {}
\\ - era/eraYear: {any}/{?}
\\ - weekOfYear/yearOfWeek: {?}/{?}
\\ - millisecond/microsecond/nanosecond: {}/{}/{}
\\ - toPlainTime: {s}
\\ - toZonedDateTime: {s}
\\ - toJSON(): {s}
\\ - toLocaleString(): {s}
\\ - valueOf supported: {}
\\
\\
, .{
try dt_cal.toString(allocator, .{}),
try dt_from.toString(allocator, .{}),
Temporal.PlainDateTime.compare(dt, dt_from),
try dt.calendarId(allocator),
dt.dayOfWeek(),
dt.dayOfYear(),
dt.daysInWeek(),
dt.daysInMonth(),
dt.daysInYear(),
try dt.monthCode(allocator),
dt.monthsInYear(),
dt.inLeapYear(),
try dt.era(allocator),
try dt.eraYear(),
try dt.weekOfYear(),
try dt.yearOfWeek(),
dt.millisecond(),
dt.microsecond(),
dt.nanosecond(),
try dt_plain_time.toString(allocator),
try dt_zdt.toString(allocator, .{}),
try dt.toJSON(allocator),
dt.toLocaleString(allocator),
dt_valueof_supported,
});
const md_from = try Temporal.PlainMonthDay.from("02-02");
const md_with = try md.with(.{ .day = 3 });
const md_date = try md.toPlainDate(2024);
const md_valueof_supported = md.valueOf() != error.ValueError;
std.log.info(
\\PlainMonthDay Coverage
\\ - from string: {s}
\\ - equals(from): {}
\\ - calendarId: {s}
\\ - with day=3: {s}
\\ - toPlainDate(2024): {s}
\\ - toJSON(): {s}
\\ - toLocaleString(): {s}
\\ - valueOf supported: {}
\\
\\
, .{
try md_from.toString(allocator),
md.equals(md_from),
try md.calendarId(allocator),
try md_with.toString(allocator),
try md_date.toString(allocator, .{}),
try md.toJSON(allocator),
try md.toLocaleString(allocator),
md_valueof_supported,
});
const tm_from = try Temporal.PlainTime.from("13:45:30.123456789");
const tm_valueof_supported = tm.valueOf() != error.ValueError;
std.log.info(
\\PlainTime Coverage
\\ - from string: {s}
\\ - compare(tm, from): {}
\\ - millisecond/microsecond/nanosecond: {}/{}/{}
\\ - toJSON(): {s}
\\ - toLocaleString(): {s}
\\ - valueOf supported: {}
\\
\\
, .{
try tm_from.toString(allocator),
Temporal.PlainTime.compare(tm, tm_from),
tm.millisecond(),
tm.microsecond(),
tm.nanosecond(),
try tm.toJSON(allocator),
try tm.toLocaleString(allocator),
tm_valueof_supported,
});
const ym_from = try Temporal.PlainYearMonth.from("2024-02");
const ym_date = try ym.toPlainDate(2);
const ym_valueof_supported = ym.valueOf() != error.ValueError;
std.log.info(
\\PlainYearMonth Coverage
\\ - from string: {s}
\\ - compare(ym, from): {}
\\ - calendarId: {s}
\\ - monthCode: {s}
\\ - daysInMonth/daysInYear/monthsInYear: {}/{}/{}
\\ - inLeapYear: {}
\\ - era/eraYear: {any}/{?}
\\ - toPlainDate(2): {s}
\\ - toJSON(): {s}
\\ - toLocaleString(): {s}
\\ - valueOf supported: {}
\\
\\
, .{
try ym_from.toString(allocator),
Temporal.PlainYearMonth.compare(ym, ym_from),
try ym.calendarId(allocator),
try ym.monthCode(allocator),
ym.daysInMonth(),
ym.daysInYear(),
ym.monthsInYear(),
ym.inLeapYear(),
try ym.era(allocator),
ym.eraYear(),
try ym_date.toString(allocator, .{}),
try ym.toJSON(allocator),
try ym.toLocaleString(allocator),
ym_valueof_supported,
});
const zdt_init = try Temporal.ZonedDateTime.init(zdt_epoch_ns, tz);
const zdt_from_ms = try Temporal.ZonedDateTime.fromEpochMilliseconds(1_706_881_530_123, tz);
const zdt_from = try Temporal.ZonedDateTime.from("2024-02-02T13:45:30.123456789+00:00[UTC]", null, .compatible, .reject);
const zdt_transition_next = try zdt.getTimeZoneTransition(.next);
const zdt_transition_previous = try zdt.getTimeZoneTransition(.previous);
const zdt_day_start = try zdt.startOfDay();
const zdt_plain_date = try zdt.toPlainDate();
const zdt_plain_datetime = try zdt.toPlainDateTime();
const zdt_plain_time = try zdt.toPlainTime();
const zdt_valueof_supported = zdt.valueOf() != error.ValueOfNotSupported;
const zdt_with_coverage = try zdt.with(allocator, .{ .year = 2025 });
defer zdt_with_coverage.deinit();
std.log.info(
\\ZonedDateTime Coverage
\\ - init: {s}
\\ - fromEpochMilliseconds: {s}
\\ - from string: {s}
\\ - compare(zdt, from): {}
\\ - next/previous transition exists: {}/{}
\\ - startOfDay: {s}
\\ - toJSON(): {s}
\\ - toLocaleString(): {s}
\\ - toPlainDate: {s}
\\ - toPlainDateTime: {s}
\\ - toPlainTime: {s}
\\ - calendarId: {s}
\\ - dayOfWeek/dayOfYear: {}/{}
\\ - daysInWeek/daysInMonth/daysInYear: {}/{}/{}
\\ - epochMilliseconds/epochNanoseconds: {}/{}
\\
, .{
try zdt_init.toString(allocator, .{}),
try zdt_from_ms.toString(allocator, .{}),
try zdt_from.toString(allocator, .{}),
Temporal.ZonedDateTime.compare(zdt, zdt_from),
zdt_transition_next != null,
zdt_transition_previous != null,
try zdt_day_start.toString(allocator, .{}),
try zdt.toJSON(allocator),
try zdt.toLocaleString(allocator),
try zdt_plain_date.toString(allocator, .{}),
try zdt_plain_datetime.toString(allocator, .{}),
try zdt_plain_time.toString(allocator),
try zdt.calendarId(allocator),
zdt.dayOfWeek(),
zdt.dayOfYear(),
zdt.daysInWeek(),
zdt.daysInMonth(),
zdt.daysInYear(),
zdt.epochMilliseconds(),
zdt.epochNanoseconds(),
});
std.log.info(
\\ZonedDateTime Coverage Continued
\\ - era/eraYear: {any}/{?}
\\ - hoursInDay/inLeapYear: {d}/{}
\\ - millisecond/microsecond/nanosecond: {}/{}/{}
\\ - monthCode/monthsInYear: {s}/{}
\\ - offset/offsetNanoseconds: {s}/{}
\\ - weekOfYear/yearOfWeek: {?}/{?}
\\ - valueOf supported: {}
\\ - with year=2025: {s}
\\
\\
, .{
try zdt.era(allocator),
zdt.eraYear(),
try zdt.hoursInDay(),
zdt.inLeapYear(),
zdt.millisecond(),
zdt.microsecond(),
zdt.nanosecond(),
try zdt.monthCode(allocator),
zdt.monthsInYear(),
try zdt.offset(allocator),
zdt.offsetNanoseconds(),
zdt.weekOfYear(),
zdt.yearOfWeek(),
zdt_valueof_supported,
try zdt_with_coverage.toString(allocator, .{}),
});
}
pub fn runTimeZoneExamples(
allocator: std.mem.Allocator,
io_optional: ?std.Io,
now_epoch_ms: ?i64,
) !void {
const epoch_ns: i128 = if (now_epoch_ms) |ms| @as(i128, ms) * 1_000_000 else 1_706_881_530_123_456_789;
const utc_tz = try Temporal.ZonedDateTime.TimeZone.init("UTC");
const ny_tz = try Temporal.ZonedDateTime.TimeZone.init("America/New_York");
const dhaka_tz = try Temporal.ZonedDateTime.TimeZone.init("Asia/Dhaka");
const zdt_utc = try Temporal.ZonedDateTime.fromEpochNanoseconds(epoch_ns, utc_tz);
defer zdt_utc.deinit();
const zdt_ny = try zdt_utc.withTimeZone(ny_tz);
defer zdt_ny.deinit();
const zdt_dhaka = try zdt_utc.withTimeZone(dhaka_tz);
defer zdt_dhaka.deinit();
const utc_id = try zdt_utc.timeZoneId(allocator);
defer allocator.free(utc_id);
const ny_id = try zdt_ny.timeZoneId(allocator);
defer allocator.free(ny_id);
const dhaka_id = try zdt_dhaka.timeZoneId(allocator);
defer allocator.free(dhaka_id);
std.log.info(
\\TimeZone
\\ - same instant in UTC ({s}): {s}
\\ - same instant in New York ({s}): {s}
\\ - same instant in Dhaka ({s}): {s}
\\ - UTC offset: {s}
\\ - New York offset: {s}
\\ - Dhaka offset: {s}
\\
\\
, .{
utc_id,
try zdt_utc.toString(allocator, .{}),
ny_id,
try zdt_ny.toString(allocator, .{}),
dhaka_id,
try zdt_dhaka.toString(allocator, .{}),
try zdt_utc.offset(allocator),
try zdt_ny.offset(allocator),
try zdt_dhaka.offset(allocator),
});
if (io_optional) |io| {
const system_tz_id = try Temporal.Now.timeZoneId(allocator, io);
defer allocator.free(system_tz_id);
const now_zdt = try Temporal.Now.zonedDateTimeISO(allocator, io, null);
defer now_zdt.deinit();
const now_zdt_utc = try Temporal.Now.zonedDateTimeISO(allocator, io, "UTC");
defer now_zdt_utc.deinit();
const now_date = try Temporal.Now.plainDateISO(allocator, io, null);
defer now_date.deinit();
std.log.info(
\\TimeZone (system)
\\ - system timeZoneId(): {s}
\\ - Now.zonedDateTimeISO(): {s}
\\ - Now.zonedDateTimeISO("UTC"): {s}
\\ - Now.plainDateISO(): {s}
\\
\\
, .{
system_tz_id,
try now_zdt.toString(allocator, .{}),
try now_zdt_utc.toString(allocator, .{}),
try now_date.toString(allocator, .{}),
});
} else if (now_epoch_ms) |ms| {
const inst = try Temporal.Instant.fromEpochMilliseconds(ms);
defer inst.deinit();
const inst_dhaka_tz = try Temporal.Instant.TimeZone.init("Asia/Dhaka");
const inst_utc_tz = try Temporal.Instant.TimeZone.init("UTC");
const host_zdt = try inst.toZonedDateTimeISO(inst_dhaka_tz);
defer host_zdt.deinit();
const host_zdt_utc = try inst.toZonedDateTimeISO(inst_utc_tz);
defer host_zdt_utc.deinit();
std.log.info(
\\TimeZone (host epoch)
\\ - Instant.toZonedDateTimeISO("Asia/Dhaka"): {s}
\\ - Instant.toZonedDateTimeISO("UTC"): {s}
\\
\\
, .{
try host_zdt.toString(allocator, .{}),
try host_zdt_utc.toString(allocator, .{}),
});
}
}

@ -0,0 +1 @@
Subproject commit 80286aa081b04bb9c9881615af62ae0d47912791

683
test/test262/polyfill.js Normal file
View file

@ -0,0 +1,683 @@
// This polyfill is executed in a vm.Script context by test262-runner,
// so it must be synchronous and self-contained.
// The wasm bytes are injected as global.__TEMPORALZ_WASM_BYTES__ by the runner.
(function () {
if (!globalThis.__TEMPORALZ_WASM_BYTES__) {
throw new Error("WASM bytes not injected into test context");
}
const wasmBinary = globalThis.__TEMPORALZ_WASM_BYTES__;
const wasmModule = new WebAssembly.Module(wasmBinary);
const wasmInstance = new WebAssembly.Instance(wasmModule, {
env: {
console(ptr, len) {
const bytes = new Uint8Array(memory.buffer, ptr, len);
globalThis.console.log(decoder.decode(bytes));
},
},
});
const exports = wasmInstance.exports;
const memory = exports.memory;
const encoder = {
encode(str) {
const buf = [];
for (let i = 0; i < str.length; i++) {
const code = str.charCodeAt(i);
if (code < 0x80) {
buf.push(code);
} else if (code < 0x800) {
buf.push(0xc0 | (code >> 6), 0x80 | (code & 0x3f));
} else if (code < 0xd800 || code >= 0xe000) {
buf.push(0xe0 | (code >> 12), 0x80 | ((code >> 6) & 0x3f), 0x80 | (code & 0x3f));
} else {
const code2 = str.charCodeAt(++i);
const codePoint = 0x10000 + (((code & 0x3ff) << 10) | (code2 & 0x3ff));
buf.push(
0xf0 | (codePoint >> 18),
0x80 | ((codePoint >> 12) & 0x3f),
0x80 | ((codePoint >> 6) & 0x3f),
0x80 | (codePoint & 0x3f)
);
}
}
return new Uint8Array(buf);
},
};
const decoder = {
decode(bytes) {
let str = "";
for (let i = 0; i < bytes.length; i++) {
const byte = bytes[i];
if (byte < 0x80) {
str += String.fromCharCode(byte);
} else if ((byte & 0xe0) === 0xc0) {
str += String.fromCharCode(((byte & 0x1f) << 6) | (bytes[++i] & 0x3f));
} else if ((byte & 0xf0) === 0xe0) {
str += String.fromCharCode(
((byte & 0x0f) << 12) | ((bytes[++i] & 0x3f) << 6) | (bytes[++i] & 0x3f)
);
} else if ((byte & 0xf8) === 0xf0) {
const codePoint =
((byte & 0x07) << 18) |
((bytes[++i] & 0x3f) << 12) |
((bytes[++i] & 0x3f) << 6) |
(bytes[++i] & 0x3f);
const high = ((codePoint - 0x10000) >> 10) + 0xd800;
const low = ((codePoint - 0x10000) & 0x3ff) + 0xdc00;
str += String.fromCharCode(high, low);
}
}
return str;
},
};
function readString(ptr, len) {
return decoder.decode(new Uint8Array(memory.buffer, ptr, len));
}
function lastError() {
const ptr = exports.temporalz_last_error_ptr();
const len = exports.temporalz_last_error_len();
if (!ptr || !len) return new Error("temporalz error");
const msg = readString(ptr, len);
exports.temporalz_last_error_clear();
if (msg.includes("Range")) return new RangeError(msg);
if (msg.includes("Type")) return new TypeError(msg);
return new Error(msg);
}
function requireHandle(handle) {
if (!handle) throw lastError();
return handle;
}
function allocString(text) {
const bytes = encoder.encode(text);
const ptr = exports.temporalz_alloc(bytes.length);
if (!ptr) throw lastError();
new Uint8Array(memory.buffer, ptr, bytes.length).set(bytes);
return { ptr, len: bytes.length };
}
function takeString(packed) {
if (!packed) throw lastError();
const value = BigInt(packed);
const ptr = Number(value >> 32n);
const len = Number(value & 0xffffffffn);
const text = readString(ptr, len);
exports.temporalz_string_free(ptr, len);
return text;
}
function splitI128(value) {
const v = typeof value === "bigint" ? value : BigInt(value);
const mask = (1n << 64n) - 1n;
return { hi: v >> 64n, lo: v & mask };
}
function joinI128(hi, lo) {
const mask = (1n << 64n) - 1n;
return (BigInt(hi) << 64n) | (BigInt(lo) & mask);
}
const unitCodes = {
nanosecond: 1,
microsecond: 2,
millisecond: 3,
second: 4,
minute: 5,
hour: 6,
day: 7,
week: 8,
month: 9,
year: 10,
auto: 11,
};
const roundingModeCodes = {
ceil: 1,
floor: 2,
expand: 3,
trunc: 4,
halfCeil: 5,
halfFloor: 6,
halfExpand: 7,
halfTrunc: 8,
halfEven: 9,
};
function toUnitCode(value, name) {
if (value === undefined || value === null) return 255;
const code = unitCodes[value];
if (!code) throw new RangeError(`Invalid ${name}`);
return code;
}
function toRoundingModeCode(value) {
if (value === undefined || value === null) return 255;
const code = roundingModeCodes[value];
if (!code) throw new RangeError("Invalid roundingMode");
return code;
}
function toIntegerBigInt(value, name) {
if (typeof value === "bigint") return value;
const number = Number(value);
if (!isFiniteNumber(number)) throw new RangeError(`${name} must be finite`);
if (!Number.isInteger(number)) throw new RangeError(`${name} must be an integer`);
return BigInt(number);
}
function toNumber(value, name) {
const number = Number(value);
if (!isFiniteNumber(number)) throw new RangeError(`${name} must be finite`);
return number;
}
function toInteger(value, name) {
const number = Number(value);
if (!isFiniteNumber(number)) throw new RangeError(`${name} must be finite`);
if (!Number.isInteger(number)) throw new RangeError(`${name} must be an integer`);
return number;
}
function isFiniteNumber(value) {
return value === value && value !== Infinity && value !== -Infinity;
}
function unimplemented(name) {
return function () {
throw new Error(`${name} is not implemented yet`);
};
}
class Instant {
constructor(handle) {
this._handle = handle;
}
static _fromHandle(handle) {
return new Instant(handle);
}
static fromEpochMilliseconds(epochMs) {
const number = Number(epochMs);
if (!isFiniteNumber(number)) throw new RangeError("epochMilliseconds must be finite");
const handle = exports.temporalz_instant_from_epoch_milliseconds(number);
return Instant._fromHandle(requireHandle(handle));
}
static fromEpochNanoseconds(epochNs) {
const parts = splitI128(epochNs);
const handle = exports.temporalz_instant_from_epoch_nanoseconds_parts(
parts.hi,
parts.lo
);
return Instant._fromHandle(requireHandle(handle));
}
static from(value) {
if (value instanceof Instant) return value;
if (typeof value === "string") {
const text = allocString(value);
const handle = exports.temporalz_instant_from_utf8(text.ptr, text.len);
exports.temporalz_free(text.ptr, text.len);
return Instant._fromHandle(requireHandle(handle));
}
if (value && typeof value === "object") {
if (value.epochNanoseconds !== undefined) {
return Instant.fromEpochNanoseconds(value.epochNanoseconds);
}
if (value.epochMilliseconds !== undefined) {
return Instant.fromEpochMilliseconds(value.epochMilliseconds);
}
}
throw new TypeError("Instant.from expects a string or object");
}
get epochMilliseconds() {
return exports.temporalz_instant_epoch_milliseconds(this._handle);
}
get epochNanoseconds() {
const hi = exports.temporalz_instant_epoch_nanoseconds_hi(this._handle);
const lo = exports.temporalz_instant_epoch_nanoseconds_lo(this._handle);
return joinI128(hi, lo);
}
toString() {
return takeString(exports.temporalz_instant_to_string(this._handle));
}
toJSON() {
return this.toString();
}
add(durationLike) {
const dur = Duration.from(durationLike);
const handle = exports.temporalz_instant_add(this._handle, dur._handle);
return Instant._fromHandle(requireHandle(handle));
}
subtract(durationLike) {
const dur = Duration.from(durationLike);
const handle = exports.temporalz_instant_subtract(this._handle, dur._handle);
return Instant._fromHandle(requireHandle(handle));
}
round(options) {
if (!options || typeof options !== "object") {
throw new TypeError("round options must be an object");
}
const smallestUnit = toUnitCode(options.smallestUnit, "smallestUnit");
if (smallestUnit === 255) throw new RangeError("smallestUnit is required");
const roundingMode = toRoundingModeCode(options.roundingMode);
let roundingIncrement = 0;
if (options.roundingIncrement !== undefined) {
const inc = Number(options.roundingIncrement);
if (!isFiniteNumber(inc) || !Number.isInteger(inc) || inc <= 0) {
throw new RangeError("Invalid roundingIncrement");
}
roundingIncrement = inc;
}
const handle = exports.temporalz_instant_round(
this._handle,
smallestUnit,
roundingMode,
roundingIncrement
);
return Instant._fromHandle(requireHandle(handle));
}
equals(other) {
const rhs = Instant.from(other);
return exports.temporalz_instant_equals(this._handle, rhs._handle) === 1;
}
toLocaleString() {
return this.toString();
}
valueOf() {
throw new TypeError("Cannot convert Temporal.Instant to a number");
}
static compare(a, b) {
const left = Instant.from(a);
const right = Instant.from(b);
return Number(exports.temporalz_instant_compare(left._handle, right._handle));
}
}
const plainDateHandleToken = Symbol("PlainDateHandle");
class PlainDate {
constructor(year, month, day) {
if (year === plainDateHandleToken) {
this._handle = month;
return;
}
const yearValue = toInteger(year ?? 0, "year");
const monthValue = toInteger(month ?? 0, "month");
const dayValue = toInteger(day ?? 0, "day");
const handle = exports.temporalz_plain_date_init(yearValue, monthValue, dayValue);
this._handle = requireHandle(handle);
}
static _fromHandle(handle) {
return new PlainDate(plainDateHandleToken, handle);
}
static from(value) {
if (value instanceof PlainDate) return value;
if (typeof value === "string") {
const text = allocString(value);
const handle = exports.temporalz_plain_date_from_utf8(text.ptr, text.len);
exports.temporalz_free(text.ptr, text.len);
return PlainDate._fromHandle(requireHandle(handle));
}
if (value === null || typeof value !== "object") {
throw new TypeError("PlainDate.from expects a string or object");
}
const year = toInteger(value.year, "year");
const month = toInteger(value.month, "month");
const day = toInteger(value.day, "day");
const handle = exports.temporalz_plain_date_init(year, month, day);
return PlainDate._fromHandle(requireHandle(handle));
}
toString() {
return takeString(exports.temporalz_plain_date_to_string(this._handle));
}
}
const durationHandleToken = Symbol("DurationHandle");
class Duration {
constructor(
years,
months,
weeks,
days,
hours,
minutes,
seconds,
milliseconds,
microseconds,
nanoseconds
) {
if (years === durationHandleToken) {
this._handle = months;
return;
}
const yearsValue = toIntegerBigInt(years ?? 0, "years");
const monthsValue = toIntegerBigInt(months ?? 0, "months");
const weeksValue = toIntegerBigInt(weeks ?? 0, "weeks");
const daysValue = toIntegerBigInt(days ?? 0, "days");
const hoursValue = toIntegerBigInt(hours ?? 0, "hours");
const minutesValue = toIntegerBigInt(minutes ?? 0, "minutes");
const secondsValue = toIntegerBigInt(seconds ?? 0, "seconds");
const millisecondsValue = toIntegerBigInt(milliseconds ?? 0, "milliseconds");
const microsecondsValue = toNumber(microseconds ?? 0, "microseconds");
const nanosecondsValue = toNumber(nanoseconds ?? 0, "nanoseconds");
const created = exports.temporalz_duration_init(
yearsValue,
monthsValue,
weeksValue,
daysValue,
hoursValue,
minutesValue,
secondsValue,
millisecondsValue,
microsecondsValue,
nanosecondsValue
);
this._handle = requireHandle(created);
}
static _fromHandle(handle) {
return new Duration(durationHandleToken, handle);
}
static from(value) {
if (value instanceof Duration) return value;
if (typeof value === "string") {
const text = allocString(value);
const handle = exports.temporalz_duration_from_utf8(text.ptr, text.len);
exports.temporalz_free(text.ptr, text.len);
return Duration._fromHandle(requireHandle(handle));
}
if (value === null || typeof value !== "object") {
throw new TypeError("Duration.from expects a string or object");
}
const fields = [
"years",
"months",
"weeks",
"days",
"hours",
"minutes",
"seconds",
"milliseconds",
"microseconds",
"nanoseconds",
];
let mask = 0;
const values = [0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n, 0, 0];
fields.forEach((field, index) => {
if (value[field] !== undefined) {
mask |= 1 << index;
if (field === "microseconds" || field === "nanoseconds") {
values[index] = toNumber(value[field], field);
} else {
values[index] = toIntegerBigInt(value[field], field);
}
}
});
const handle = exports.temporalz_duration_from_parts(
mask,
values[0],
values[1],
values[2],
values[3],
values[4],
values[5],
values[6],
values[7],
values[8],
values[9]
);
return Duration._fromHandle(requireHandle(handle));
}
static compare(a, b, options) {
const left = Duration.from(a);
const right = Duration.from(b);
return Duration.compareWithOptions(left, right, options);
}
static compareWithOptions(left, right, options) {
if (options !== undefined && (options === null || typeof options !== "object")) {
throw new TypeError("options must be an object");
}
const relativeTo = toRelativeTo(options);
if (!relativeTo && (hasYearMonthWeek(left) || hasYearMonthWeek(right))) {
throw new RangeError("relativeTo is required for calendar units");
}
if (relativeTo) {
return Number(
exports.temporalz_duration_compare_plain_date(
left._handle,
right._handle,
relativeTo._handle
)
);
}
return Number(exports.temporalz_duration_compare(left._handle, right._handle));
}
add(other) {
const rhs = Duration.from(other);
const handle = exports.temporalz_duration_add(this._handle, rhs._handle);
return Duration._fromHandle(requireHandle(handle));
}
subtract(other) {
const rhs = Duration.from(other);
const handle = exports.temporalz_duration_subtract(this._handle, rhs._handle);
return Duration._fromHandle(requireHandle(handle));
}
abs() {
const handle = exports.temporalz_duration_abs(this._handle);
return Duration._fromHandle(requireHandle(handle));
}
negated() {
const handle = exports.temporalz_duration_negated(this._handle);
return Duration._fromHandle(requireHandle(handle));
}
round(options = {}) {
if (options === undefined) options = {};
if (options === null || typeof options !== "object") {
throw new TypeError("round options must be an object");
}
const relativeTo = toRelativeTo(options);
if (!relativeTo && hasCalendarUnits(this)) {
throw new RangeError("relativeTo is required for calendar units");
}
const smallestUnit = toUnitCode(options.smallestUnit, "smallestUnit");
const largestUnit = toUnitCode(options.largestUnit, "largestUnit");
const roundingMode = toRoundingModeCode(options.roundingMode);
let roundingIncrement = 0;
if (options.roundingIncrement !== undefined) {
const inc = Number(options.roundingIncrement);
if (!Number.isFinite(inc) || !Number.isInteger(inc) || inc <= 0) {
throw new RangeError("Invalid roundingIncrement");
}
roundingIncrement = inc;
}
const handle = relativeTo
? exports.temporalz_duration_round_plain_date(
this._handle,
smallestUnit,
largestUnit,
roundingMode,
roundingIncrement,
relativeTo._handle
)
: exports.temporalz_duration_round(
this._handle,
smallestUnit,
largestUnit,
roundingMode,
roundingIncrement
);
return Duration._fromHandle(requireHandle(handle));
}
total(options) {
if (!options || typeof options !== "object") {
throw new TypeError("total options must be an object");
}
const relativeTo = toRelativeTo(options);
if (!relativeTo && hasCalendarUnits(this)) {
throw new RangeError("relativeTo is required for calendar units");
}
const unit = toUnitCode(options.unit, "unit");
if (unit === 255) throw new RangeError("Invalid unit");
const result = relativeTo
? exports.temporalz_duration_total_plain_date(
this._handle,
unit,
relativeTo._handle
)
: exports.temporalz_duration_total(this._handle, unit);
if (!Number.isFinite(result)) throw lastError();
return result;
}
get sign() {
return Number(exports.temporalz_duration_sign(this._handle));
}
get blank() {
return exports.temporalz_duration_blank(this._handle) === 1;
}
toString() {
return takeString(exports.temporalz_duration_to_string(this._handle));
}
toJSON() {
return this.toString();
}
toLocaleString() {
return this.toString();
}
valueOf() {
throw new TypeError("Cannot convert Temporal.Duration to a number");
}
get years() {
return Number(exports.temporalz_duration_years(this._handle));
}
get months() {
return Number(exports.temporalz_duration_months(this._handle));
}
get weeks() {
return Number(exports.temporalz_duration_weeks(this._handle));
}
get days() {
return Number(exports.temporalz_duration_days(this._handle));
}
get hours() {
return Number(exports.temporalz_duration_hours(this._handle));
}
get minutes() {
return Number(exports.temporalz_duration_minutes(this._handle));
}
get seconds() {
return Number(exports.temporalz_duration_seconds(this._handle));
}
get milliseconds() {
return Number(exports.temporalz_duration_milliseconds(this._handle));
}
get microseconds() {
return Number(exports.temporalz_duration_microseconds(this._handle));
}
get nanoseconds() {
return Number(exports.temporalz_duration_nanoseconds(this._handle));
}
}
function hasCalendarUnits(duration) {
return (
duration.years !== 0 ||
duration.months !== 0 ||
duration.weeks !== 0 ||
duration.days !== 0
);
}
function hasYearMonthWeek(duration) {
return duration.years !== 0 || duration.months !== 0 || duration.weeks !== 0;
}
function toRelativeTo(options) {
if (!options || options.relativeTo === undefined) return null;
const rel = options.relativeTo;
if (rel instanceof PlainDate) return rel;
if (typeof rel === "string") return PlainDate.from(rel);
if (rel && typeof rel === "object") return PlainDate.from(rel);
throw new TypeError("Invalid relativeTo");
}
const Temporal = {
Instant,
Duration,
Now: {
instant: unimplemented("Temporal.Now.instant"),
plainDateISO: unimplemented("Temporal.Now.plainDateISO"),
plainDateTimeISO: unimplemented("Temporal.Now.plainDateTimeISO"),
plainTimeISO: unimplemented("Temporal.Now.plainTimeISO"),
timeZoneId: unimplemented("Temporal.Now.timeZoneId"),
zonedDateTimeISO: unimplemented("Temporal.Now.zonedDateTimeISO"),
},
PlainDate,
PlainTime: unimplemented("Temporal.PlainTime"),
PlainDateTime: unimplemented("Temporal.PlainDateTime"),
PlainYearMonth: unimplemented("Temporal.PlainYearMonth"),
PlainMonthDay: unimplemented("Temporal.PlainMonthDay"),
ZonedDateTime: unimplemented("Temporal.ZonedDateTime"),
};
globalThis.Temporal = Temporal;
})();

35
test/test262/runner.mjs Normal file
View file

@ -0,0 +1,35 @@
import runTest262 from "../temporal-test262-runner/index.mjs";
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const wasmPath =
process.env.TEMPORALZ_WASM ||
path.resolve(__dirname, "../../zig-out/bin/temporalz.wasm");
const wasmBytes = fs.readFileSync(wasmPath);
const polyfillPath = path.resolve(__dirname, "../test262/polyfill.js");
let polyfillCode = fs.readFileSync(polyfillPath, "utf-8");
const bytesArray = JSON.stringify(Array.from(wasmBytes));
// TextEncoder/TextDecoder need to be manually constructed and passed via context
// Since we can't serialize them, we inject polyfill-compatible shim versions
const injection = `globalThis.__TEMPORALZ_WASM_BYTES__ = new Uint8Array(${bytesArray});
`;
polyfillCode = injection + polyfillCode;
const tempPolyfillPath = path.resolve(__dirname, "../test262/polyfill-injected.js");
fs.writeFileSync(tempPolyfillPath, polyfillCode);
const result = runTest262({
test262Dir: "test/temporal-test262-runner/test262",
polyfillCodeFile: tempPolyfillPath,
testGlobs: process.argv.slice(2),
});
fs.unlinkSync(tempPolyfillPath);
process.exit(result ? 0 : 1);