// Check it out here: https://www.typescriptlang.org/play?ts=4.1.0-dev.20201001#code/C4TwDgpgBAcgrgWwEYQE4GcoF4oHIAMuUAPngIxGm4BMleAzHbgCxMCsTAbEwOxMAcTAJy4A3AChQkWAHsAdgC00M7FACiADwDGAGzgATCAB54yNOgA0eQgD4Jk8NACaEAIapVAAwAkAb1MoGAC+fgHmIf6IgegRYcGeElLQALLywAAWmDie+KHySqgyQZ4k5ISluGQUFWS0iY5QACKuIFlQPr4ETNVUtLH5ysUV9OVU9BT2SVAAEjJwGF65kWbxpZ5koVHhJb2jeNQ9+7QV1IwnrPXSCvIQs-NtMAOFa0uPioM7Zd2HlbQO0skAJZyODACBtDpdGpMY5jJisCocWJbeKXaAAZQgWnk+jaQJBYPQaKgQJ0OkB6CxOIhmxWMVp0WRdOKkwa1zkEAACqgIAAzQEaVS4ADUTAAtGJxP9oM0wZz3JS1KhCqgjMlwehXABzaAQDRguS4qDoYCoYFamyqXxQNAqgBcJI12ugQVZ0llEAAKoCEMZxFAA1BPTb9RBDZgTWa5FrxJacP7A8G9QajR1gby0E1XGDvb6ggo-OnM+yIEMAPxQBOBwPyjAQD25iAlowNn0QKwly12qtBkMpzBpuQZjwe8s96u1ymt32PZseruV6seycQJUqoyeacQB0ASTkADdXOT9Fmc22HX5PcU7FKpiut82e1v0aa+2GjZHzRYeyWXx5k++Eaml+PYrvoW6qPe2Zem2s43C20GNn+NjfhOCoQPoJaQehza-qaNixthdbgYhbZvuGp4wb6f5QGW441uhmE3ORRp4R4dHVpxgYdGBW75n4YElkM3ZcQGgnMSJDHEVubrQFBZ4zjIj5LqRilsSxQFRjGcaLoGW5wRyNEARRg7DpRQSeoWQ6Zo25a6Vx8lUcYHpWI2XZPqpEAGRARmhiZVlmaOJQcaJjkIWCC4eXK6FrjIqqeI5jbebuB5HoCJ4ehevj6UpNx-teslQIlbZGFFPmvsZH7AdGqGJm2vn9sa1VarVYmMR6RFTtB4XlagKGgYxjadU5RhIfhhE4Lx0EaZRNEVvRbXEUNlWYGN7H2aJAY8e10EWQJg1tsJC1FQdvpQJJi2UiRYKFWFZUNYBTVaRNG0eg9-m+EWHguO4+VigFmapHIGR-QDI4tOg+XBcdK4-agQMZM0IBGHDf5WAj6Ro1mrTIed90VX5qZg1AqOmkE-2fdZHgY1DtEw+hcMYyjbioFjNP4XjKlgu9ROU2ZpOoGOm2wyzzO-RzF2USusXxY5KWHselFZW9ZOeDe0onXWjNpOkSOldWAszZ+NU9uz-6E5pIEqSAPOWybaHEXDw1w2LrP4a1mtXRjw1M2b-UO1dSPDXrSPId+OlgU7K0kyzc0bQHGHe9HZu0fHoU7SAM2h6+82bZtHQC+Tfhm0X2UtLTkvCxnnPp8R3uS5HLP2BrIvuEzPaG9HxstabOu209VtSVdTuTQzosC-7Q+JzrPs62qffuy9jfuDNhu57XXsz8nC-scd1YF7HZMUyXJSV1P+j1wNjtN7eDSt6qHeH+bjXd+HqiP+Lz+PU769cYbDplWlsqOKG577yzSieOGWVC5q1uuhdu1YU5d2am-eMiCd4zQxpgX+nEU4AK5lyGKwDZbwJ1uAxWGMson3VnedCesPI2wJi-FBL0GH9yRtgtOAZs4eHwXpaCQD1wJToS0ch6UlZQD8Dwgqt9pArmUoGdSyDno6R-HlJhj0Sx3AWCFLi6k+EBiURbdofgSzcj5AKCIX0oAAHleS8kpMAOy9M6wljsQ4iAwAjDuMcZaaOPjPF0zzoo9RvCXGUjcfYxx3iomePctWIxjVTKZgCU44KXDPZNhuKkmJHjgB+OMakoJwSoD6PCVkjkOTUnxP4dFOsMtQE4RuGIk8JYspsWvLIuSTTKmxK8T2VJ-dX6sOrIMjRH1rHaJiHaYm+JQTgiFhvW4cwMBzMJEYKZ6NgTzPQDUgMYyv4TKpjMFZMRoZVzrFMjZpy9lSyIUI+R2S+ktNsc8yRvgDkyJbuhRs+s6rUXGVVFR79qxrRmskjwUz8ozL5oDbZhJoXE0xNicM+UAB0szARkgpLTXRnEVxTLWeCZF1JSTknQNc+4bN4XEtNFYElqK6UkixeS3GkswXRwhScqlZMYXWKJZDXlSKqSMsFucpZhKaWQxFbiSlGBqUElpagelMrBV9RrgGDlxiuVQqFbC6mUrcXlMlYqilurlXMtNWywB9yQHCLrI2F5jr3lrQKnAy5pyBUMtxGSikfyAzmqNiwxBhrAV2x7tWb1aqg1aQ9r66NyjB6XQwlM4aVzzWT2TRfKVPspVqlDX1D2YEo3DSjUYKNYcr5exZRSXN2KKXxuQiM8+qbo6BrxQnbNprMEFuKcE4tqqZoVpznvJZ2b609vrXNUdwSOjmqCDCr1erh2Cwxb4RtqsNUlKzfGrdFyrolrPjunNDdGJTPdZSE1Oyy09kDYm+2gYl2HKBUmqAK6Y2vrAqm0eHr7hyrVZmzJXadm5tNfmq1i9O0lp-ZSMtK6CKqM7a24x7bynAcJD2iDu9t0DpRUaaO76O0lLnacxF66C0Lr8Cuo6OHGKHrQwKrdX7TkXuWfcAV-ruXyrDQPB9AYn0fr40B79mT02kcg+fRjMGIAcafQhkFLbTkzVQ-uxOObk69qI1xEjPLBaLoo6fBjJ6q0ppY100TpzOPaKGSwxDgZrM8dTTg6sDneGvQEbakhv6MAvO0VlVzXzaF1g46bXt96e52f42F4xjHnOPt7QYu59TiGNOC1Kl5AqqEGZoXfdCN7I2qps7G5tAZ30EcHXF0rhXXyJeXJ51LsHVUvKjVlajsCpTfLS-WzjG7n3htQRtXrk7yUVYyUN2rHnksPPgTW9AGXZtNfeb1wLDR8Qj0or8gg+Btu4BvFMZIrgNDra3EYXAQhzsiD2w0OGMtVAncqBdy7xI4ZYRwPdsgF2FAUCu9IF7NxtF3c8qdj752FD4G+89lmWjPU5re0Dh7oPwd2jIBwH7zgoc3BgBALU2ZAT7mgHDhSxgEdCAUGKcHu3IfuGh+xqVWOcfADxwTjbJUSdk6RyjynGs-sck5DIdAgJGf48B0T4Hn3hTUFYGjmO1P-sw9NXzgXQvmfvfFxz1HVP4Yz0JyNEn5PGDS+1sDdIt2debZB0IYU+ADea73ArdKGMZbogQEeHQIvdcW-J7YW3qVjyO+IQAIUBFqd35uLtijIDb7nLMMavZZ76MX539dfa51MI3GQaceDN6zz31uwcQ+j23HWJZ6e4+F9nhPeu8-k4L2nmPxebiK8F0z0POfw954l1LzXGMkam-j8T3P9ArdR7r0X43QcK8D-b-QfXqfrv1+N3biBvfiHO9d63yvg+vdz9+wvjIS-jwr5VEHkPk-E9CH12KegtBDd791i0OPquk-W+T7X+fY-EYP7l-MDfU-n8z7zwp1vw-3vxABL2xzLxV3hy32ryAO7x1iRjMX52b3L373P0vw70lx33RxAKRm0T7yfwvxf2t09DgMLy13HxaG0SJV-3QOIPoFILIDtB22AIoM-xAGoJpSdxdzJFoKrwAIYI52wJlzYNAM4MVRlhPz4JgMEKYM4G93IJ7yoJWSJUf2gOn310YLtDYFJzf131wOUPmFUO-yzzQP4M0KRx0LBxH3f1ELwJUJpXAIZxbzP3MJIMsNJ3Jxv3gMoI4IcMVSQKVxcLMJkK0KsIlxsP0LsMMPhhpW9WkI0PcKYJ0O0Ke0UIQJiKJW9W4PX1cNCI8OYOEPTzEP8PmWyMD2DwSP-wsOSKEDtHkKKLv3sKMLiJlTUNFzcNkNSLtGYHwAUG4FYKUL8JaMVW9UzyqKIIELCLqN6LBz4EGIyOGNiNGLaJMNL2VwmIwK6JSNmPJy73SN8PELKNWI5G0Sbw2LyMSO2JmL6Ktw1wOPYKOO5hlV9U2PoOmNSLRW2wUNH2iKWKyJeJrRyN4MuOqKSO6J0K+MaIMP+NaLw19UkMqNBMmJqIhKEDRTIG+OhL+KeJ8kBOxXaI9yuI+MhO+IUHmJ8MeNKOePhJrXGORK2JJPRLJPwEEAWMOOpLxNpIJMxwgIuJCOJIKNJO23ZzSN+KGNxO9V9UCJQKgI6PyNqM+LJOFExK5yAA type Numbers = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'; type NonZero = Exclude; type Year = `${Numbers}${Numbers}${Numbers}${Numbers}`; type Months = `0${NonZero}` | '10' | '11' | '12'; type Days = `${'0' | '1' | '2'}${NonZero}` | '30' | '31'; type Hours = `0${Numbers}` | `1${Numbers}` | '20' | '21' | '22' | '23' | '24'; type ZoneHours = NonZero | `0${NonZero}` | '10' | '11' | '12' type Minutes = `${'0' | '1' | '2' | '3' | '4' | '5'}${Numbers}`; type Seconds = Minutes; type Milliseconds = `${Numbers}${Numbers}${Numbers}`; type ZonePrefix = '+' | '-'; type DateParseError = { error: Message }; type DateTime< T extends string > = T extends `${infer DateTime}Z${infer Zone}` ? ParseDateTimeZone : T extends `${infer Date}` ? ParseDateTimeNoZone : DateParseError<`DateTime: Invalid DateTime: ${T}`>; type ParseDateTimeZone< DateTimeStr extends string, ZoneStr extends string, ParsedDateTime = ParseDateTimeNoZone, ParsedZone = ParseZone > = ParsedDateTime extends DateTimeStr ? ParsedZone extends ZoneStr ? `${ParsedDateTime}Z${ParsedZone}` : ParsedZone : ParsedDateTime; type ParseDateTimeNoZone< DateTimeNoZoneStr extends string > = DateTimeNoZoneStr extends `${infer Date}T${infer Time}` ? ParseDateTime : DateTimeNoZoneStr extends `${infer Date}` ? ParseDate : DateParseError<`ParseDateTimeNoZone: Invalid Date: ${DateTimeNoZoneStr}`>; type ParseDateTime< DateStr extends string, TimeStr extends string, ParsedDate = ParseDate, ParsedTime = ParseTime > = ParsedDate extends DateStr ? ParsedTime extends TimeStr ? `${ParsedDate}T${ParsedTime}` : ParsedTime : ParsedDate; type ParseDate< DateStr extends string > = DateStr extends `${infer YearStr}-${infer MonthStr}-${infer DaysStr}` ? ParseYearMonthDay : DateStr extends `${infer YearStr}-${infer MonthStr}` ? ParseYearMonth : DateStr extends `${infer YearStr}` ? ParseYear : DateParseError<`ParseDate: Invalid Date: ${DateStr}`>; type ParseYearMonthDay< YearStr extends string, MonthStr extends string, DayStr extends string, ParsedYear = ParseYear, ParsedMonth = ParseMonth, ParsedDay = ParseDay, > = ParsedYear extends YearStr ? ParsedMonth extends MonthStr ? ParsedDay extends DayStr ? `${YearStr}-${MonthStr}-${DayStr}` : ParsedDay : ParsedMonth : ParsedYear; type ParseYearMonth< YearStr extends string, MonthStr extends string, ParsedYear = ParseYear, ParsedMonth = ParseMonth, > = ParsedYear extends YearStr ? ParsedMonth extends MonthStr ? `${YearStr}-${MonthStr}` : ParsedMonth : ParsedYear; type ParseYear< YearStr extends string, > = YearStr extends Year ? YearStr : DateParseError<`ParseYear: Invalid Year: ${YearStr}`>; type ParseMonth< MonthStr extends string, > = MonthStr extends Months ? MonthStr : DateParseError<`ParseMonth: Invalid Month: ${MonthStr}`>; type ParseDay< DayStr extends string, > = DayStr extends Days ? DayStr : DateParseError<`ParseDay: Invalid Date: ${DayStr}`>; type ParseZone< ZoneStr extends string > = ZoneStr extends ZoneHours ? ZoneStr : ZoneStr extends `${ZonePrefix}${infer Offset}` ? ParseZoneOffset extends Offset ? ZoneStr : ParseZoneOffset : ZoneStr extends `${infer Offset}` ? ParseZoneOffset extends Offset ? ZoneStr : ParseZoneOffset : DateParseError<`ParseZone: Invalid Zone: ${ZoneStr}`> type ParseZoneOffset< OffsetStr extends string, > = OffsetStr extends `${infer Hours}:${infer Minutes}` ? ParseHoursMinutes : OffsetStr extends `${infer Hours}` ? ParseHours : DateParseError<`ParseZoneOffset: Invalid Offset: ${OffsetStr}`>; type ParseTime< TimeStr extends string > = TimeStr extends `${infer HoursStr}:${infer MinutesStr}:${infer SecondsStr}.${infer MillisStr}` ? ParseHoursMinutesSecondsMillis : TimeStr extends `${infer HoursStr}:${infer MinutesStr}:${infer SecondsStr}` ? ParseHoursMinutesSeconds : TimeStr extends `${infer HoursStr}:${infer MinutesStr}` ? ParseHoursMinutes : DateParseError<`ParseTime: Invalid Time: ${TimeStr}`>;; type ParseHoursMinutesSecondsMillis< HoursStr extends string, MinutesStr extends string, SecondsStr extends string, MillisStr extends string, ParsedHours = ParseHours, ParsedMinutes = ParseMinutes, ParsedSeconds = ParseSeconds, ParsedMillis = ParseMillis > = ParsedHours extends HoursStr ? ParsedMinutes extends MinutesStr ? ParsedSeconds extends SecondsStr ? ParsedMillis extends MillisStr ? `${HoursStr}:${MinutesStr}:${SecondsStr}.${MillisStr}` : ParsedMillis : ParsedSeconds : ParsedMinutes : ParsedHours; type ParseHoursMinutesSeconds< HoursStr extends string, MinutesStr extends string, SecondsStr extends string, ParsedHours = ParseHours, ParsedMinutes = ParseMinutes, ParsedSeconds = ParseSeconds > = ParsedHours extends HoursStr ? ParsedMinutes extends MinutesStr ? ParsedSeconds extends SecondsStr ? `${HoursStr}:${MinutesStr}:${SecondsStr}` : ParsedSeconds : ParsedMinutes : ParsedHours; type ParseHoursMinutes< HoursStr extends string, MinutesStr extends string, ParsedHours = ParseHours, ParsedMinutes = ParseMinutes > = ParsedHours extends HoursStr ? ParsedMinutes extends MinutesStr ? `${HoursStr}:${MinutesStr}` : ParsedMinutes : ParsedHours; type ParseHours< HourStr extends string, > = HourStr extends Hours ? HourStr : DateParseError<`ParseHours: Invalid Hour: ${HourStr}`>; type ParseMinutes< MinutesStr extends string, > = MinutesStr extends Minutes ? MinutesStr : DateParseError<`ParseMinutes: Invalid Minutes: ${MinutesStr}`>; type ParseSeconds< SecondsStr extends string, > = SecondsStr extends Seconds ? SecondsStr : DateParseError<`ParseSeconds: Invalid Seconds: ${SecondsStr}`>; type ParseMillis< MillisStr extends string, > = MillisStr extends Milliseconds ? MillisStr : DateParseError<`ParseMillis: Invalid Milliseconds: ${MillisStr}`>; type MinYear = DateTime<'0000'>; type MaxYear = DateTime<'9999'>; type YearError = DateTime<'19999'>; type YearZone = DateTime<'1999Z1'>; type YearZoneHour = DateTime<'1999Z01'>; type YearZoneHoursMinutes = DateTime<'1999Z01:15'>; type YearZoneNegative = DateTime<'1999Z-01'>; type YearZoneHoursMinutesNegative = DateTime<'1999Z-01:15'>; type YearZonePositive = DateTime<'1999Z+24'>; type YearZoneHoursMinutesPositive = DateTime<'1999Z+01:15'>; type YearMonth = DateTime<'1999-03'>; type YearMonthError = DateTime<'1999+03'>; type YearInvalidMonthErrorSmall = DateTime<'1999-00'>; type YearInvalidMonthErrorBig = DateTime<'1999-13'>; type YearMonthZone = DateTime<'1999-03Z1'>; type YearMonthZoneHour = DateTime<'1999-03Z01'>; type YearMonthZoneNegative = DateTime<'1999-03Z-01'>; type YearMonthZonePositive = DateTime<'1999-03Z+24'>; type YearMonthDayError = DateTime<'1999-03+03'>; type YearMonthDay = DateTime<'1999-03-03'>; type YearMonthInvalidDayErrorSmall = DateTime<'1999-03-00'>; type YearMonthInvalidDayErrorBig = DateTime<'1999-03-32'>; type YearMonthDayZone = DateTime<'1999-03-03Z1'>; type YearMonthDayZoneHour = DateTime<'1999-03-03Z01'>; type YearMonthDayZoneNegative = DateTime<'1999-03-03Z-01'>; type YearMonthDayZonePositive = DateTime<'1999-03-03Z+24'>; type YearMonthDayHourError = DateTime<'1999-03-03T01'>; type YearMonthDayHourMinute = DateTime<'1999-03-03T01:00'>; type YearMonthDayHourMinuteErrorSmall = DateTime<'1999-03-03T01:1'>; type YearMonthDayHourMinuteErrorBig = DateTime<'1999-03-03T01:60'>; type YearMonthDayHourMinuteZone = DateTime<'1999-03-03T01:59Z1'>; type YearMonthDayHourMinuteZoneHour = DateTime<'1999-03-03T01:59Z03'>; type YearMonthDayHourMinuteZoneNegative = DateTime<'1999-03-03T01:59Z-02'>; type YearMonthDayHourMinuteZonePositive = DateTime<'1999-03-03T01:59Z+23'>; type YearMonthDayHourMinuteSecond = DateTime<'1999-03-03T01:59:59'>; type YearMonthDayHourMinuteSecondErrorSmall = DateTime<'1999-03-03T01:59:0'>; type YearMonthDayHourMinuteSecondErrorBig = DateTime<'1999-03-03T01:59:60'>; type YearMonthDayHourMinuteSecondZone = DateTime<'1999-03-03T01:59:40Z6'>; type YearMonthDayHourMinuteSecondZoneHour = DateTime<'1999-03-03T01:59:40Z07'>; type YearMonthDayHourMinuteSecondZoneHourNegative = DateTime<'1999-03-03T01:59:40Z-04'>; type YearMonthDayHourMinuteSecondZoneHourPositive = DateTime<'1999-03-03T01:59:40Z+05'>; type YearMonthDayHourMinuteSecondMilli = DateTime<'1999-03-03T01:59:59.000'>; type YearMonthDayHourMinuteSecondMilliErrorSmall = DateTime<'1999-03-03T01:59:59.0'>; type YearMonthDayHourMinuteSecondMilliErrorBig = DateTime<'1999-03-03T01:59:59.1000'>; type YearMonthDayHourMinuteSecondMilliZone = DateTime<'1999-03-03T01:59:59.000Z7'>; type YearMonthDayHourMinuteSecondMilliZoneHour = DateTime<'1999-03-03T01:59:59.000Z08'>; type YearMonthDayHourMinuteSecondMilliZoneNegative = DateTime<'1999-03-03T01:59:59.000Z-09'>; type YearMonthDayHourMinuteSecondMilliZonePositive = DateTime<'1999-03-03T01:59:59.000Z+10'>;