英語の長い日付への短い日付


14

可能な限り少ないバイト数で短い日付形式を英語の長い日付に変換します。

入力

入力はyyyy-mm-dd、すべての値に対してオプションのゼロパディングを使用した、形式の文字列の形式になります。これは構文的に正しいと仮定できますが、必ずしも有効な日付ではありません。負の年の値をサポートする必要はありません。

出力

日付を英語の長い日付形式(例:)に変換する必要があります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
値インク

@ValueInk以前のコメントを読んだ場合は無視してください。私は質問を誤解しました。出力のゼロパディングは許可されません。
-GarethPW

1年を4文字以上で検討する必要があります(例:10987-01-01)。
mdahmoune

@mdahmouneこれをサポートする必要はありません。
GarethPW

どう2016-2-29
オリビエグレゴワール

回答:


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

ワオ。ありがとう。それは完全に予想外です。今まで、専用のゴルフ言語が存在しないことに気づきませんでした。しかし、たった1日で解決策を受け入れるのはもうすぐです。
マナトワーク

@manatwork少し早いのではないかと思いました。ただし、必要に応じて変更できます。
GarethPW

7

パイソン3.6、137の 129バイト

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からの数字は1-9と20+と同じ規則に従っていない)
バリューインク

1
+1。f弦について知らなかった
フェリペナルディバティスタ

@ValueInkありがとう!また、固定序の問題
ウリエル

5

JavaScript(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日」を提供します。それは難しい修正かもしれません。
リックヒッチコック

5

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

オンラインでお試しください!(入力ストリームを設定して実行します。)

以下のコメント投稿者からの良い提案に感謝します。


リストカンプint(x)forリストコンプの間のスペースを削除することで、バイトを節約できます。
クリスチャンディーン

@ChristianDeanありがとうございます!
ルークソーチャック

(('st','nd','rd')[b%10-1]if b<4 or 20<b<24 else'th')-3バイトの現在の条件の代わりに。
バリューインク

@ValueInk悲しいことに、それは31番目を生成します。私がそれを分解する別の方法は、0 <b%10 <4または10 <b <14でない場合は「th」でしたが、バイトを保存しませんでした。
ルークSawczak

その場合、タイプ強制を悪用します。(3<b<21)+(23<b<31)-1バイト。オンラインでお試しください!
バリューインク

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

Bash + coreutils、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"
マナトワーク

1
ところで、あなたのリビジョン1Bashのヒントに影響を与えました。;)
マナトワーク

@manatworkはい-その面白い-私はそれを試してみると思ったが、それが役立つとは思わなかった。ナッジをありがとう。
デジタル外傷

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バイトを節約するために2番目t.Dayを置き換えることはできませんdか?
The_Lone_Devil

@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プログラムフラグを使用します。

マナトワークから-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のような数は、範囲外のルックアップ文字列の26インデックス12..13にアクセスしようとするため、を返しますnil。したがって、3進数を使用するとd<4||d>20?"..stndrd"[d%10*2,2]||"th":"th"、2バイトだけ長くなります。
バリューインク

ああ、分かった。それでは、@ ValueInkのクールなトリックです。
マナトワーク

ほとんど忘れてしまった、小さな変更:"th":th
マナトワーク

2

C#(.NET Core)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()


3進チェックを逆にすると!、-1バイトを取り除くことができます。また、-3バイトの&&to &を変更できます。また、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
入力をaとして取得し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()文字列の最後の2文字から日番号を取得します。ハイフンが含まれている可能性があるため、ABSそれを正に変換します。
  • IF((ABS-12)<2,"th",SWITCH())序数を追加します。-1211、12、および13は、通常のルールに従わないと、彼らはすべてを得るためのビットがあるth代わりにstndrd。これはそれを修正します。
    • 注:この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")

もう1つの大きなハードルは、序数を含める必要がありました。それがなければ、ソリューションはわずか34バイトです:

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

1

Swift 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

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のテキスト列iを介して行われます、。私たちの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で導入されたデータ型は、よりはるかに広い範囲を可能にDATETIME1月1日、0001から12月31日、9999、。

一部の非常に早い日付は、米国の地域設定で間違って解析される可能性があるため(「01-02-03」は「Jan 2 2003」になります)、最初の値が年であることを認識できるように、余分なゼロをいくつか追加しました。

その後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バイト)から月を作成する必要があります。

以下にゴルフのないソリューションを示します。基本的に入力文字列を分割し、サフィックスを追加して月を切り替えた後、結合し直します。

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にのみ戻るため、日付を検証する簡単な方法はありません。したがって、これは競合しないエントリです。 > 12および0を返します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.