Leer mi fecha de forma libre

10

Dada una fecha escrita en cualquiera (debe manejar todos en el mismo programa) de los siguientes formatos, analícela en una válida yyyy/mm/dd date.

17th May 2012
March 14th, 2016
20 February 2014
September 14, 2017
Sunday, June 8, 2015

Reglas

  • Las fechas a veces serán inválidas, es decir. día incorrecto para el mes o número de meses en un año, debe manejar ambos casos. Ya sea por error o devolviendo un valor de falsey consistente, usted elige. (Sin embargo, se apegarán a los formatos de plantilla anteriores)
  • El relleno para días y meses inferiores a 10 debe usarse para crear una salida de dos dígitos.
  • Los nombres de los meses siempre serán el nombre completo, no abreviado a sus contrapartes de tres caracteres.
  • Puede asumir que el año siempre estará dentro del rango de9999.
  • Los números negativos no necesitan ser manejados.
  • Puede crear un programa o función completa para que la salida pueda estar en cualquier formato, imprimirse en la consola o devolverse desde una función.
  • La entrada siempre será una cadena, la salida siempre debe ser una cadena, si hace que sea más corto tomarlo como un argumento único en una matriz, por ejemplo. ["17th May 2012"]puede hacerlo y la salida puede ser la misma["2012/05/17"]
  • Puede suponer que la ortografía en la entrada será correcta.

BONIFICACIÓN: porque a quién aquí no le gusta un desafío;)

Si puede permitir también los formatos de entrada The Fourteenth of March, 2016o March the Fourteenth, 2016puede quitar 20 bytes adicionales de su código con cualquier recuento final de bytes inferior a 1, lo que da como resultado 1.

Aquí están los números escritos completos para cada uno de los días para evitar cualquier confusión en la ortografía.

First, Second, Third, Fourth, Fifth, Sixth, Seventh, Eighth, Nineth, Tenth, Eleventh, Twelfth, Thirteenth, Fourteenth, Fifteenth, Sixteenth, Seventeenth, Eighteenth, Nineteenth, Twentieth, Twenty First, Twenty Second, Twenty Third, Twenty Fourth, Twenty Fifth, Twenty Sixth, Twenty Seventh, Twenty Eighth, Twenty Nineth, Thirtieth, Thirty First

Casos de prueba

INPUT                           | Output
17th May 2012                   | 2012/05/17
March 14th, 2016                | 2016/03/14
20 February 2014                | 2014/02/20
September 14, 2017              | 2017/09/14
Sunday, June 8, 2015            | 2015/06/08
1st January 1918                | 1918/01/01

The Fourteenth of March, 2016   | 2016/03/14
March the Fourteenth, 2016      | 2016/03/14
November the Seventeenth, 2019  | 2019/11/17
The Thirtieth of April, 2016    | 2016/04/30

30 February 2014                | Invalid
September 99, 2017              | Invalid
Sunday, June8, 2015             | Invalid

The Thirty First of April, 2016 | Invalid
MysticVagabond
fuente
10
" Porque a quién no le gusta un desafío " - cuando vienen en forma de bonificación, ¡a la mayoría de nosotros no! Y boo-urns para la validación de entrada.
Shaggy
3
@ Mr.Xcoder Creo que todo el reto es dar soporte a múltiples formatos de entrada .. cosas como 20 February 2014son soportados por omisión en un montón de fecha-analizadores, pero 17thy Sunday, June 8, 2015son un poco más difícil de analizar (en función del idioma).
Kevin Cruijssen
1
@ Mr.Xcoder Nunca dije que fuera un desafío de código divertido / aburrido, fácil / difícil, bueno / malo. Simplemente estoy afirmando que, según lo que leí en el desafío, la compatibilidad con múltiples formatos de entrada parece ser el objetivo principal del desafío. Estoy de acuerdo en que lo más probable es que sea un if-else para los cinco formatos de entrada, o algún tipo de expresión regular para extraer el año, el mes y el día (que actualmente es mi enfoque).
Kevin Cruijssen
3
¿El día de la semana siempre es correcto? Sería Thursday, August 25, 2017valido? Veo presentaciones ignorando el DOW.
Benjamin Cuningham

Respuestas:

4

Carriles, 41 , 37 35 bytes

->x{x.to_date.strftime('%Y/%m/%d')}

No conozco un intérprete en línea para Rails, pero aquí hay una captura de pantalla que demuestra este proceso

ingrese la descripción de la imagen aquí

Suever
fuente
Enlace de intérprete en línea?
Jonathan Allan
1
¿Esto realmente funciona para todos los formatos en cuestión? : o
totalmente humano
@totallyhuman Se agregó una captura de pantalla que muestra los resultados. Lamentablemente no conozco un intérprete en línea :(
Suever
8

PowerShell , 91 89 91 56 bytes

date("$args"-replace'th|rd|st|(\b.*)day|,')-f yyyy/MM/dd

Pruébalo en línea!

Toma la entrada como una cadena. Utiliza a -replacepara deshacerse de la basura, luego usa el Get-Datecomando incorporado con el -findicador ormat para especificar el yyyy/MM/ddformato requerido . Esa cadena se deja en la tubería y la salida es implícita.

Ahorré dos bytes gracias al Sr. Xcoder. Ahorró una gran parte gracias al juego de golf regex de TessellatingHeckler.

AdmBorkBork
fuente
1
¡Hola, mira la presentación competitiva de PowerShell!
Erik the Outgolfer
La manipulación de @EriktheOutgolfer Date es una de las fortalezas de PowerShell.
AdmBorkBork
@ Mr.Xcoder "todos esos" = 2. jajaja. ¡Gracias!
AdmBorkBork
Puede eliminar el ''del formato de fecha, para -2. Si desea apegarse a su enfoque, dado que "la ortografía es correcta", puede reemplazarlo 'th|rd|st|(\b.*)day|,'y se reduce a 56 bytes y maneja los mismos casos. Aunque creo que está mal porque si abandonas los días, no puedes recoger el Sunday, June8, 2015 | Invalidcaso porque era lunes. Debe error, pero se analiza como válido. No estoy seguro de cuál será la decisión sobre eso, o si otros lo están revisando.
TessellatingHeckler
4

PHP, 73 164 + 1 bytes

for(preg_match("#(\d+)[^\d]+(\d+)#",$d=$argn,$r);$m++<12;)strpos(_.$d,date(F,strtotime($r[2].-$m)))&&printf(checkdate($m,$r[1],$r[2])?"$r[2]/%02d/%02d":E,$m,$r[1]);

Ejecutar como tubería -nRo probarlo en línea .

La verificación de la fecha fue realmente costosa: tuve que desarmar la fecha antes de usar un incorporado, y luego intentar y error en el nombre del mes.

Titus
fuente
¿Creo que debe admitir todos los formatos, no solo uno de ellos?
Erik the Outgolfer
1
@EriktheOutgolfer lo hace. Pero no los formatos de bonificación.
Titus
@EriktheOutgolfer Esto maneja todos los formatos.
Sr. Xcoder
1
Esto falla por fechas inválidas. 30 February 2014vuelve 2014/03/02. Ya sea por error o devolviendo un valor de falsey consistente, usted elige. (Sin embargo, se apegarán a los formatos de plantilla anteriores)
Sr. Xcoder
@ Mr.Xcoder Eso arruina bastante ...
Tito
3

Python 3 + biblioteca parsedatetime, 152 139 155 153 bytes

Guardado 13 bytes gracias a Jonathan Allan

Se agregaron 16 bytes para manejar fechas con días de longitud no válidos

Se guardaron 2 bytes al eliminar la asignación lambda

lambda s:re.search(f'(^| ){str(h(s)[0].tm_mday)[:2]}[^\d]',s)and time.strftime('%Y/%m/%d',h(s)[0])
import parsedatetime as p,time,re
h=p.Calendar().parse

Pruébalo en línea!

No admite fechas de bonificación

Noskcaj
fuente
Bienvenido a PPCG! Bonito primer post. Ahorre 13 bytes usando: el valor de retorno de falsey de None; import ...as; & a lambdareutilizando parsecomo h.
Jonathan Allan
1

Java (OpenJDK 8) , 190 + 26 = 216 bytes

import java.time.format.*;

s->DateTimeFormatter.ofPattern("uuuu/MM/dd").format(DateTimeFormatter.ofPattern("[EEEE, ][d ]MMMM [d, ]uuuu").withResolverStyle(ResolverStyle.STRICT).parse(s.replaceAll("(\\d)[a-z].","$1")))

Pruébalo en línea!

Nota importante: fue más corto validar también el día de la semana en lugar de deshacerse de él, por lo que se incluye la validación.

No he intentado con SimpleDateFormatmás allá de los casos obvios que todos aceptaron fechas como el 30 de febrero. Así que tuve que deshacerme de él y usé Java 8 DateTimeFormatter.

Explicación

"[EEEE, ][d ]MMMM [d, ]uuuu"

Este formato significa:

  • día de la semana opcional seguido de coma y espacio [EEEE, ](sucede en Sunday, ...),
  • seguido de un día opcional con espacio [d ],
  • seguido por mes en letras completas MMMMy espacio,
  • seguido de un día opcional con coma y espacio [d, ],
  • seguido por el año de la era uuuupara hacerle saber al analizador que estamos en la era gregoriana.

Código:

import java.time.format.*;                                     // Required for DateTimeFormatter, *and* ResolverStyle

s->DateTimeFormatter.ofPattern("uuuu/MM/dd")                   // Output format
  .format(
    DateTimeFormatter.ofPattern("[EEEE, ][d ]MMMM [d, ]uuuu")  // Input format
      .withResolverStyle(ResolverStyle.STRICT)                 // Invalidates xxxx-02-30 instead of transforming it into xxxx-02-28
      .parse(
        s.replaceAll("(\\d)[a-z].","$1")                       // remove st, nd, rd, th
       )
    )

Créditos

  • 2 bytes en la expresión regular gracias a Neil.
Olivier Grégoire
fuente
1
¿Necesitas los corchetes en el replaceAllpatrón?
Neil
Parece que no. Gracias, @Neil!
Olivier Grégoire
1

JavaScript (ES6), 124 122 bytes

f=
s=>(d=new Date(s.replace(/.[dht]\b/,'')+' +0')).getDate()==s.match(/\d\d?/)&&d.toISOString().replace(/-(..)(T.*)?/g,'/$1')
<input oninput=o.textContent=f(this.value)><pre id=o>

Neil
fuente
Devoluciones 2015/06/07para June 8, 2015(¿problema UTC? Estoy en UTC + 2) y falsepara cualquiera Sunday, June 8, 2015o Monday, June 8, 2015.
Olivier Grégoire
1
@ OlivierGrégoire Gracias por señalarlos. Solo había intentado fechas en el Reino Unido fuera del horario de verano, por lo que ya estaban usando UTC, y no había intentado entre semana terminando nday.
Neil