Resolviendo la disputa de formato de fecha

17

El orden de formato de las fechas es uno de los problemas más complejos y divisivos que el mundo enfrenta hoy. Algunos de nosotros argumentamos con vehemencia que Mes / Día / Año es apropiado, considerando que así es como decimos las fechas en voz alta. Otros proclaman en voz alta que Día / Mes / Año es mejor, porque pone los términos en orden ascendente de la duración que representan.

Suficiente es suficiente. Las computadoras pueden resolver esta disputa de manera simple y justa. Su código, una función o programa completo, tomará una cadena de fecha delimitada por barras, por ejemplo 12/1/2015. Tenga en cuenta que este es el formato exacto, sin ceros a la izquierda y con un año de cuatro dígitos al final.

  • Si definitivamente es Mes / Día / Año, por ejemplo 10/31/1998, envíe una representación de texto de esa fecha en este formato exacto, con el nombre completo del mes, día y año:October 31, 1998
  • Si es sin duda el día / mes / año, por ejemplo 25/12/1989, la salida de la misma clase de representación de texto: December 25, 1989.
  • Si es ambiguo ya sea Mes / Día / Año o Día / Mes / Año, genere una fecha que resuelva la ambigüedad combinando las dos fechas posibles de la siguiente manera:
    1. Cree un nuevo nombre de mes tomando la primera mitad del nombre del mes anterior y agregue la segunda mitad del mes posterior . Para meses con longitud impar, la primera mitad recibe la carta extra. Para ser explícitos, las primeras mitades de los meses son Janu, Febr, Mar, Apr, Ma, Ju, Ju, Aug, Septe, Octo, Nove, y Decey las segundas mitades son, por lo tanto ary, uary, ch, il, y, ne, ly, ust, mber, ber, mber, y mber.
    2. Calcule el día promediando los dos días posibles, tomando el piso cuando el promedio no es un número entero.
    3. Salida de la representación de texto de esta fecha, por ejemplo 10/8/2011, para salida Augber 9, 2011.

Si la fecha de entrada no puede ser Mes / Día / Año o Día / Mes / Año (por ejemplo, 13/13/2013o incluso 2/30/2002), cualquier comportamiento es aceptable. Este código de golf, el código más corto gana!

Casos de prueba:

10/31/1998 da October 31, 1998

25/12/1989 da December 25, 1989

10/8/2011 da Augber 9, 2011

8/5/1957 da Maust 6, 1957

9/12/2012 (curiosamente) da September 10, 2012

1/1/2000 da January 1, 2000

Luke
fuente
20
Por lo que vale, muchos de los que abogan por día-mes-año también dicen fechas en ese orden. (Por supuesto, los programadores reales abogan por año-mes-día).
Peter Taylor
Solo para estar seguro: without leading zeroes and with a four-digit year at the endimplicayear >= 1000
edc65
Eso es correcto.
Lucas
1
+ ∞ para el 10 de septiembre de 2012
ev3commander

Respuestas:

1

Pyth - 156 bytes

Código realmente malo, y necesitará usar cadenas empaquetadas, pero es algo.

Kc"January February March April May June July August September October November December"dJhM.g>k12=GsMcz\/?<eJ32++@KthJdtP`,eJeGss[@VCcL2KStMPGdPt`,s.OPGeG

Test Suite .

Maltysen
fuente
3

Mathematica 341 304 298 288 293 bytes

Utiliza una función pura o anónima, es decir, una función sin nombre propio.

DateStringdevuelve un mensaje de error si la fecha es ambigua. Checkcapta la ambigüedad y envía la fecha del delito a DateList, que lo transforma en una lista de 3 enteros (que cree que es {year, month, day}). Los enteros de mes y día se ordenan por tamaño y se utilizan para determinar el mes y el día según las instrucciones del OP.

Quiet silencia la impresión de error.

t=StringSplit;v=ToString;x=t[#,"-"]&/@t["Janu-ary Febr-uary Mar-ch Apr-il Ma-y Ju-ne Ju-ly Aug-ust Septe-mber Octo-ber Nove-mber Dece-mber"];
Quiet@Check[#~DateString~{"MonthName"," ","DayShort",", ","Year"},
{m,n,o}=DateList@#;{p,q}=Sort@d[[2;;3]];x[[p,1]]<>x[[q,2]]<>" "<>v@Floor@Mean@{n,o}<>", "<>v@d[[1]]]&

t=StringSplit;v=ToString;x=t[#,"-"]&/@t["Janu-ary Febr-uary Mar-ch Apr-il Ma-y Ju-ne Ju-ly Aug-ust Septe-mber Octo-ber Nove-mber Dece-mber"];
Quiet@Check[#~DateString~{"MonthName"," ","DayShort",", ","Year"},
{m,n,o}=DateList@#;{p,q}=Sort@d[[2;;3]];x[[p,1]]<>x[[q,2]]<>" "<>v@Floor@Mean@{n,o}<>", "<>v@d[[1]]]& /@ 
{"10/31/1998","25/12/1989", "10/8/2011", "8/5/1957", "9/12/2012", "1/1/2012"}

{"31 de octubre de 1998", "25 de diciembre de 1989", "9 de agosto de 2011", "6 de agosto de 1957", "10 de septiembre de 2012", "1 de enero de 2012"}

DavidC
fuente
Personalmente, me encantaría verte eliminar ese 0, pero dejaré que caigan los votos como puedan.
Lucas
Ahora devuelve "1 de enero de 2012" según lo solicitado.
DavidC
3

Javascript (ES6), 311 295 282 274 246 238 bytes

a=>(a=a.split`/`,b=c=>e(c).length+1>>1,d=' ',e=f=>new Date(99,a[+f]-1).toLocaleString('en',{month:'long'}),g=+a[0],h=+a[1],i=g>h,j=g>12,k=h>12,(j&&!k?e(1)+d+g:k&&!j?e(0)+d+h:e(i).slice(0,b(i))+e(1-i).slice(b(1-i))+d+((g+h)>>1))+', '+a[2])

Editar: se utiliza toLocaleStringpara generar nombres de mes. ¡Cambie la configuración regional para obtener resultados utilizando nombres de mes en diferentes configuraciones regionales!

Edición 2: ¡ Ahora genera nombres de dos meses en lugar de los 12!

Sin golf:

func = inp => (
    inp = inp.split `/`,
    get = arg => months(arg).length + 1 >> 1,
    space = ' ',
    months = key => new Date(99, inp[+key] - 1).toLocaleString('en', { month: 'long' }),
    tmp1 = +inp[0],
    tmp2 = +inp[1],
    first = tmp1 > tmp2,
    t1greater = tmp1 > 12,
    t2greater = tmp2 > 12,
    (t1greater && !t2greater ?
        months(1) + space + tmp1
    :
        t2greater && !t1greater ?
            months(0) + space + tmp2
        :
            months(first).slice(0, get(first)) + months(1 - first).slice(get(1 - first)) + space + ((tmp1 + tmp2) >> 1)
    )
    + ', ' + inp[2]
)

Ejemplo:

console.log(
    func('10/31/1998') + '\n' +
    func('25/12/1989') + '\n' +
    func('10/8/2011') + '\n' +
    func('8/5/1957') + '\n' +
    func('9/12/2012') + '\n' +
    func('1/1/2000')
);

Gracias a:
@ user81655 , 274 => 246 bytes
@ edc65 , 246 => 238 bytes

usandfriends
fuente
1
No he mirado muy a fondo, pero aquí hay algunas mejoras que usted podría hacer el cambio: Math.ceil(e[c].length/2)a (r=e[c].length/2)+r%1, Array(2).fill().map((_,f)=>...)a f=>..., y todos los e[n]que e(n), i=+(g>h)a i=g>hy e[i]a e[+i], quitar los soportes innecesarios en el último operador ternario, también, newDatedebe ser new Date.
user81655
1
Evite Math.ceilusarb=c=>e(c).length+1>>1
edc65
2

JavaScript ES6, 204

x=>(s=x=>x.split`/`,[a,b,y]=s(x).sort((a,b)=>a-b),(c=b)>12?c=a:b=a- -b>>1,s('/Janu/Febr/Mar/Apr/Ma/Ju/Ju/Aug/Septe/Octo/Nove/Dece')[a]+s('/ary/uary/ch/il/y/ne/ly/ust/mber/ber/mber/mber')[c]+` ${b}, `+y)

Fragmento de prueba:

F=x=>(
  s=x=>x.split`/`,
  [a,b,y]=s(x).sort((a,b)=>a-b),
  (c=b)>12?c=a:b=a- -b>>1,
  s('/Janu/Febr/Mar/Apr/Ma/Ju/Ju/Aug/Septe/Octo/Nove/Dece')[a]
  +s('/ary/uary/ch/il/y/ne/ly/ust/mber/ber/mber/mber')[c]+` ${b}, `+y
)

console.log=x=>O.innerHTML+=x+'\n'

;['10/31/1998','25/12/1989','10/8/2011','8/5/1957','9/12/2012','1/1/2000']
.forEach(x=>console.log(x+' -> '+F(x)))
<pre id=O></pre>

edc65
fuente
2

Python 3 (290 bytes)

Similar a la respuesta de Ashwin Gupta, pero aprovechando el módulo de calendario de Python para evitar escribir todos los nombres de los meses.

import calendar as C
M,I,P,S,L,A=C.month_name,int,print," ",len,", "
def d(i):
 w=i.split("/")
 f,s,y=I(w[0]),I(w[1]),w[2]
 if(f>12):P(M[s]+S+w[0]+A+y)
 elif(s>12):P(M[f]+S+w[1]+A+y)
 else:l,h=min(f,s),max(f,s);P(M[l][:I(L(M[l])/2+.5)]+M[h][I(L(M[h])/2+.5):]+S+str(I((f+s)/2))+A+y)

Python 2 debería recortar algunos bytes con división entera y perder los paréntesis print.

Jack Brounstein
fuente
1

Python, 558 554 bytes

Un ejemplo realmente, realmente horrible de cómo hacer esto en Python. Lo siento, soy súper malo en estas cosas de golf D:. Funciona sin embargo. Estoy seguro de que hay muchas maneras de simplificar esto, así que hágamelo saber en los comentarios. Golfizado:

import math
def d(i):
 l=["","January","February","March","April","May","June","July","August","September","October","November","December"]
 w=i.split('/')
 f=int(w[0])
 s=int(w[1])
 S=" "
 y=w[2]
 if(f>12):
  e=int(w[1])
  print(l[e]+S+w[0]+", "+y)
  elif(f<=12 and s>12):
   e=int(w[0])
   print(l[e]+S+w[0]+", "+y)
   else:
    if(f<s):
     o=l[f]
     t=l[s]
    else:
     o=l[s]
     t=l[f]
    o=o[0:int(math.ceil(len(o)/2))]
    t=t[int(math.ceil(len(t)/2)):len(t)]
    print(o+t+S +  str(math.floor((f + s)/2)) + ", " + y)

Sin golf

import math
def d(i):
    l = ["", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
    w = i.split('/')
    f = int(w[0])
    s = int(w[1])
    y = w[2]
    if(f > 12):
        e = int(w[1])
        print(l[e] + " " + w[0] + ", " + y)

    elif(f <= 12 and s > 12):
         e = int(w[0])
         print(l[e] + " " + w[0] + ", " + y)
    else:
         if(f < s):
            o=l[f]
            t=l[s]
         else:
            o=l[s]
            t=l[f]
         o = o[0:int(math.ceil(len(o)/2))]
         t = t[int(math.ceil(len(t)/2)):len(t)]
         print(o+t+" " +  str(math.floor((f + s)/2)) + ", " + y)

Captura de pantalla: ingrese la descripción de la imagen aquí

Ashwin Gupta
fuente
coloque S=" "en la parte superior, luego reemplace cada instancia de " "con S- eso eliminará algunos bytes
cat
Hay algunos espacios innecesarios después de las asignaciones ( e= int[..., o = o...). Además, puede resultar ventajoso establecer llamadas de uso frecuente como intletras mayúsculas de una sola letra
cat
1
Aquí hay 447 bytes:from math import* I=int S=" " C="," L=len P=print def d(i): l=["","January","February","March","April","May","June","July","August","September","October","November","December"];w=i.split('/');f=I(w[0]);s=I(w[1]);y=w[2] if f>12:e=I(w[1]);P(l[e]+S+w[0]+C+S+y) elif f<13and s>12:e=I(w[0]);P(l[e]+S+w[0]+C+S+y) else: if f<s:o=l[f];t=l[s] else:o=l[s];t=l[f];o=o[0:I(ceil(L(o)/2))];t=t[I(ceil(L(t)/2)):L(t)] P(o+t+S+str(floor((f+s)/2))+C+S+y)
cat
1
@sysreq ok, mi mente está explotada oficialmente. No sabía que podía almacenar funciones en una variable. Gracias. Lo editaré. Además, ¿podrías hacerme un favor e intentar ejecutar mi código (uno de golf) y ver si funciona como debería porque Luke parece estar obteniendo resultados diferentes que yo, así que solo quiero verlo.
Ashwin Gupta
1
@sysreq, sí, idk. Por qué es diferente para él. De todos modos, gracias de nuevo por los consejos, realmente ayuda no solo para jugar al golf, sino en general, ya que todavía soy nuevo en Python. Además, me acabo de dar cuenta de que puedo eliminar mis asignaciones iniciales de o y t y guardar 4 bytes poniendo el elemento de matriz directamente en mi divisor. Haré todos estos cambios esta tarde. ¡Gracias a ti, el nuevo recuento de bytes será significativamente menor!
Ashwin Gupta
0

PHP, 301 294 bytes

function r($t){$e='return date("F",mktime(0,0,0,$o));';list($a,$b,$c)=explode('/',$t);$o=min($a,$b);$m=eval($e);$o=max($a,$b);$n=eval($e);echo(($a|$b)<13)?substr($m,0,ceil(strlen($m)/2)).substr($n,ceil(strlen($n)/2))." ".floor(($a+$b)/2).", $c":date("F j, Y",strtotime(($a>12)?"$b/$a/$c":$t));}

Pensé que podía competir con la respuesta de Javascript. Oh bien.

Creo que podría hacerlo más pequeño y no me gusta el código que usé para las fechas ambiguas. Creo que hay una mejor manera de hacerlo.

Sin golf:

function r($t){
    // Eval'd code to reduce char count
    $e='return date("F",mktime(0,0,0,$o));';

    // Split the date
    list($a,$b,$c)=explode('/',$t);

    // Get the earliest month
    $o=min($a,$b);
    $m=eval($e);

    // Get the latest month
    $o=max($a,$b);
    $n=eval($e);

    // If ambiguous
    if ($a<13 && $b<13) {
        print substr($m,0,ceil(strlen($m)/2)).substr($n,ceil(strlen($n)/2))." ".floor(($a+$b)/2).", $c";
    }
    else {
        print date("F j, Y",strtotime(($a>12)?"$b/$a/$c":$t));
    }
}
Kodos Johnson
fuente