-2

I need to receive a code in bash, which will give me current date in this format:

Sunday, 1^st January 2016 (with superscript st, nd, rd or th) in 4 cases.

What is the way to receive superscript?

I would be thankful for any help.

DimaSan
  • 12,264
  • 11
  • 65
  • 75
AngelikaG
  • 11
  • 1
  • Look here this may be helpful: http://stackoverflow.com/questions/13627308/add-st-nd-rd-and-th-ordinal-suffix-to-a-number – DimaSan Nov 15 '16 at 10:59
  • 2
    It is bit harsh that your question is down voted, because you are a newbie , however sadly the users who did it had some reason. Next time try to include some code examples about what have you tried so far. Or try to write more explicit questions instead of one implicit.: 1. How can I get only the day of the month in bash? 2. How can I write conditional statements? 3. How can I replace match in strings – atevm Nov 15 '16 at 11:53
  • I'm afraid, it's impossible to print superscript versions of these characters in a terminal, at least in a portable way. – Ruslan Osmanov Nov 15 '16 at 13:52
  • Agreed, though you might be able to use `ˢᵗ`, `ⁿᵈ`, `ʳᵈ` and `ᵗʰ` if your terminal supports those characters. – Toby Speight Sep 20 '22 at 12:11

2 Answers2

6

The date program doesn't have any conversions that produce ordinal numbers, so you'll need to substitute the suffix outside of it:

#!/bin/bash

d=$(date +%e)

case $d in
    1?) d=${d}th ;;
    *1) d=${d}st ;;
    *2) d=${d}nd ;;
    *3) d=${d}rd ;;
    *)  d=${d}th ;;
esac

date "+%A, $d %B %Y"

Note that most English style guides recommend against writing the ordinal suffix as a superscript; if you really insist on it, you can treat that as an exercise!


Note also, that by invoking date twice, we risk a race condition at midnight. We can avoid this by separately finding the current time and then formatting it:

#!/bin/bash

s=$(date +@%s)
d=$(date -d $s +%e)

case $d in
    1?) d=${d}th ;;
    *1) d=${d}st ;;
    *2) d=${d}nd ;;
    *3) d=${d}rd ;;
    *)  d=${d}th ;;
esac

date -d $s "+%A, $d %B %Y"

Alternatively, read the date (once) into separate variables, and then format them in shell:

#!/bin/bash

IFS=_ read a d b y < <(date +%A_%e_%B_%Y)

case $d in
    1?) d=${d}th ;;
    *1) d=${d}st ;;
    *2) d=${d}nd ;;
    *3) d=${d}rd ;;
    *)  d=${d}th ;;
esac

echo "$a, $d $b $y"
Toby Speight
  • 27,591
  • 48
  • 66
  • 103
  • 1
    Excellent answer otherwise, disappointed by this: "Note that most English style guides recommend against writing the ordinal suffix as a superscript" -- no reference? The Chicago MoS (sure, I have it at my desk) recommends against numeric ordinals: "Tuesday, May 5" but "Tuesday, May [the] fifth". – Rich May 09 '18 at 18:18
  • 1
    Isn't Chicago an American guide? I don't have my Fowler's with me right now, but *not using ordinals* seems to include *not using superscript ordinals*. Thanks for picking up on this, anyway. – Toby Speight May 10 '18 at 08:09
0

I hope this helps:

#!/bin/bash

# get the day of the month to decide which postfix should be used
dayOfMonth=$(date +%d)

# Choose postfix
case "$dayOfMonth" in
    1)
    postfix="st"
    ;;
    2)
    postfix="nd"
    ;;
    3)
    postfix="rd"
    ;;
    *)
    postfix="th"
    ;;
esac

# Generate date string
myDate=$(date +%A,\%d\^$postfix\ %B\ %Y)
echo $myDate

Explanation:

  1. Mind the comments.

  2. The date command output can be formatted from the command line with a string starting with a "+", containing varius format options like %d for day of the month.

Type this into your terminal:

man date

to get the manual and check the FORMAT section.

Or if you want to run your app at very midnight as Toby Speight warned about it. Call date only once:

#!/bin/bash

# Generate date template
dateTpl=$(date +%A,\ \%d\^postfix\ %B\ %Y)
# get the day of the month from the template, to decide which postfix should be use
dayOfMonth=$(echo $dateTpl | cut -d ' ' -f 2 | sed 's/\^postfix//g' )

# Choose postfix
case "$dayOfMonth" in
    1)
    postfix="st"
    ;;
    2)
    postfix="nd"
    ;;
    3)
    postfix="rd"
    ;;
    *)
    postfix="th"
    ;;
esac

# Generate date string from template
myDate=$(echo $dateTpl | sed "s/postfix/$postfix/g")
echo $myDate
atevm
  • 801
  • 1
  • 14
  • 27