microsoft / microsoft/typespec

Support fractional seconds in the unixTimestamp datetime encoding

Open
#11,840 4 comments 1 reaction 1 assignee Claimed by @iscai-msft View on GitHub
compiler:core design:needed feature triaged:core
Dominant language
Java
Stars
5.9k
Forks
394
Avg merge
1d 23h
Merged PRs (30d)
104

Description

### Describe the problem

`DateTimeKnownEncoding.unixTimestamp` currently requires an integer wire type:

```tsp
@encode(DateTimeKnownEncoding.unixTimestamp, int64)
scalar UnixTimestamp extends utcDateTime;
```

Unix time can also be represented as seconds with a fractional component, and JWT
[`NumericDate`](https://datatracker.ietf.org/doc/html/rfc7519#section-2) explicitly permits
non-integer values. TypeSpec currently cannot preserve both the datetime semantics and a
floating-point wire contract such as OpenAPI `type: number, format: double`:

- Modeling the field as `float64` preserves the wire value but loses the `utcDateTime`
semantics and causes SDKs to expose a numeric value.
- Using `@encode("unixTimestamp", int64)` produces the desired datetime SDK type but narrows
the wire contract to whole-second integer values.

This surfaced while migrating Azure Attestation's JWT `iat`, `exp`, and `nbf` claims from
Swagger to TypeSpec. Modeling contemporary Unix timestamps as `float32` introduces severe
precision loss, while changing them to `int64` would no longer permit fractional values.

### Proposed behavior

Allow `unixTimestamp` to use a floating-point wire type:

```tsp
@encode(DateTimeKnownEncoding.unixTimestamp, float64)
scalar FractionalUnixTimestamp extends utcDateTime;
```

The unit would remain seconds since the Unix epoch:

- An integer encoded type represents whole seconds.
- A floating-point or decimal encoded type permits fractional seconds.
- Existing integer usages retain their current behavior.

Milliseconds or other units would still require separate encodings because they change the
unit, rather than only the precision.

The design should define how emitters round values to the precision supported by each
language's datetime type. `float32` should either be rejected or produce a diagnostic because
it cannot accurately represent contemporary Unix-second timestamps.

### Implementation considerations

- Compiler validation currently restricts `unixTimestamp` to an `integer` encoded type.
- Emitters need to preserve the selected numeric wire type while exposing their native
datetime/instant type.
- The C# emitter currently uses `GetInt64()`, `DateTimeOffset.FromUnixTimeSeconds()`, and
`DateTimeOffset.ToUnixTimeSeconds()` for this encoding and would need fractional-second
handling.

Related: microsoft/typespec#2887 clarified that `unixTimestamp` is measured in seconds. This
proposal retains that unit and only adds support for fractional seconds.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.