İngilizceye Kısa Tarih Uzun Tarih


14

Kısa tarih biçimini olabildiğince az bayt olarak İngiliz uzun tarihine dönüştürün.

Giriş

Giriş, yyyy-mm-ddtüm değerler için sıfır dolgusu isteğe bağlı olarak formatlı bir dize biçiminde olacaktır . Bunun sözdizimsel olarak doğru olduğunu, ancak mutlaka geçerli bir tarih olmadığını varsayabilirsiniz. Negatif yıl değerlerinin desteklenmesi gerekmez.

Çıktı

Tarihi İngilizce uzun tarih biçimine dönüştürmelisiniz (örn. 14th February 2017). Burada sıfır dolguya izin verilmez.

Tarih geçersizse (örn. 2011-02-29), Bu bir şekilde tanınmalıdır. İstisna atmaya izin verilir.

Daha fazla örnek aşağıda görülebilir.

Test Durumları

"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
Sıfır doldurmaya izin veriliyor mu? aka 03rdyerine3rd
Value Ink

@ValueInk Önceki yorumumu okuduysanız, dikkate almayın; Soruyu yanlış anladım. Çıktıda sıfır dolguya izin verilmez.
GarethPW

Bir yılı 4 karakterden fazla düşünmeliyiz (örneğin 10987-01-01)?
mdahmoune

@mdahmoune Daha kolay olmadıkça bunu desteklemenize gerek yoktur.
GarethPW

Ne olmuş 2016-2-29?
Olivier Grégoire

Yanıtlar:


5

PostgreSQL, 61 karakter

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

Hazırlanan ifade, girdiyi parametre olarak alır.

Örnek çalışma:

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.

Güzel, keşke MS-SQL "th" biçimlendirme stilini tanıdı.
BradC

Görevi en az baytla düzgün bir şekilde tamamladığınızı düşünürsek, çözümünüzün kazanan olduğunu düşünüyorum!
GarethPW

Vay. Teşekkürler. Bu tamamen beklenmedik bir durum. Adanmış golf dillerinin yokluğu şimdiye kadar fark etmedi. Ancak sadece bir gün sonra bir çözümü kabul etmek biraz yakında.
manatwork

@manatwork Biraz erken olup olmayacağını merak ettim. Ama yine de gerekirse değiştirebilirim.
GarethPW

7

Python 3.6, 137129 bayt

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}"

Çevrimiçi deneyin!


3
%-d%dbunun yerine dize biçimlendirmenizde kullanabileceğiniz dolgu içermeyen sürümüdür {g[2]}. Ayrıca, 12olması gerektiğini 12thdeğil, 12nd(10-19 den sayılar 1-9 ve 20 + aynı kurallara uymaz)
Değer Mürekkep

1
+1. fdizeleri hakkında bilmiyordum
Felipe Nardi Batista

@ValueInk teşekkürler! ayrıca, ordinals sorunu düzeltildi
Uriel

5

JavaScript (ES6), 142 140 bayt

NaNth Invalid DateGeçersiz tarihler için çıktılar .

Sıra sayılarının kodu bu cevaptan uyarlanmıştır .

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


1
Chrome'da 2011-2-29 için "1 Mart 2011" verir. Bu zor bir düzeltme olabilir.
Rick Hitchcock

5

Python 3.6 , 154 bayt

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

Çevrimiçi deneyin! (Giriş akışını ayarlayın ve çalıştırın.)

Aşağıdaki yorumculardan iyi öneriler için teşekkürler.


Listenizdeki int(x)ve forlistenizdeki boşluğu kaldırarak bir bayt kaydedebilirsiniz .
Christian Dean

@ChristianDean Teşekkürler, bitti!
Luke Sawczak

(('st','nd','rd')[b%10-1]if b<4 or 20<b<24 else'th')-3 baytlık geçerli koşulunuz yerine.
Değer Mürekkebi

@ValueInk Ne yazık ki, bu 31. üretecek. Onu parçalamayı düşündüğüm başka bir yol, eğer 0 <b% 10 <4 veya 10 <b <14 değilse 'th' idi, ancak herhangi bir bayt kaydetmedi.
Luke Sawczak

Bu durumda, kötüye kullanım tipi baskı. (3<b<21)+(23<b<31)-1 bayt için. Çevrimiçi deneyin!
Değer Mürekkep

5

PHP, 87 bayt

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

Pipo ile çalıştırın -Fveya çevrimiçi test edin . Her zaman 4 haneli bir yıl yazdırır; yıllarca başarısız olur> 9999.

geçerlilik kontrolü yok, 35 bayt:

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

5

Bash + coreutils, 115 78

  • @Manatwork sayesinde 2 bayt tasarruf edildi.
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"

Çevrimiçi deneyin .


1
Dizi yerine dize kullanmanın biraz yardımcı olacağını düşünüyoruz f=thstndrd; $d"${f:t/10-1?t%10<4?t%10*2:0:0:2} %B %Y".
manatwork

1
BTW, revizyon 1'iniz bir Bash ipucuna ilham verdi . ;)
manatwork

@manatwork evet - komik - bunu denemeyi düşündüm ama yardımcı olacağını düşünmedim. Dürtmek için teşekkürler.
Dijital Travma

4

C #, 147 143 bayt

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 sayesinde 4 bayt kaydedildi.


Eğer ikinci yerini Could t.Dayile d4 bayt tasarrufu için?
The_Lone_Devil

@The_Lone_Devil Elbette teşekkür edebilirim, bunu nasıl özlediğimi bilmiyorum.
TheLethalCoder

4

mIRC sürüm 7.49 (197 bayt)

//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

Yakut , 104 103 , 102 ± 8 = 112 111 110 bayt

-rdate -pProgram bayraklarını kullanır .

Yapıttan -1 bayt.

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

Çevrimiçi deneyin!


Üçlü operatör kullanmamanın bir sebebini kaçırıyor muyum? d<4||d>20?"..stndrd"[d%10*2,2]:"th"
manatwork

@manatwork gibi bir sayı , arama dizesindeki sınırların dışında olan ve böylece geri dönen 26dizinlere erişmeye çalışacaktır . Böylece üçlü kullanımı 2 bayt daha uzun yapar . 12..13nild<4||d>20?"..stndrd"[d%10*2,2]||"th":"th"
Değer Mürekkebi

Ah, anlıyorum. Peki, o zaman serin numara @ValueInk.
manatwork

Neredeyse unuttum, küçük bir değişiklik: "th":th.
manatwork

2

C # (.NET Çekirdek) , 167 197 bayt

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

Çevrimiçi deneyin!

İçin +30 bayt

using System;

DateTime.Parse()


!-1 bayttan kurtulmak için üçlü kontrolü tersine çevirebilirsiniz . Ve &&değerini &-3 bayt olarak değiştirebilirsiniz. Ayrıca, s.Day7 kez kullandığınız için, bunun için geçici bir değer oluşturmak üzere bazı baytlar kaydeder: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;}
Kevin Cruijssen

@KevinCruijssen Teşekkürler!
kakkarot

Ayrıca nesneyi eklemeniz using System;veya tam olarak nitelendirmeniz gerekir DateTime.
TheLethalCoder

Ayrıca DateTime.MinValueolduğunu 1-1-1Bunu çek gerek kalmaz. Bu da benim önceki noktamı ilgisiz kılar.
TheLethalCoder

1
Girdiyi bir DateTimeyöntem olarak almak ve yöntemin dışında ayrıştırmak kabul edilemez. Veya işi bölmek için ekstra bir yöntem ekleyin.
TheLethalCoder

2

Excel, 212 bayt

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

Her veda her parçaya ayırırsanız, şu parçaları elde edersiniz:

  • ABS()dizenin son iki karakterinden gün sayısını alır. Bu bir kısa çizgi içerebileceğinden, ABSpozitif olarak dönüştürür.
  • IF((ABS-12)<2,"th",SWITCH())ordinal ekler. -1211, 12, ve 13 normal kural uymayan ve hepsi olsun çünkü biraz thyerine st, ndve rd. Bu durumu düzeltir.
    • Not: SWITCHİşlev yalnızca Excel 2016 ve sonraki sürümlerde kullanılabilir. ( Kaynak ) CHOOSEBu durumda olduğundan daha kısadır, çünkü eşleşme bulunmazsa bir değer döndürebilir, oysa CHOOSEsayısal girdi gerektirir ve olası her değer için karşılık gelen bir dönüşe sahip olmalıdır.
  • TEXT(MID()*30," mmmm ")ay adını ayıklar. MID()ay numarasını bir dize olarak çıkarır ve 30 ile çarpmak bir sayı döndürür. Excel bu sayıyı tarih olarak görür (1900-01-30, 1900-02-29, 1900-03-30, vb.) Ve TEXT()her iki uçta da boşluk olacak şekilde ay adı olarak biçimlendirir. 28 ve 29 da çalışır ama 30 "daha güzel" görünüyor.
  • LEFT() yıl sayısını çıkarır.

Şimdi, tüm bunlar göz önüne alındığında, test senaryolarının tümü Excel'in gerçek bir tarih olarak işleyebileceği bir tarih aralığında olsaydı daha kolay olurdu: 1900-01-01 ila 9999-12-31. En büyük avantaj, tüm tarihin bir kerede biçimlendirilmiş olmasıdır. Bu çözüm 133 bayttır :

=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")

Diğer büyük engel ordinali eklemek zorundaydı. Bu olmadan, çözüm sadece 34 bayttır :

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

1

Hızlı 3: 298 bayt

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)")}

Çevrimiçi deneyin!


8
Siteye Hoşgeldiniz! Burada amaç kodu olabildiğince kısa yapmaktır, uzun değişken isimleriniz ve çok fazla boşlukunuz olduğunu görebilirim, çok fazla bayt kaydetmek için bunları kısaltabilir ve kaldırabilirsiniz. Ayrıca genellikle cevabın üst kısmına şeklinde bir başlık ekleriz # Language, N bytes. Siz de bir tane eklerseniz iyi olur.
TheLethalCoder

1

T-SQL, 194 bayt

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

Giriş metin sütunu üzerinden gerçekleştirilir i önceden var olan Tablo içinde t , bizim ES standartlarına göre .

1 Ocak 0001 - 31 Aralık 9999 tarihleri ​​için çalışır. Yıl, en az 3 basamakla (150AD örneği başına) verilir.

Geçersiz tarihler şu çirkin hataya neden olur:

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

Farklı varsayılan dil / kültür ayarları bu davranışı değiştirebilir. Eğer biraz daha zarif hata çıktı (NULL) istiyorsanız, değiştirerek 4 bayt eklemek PARSE()için TRY_PARSE().

Biçim ve açıklama:

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'de tanıtılan veri türü çok daha geniş yelpazede verir DATETIMEJan 1, 0001 den 31 Ara 9999,.

Bazı çok erken tarihler benim ABD yer ayarları ile yanlış ayrıştırılabilir ("01-02-03" "2 Ocak 2003" olur), bu yüzden ilk değeri yıl olduğunu bilir, bu yüzden birkaç ekstra sıfır bekledi.

Bundan sonra CASE, güne sıra sıra eklemek için sadece dağınık bir ifade. Can sıkıcı bir şekilde, SQL FORMATkomutunun bunu otomatik olarak yapmasının bir yolu yoktur.


1

q / kdb + 210 bayt, rakip olmayan

Çözüm:

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

Örnekler:

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

Açıklama:

Tarih biçimlendirme olmadığı için bu korkunç bir meydan okumadır, bu yüzden sıfırdan (95 bayt) aylar oluşturmak ve sonek oluşturmak zorundayım.

Ungolfed çözümü aşağıdadır, temel olarak giriş dizesini bölün ve soneki ekledikten ve ayı değiştirdikten sonra tekrar birleştirin.

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

Notlar:

Q Tarihler sadece ~ 1709 geri dönün, bu yüzden tarihi doğrulamak için önemsiz bir yolum yok, bu yüzden bu rakipsiz bir giriş ... Yapabileceğim en iyi şey, günün 31'inden mi yoksa ay mı olduğunu kontrol etmektir. > 12 ve 0 döndür.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.