| Bytes | Lang | Time | Link |
|---|---|---|---|
| 141 | C | 250819T172320Z | Toby Spe |
| 061 | Uiua | 250412T131554Z | Joao-3 |
| nan | PHP | 190313T161552Z | 640KB |
| 081 | Vyxal ṡ | 210817T220056Z | emanresu |
| 069 | 05AB1E | 190314T105015Z | Kevin Cr |
| 098 | C# Visual C# Interactive Compiler | 190313T195845Z | Gymhgy |
| 077 | Jelly | 190314T164310Z | Jonathan |
| 155 | C gcc | 190315T092922Z | GPS |
| 126 | Smalltalk | 190314T020528Z | Leandro |
| 086 | Google Sheets | 190314T201056Z | Zylviij |
| 097 | Jelly | 190313T213722Z | Nick Ken |
| 042 | MySQL | 190314T152746Z | NicolasB |
| 090 | Shell + coreutils | 190313T234547Z | Neil |
| 080 | bash | 190314T092822Z | Nahuel F |
| 470 | APLNARS | 190314T073855Z | user5898 |
| 124 | Red | 190314T083547Z | Galen Iv |
| 113 | JavaScript ES6 | 190313T160150Z | Arnauld |
| 161 | Perl 6 | 190313T220139Z | Jo King |
| 112 | Python 3.8 prerelease | 190313T205120Z | Erik the |
| 134 | R | 190313T170154Z | Chthonyx |
| 122 | C# Visual C# Interactive Compiler | 190313T155802Z | Expired |
| 039 | Hack | 190313T160855Z | Ven |
C, 141 bytes
This answer is for ASCII systems; the constants 48, 49 and 52 need to be adjusted for other targets. The two arguments are the day number and a destination buffer at least 15 chars in size.
#include<time.h>
f(time_t n,char*s){--n;n*=86400;strftime(s,15,"%_dxx %B",gmtime(&n));memcpy(s+2,"thstndrd"+2*(s[1]-48)*(*s-49&&s[1]<52),2);}
How it works
#include <string.h>
#include <time.h>
char const *t[4]= {"th", "st", "nd", "rd"};
f(time_t n, char *s){
n = 86400*(n-1);
strftime(s, 15, "%_dxx %B", gmtime(&n));
/* Now overwrite the xx above */
int suffix = s[0] == '1' || s[1] > '3' ? 0 : s[1]-'0';
memcpy(s+2, t[suffix], 2);
}
Uiua, 61 bytes
$"__ _":⨬"th""st"×≠11,=1◿10.⊣:⊡⊙Months-1⊸⧻▽⊸>₀⬚∘\˜-⊙MonthDays
Uiua conveniently has constants for the names and lengths of months, but the formatting is still a hassle.
I had to sacrifice readability to make it shorter (I appreciate suggestions!), and even had to use the deprecated , over primitive.
PHP, 38 40 30 28 bytes
<?=date("jS F",86399*$argn);
Run with php -nF input is from STDIN. Example (above script named y.php):
$ echo 1|php -nF y.php
1st January
$ echo 2| php -nF y.php
2nd January
$ echo 3| php -nF y.php
3rd January
$ echo 11|php -nF y.php
11th January
$ echo 21|php -nF y.php
21st January
$ echo 60|php -nF y.php
1st March
$ echo 365|php -nF y.php
31st December
Explanation
Construct an epoch timestamp for the desired day in 1970 (conveniently not a leap year) by multiplying the day number * number of seconds per day (86400). However, this would yield one day higher so instead multiply by number of seconds in a day - 1 (86399) which for the range of input numbers (1≤n≤365) will result with the timestamp of the end of each correct day. Then just use PHP's built-in date formatting for output.
Vyxal ṡ, 81 bytes
kṁ¦Ṫ0p-'0>;:L`ƛǓ ⟇∩ ∨₄ ∨⋏ λ√ ∨ɾ ∨∑ ⟇τ ∨₆ ∨Þ ∨∞ ⟑√`⌈$i$t:t:4<[` ∨ǐ`3/vḢȮ‹i|‛th]$_+
Try it Online! What a mess.
kṁ # List of month lengths
¦ # Cumulative sums
Ṫ0p # Pop off the last and prepend a 0
- # Subtract from input
'0>; # Filter by positive
:L # Duplicate and get length
`...`⌈$i # Index into list of month names
$t:t # Get the last digit
:4<[ # If it's less than 4 then...
`...` # Push ' standard'
3/ # Split into 3
vḢ # Lop off the first char of each
Ȯ‹i # Index the number into this
| ] # Else
‛th # Push 'th'
$_+ # Swap, pop and concatenate
# (ṡ flag) join stack by spaces
05AB1E, 81 79 78 76 75 74 73 71 70 69 bytes
•ΘÏF•ºS₂+.¥-D0›©ÏθDT‰ć≠*4šß„—ÊØ3ôsè¨ð”……‚應…ä†ï€¿…Ë…ê†Ä…æ…Ì…Í”#®OèJ
-9 bytes thanks to @Grimy.
-1 byte thanks to @JonathanAllan's standard the trick for th,st,nd,rd, which he used in his Jelly answer.
Try it online or verify all possible test cases.
Explanation:
•ΘÏF• # Push compressed integer 5254545
º # Mirror it vertically: 52545455454525
S # Converted to a list of digits: [5,2,5,4,5,4,5,5,4,5,4,5,2,5]
₂+ # And 26 to each: [31,28,31,30,31,30,31,31,30,31,30,31,28,31]
# (the additional trailing 28,31 won't cause any issues)
.¥ # Undelta this list (with automatic leading 0):
# [0,31,59,90,120,151,181,212,243,273,304,334,365,393,424]
- # Subtract each from the (implicit) input-integer
D0› # Duplicate the list, and check for each if it's positive (> 0)
© # Store the resulting list in the register (without popping)
Ï # Only leave the values at those truthy indices
θ # And get the last value from the list, which is our day
D # Duplicate this day
T‰ # Take the divmod-10 of this day: [day//10, day%10]
ć # Extract the head; pop and push the remainder-list and head: [day%10], day//10
≠ # Check whether the day//10 is NOT 1 (0 if day//10 == 1; 1 otherwise)
* # Multiply that by the [day%10] value
4š # Prepend a 4 to this list
ß # Pop and push the minimum of the two (so the result is one of [0,1,2,3,4],
# where the values are mapped like this: 1..3→1..3; 4..9→4; 10..19→0; 20..23→0..3; 24..29→4; 30,31→0,1)
…thŠØ # Push dictionary string "th standards"
3ô # Split it into parts of size 3: ["th ","sta","nda","rds"]
sè # Swap and index the integer into this list (4 wraps around to index 0)
¨ # And remove the trailing character from this string
ð # Push a space " "
”……‚應…ä†ï€¿…Ë…ê†Ä…æ…Ì…Í”
# Push dictionary string "December January February March April May June July August September October November"
# # Split on spaces
® # Push the list of truthy/falsey values from the register again
O # Get the amount of truthy values by taking the sum
è # Use that to index into the string-list of months (12 wraps around to index 0)
J # Join everything on the stack together to a single string
# (and output the result implicitly)
See this 05AB1E tip of mine to understand why:
- (section How to use the dictionary?)
”……‚應…ä†ï€¿…Ë…ê†Ä…æ…Ì…Í”is"December January February March April May June July August September October November" - (section How to use the dictionary?)
…thŠØis"th standards" - (section How to compress large integers?)
•ΘÏF•is5254545
C# (Visual C# Interactive Compiler), 115 113 109 98 bytes
g=>$"{f=(g=p.AddDays(g-1)).Day}{"tsnr"[f=f%30%20<4?f%10:0]}{"htdd"[f]} {g:MMMM}";DateTime p;int f;
Thanks to @someone for saving 9 bytes
Jelly, 79 78 77 bytes
-1 fixing a bug :) (shouldn't pre-transpose to find index, should post-reverse, but then we can tail rather than head)
-1 using reflection (⁽©ṅB+30_2¦2 -> ⁽0ṗb4+28m0)
⁽0ṗb4+28m0SRṁRƲœiµṪȮ%30%20«4ị“nḄƲf⁷»s3¤Ṗ,ị“£ṢtẒ⁽ẹ½MḊxɲȧėAṅ ɓaṾ¥D¹ṀẏD8÷ṬØ»Ḳ¤$K
A full program which prints the result
How?
will update this later...
⁽©ṅB+30_2¦2SRṁRƲZœiµḢȮ%30%20«4ị“nḄƲf⁷»s3¤Ṗ,ị“...»Ḳ¤$K - Main Link: integer, n
⁽©ṅB+30_2¦2SRṁRƲZœi - f(n) to get list of integers, [day, month]
⁽©ṅ - compressed literal 2741
B - to a list of binary digits -> [ 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1]
+30 - add thirty [31,30,31,30,31,30,31,31,30,31,30,31]
¦ - sparse application...
2 - ...to indices: [2]
_ 2 - ...action: subtract two [31,28,31,30,31,30,31,31,30,31,30,31]
Ʋ - last four links as a monad - i.e. f(x):
S - sum x 365
R - range [1..365]
R - range x (vectorises) [[1..31],[1..28],...]
ṁ - mould like [[1..31],[32..59],...]
Z - transpose [[1,32,...],[2,33,...],...]
œi - 1st multi-dimensional index of n -> [day, month]
µḢȮ%30%20«4ị“nḄƲf⁷»s3¤Ṗ,ị“...»Ḳ¤$K - given [day, month] format and print
µ - start a new monadic chain - i.e. f(x=[day, month])
Ḣ - head -- get the day leaving x as [month])
Ȯ - print it (with no newline) and yield it
%30 - modulo by thirty
%20 - modulo by twenty
«4 - minimum of that and four
¤ - nilad followed by link(s) as a nilad:
“nḄƲf⁷» - dictionary words "standard"+" the" = "standard the"
s3 - split into threes = ["sta","nda","rd ","the"]
ị - index into
Ṗ - remove rightmost character
¤ - nilad followed by link(s) as a nilad:
“...» - dictionary words "January"+" February"+...
Ḳ - split at spaces = ["January","February",...]
ị - index into (vectorises across [month])
, - pair e.g. ["th", ["February"]]
K - join with spaces ["th ", "February"]
- print (implicitly smashes) th February
C (gcc), 174 155 bytes
i;char a[99],*b="thstndrd";f(long x){x--;x*=86400;strftime(a,98,"%d %B\0",gmtime(&x));i=*a==49?0:a[1]-48;a[2]=b[i=i>3?0:i*2];a[3]=b[++i];x=*a==48?a+1:a;}
Smalltalk, 126 bytes
d:=Date year:1day:n.k:=m:=d dayOfMonth.10<k&(k<14)and:[k:=0].o:={#st.#nd.#rd}at:k\\10ifAbsent:#th.m asString,o,' ',d monthName
Google Sheets, 118 103 86 bytes
=day(A1+1)&mid("stndrdth",min(7,1+2*mod(mod(day(A1+1)-1,30),20)),2)&text(A1+1," mmmm")
I can't edit my comment so, here's a working version of the Google Sheets code.
Jelly, 115 114 101 97 bytes
%30%20¹0<?4Ḥ+ؽị“thstndrd”ṭ
“5<Ḟ’b4+28ÄŻ_@µ>0T,>0$ƇZṪµ1ịị“£ṢtẒ⁽ẹ½MḊxɲȧėAṅ ɓaṾ¥D¹ṀẏD8÷ṬØ»Ḳ¤,2ịÇƊṚK
Long by Jelly standards, but done from first principles.
Thanks to @JonathanAllan for saving 13 bytes through better understanding of string compression.
MySQL, 47 45 42 bytes
SELECT DATE_FORMAT(MAKEDATE(1,n),"%D %M")
1901 can be replaced with any year that was/is not a leap year.
Edit: saved two bytes by removing spaces and another three bytes by changing the year to 1, thanks to @Embodyment of Ignorance.
Shell + coreutils, 112 90 bytes
date -d0-12-31\ $1day +%-dth\ %B|sed 's/1th/1st/;s/2th/2nd/;s/3th/3rd/;s/\(1.\).. /\1th /'
Try it online! Link includes test cases. Edit: Saved 22 bytes thanks to @NahuelFouilleul. Explanation:
date -d0-12-31\ $1day
Calculate the number of day(s) after the first day preceding a non-leap year. (Sadly you can't do relative date calculations from @-1.)
+%-dth\ %B|sed
Output the day of month (without leading zero), th, and the full month name.
's/1th/1st/;s/2th/2nd/;s/3th/3rd/;
Fix up 1st, 2nd, 3rd, 21st, 22nd, 23rd and 31st.
s/\(1.\).. /\1th /'
Restore 11th to 13th.
bash, 82 80 bytes
-2 bytes thanks to @ASCII-only
a=(th st nd rd);set `printf "%(%e %B)T" $[$1*86399]`;echo $1${a[$1%30%20]-th} $2
bash +GNU date, 77 bytes
a=(th st nd rd);set `date -d@$[$1*86399] +%e\ %B`;echo $1${a[$1%30%20]-th} $2
APL(NARS), 235 chars, 470 bytes
{k←↑⍸0<w←+\v←(1-⍵),(12⍴28)+13561787⊤⍨12⍴4⋄k<2:¯1⋄d←1+v[k]-w[k]⋄(⍕d),({d∊11..13:'th'⋄1=10∣d:'st'⋄2=10∣d:'nd'⋄3=10∣d:'rd'⋄'th'}),' ',(k-1)⊃(m≠' ')⊂m←'January February March April May June July August September October November December'}
13561787 is the number that in base 4 can be summed to (12⍴28) for obtain the lenght of each month... test:
f←{k←↑⍸0<w←+\v←(1-⍵),(12⍴28)+13561787⊤⍨12⍴4⋄k<2:¯1⋄d←1+v[k]-w[k]⋄(⍕d),({d∊11..13:'th'⋄1=10∣d:'st'⋄2=10∣d:'nd'⋄3=10∣d:'rd'⋄'th'}),' ',(k-1)⊃(m≠' ')⊂m←'January February March April May June July August September October November December'}
⊃f¨1 2 3 365 60 11
1st January
2nd January
3rd January
31st December
1st March
11th January
Red, 124 bytes
func[n][d: 1-1-1 + n - 1[rejoin[d/4 either 5 > t: d/4 % 30 % 20[pick[th st nd rd]t + 1]['th]]pick system/locale/months d/3]]
Adds n - 1 days to 1-1-1 (1-Jan-2001) to form a date, than uses Arnauld's method to index into month suffixes. Too bad Red is 1-indexed, this requires additional tweaking. The good thing is that Red knows the names of the months :)
JavaScript (ES6), 117 113 bytes
Saved 4 bytes thanks to @tsh
d=>(n=(d=new Date(1,0,d)).getDate())+([,'st','nd','rd'][n%30%20]||'th')+' '+d.toLocaleString('en',{month:'long'})
Commented
d => // d = input day
( n = //
( d = // convert d to
new Date(1, 0, d) // a Date object for the non leap year 1901
).getDate() // save the corresponding day of month into n
) + ( //
[, 'st', 'nd', 'rd'] // ordinal suffixes
[n % 30 % 20] // map { 1, 2, 3, 21, 22, 23, 31 } to { 'st', 'nd', 'rd' }
|| 'th' // or use 'th' for everything else
) + ' ' + // append a space
d.toLocaleString( // convert d to ...
'en', // ... the English ...
{ month: 'long' } // ... month name
) //
Without date built-ins, 188 bytes
f=(d,m=0)=>d>(k=31-(1115212>>m*2&3))?f(d-k,m+1):d+([,'st','nd','rd'][d%30%20]||'th')+' '+`JanuaryFebruaryMarchAprilMayJuneJulyAugustSeptemberOctoberNovemberDecember`.match(/.[a-z]*/g)[m]
Perl 6, 166 161 bytes
{~(.day~(<th st nd rd>[.day%30%20]||'th'),<January February March April May June July August September October November December>[.month-1])}o*+Date.new(1,1,1)-1
Hardcodes all the month names, which takes up most of the space. Man, Perl 6 really needs a proper date formatter.
Python 3.8 (pre-release), 112 bytes
lambda x:str(d:=(t:=gmtime(x*86399)).tm_mday)+'tsnrhtdd'[d%5*(d%30%20<4)::4]+strftime(' %B',t)
from time import*
Weirdly enough, I don't have to parenthesize d:=(t:=gmtime(~-x*86400), probably because the interpreter only checks if there are () characters around the assignment expression and not that the expression itself is parenthesized.
R, 158 134 bytes
-24 bytes @Nick Kennedy for golfing the 'st', 'nd', 'rd', & 'th'. Thanks!
f=format;paste0(a<-as.double(f(d<-as.Date(scan(,''),'%j'),'%e')),`if`((a-1)%%10>2|a%/%10==1,'th',c("st","nd","rd")[a%%10]),f(d,' %B'))
C# (Visual C# Interactive Compiler), 141 139 133 124 122 bytes
a=>{var d=s.AddDays(a-1);int x=d.Day,m=x%30%20;return x+"thstndrd".Substring(m<4?m*2:0,2)+d.ToString(" MMMM");};DateTime s
Thanks to Arnauld for faster method of removing 11,12,13th saving 4 bytes
Hack, 115 59 39 bytes
$x==>date("jS F",mktime(0,0,0,1,$x));
Since @gwaugh got to the same solution as mine while I was golfing, I'm posting this in Hack instead :).