Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Static string validation of PlainDate, PlainTime and PlainDateTime #22

Open
dotnetCarpenter opened this issue Dec 27, 2021 · 3 comments

Comments

@dotnetCarpenter
Copy link

String validation of date, time or date with time is currently error prone and/or memory hungry. With this proposal, String validation will have native performance and be correct.

String is very useful for serialization and communication between services but require validation when expressing date, time or date with time.

By adding a static .test method to Temporal.PlainDate, Temporal.PlainTime and Temporal.PlainDateTime, validation would be performant, easy and correct.

API:

  • Temporal.PlainDate.test (String) Where String = YYYY-MM-DD or ±YYYY-MM-DD
  • Temporal.PlainTime.test (String) Where String = hh:mm:ss
  • Temporal.PlainDateTime.test (String) Where String = YYYY-MM-DDThh:mm:ss

YYYY refers to a year between 0001 and 9999, both included.

MM refers to a a zero-padded month between 01 and 12, both included.

DD refers to a a zero-padded month day between 01 and 31, both included, in the Gregorian calendar.

hh refers to a zero-padded hour between 00 and 23, both included.

mm refers to a zero-padded minute between 00 and 59, both included.

ss refers to a zero-padded second between 00 and 60 (where 60 is only used to denote an added leap second), both included.

Ref: https://en.wikipedia.org/wiki/ISO_8601

Advantages:

One use-case is to send a valid date as a String to a database and while the database will validate the date, we would want to check the date before opening a database connection and wait for the response. This can obviously be done both client-side and server-side before communicating with the database.

With Temporal proposal 1, it can be implemented like so:

const validateDate = x => {
    try {
        Temporal.PlainDate.from (x)
    } catch (e) {
        return false
    }
    return true
}

validateDate ('2022-02-29') // <- false, because there is only 28 days in February 2022.

An optimization would be to have Temporal.PlainDate.test so that the static .test method can bypass the instantiation process and return a Boolean. Perhaps bringing it on par with the performance of the regex solution.

const validateDate = x => /^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2]\d|3[0-1])$/.test (x)

validateDate ('2022-02-29') // <- true, because regex has no concept of dates

Concerns:

Communicating between services sometimes also means different formats. This is covered in #2 which in contrast to this suggestion, creates an object instance. Similarly to #2, it might be useful to be able to validate other serializable formats than the ones Temporal's from method accept.

For outputting different serializable formats from Temporal, there is #5.

I have not gone much into Temporal.PlainTime.test and Temporal.PlainDateTime.test. Further examination of use-cases might reveal that it's more complicated than stated here.

Prior art:

There does not seem to be any static date parsing libraries in the current JS ecosystem (as of 2021).
All four libraries below will create instance of Date.

Lib Name Static Syntax URL
Moment.js No moment("2022-02-29").isValid() https://momentjs.com/docs/#/parsing/is-valid/
luxon No DateTime.fromISO("2022-02-29").isValid https://moment.github.io/luxon/#/validity
date-fns No isValid (parseISO('2022-02-29')) https://date-fns.org/v2.27.0/docs/isValid#examples
date-fp No isValid (parse ('YYYY-MM-DD', '2022-02-29')) https://cullophid.github.io/date-fp/docs/functions/is-valid.html

Constraints / corner cases:

@ptomato
Copy link
Collaborator

ptomato commented Jan 7, 2022

Thanks! If I understand correctly, the main advantage of this API would be validating the string without constructing a Temporal.(Whatever) instance, and the reason it's not ideal to do in user code is because you either have to construct the instance, or you write your own regex and then you have no guarantee that it corresponds 100% to what from() would accept. Is that accurate?

@dotnetCarpenter
Copy link
Author

dotnetCarpenter commented Jan 8, 2022

Yes, that is correct. The main points are to put it simply, for Temporal.PlainDate,

  1. Static test function that can validate an ISO date string is valid, without relaying on try...catch and creating Temporal JS instances.
  2. Regex does not work since there is no guarantee that the ISO date string is a valid date.

AFAIK the two points are identical for Temporal.PlainTime and Temporal.PlainDateTime.

@dotnetCarpenter
Copy link
Author

On second thought, Temporal.PlainTime.test (String) can easily be coded in regex. But omitting that, would break polymorphism for Temporal objects.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants