g | x | w | all
Bytes Lang Time Link
141C250819T172320ZToby Spe
061Uiua250412T131554ZJoao-3
nanPHP190313T161552Z640KB
081Vyxal ṡ210817T220056Zemanresu
06905AB1E190314T105015ZKevin Cr
098C# Visual C# Interactive Compiler190313T195845ZGymhgy
077Jelly190314T164310ZJonathan
155C gcc190315T092922ZGPS
126Smalltalk190314T020528ZLeandro
086Google Sheets190314T201056ZZylviij
097Jelly190313T213722ZNick Ken
042MySQL190314T152746ZNicolasB
090Shell + coreutils190313T234547ZNeil
080bash190314T092822ZNahuel F
470APLNARS190314T073855Zuser5898
124Red190314T083547ZGalen Iv
113JavaScript ES6190313T160150ZArnauld
161Perl 6190313T220139ZJo King
112Python 3.8 prerelease190313T205120ZErik the
134R190313T170154ZChthonyx
122C# Visual C# Interactive Compiler190313T155802ZExpired
039Hack190313T160855ZVen

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

Try it online!

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

Try it in the pad!

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

Try it online!

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:

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

Try it online!

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

Try it online!

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

Try it online!

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.

Try it Online!

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

Try it online!

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

TIO

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

Try it online!

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

Try it online!

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]

Try it online!

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

Try it online!

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*

Try it online!

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.

-2 thanks to gwaugh.
-5 thanks to xnor.

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

Try it online!

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

Try it online!

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 :).