[Question]
  [
**Problem**
One day, you boss walks up to you and tells you he needs to know the time. He still insists after you pointing at the clock directly above your head, and confesses he has a severe case of [dyscalculia](https://en.wikipedia.org/wiki/Dyscalculia), which causes him to not even be able to see numbers on a clock. While you're still left wondering how someone unable to see numbers can run a company, he tells you to "do something about it", whatever that is.
Your task is now to create a program or function that, given an input time with hours and minutes (seconds are optional)(hours are 24-based), outputs a readable english sentence, that doesn't contain numbers.
It is not necessary to ouput the seconds.
For example, `08:45:15` should output `quarter to nine o'clock AM`
**Test cases**
```
00:00:00 > twelve night
12:00:00 > twelve noon
06:00:00 > six o'clock AM
18:00:00 > six o'clock PM
06:15:00 > quarter past six o'clock AM
18:45:00 > quarter to seven o'clock PM
11:30:00 > half past eleven o'clock AM
13:22:00 > twentytwo minutes past one o'clock PM
17:43:00 > seventeen minutes to six o'clock PM
00:09:00 > nine minutes past twelve o'clock AM
```
**Rules**
Outputting numbers can be both in the form of fortytwo or forty-two, whichever you like best. Standard loopholes are not allowed. Trailing newlines are allowed, but the sentence should be on 1 line.
Input can be in any format you want, for example `HH:MM:SS`, `HH,MM,SS`, `HHMMSS`, `HH/MM/SS`, or any variant without seconds, but you should make the input format clear in your answer. It's not needed to output `one minute` instead of `one minutes`
for minutes ranging from 0 trough 30 (0 and 30 included) you should use `past`, and for the others you should use `to`
Because time is relative, shortest code in bytes wins.
  
[Answer]
# LaTeX, 466 bytes
```
\usepackage{fmtcount,etoolbox}\def\x{\the\numexpr}\def\n[#1]{\numberstringnum{#1}}\def\h[#1]{\ifnumequal{#1}{0}{twelve night}{\ifnumequal{#1}{12}{twelve noon}{\ifnumless{#1}{13}{\n[#1] o'clock AM}{\n[\x#1-12\relax] o'clock PM}}}}\def\m[#1]{\ifnumequal{#1}{15}{quarter}{\ifnumequal{#1}{30}{half}{\n[#1] minutes}}}\newcounter{c}\def\f[#1]#2{\ifnumequal{#2}{0}{\h[#1]}{\ifnumless{#2}{31}{\m[#2] past \h[#1]}{\setcounter{c}{\x60-#2\relax}\m[\thec] to \h[\x#1+1\relax]}}}
```
Just call the macro `\f` as `\f[hour]{minutes}`, here some tests:
```
\begin{document}
\noindent
\textbf{Test cases:} \\ \\
00:00 = \f[00]{00} \\
12:00 = \f[12]{00} \\
06:00 = \f[6]{00} \\
18:00 = \f[18]{00} \\
06:15 = \f[6]{15} \\
18:45 = \f[18]{45} \\
11:30 = \f[11]{30} \\
13:22 = \f[13]{22} \\
17:43 = \f[17]{43} \\
\noindent
\textbf{More test cases:} \\ \\
00:13 = \f[00]{13} \\
12:12 = \f[12]{12} \\
12:15 = \f[12]{15} \\
11:45 = \f[11]{45} \\
11:41 = \f[11]{41} \\
\end{document}
```
[Answer]
# Python 2, 498 bytes
Input comes as function argument. First hour and then minute, both as integer. Result gets printed to the screen.
```
def g(h,m):
 a=lambda x:"twelve one two three four five six seven eigth nine ten eleven".split()[x%12];b=lambda x:a(x)+" o'clock "+["AM","PM"][x>=12]
 if m:
    z=m if m<30else 60-m;print(a(z)if z<13else("twenty"+(a(z-20)if z-20else"")if z>19else"thirteen fourteen fifteen sixteen seventeen eighteen nineteen".split()[z-13])if m%15else"quarter"if m-30else"half")+(" minutes"if m-30and m%15else"")+[" past "+b(h)," to "+b(h+1)][m>30]
 else:print"twelve "+("noon"if h else "night")if h in[0,12]else b(h)
```
[Try it online!](https://repl.it/BkMv/43) *(with slightly extended testcases)*
That was a pretty fun golf. Although all those nested ternaries drove me a little bit crazy ^^  
I was planning on doing this in Pyth after this, but I don't think that I am mentally able to do this at the moment (or ever).
**Ungolfed:**
```
def ungolfed(h,m):
    toStr=lambda x:"twelve one two three four five six seven eigth nine ten eleven".split()[x%12]
    hour=lambda x:toStr(x)+" o'clock "+["AM","PM"][x>=12]
    minute=lambda x:"twenty"+(toStr(x-20)if x-20else"")if x>19else"thirteen fourteen fifteen sixteen seventeen eighteen nineteen".split()[x-13]
    
    if m:
        s=""
        if m==30:
            s+="half"
        else:
            if m%15==0:
                s+="quarter"
            else:
                z=m if m<30 else 60-m
                if z<13:
                    s+=toStr(z)
                else:
                    s+=minute(z)
        print s+(" minutes"if m-30and m%15else "")+[" past "+hour(h)," to "+hour(h+1)][m>30]
    else:
        if h in[0,12]:
            print"twelve "+("noon"if h else "night")
        else:
            print hour(h)
```
[Answer]
# [Python 3.8 (pre-release)](https://docs.python.org/3.8/), 376 bytes
```
lambda h,m,N='one two three four five six seven eight nine ten eleven twelve thir four _ six seven eigh nine'.split()+['']:m+h%12and((m%15<1and['half','quarter'][m%2]or(lambda T:T<20and N[T-1]+T//13*'teen'or'twenty'+N[T%10-1])([m,60-m][m//31])+' minutes')+[' past ',' to '][m//31])*(m>0)+N[(h-1+m//31)%12]+" o'clock "+'APA'[(h+m//31)//12]+'M'or'twelve n'+['ight','oon'][h//12]
```
[Try it online!](https://tio.run/##ZZDdTuMwEIXveYoRUjUOcWkct92CAIkHWMRF77IRCtRZR8R2cFx@nr47Cd1V3L3z8fnOzLG7r6CdlZvOH@rbX4e2Ms@7CjQ3/OEWnVUQPhwE7ZWC2u091M27gr75hF69Kwuq@a0D2GYAB9mOt@FDtYQF3fjv1NNJZEzgZd@1TWBJWiCW1ybVM5FXdseYmYnVjaBjgbpqa@T4tq98UB7Lwszy0nl2LLq93t7kGZHwUGznoky3i4WQFxiUsug8UhMbvjAldyYyAhJWGL7O5oYmLRaSLlIE09h9UD0OTaCr@gC0EoID/EddMHOXJTSH6blIx8uE6pbpOTh8ad3LK5yneP94j0QcfapCAP48Fhm@xCKtGP6MFjhnab4eqUPnGxtYzSDjkCXJ2V8t8ljD@sTf/OeLVewvIy24jPKS5/lU/@BLOZ1Hfa6m/oqLKQ8bnmdxXkT6NE99xcn7RNxHRn04wCbm5TJ@z2rq53LUhz8 "Python 3.8 (pre-release) – Try It Online")
Stumbled on this challenge by accident and decided to give it a go.
# Explanation
Handles the edge cases of midnight and noon by using a standard `... and ... or ...` that has become ubiquitous for any Python code-golfer. For these edge cases return `twelve` , followed by night or noon depending on the hour.
In the general case, we build a string representing the minutes. If the minutes is 15 or 45, we start with `quarter`; if it is 30, we start with `half`; otherwise, we determine whether to use itself or 60 minus itself (think of it this way: 5:21 is 21 past 5, but 6:37 is 23 to 7, not 37 to 7). Let `M` denote this number. We build the appropriate number:
* if `M` is less than 20, start with the conversion of itself to letters, minus `teen`.
* if `M` is 20 or more, start with `twenty`.
Then:
* if `M` is less than 20 but more than 12, add `teen`.
* if `M` is 20 or more, add the conversion to letters of its units digit, with nothing being added if its units digit is zero.
If the minutes count was not divisible by 15, we also have to add  `minutes`.
Next, we have to deal with `past` and `to`. This is determined by indexing a list.
If the minutes count is zero, the above string goes to waste. Because `zero` or something similar does not appear in `N`, one might assume that building the string for zero would cause the program to error with an IndexError. But because Python allows negative indices, it doesn't error. When the minutes count is zero, we just don't use the above string.
Next we have to deal with `o' clock`, which is simply done using `%` and our list of text numbers again.
Finally we append `AM` or `PM` depending on the hour.
[Answer]
# [Vyxal](https://github.com/Vyxal/Vyxal), 155 bytes
```
1→m?\:/⌊:£t¬[¥h12ḋ:→d÷¬[0→m12←d h¬[‛⟇Ẏ|‛₄⟨]|¥h12%]|¥t15ḋ:→d÷¬[←d h∷[‛ɽ¢|‛»⌈]|¥t:30>[60ε]‛«¦]¥t30≤[‛×Ṡ¥h12Ḋ[12|¥h12%]|‛to¥h12%›]]←m[`o'∵₅`¥h12<‛PAi\M+]WḢ∆ċṄ
```
Takes input as HH:MM.
[Try it Online!](https://vyxal.pythonanywhere.com/#WyIiLCIiLCIx4oaSbT9cXDov4oyKOsKjdMKsW8KlaDEy4biLOuKGkmTDt8KsWzDihpJtMTLihpBkIGjCrFvigJvin4fhuo584oCb4oKE4p+oXXzCpWgxMiVdfMKldDE14biLOuKGkmTDt8KsW+KGkGQgaOKIt1vigJvJvcKifOKAm8K74oyIXXzCpXQ6MzA+WzYwzrVd4oCbwqvCpl3CpXQzMOKJpFvigJvDl+G5oMKlaDEy4biKWzEyfMKlaDEyJV184oCbdG/CpWgxMiXigLpdXeKGkG1bYG8n4oi14oKFYMKlaDEyPOKAm1BBaVxcTStdV+G4ouKIhsSL4bmEIiwiIyAwMDowMDowMCA+IHR3ZWx2ZSBuaWdodFxuIyAxMjowMDowMCA+IHR3ZWx2ZSBub29uXG4jIDA2OjAwOjAwID4gc2l4IG8nY2xvY2sgQU1cbiMgMTg6MDA6MDAgPiBzaXggbydjbG9jayBQTVxuIyAwNjoxNTowMCA+IHF1YXJ0ZXIgcGFzdCBzaXggbydjbG9jayBBTVxuIyAxODo0NTowMCA+IHF1YXJ0ZXIgdG8gc2V2ZW4gbydjbG9jayBQTVxuIyAxMTozMDowMCA+IGhhbGYgcGFzdCBlbGV2ZW4gbydjbG9jayBBTVxuIyAxMzoyMjowMCA+IHR3ZW50eXR3byBtaW51dGVzIHBhc3Qgb25lIG8nY2xvY2sgUE1cbiMgMTc6NDM6MDAgPiBzZXZlbnRlZW4gbWludXRlcyB0byBzaXggbydjbG9jayBQTVxuIyAwMDowOTowMCA+IG5pbmUgbWludXRlcyBwYXN0IHR3ZWx2ZSBvJ2Nsb2NrIEFNXG5cbiMgSW5wdXQgaXMgSEg6TU0iLCIxMzoyMiJd)
[Answer]
# Javascript, ~~384~~ 381 bytes
```
(h,m)=>(o='one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thir,,fif,,,eigh,'.split`,`,o=o.map((x,i)=>i>11?(x||o[i-10])+'teen':x),(a=m>30,t=12,m?(m-30?m%15?((m=a?59-m:m)>=(b=a?19:20)?'twenty'+((m%=b)?o[a?m:m-1]:''):o[a?m:m-1])+' minutes':'quarter':'half')+(a?' to ':' past '):'')+(h%t|m?o[(a?h:(h?h-1:11))%t]+` o'clock ${h>t?'P':'A'}M`:o[11]+(h-t?' night':' noon')))
```
```
f=
(h,m)=>(
    o='one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thir,,fif,,,eigh,'.split`,`,
    o=o.map((x,i)=>i>11?(x||o[i-10])+'teen':x),
    (a=m>30,t=12,
    m?
        (m-30?
            m%15?
                ((m=a?59-m:m)>=(b=a?19:20)?
                    'twenty'+((m%=b)?o[a?m:m-1]:'')
                :o[a?m:m-1])+' minutes'
            :'quarter'
        :'half')+(a?' to ':' past ')
    :'')
    +(h%t|m?
        o[(a?h:(h?h-1:11))%t]+` o'clock ${h>t?'P':'A'}M`
    :o[11]+(h-t?' night':' noon'))
)
document.body.innerHTML = '<pre>' +
'f(00,00) = ' + f(00,00) + '\n' +
'f(12,00) = ' + f(12,00) + '\n' +
'f(06,00) = ' + f(06,00) + '\n' +
'f(18,00) = ' + f(18,00) + '\n' +
'f(06,15) = ' + f(06,15) + '\n' +
'f(18,45) = ' + f(18,45) + '\n' +
'f(11,30) = ' + f(11,30) + '\n' +
'f(13,22) = ' + f(13,22) + '\n' +
'f(17,43) = ' + f(17,43) + '\n' +
'f(00,09) = ' + f(00,09) + '\n' +
'f(23,59) = ' + f(23,59) + '\n' +
'</pre>'
```
[Answer]
# Perl 5, ~~367 361~~ 385 Bytes
Garbled
```
use integer;$_=<>;~/(\d+):(\d+)/;@b=(one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve); @x=(@b,thirteen,(map{/fi/?quarter:$_.teen}@b[3..8]),(map{twenty.$_}'',@b[0..8]),half);@y=map{/^q|h/?$_:$_.' minutes'}@x;$s=1-$2/31;$y=abs((-29,0)[$s]+$2%31)-1;$h=$1-$s;print((+-$2?@y[$y].' '.(to,past)[$s].' ':'').@b[$h++%12]." o' clock ".($h%12?(AM,PM)[$h/12]:(night,noon)[$h/12%2]))
```
Formatted and test cases:
```
use integer;
map{
    # capture (implicit $_)
    ~/(\d+):(\d+)/;
    # bare words
    @b=(one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve);
    # construct up to 30
    @x=(@b,thirteen,
       (map{/fi/?quarter:$_.teen}@b[3..8]),
       (map{twenty.$_}'',@b[0..8]),half);
    # quarter/half business
    @y=map{/^q|h/?$_:$_.' minutes'}@x;
    # whether we are to/past
    $s=1-$2/31;
    # num minutes wrapped around
    $y=abs((-29,0)[$s]+$2%31)-1;
    # num hours
    $h=$1-$s;
    #print('$s='.$s."\th=".$h."\th%12=".($h%12)."\n");
    print($_.' > ');
    #minute component
    print((+-$2
          ?@y[$y].' '.(to,past)[$s].' '
          :'')
        # hours
        .@b[$h++%12]
        ." o' clock "
        # Night/Noon
        .($h%12
          ?(AM,PM)[$h/12]
          :(night,noon)[$h/12%2]));
    print "\n"
}
('00:00:00',
 '00:01:00',
 '11:59:00',
 '12:00:00',
 '12:01:00',
 '06:00:00', 
 '18:00:00', 
 '06:15:00', 
 '18:45:00', 
 '11:30:00', 
 '13:22:00', 
 '17:43:00',
 '23:59:59')
```
[Answer]
# C, 478 bytes
```
*w(i){char*p,*n[]={"","one","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen"};return i>19?asprintf(&p,"twenty%s",n[i%20]),p:n[i];}main(m,h){scanf("%d%d",&h,&m);m>30?h++:0;printf("%s%s%s%s%s %s\n",m%15?m>30?w(60-m):w(m):m^30?m?"quarter":"":"half",m%15?" minutes":"",m?m>30?" to ":" past ":"",w((h+11)%12+1),h%12||m?" o'clock":"",h%12||m?h>11?"PM":"AM":h?"noon":"night");}
```
## Test Cases
```
$ echo "0 0" | ./a.out
twelve night
$ echo "12 0" | ./a.out
twelve noon
$ echo "6 0" | ./a.out
six o'clock AM
$ echo "18 0" | ./a.out
six o'clock PM
$ echo "6 15" | ./a.out
quarter past six o'clock AM
$ echo "18 45" | ./a.out
quarter to seven o'clock PM
$ echo "11 30" | ./a.out
half past eleven o'clock AM
$ echo "13 22" | ./a.out
twentytwo minutes past one o'clock PM
$ echo "17 43" | ./a.out
seventeen minutes to six o'clock PM
$ echo "0 9" | ./a.out
nine minutes past twelve o'clock AM
```
Try it [here](http://ideone.com/O17u5E).
[Answer]
## Batch, ~~779~~ ~~774~~ ~~752~~ 749 bytes
```
@echo off
set t=%1
set/ah=%t:~0,2%,m=%t:~3,2%
set p=past
if %m% gtr 30 set p=to&set/am=60-m,h+=1
for %%a in ("one minute.1" quarter.15 half.30)do if %%~xa==.%m% set o=%%~na&goto g
set o=
if %m% gtr 20 set o=twenty-&set/am-=20
for %%a in (one.1 two.2 three.3 four.4 five.5 six.6 seven.7 eight.8 nine.9 ten.10 eleven.11 twelve.12 thirten.13 fourteen.14 sixteen.16 seventeen.17 eighteen.18 nineteen.19 twenty.20)do if %%~xa==.%m% set o=%o%%%~na minutes
:g
if not %m%==0 set o=%o% %p% 
set a= AM
if %h% gtr 12 set a= PM&set/ah%%=12
if %h%==0 (echo %o%twelve night)else if %h%==12 (echo %o%twelve noon)else for %%a in (one.1 two.2 three.3 four.4 five.5 six.6 seven.7 eight.8 nine.9 ten.10 eleven.11)do if %%~xa==.%h% echo %o%%%~na o'clock%a%
```
Change the second line to `set t=%1%time%` to default to saying the current time if no time is provided.
Edit: Saved 22 bytes by optimising my `set/a` statements. Saved 3 bytes thanks to @EʀɪᴋᴛʜᴇGᴏʟғᴇʀ.
When I wrote my original version I made the mistake of saying the time as I would actually say it, i.e. o'clock only on exact hours, and midnight and midday instead of twelve night and twelve noon:
```
@echo off
set t=%1
set/a h=%t:~0,2%
set/a m=%t:~3,2%
set p=past
if %m% gtr 30 set p=to&set/a m=60-m&set/a h=h+1
for %%a in ("one minute.1" quarter.15 half.30) do if %%~xa==.%m% set o=%%~na&goto g
set o=
if %m% gtr 20 set o=twenty-&set/a m=%m%-20
for %%a in (one.1 two.2 three.3 four.4 five.5 six.6 seven.7 eight.8 nine.9 ten.10 eleven.11 twelve.12 thirten.13 fourteen.14 sixteen.16 seventeen.17 eighteen.18 nineteen.19 twenty.20) do if %%~xa==.%m% set o=%o%%%~na minutes
:g
set o=%o% %p% 
set a= AM
if %h% gtr 12 set a= PM&set/a h=h%%12
if %m%==0 set a= o'clock%a%&set o=
if %h%==0 (echo %o%midnight)else if %h%==12 (echo %o%midday)else for %%a in (one.1 two.2 three.3 four.4 five.5 six.6 seven.7 eight.8 nine.9 ten.10 eleven.11) do if %%~xa==.%h% echo %o%%%~na%a%
```
]