Resolvendo a disputa de formato de data

17

A ordem de formatação das datas é uma das questões mais complexas e divisivas que o mundo enfrenta atualmente. Alguns de nós argumentam veementemente que Mês / Dia / Ano é apropriado, considerando que é assim que dizemos datas em voz alta. Outros proclamam em voz alta que Dia / Mês / Ano é o melhor, porque coloca os termos em ordem crescente da duração que representam.

Já é suficiente. Os computadores podem resolver essa disputa de maneira simples e justa. Seu código, uma função ou programa completo, terá uma sequência de datas delimitada por barras, por exemplo 12/1/2015. Observe que este é o formato exato, sem zeros à esquerda e com um ano de quatro dígitos no final.

  • Se for definitivamente Mês / Dia / Ano, por exemplo 10/31/1998, produza uma representação de texto dessa data neste formato exato, com o nome completo do mês, dia e ano:October 31, 1998
  • Se é definitivamente Dia / Mês / Ano, por exemplo 25/12/1989, a saída do mesmo tipo de representação de texto: December 25, 1989.
  • Se for ambíguo, seja Mês / Dia / Ano ou Dia / Mês / Ano, produza uma data que resolva a ambiguidade combinando as duas datas possíveis da seguinte maneira:
    1. Criar um novo nome do mês, tendo a primeira metade do nome do anteriormente mês e anexar a segunda metade da tarde mês. Por meses com duração ímpar, a primeira metade recebe a letra extra. Para ser explícito, as primeiras metades dos meses são Janu, Febr, Mar, Apr, Ma, Ju, Ju, Aug, Septe, Octo, Nove, e Decee as segundas metades são, portanto ary, uary, ch, il, y, ne, ly, ust, mber, ber, mber, e mber.
    2. Calcule o dia calculando a média dos dois dias possíveis, tomando a palavra quando a média não for um número inteiro.
    3. Emita a representação de texto desta data, por exemplo 10/8/2011, para , saídaAugber 9, 2011 .

Se a data de entrada não puder ser Mês / Dia / Ano ou Dia / Mês / Ano (por exemplo, 13/13/2013 ou mesmo 2/30/2002), qualquer comportamento é aceitável. Este código de golfe, o código mais curto vence!

Casos de teste:

10/31/1998October 31, 1998

25/12/1989December 25, 1989

10/8/2011Augber 9, 2011

8/5/1957Maust 6, 1957

9/12/2012 (por incrível que pareça) September 10, 2012

1/1/2000January 1, 2000

Lucas
fonte
20
Pelo que vale, muitos dos que argumentam por dia-mês-ano também dizem datas nessa ordem. (É claro, os programadores reais argumentam por ano-mês-dia).
Peter Taylor
Apenas para ter certeza: without leading zeroes and with a four-digit year at the endimplicayear >= 1000
edc65
Está correto.
Lucas
11
+ ∞ para 10 de setembro de 2012
ev3commander

Respostas:

1

Pitão - 156 bytes

Código muito ruim e precisará usar seqüências de caracteres compactadas, mas é algo.

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

Conjunto de Teste .

Maltysen
fonte
3

Mathematica 341 304298288293 bytes

Isso usa uma função pura ou anônima, ou seja, uma função sem seu próprio nome.

DateStringretorna uma mensagem de erro se a data for ambígua. Checkcaptura a ambiguidade e envia a data incorreta para DateList, que a transforma em uma lista de 3 números inteiros (que acredita ser {year, month, day}). Os números inteiros mês e dia são classificados por tamanho e usados ​​para determinar o mês e o dia de acordo com as instruções do OP.

Quiet silencia o erro de impressão.

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 outubro de 1998", "25 de dezembro de 1989", "9 de agosto de 2011", "6 de agosto de 1957", "10 de setembro de 2012", "1 de janeiro de 2012"}

DavidC
fonte
Pessoalmente, eu adoraria vê-lo eliminar esse 0, mas deixarei os votos caírem como puderem.
Lucas
Agora ele retorna "1 de janeiro de 2012" conforme 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: Usa toLocaleStringpara gerar nomes de meses. Altere a localidade para obter resultados usando nomes de meses em diferentes localidades!

Editar 2: agora gera nomes de dois meses em vez dos 12!

Ungolfed:

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]
)

Exemplo:

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')
);

Graças a:
@ user81655 , 274 => 246 bytes
@ edc65 , 246 => 238 bytes

usandfriends
fonte
11
Eu não olhei muito bem, mas é aqui algumas melhorias que você pode fazer: mudança Math.ceil(e[c].length/2)para (r=e[c].length/2)+r%1, Array(2).fill().map((_,f)=>...)de f=>...e todos os e[n]que e(n), i=+(g>h)de i=g>he e[i]para e[+i], remova os suportes desnecessários no último operador ternário, também, newDatedeve ser new Date.
User81655
11
Evite Math.ceilusar #b=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)

Snippet de teste:

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
fonte
2

Python 3 (290 bytes)

Semelhante à resposta de Ashwin Gupta, mas aproveitando o módulo de calendário do Python para evitar escrever todos os nomes dos 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)

O Python 2 deve aparar alguns bytes com divisão inteira e perdendo os parênteses para print.

Jack Brounstein
fonte
1

Python, 558 554 bytes

Um exemplo muito, muito, muito horrível de como fazer isso em python. Desculpe, eu sou super mal com esse material de golfe D:. Funciona embora. Tenho certeza de que existem várias maneiras de simplificar isso, então me informe nos comentários. Golfe:

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)

Ungolfed

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 tela: insira a descrição da imagem aqui

Ashwin Gupta
fonte
colocar S=" "no topo, em seguida, substituir cada instância de " "com S- que vai raspar alguns bytes
gato
existem alguns espaços desnecessários após as atribuições ( e= int[..., o = o...). Além disso, ele pode provar adventageous para definir chamadas frequentemente utilizados como inta única letra maiúscula vars
gato
11
Aqui estão 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
11
@ sysreq ok minha mente está oficialmente explodida. Eu não sabia que você poderia armazenar funções em uma variável. Obrigado. Vou editar isso. Além disso, você poderia me fazer um favor e tentar executar meu código (um código de golfe) e ver se está funcionando como deveria, porque Luke parece estar obtendo resultados diferentes dos meus, então eu só quero ver.
Ashwin Gupta
11
@sysreq yeah idk. Por que é diferente para ele. De qualquer forma, obrigado novamente pelas dicas, isso realmente ajuda não apenas no golfe, mas em geral, pois ainda sou novo no Python. Além disso, acabei de perceber que posso remover minhas atribuições iniciais de o e te salvar 4 bytes, colocando o elemento da matriz diretamente no meu divisor. Farei todas essas mudanças esta tarde. Graças a você, a nova contagem 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));}

Eu pensei que poderia competir com a resposta Javascript. Ah bem.

Acho que poderia diminuí-lo e não gosto do código que usei para datas ambíguas. Eu acho que existe uma maneira melhor de fazer isso.

Ungolfed:

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
fonte