No ValiDate ISO 8601 da RX , o desafio era usar apenas expressões regulares padrão para validar formatos e valores de data padrão (o primeiro é um trabalho comum para o RX, o segundo é incomum). A resposta vencedora usou 778 bytes. Esse desafio é superar isso usando qualquer idioma de sua escolha, mas sem funções ou classes especiais de data .
Desafio
Encontre o código mais curto que
- valida todas as datas possíveis no calendário gregoriano proléptico (que também se aplica a todas as datas anteriores à sua primeira adoção em 1582),
- não corresponde a nenhuma data inválida e
- não usa funções, métodos, classes, módulos ou similares predefinidos para lidar com datas (e horários), ou seja, depende de operações numéricas e de sequência.
Resultado
A saída é verdadeira ou falsey. Não é necessário gerar ou converter a data.
Entrada
A entrada é uma sequência única em qualquer um dos três formatos de data ISO 8601 expandidos - sem hora.
Os dois primeiros são ±YYYY-MM-DD
(ano, mês, dia) e ±YYYY-DDD
(ano, dia). Ambos precisam de revestimento especial para o dia do salto. Eles são ingenuamente correspondidos separadamente por esses RXs estendidos:
(?<year>[+-]?\d{4,})-(?<month>\d\d)-(?<day>\d\d)
(?<year>[+-]?\d{4,})-(?<doy>\d{3})
O terceiro formato de entrada é ±YYYY-wWW-D
(ano, semana, dia). É o complicado por causa do padrão complexo da semana dos saltos.
(?<year>[+-]?\d{4,})-W(?<week>\d\d)-(?<dow>\d)
Condições
Um ano bissexto no calendário gregoriano proléptico contém o dia bissexto …-02-29
e, portanto, tem 366 dias, portanto, …-366
existe. Isso acontece em qualquer ano cujo número ordinal (possivelmente negativo) é divisível por 4, mas não por 100, a menos que também seja divisível por 400. O
ano zero existe neste calendário e é um ano bissexto.
Um longo ano no calendário semanal da ISO contém uma 53ª semana …-W53-…
, que pode ser denominada " semana bissexta ". Isso acontece em todos os anos em que 1º de janeiro é quinta-feira e, adicionalmente, em todos os anos bissextos em que é quarta-feira. 0001-01-01
e 2001-01-01
são segundas-feiras. Ocorre geralmente a cada 5 ou 6 anos, em um padrão aparentemente irregular.
Um ano tem pelo menos 4 dígitos. Anos com mais de 10 dígitos não precisam ser suportados, porque isso é próximo o suficiente da idade do universo (cerca de 14 bilhões de anos). O sinal de adição inicial é opcional, embora o padrão real sugira que seja necessário por anos com mais de 4 dígitos.
Datas parciais ou truncadas, ou seja, com precisão menor que o dia, não devem ser aceitas. Hífens separados -
são necessários em todos os casos. (Essas pré-condições possibilitam que o lead +
seja sempre opcional.)
Regras
Isso é código-golfe. O código mais curto em bytes vitórias. A resposta anterior vence um empate.
Casos de teste
Testes válidos
2015-08-10
2015-10-08
12015-08-10
-2015-08-10
+2015-08-10
0015-08-10
1582-10-10
2015-02-28
2016-02-29
2000-02-29
0000-02-29
-2000-02-29
-2016-02-29
+2016-02-29
200000-02-29
-200000-02-29
+200000-02-29
2016-366
2000-366
0000-366
-2000-366
-2016-366
+2016-366
2015-081
2015-W33-1
2015-W53-7
+2015-W53-7
+2015-W33-1
-2015-W33-1
2015-08-10
O último é opcionalmente válido, ou seja, os espaços à esquerda e à direita nas sequências de entrada podem ser cortados.
Formatos inválidos
-0000-08-10 # that's an arbitrary decision
15-08-10 # year is at least 4 digits long
2015-8-10 # month (and day) is exactly two digits long, i.e. leading zero is required
015-08-10 # year is at least 4 digits long
20150810 # though a valid ISO format, we require separators; could also be interpreted as a 8-digit year
2015 08 10 # separator must be hyphen-minus
2015.08.10 # separator must be hyphen-minus
2015–08–10 # separator must be hyphen-minus
2015-0810
201508-10 # could be October in the year 201508
2015 - 08 - 10 # no internal spaces allowed
2015-w33-1 # letter ‘W’ must be uppercase
2015W33-1 # it would be unambiguous to omit the separator in front of a letter, but not in the standard
2015W331 # though a valid ISO format we require separators
2015-W331
2015-W33 # a valid ISO date, but we require day-precision
2015W33 # though a valid ISO format we require separators and day-precision
2015-08 # a valid ISO format, but we require day-precision
201508 # a valid but ambiguous ISO format
2015 # a valid ISO format, but we require day-precision
Datas inválidas
2015-00-10 # month range is 1–12
2015-13-10 # month range is 1–12
2015-08-00 # day range is 1–28 through 31
2015-08-32 # max. day range is 1–31
2015-04-31 # day range for April is 1–30
2015-02-30 # day range for February is 1–28 or 29
2015-02-29 # day range for common February is 1–28
2100-02-29 # most century years are non-leap
-2100-02-29 # most century years are non-leap
2015-000 # day range is 1–365 or 366
2015-366 # day range is 1–365 in common years
2016-367 # day range is 1–366 in leap years
2100-366 # most century years are non-leap
-2100-366 # most century years are non-leap
2015-W00-1 # week range is 1–52 or 53
2015-W54-1 # week range is 1–53 in long years
2016-W53-1 # week range is 1–52 in short years
2015-W33-0 # day range is 1–7
2015-W33-8 # day range is 1–7
-0000-08-10
que é exatamente a decisão arbitrária? Não permitindo o ano como 0 negativo?
+0000-08-10
e 0000-08-10
deve ser usado em seu lugar. Observe, no entanto, que a resposta aceita na variante de expressão regular desse desafio falha neste caso de teste específico, portanto, não é realmente uma condição com falha (isto é , deve , não deve ).