영어 긴 날짜로 짧은 날짜


14

짧은 날짜 형식을 가능한 한 적은 바이트로 영어 긴 날짜로 변환하십시오.

입력

입력은 yyyy-mm-dd모든 값에 대해 선택 사항 인 0으로 채워진 형식의 문자열 형식 입니다. 이것이 구문 상으로는 정확하지만 반드시 유효한 날짜는 아니라고 가정 할 수 있습니다. 음수 값은 지원하지 않아도됩니다.

산출

날짜를 영어 긴 날짜 형식으로 변환해야합니다 (예 :) 14th February 2017. 여기에 제로 패딩은 허용되지 않습니다.

날짜가 유효하지 않은 경우 (예 :) 2011-02-29어떤 방식 으로든 인식해야합니다. 예외를 던질 수 있습니다.

더 많은 예는 아래에서 볼 수 있습니다.

테스트 사례

"1980-05-12" -> 12th May 1980
"2005-12-3"  -> 3rd December 2005
"150-4-21"   -> 21st April 150
"2011-2-29"  -> (error/invalid)
"1999-10-35" -> (error/invalid)

5
제로 패딩이 허용됩니까? 03rd대신 일명3rd
Value Ink

@ValueInk 이전 주석을 읽으면 무시하십시오. 나는 그 질문을 오해했다. 출력에서 제로 패딩은 허용되지 않습니다.
GarethPW

연도를 4 자 이상 (예 : 10987-01-01)으로 고려해야합니까?
mdahmoune 2016 년

@mdahmoune 더 쉬운 방법이 아니라면 이것을 지원할 필요가 없습니다.
GarethPW

무엇에 대해 2016-2-29?
Olivier Grégoire

답변:


5

PostgreSQL, 61 자

prepare f(date)as select to_char($1,'fmDDth fmMonth fmYYYY');

준비된 명령문은 매개 변수로 입력을받습니다.

샘플 실행 :

Tuples only is on.
Output format is unaligned.
psql (9.6.3, server 9.4.8)
Type "help" for help.

psql=# prepare f(date)as select to_char($1,'fmDDth fmMonth fmYYYY');
PREPARE

psql=# execute f('1980-05-12');
12th May 1980

psql=# execute f('2005-12-3');
3rd December 2005

psql=# execute f('150-4-21');
21st April 150

psql=# execute f('2011-2-29');
ERROR:  date/time field value out of range: "2011-2-29"
LINE 1: execute f('2011-2-29');
                  ^
psql=# execute f('1999-10-35');
ERROR:  date/time field value out of range: "1999-10-35"
LINE 1: execute f('1999-10-35');
                  ^
HINT:  Perhaps you need a different "datestyle" setting.

MS-SQL이 "th"형식 스타일을 인식했으면 좋겠습니다.
BradC

가장 적은 바이트로 작업을 올바르게 완료했다고 생각하면 솔루션이 승자라고 생각합니다!
GarethPW

와. 감사. 완전히 예상치 못한 일입니다. 지금까지 전용 골프 언어가 없다는 것을 알지 못했습니다. 그러나 하루 만에 해결책을 받아들이는 것은 약간의 시간입니다.
manatwork 2016 년

@manatwork 나는 그것이 조금 이른 지 궁금했다. 그러나 어쨌든 필요할 경우 변경할 수 있습니다.
GarethPW 2016 년

7

Python 3.6, 137129 바이트

from datetime import*
def f(k):g=[*map(int,k.split('-'))];n=g[2];return f"{date(*g):%-d{'tsnrhtdd'[n%5*(n^15>4>n%10)::4]} %B %Y}"

온라인으로 사용해보십시오!


3
%-d의 패딩 없음 버전은 %d대신 문자열 형식으로 사용할 수 있습니다 {g[2]}. 또한, 12이되어야 12th하지, 12nd(10-19에서 숫자 9와 20 개 이상의 같은 규칙을 따르지 않는)
값 잉크

1
+1. 에 대해 알고하지 않았다 f문자열
펠리페 나르디 바티스타에게

@ValueInk 감사합니다! 또한 서수 문제를 해결했습니다
Uriel

5

자바 스크립트 (ES6) 142 140 바이트

NaNth Invalid Date유효하지 않은 날짜를 출력 합니다.

서수 코드 는이 답변에서 수정되었습니다 .

d=>`${s=(D=new Date(d)).getDate()+''}${[,'st','nd','rd'][s.match`1?.$`]||'th'} `+D.toLocaleDateString('en-GB',{month:'long',year:'numeric'})


1
Chrome에서 2011 년 2 월 29 일에 "2011 년 3 월 1 일"을 제공합니다. 그것은 힘든 수정 일 수 있습니다.
Rick Hitchcock

5

파이썬 3.6 , 154 바이트

from datetime import*
s=[*map(int,input().split('-'))]
b=s[2]
print(date(*s).strftime(f"%-d{'th'if(3<b<21)+(23<b<31)else('st','nd','rd')[b%10-1]} %B %Y"))

온라인으로 사용해보십시오! (입력 스트림을 설정 한 후 실행하십시오.)

아래의 의견 작성자의 좋은 제안 덕분에.


목록 comp 사이 int(x)와 공백을 제거하여 바이트를 저장할 수 있습니다 for.
Christian Dean

@ChristianDean 감사합니다!
Luke Sawczak 2016 년

(('st','nd','rd')[b%10-1]if b<4 or 20<b<24 else'th')-3 바이트에 대한 현재 조건 대신.
Value Ink

@ValueInk 슬프게도, 31 번째를 생산할 것입니다. 내가 그것을 깰 생각하는 또 다른 방법은 0 <b % 10 <4 또는 10 <b <14가 아니라면 'th'였지만 바이트를 저장하지 않았습니다.
Luke Sawczak

이 경우 남용 유형 강제. (3<b<21)+(23<b<31)-1 바이트 온라인으로 사용해보십시오!
Value Ink

5

PHP, 87 바이트

<?=checkdate(($a=explode("-",$argn))[1],$a[2],$a[0])?date("jS F Y",strtotime($argn)):E;

파이프로 실행 -F하거나 온라인으로 테스트하십시오 . 항상 4 자리 연도를 인쇄합니다. > 9999 년 동안 실패합니다.

유효성 검사 없음, 35 바이트 :

<?=date("jS F Y",strtotime($argn));

5

배쉬 + 코어 유틸리티, 115 78

  • @manatwork 덕분에 2 바이트가 절약되었습니다.
d="date -d$1 +%-e"
t=`$d`
f=thstndrd
$d"${f:t/10-1?t%10<4?t%10*2:0:0:2} %B %Y"

온라인으로 사용해보십시오 .


1
배열 대신 문자열을 사용하면 약간 도움이 될 것 같습니다 f=thstndrd; $d"${f:t/10-1?t%10<4?t%10*2:0:0:2} %B %Y".
manatwork

1
BTW, 개정 1Bash 팁에 영감을주었습니다 . ;)
manatwork

@manatwork yes-그 재미-나는 그것을 시도하는 것을 고려했지만 그것이 도움이 될 것이라고 생각하지 않았습니다. 너지 주셔서 감사합니다.
디지털 외상

4

C #, 147143 바이트

s=>{var t=System.DateTime.Parse(s);int d=t.Day,o=d%10;return d+((d/10)%10==1?"th":o==1?"st":o==2?"nd":o==3?"rd":"th")+t.ToString(" MMMM yyy");}

@The_Lone_Devil 덕분에 4 바이트를 절약했습니다.


4 바이트 절약 t.Dayd위해 초 를 대체 할 수 없습니까?
The_Lone_Devil 12

@The_Lone_Devil 물론 감사합니다. 어떻게 그리웠는지 모르겠습니다.
TheLethalCoder

4

mIRC 버전 7.49 (197 바이트)

//tokenize 45 2-2-2 | say $iif($3 isnum 1- $iif($2 = 2,$iif(4 // $1 && 25 \\ $1||16//$1,29,28),$iif($or($2,6) isin 615,30,31))&&$2 isnum1-12&&1//$1,$asctime($ctime($+($1,-,$2,-,$3)date), doo mmmm yyyy))

3

루비 , 104 (103) 102 + 8 = 112 111 110 바이트

용도 -rdate -p프로그램 플래그를 합니다.

manatwork에서 -1 바이트

sub(/.*-(\d*)/){Date.parse($&).strftime"%-d#{d=eval$1;(d<4||d>20)&&"..stndrd"[d%10*2,2]||:th} %B %-Y"}

온라인으로 사용해보십시오!


삼항 연산자를 사용하지 않은 이유가 누락 되었습니까? d<4||d>20?"..stndrd"[d%10*2,2]:"th"
manatwork 2016 년

@manatwork 같은 숫자 가 범위를 벗어난 조회 문자열의 26인덱스 12..13에 액세스하려고 시도하여 를 반환합니다 nil. 따라서 삼항을 사용하면 d<4||d>20?"..stndrd"[d%10*2,2]||"th":"th"2 바이트 더 길어집니다.
Value Ink

아, 알겠습니다 그런 다음 @ValueInk 트릭을 시원하게하십시오.
manatwork 2016 년

거의 잊어 버렸습니다, 작은 변화 : "th":th.
manatwork 2016 년

2

C # (.NET 코어) , 167 (197) 바이트

s=>s.Equals(DateTime.MinValue)?"":s.Day+((s.Day%10==1&s.Day!=11)?"st":(s.Day%10==2&s.Day!=12)?"nd":(s.Day%10==3&s.Day!=13)?"rd":"th")+" "+s.ToString("MMMM")+" "+s.Year

온라인으로 사용해보십시오!

+30 바이트

using System;

DateTime.Parse()


!-1 바이트를 제거하기 위해 3 진 검사를 취소 할 수 있습니다 . 그리고 -3 바이트 &&&위해를 변경할 수 있습니다 . 당신이 사용하기 때문에 또한, s.Day7 번 그것을 위해 임시 값을 만들기 위해 몇 바이트를 저장합니다s=>{var t=s.Day;return s.Equals(DateTime.MinValue)?"":t+((t%10==1&t!=11)?"st":(t%10==2&t!=12)?"nd":(t%10==3&t!=13)?"rd":"th")+" "+s.ToString("MMMM")+" "+s.Year;}
케빈 Cruijssen

@KevinCruijssen 감사합니다!
kakkarot

또한 객체 를 포함 using System;하거나 완전히 규정해야 DateTime합니다.
TheLethalCoder

또한 DateTime.MinValue입니다 1-1-1당신이 그 수표를 필요가 있다고 생각하지 않도록. 또한 이전의 요점을 무의미하게 만듭니다.
TheLethalCoder

1
DateTime메소드 외부 에서 입력을 가져와 메소드 외부에서 구문 분석 하는 것은 허용되지 않습니다. 메소드 내부의 모든 작업을 수행해야합니다. 또는 다른 방법으로 작업을 분리하십시오.
TheLethalCoder

2

Excel, 212 바이트

=ABS(RIGHT(A1,2))&IF(ABS(ABS(RIGHT(A1,2))-12)<2,"th",SWITCH(RIGHT(A1,1),"1","st","2","nd","3","rd","th"))&TEXT(MID(A1,FIND("-",A1)+1,FIND("-",REPLACE(A1,1,FIND("-",A1),""))-1)*30," mmmm ")&LEFT(A1,FIND("-",A1)-1)

모든 앰퍼샌드에서 덩어리로 나누면 다음과 같은 조각이 나타납니다.

  • ABS()문자열의 마지막 두 문자에서 요일 번호를 가져옵니다. 하이픈이 포함될 수 있으므로 하이픈 ABS을 양수로 변환합니다.
  • IF((ABS-12)<2,"th",SWITCH())서수를 추가합니다. -1211, 12, 13는 일반 규칙을 따르지 않는 그들은 모두 얻을 수 있기 때문에 비트는 th대신 st, nd하고 rd. 이 문제가 해결되었습니다.
    • 참고 :이 SWITCH기능은 Excel 2016 이상에서만 사용할 수 있습니다. ( Source ) CHOOSE일치하지 않는 경우 값을 반환 할 수 있지만 CHOOSE숫자 입력이 필요하고 가능한 각 값에 해당하는 반환 값이 있어야하므로이 경우 보다 짧습니다 .
  • TEXT(MID()*30," mmmm ")월 이름을 추출합니다. MID()월 숫자를 문자열로 가져오고 30을 곱하면 숫자가 반환됩니다. Excel에서 날짜로 그 숫자를보고 (1900년 1월 30일, 1900년 2월 29일, 1900년 3월 30일 등)TEXT()양쪽에 공간이 한 달에 이름과 형식을. 28과 29도 작동하지만 30은 "더욱 깔끔해 보인다".
  • LEFT() 연도 번호를 추출합니다.

이제 모든 경우에 테스트 사례가 Excel에서 실제 날짜로 처리 할 수있는 날짜 범위 (1900-01-01 ~ 9999-12-31)에 있으면 훨씬 쉬웠을 것입니다. 가장 큰 장점은 전체 날짜가 한 번에 형식화된다는 것입니다. 그 해결책은 133 바이트입니다 .

=TEXT(DATEVALUE(A1),"d""" & IF(ABS(ABS(RIGHT(A1,2))-12)<2,"th",SWITCH(RIGHT(A1,1),"1","st","2","nd","3","rd","th")) & """ mmmm yyyy")

다른 큰 장애물은 서수를 포함해야했습니다. 그것 없이는 해결책은 단지 34 바이트입니다 .

=TEXT(DATEVALUE(A1),"d mmmm yyyy")

1

스위프트 3 : 298 바이트

let d=DateFormatter()
d.dateFormat="yyyy-MM-dd"
if let m=d.date(from:"1999-10-3"){let n=NumberFormatter()
n.numberStyle = .ordinal
let s=n.string(from:NSNumber(value:Calendar.current.component(.day, from:m)))
d.dateFormat="MMMM YYY"
print("\(s!) \(d.string(from:m))")}else{print("(error/invalid)")}

온라인으로 사용해보십시오!


8
사이트에 오신 것을 환영합니다! 여기서 목표는 코드를 가능한 한 짧게 만드는 것입니다. 변수 이름이 길고 공백이 많음을 볼 수 있습니다. 짧게 제거하여 많은 바이트를 절약 할 수 있습니다. 또한 일반적으로 답변 맨 위에 머리글을 형식으로 포함 # Language, N bytes합니다. 당신도 하나를 추가 할 수 있다면 좋을 것입니다.
TheLethalCoder 2016 년

1

T-SQL, 194 바이트

DECLARE @ DATE;SELECT @=PARSE('00'+i AS DATE)FROM t;PRINT DATENAME(d,@)+CASE WHEN DAY(@)IN(1,21,31)THEN'st'WHEN DAY(@)IN(2,22)THEN'nd'WHEN DAY(@)IN(3,23)THEN'rd'ELSE'th'END+FORMAT(@,' MMMM yyy')

입력 텍스트 열 경유 나는 기존의 테이블에 t , 우리의 IO의 기준에 따라 .

0001 년 1 월 1 일부터 9999 년 12 월 31 일까지의 날짜에 적용됩니다. 연도는 최소 3 자리 (150AD 예당)로 출력됩니다.

날짜가 잘못되면 다음과 같은 추악한 오류가 발생합니다.

Error converting string value 'foo' into data type date using culture ''.

기본 언어 / 문화 설정이 다르면이 동작이 변경 될 수 있습니다. 약간 더 우아한 오류 출력 (NULL)을 원하면로 변경 PARSE()하여 4 바이트를 추가하십시오 TRY_PARSE().

형식과 설명 :

DECLARE @ DATE;
SELECT @=PARSE('00'+i AS DATE)FROM t;
PRINT DATENAME(d,@) + 
    CASE WHEN DAY(@) IN (1,21,31) THEN 'st'
         WHEN DAY(@) IN (2,22)    THEN 'nd'
         WHEN DAY(@) IN (3,23)    THEN 'rd'
         ELSE 'th' END
    + FORMAT(@, ' MMMM yyy')

DATESQL 2008에서 도입 된 데이터 형식보다 훨씬 넓은 범위를 허용 DATETIME년 1 월 1 일 0001 년 12 월까지 9999.

매우 이른 날짜는 미국 지역 설정 ( "01-02-03"이 "Jan 2 2003"이 됨)으로 잘못 구문 분석 될 수 있으므로 몇 개의 0을 추가하여 첫 번째 값이 연도임을 알 수 있습니다.

그 후, CASE서수에 접미사를 추가하는 것은 지저분한 말입니다 . 귀찮게도 SQL FORMAT명령은 자동으로 수행 할 수있는 방법이 없습니다.


1

q / kdb + 210 바이트, 비경쟁

해결책:

f:{a:"I"$"-"vs x;if[(12<a 1)|31<d:a 2;:0];" "sv(raze($)d,$[d in 1 21 31;`st;d in 2 22;`nd;d in 3 23;`rd;`th];$:[``January`February`March`April`May`June`July`August`September`October`November`December]a 1;($)a 0)};

예 :

q)f "2017-08-03"
"3rd August 2017"
q)f "1980-05-12"
"12th May 1980"
q)f "2005-12-3"
"3rd December 2005"
q)f "150-4-21" 
"21st April 150"
q)f "2011-2-29"       / yes it's wrong :(
"29th February 2011"
q)f "1999-10-35"
0

설명:

날짜 형식이 없기 때문에 끔찍한 도전이므로 서 픽스를 생성 할뿐만 아니라 처음부터 몇 달 (95 바이트)을 만들어야합니다.

Ungolfed 솔루션은 다음과 같습니다. 기본적으로 입력 문자열을 분할 한 다음 접미사를 추가하고 월을 전환 한 후 다시 연결하십시오.

f:{
   // split input on "-", cast to integers, save as variable a
   a:"I"$ "-" vs x;
   // if a[1] (month) > 12 or a[2] (day) > 31 return 0; note: save day in variable d for later
   if[(12<a 1) | 31<d:a 2;
     :0];
   // joins the list on " " (like " ".join(...) in python)
   " " sv (
           // the day with suffix
           raze string d,$[d in 1 21 31;`st;d in 2 22;`nd;d in 3 23;`rd;`th];
           // index into a of months, start with 0 as null, to mimic 1-indexing
           string[``January`February`March`April`May`June`July`August`September`October`November`December]a 1;
           // the year cast back to a string (removes any leading zeroes)
           string a 0)
  };

노트:

q의 날짜는 ~ 1709로 돌아가서 날짜를 확인하는 사소한 방법이 없으므로 경쟁이 아닌 항목입니다 ... 내가 할 수있는 최선의 일은 하루가> 31 또는 월인지 확인하는 것입니다. > 12이고 0을 반환합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.