Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Datetime validation without offset should allow omission of Z zone designator #2385

Closed
MattSidor opened this issue Apr 28, 2023 · 10 comments · Fixed by #2522
Closed

Datetime validation without offset should allow omission of Z zone designator #2385

MattSidor opened this issue Apr 28, 2023 · 10 comments · Fixed by #2522

Comments

@MattSidor
Copy link

ISO-8601 allows datetime strings to not have any timezone offset or Z zone designator. In these instances, it is assumed to be in local time. (Reference: https://en.wikipedia.org/wiki/ISO_8601#Local_time_(unqualified))

However, the datetime validator currently marks these as invalid.

const schema = z.string().datetime() // offset: false is default behavior
console.log( schema.safeParse( '2022-01-01T00:00:00' ).success ) // false
@MattSidor MattSidor changed the title Datetime validation without offset should allow all variants from ISO 8601 Datetime validation without offset should allow omission of Z zone designator Apr 28, 2023
@stale
Copy link

stale bot commented Jul 27, 2023

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale No activity in last 60 days label Jul 27, 2023
@bchrobot
Copy link
Contributor

This is still an issue. I am still working on the draft PR for it.

@stale stale bot removed the stale No activity in last 60 days label Jul 30, 2023
@0xturner
Copy link

I've opened PR that adds optional support for local (unqualified) date times here #2913

@Pyrolistical
Copy link

Pyrolistical commented Nov 25, 2023

My workaround is just to refine for now. This also makes seconds optional.

const Timestamp = z
  .string()
  .refine(
    (value) => /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2}(\.\d+)?)?$/.test(value),
    {
      message:
        "timestamp must be of the unqualified form yyyy-mm-ddThh:mm[:ss[.mmm]]",
    },
  );

Example on where unqualified timestamps can come from using upcoming TC39 Temporal

> Temporal.Now.plainDateTimeISO('UTC').toString()
'2023-11-25T03:56:32.870588264'
> Temporal.Now.plainDateTimeISO('UTC').toString({smallestUnit: 'minute'})
'2023-11-25T03:56'

@kornysietsma
Copy link

This is an issue as well for us, dealing with OpenAPI datetime fields.

We are using zod-to-openapi to build clients for services we use - it sees an OpenAPI schema like "type": "string", "format": "date-time" and turns it into z.string().datetime({ offset: true }) - which is technically correct.

But we have an API that actually returns a datetime with no trailing Z - so when we query it, the zodios API throws a validation error as it's not a valid ISO8601 (well, really rfc3339) datetime.

The root problem is that API - but having a workaround in Zod would be very useful.

@Armadillidiid
Copy link

Just encountered this same issue

@jcollum-nutrien
Copy link

jcollum-nutrien commented Apr 11, 2024

This is almost a year old. Please prioritize this Zod team. I'm here because Zod validation is failing on dates coming from our ERP system. edit: we decided to just use a preprocess to fix the date, which isn't great...

@colinhacks
Copy link
Owner

This is available in canary and will land in Zod 3.23.

@plehnen
Copy link

plehnen commented Sep 18, 2024

If you also land here and wonder why this is closed but still doesn't work and there is nothing about it in the documentation:
add flag: { local: true }

This is mentioned (only) in the release notes for v3.23.0:
You can now allow unqualified (timezone-less) datetimes using the local: true flag.

const schema = z.string().datetime({ local: true });
schema.parse("2022-01-01T12:00:00"); // OK

@MattSidor
Copy link
Author

Thanks for calling this out @plehnen. I opened a PR to update the docs: #3760

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
9 participants