2

I have a text file with date value.

Data:

01-Sep-21
02-Jan-22
12-Aug-21
24-Dec-21
11-Jul-22

How to sort these data from old to new date value?

2 Answers 2

10

With the GNU implementation of sort and assuming all dates are from the same century:

<your-file LC_ALL=C sort -t- -k3,3n -k2,2M -k1,1n

Where -t specifies the field separator, -k <start>,<end><flags> specifies where the sort keys start, end and how they should be interpreted / compared via the <flags>.

The n flag is for numeric comparison, M (a GNU extension) for month name or abbreviation comparison (here, assumed to be in English by fixing the locale to C where the month names are in English).

So here, the sort keys, are the year first (compared numerically, though lexical comparison would also work as they're always on 2 digits on your sample), then the month abbreviation field (compared as Month), then the day (again compared numerically, though lexical would also work).

With the GNU implementation of date, you could also do:

date -f your-file +%F | sort

Same as:

date --iso-8601 -f your-file | sort

To convert those dates to the standard YYYY-MM-DD format, which can be sorted lexically as is (at least until 9999-12-31).

For current versions of GNU date, from testing, it seems 01-Jan-00 to 31-Dec-69 are 2000-01-01 to 2069-12-31, and 01-Jan-70 to 31-Dec-99 are 1970-01-01 to 1999-12-31.

On non-GNU systems, you can always use a Schwartzian transform / decorate-sort-undecorate approach with:

<your-file awk -F- '{printf "%s%02d%s\t%s\n", $3, index("JanFebMarAprMayJunJulAugSepOctNovDec",$2), $1, $0}' |
  sort | cut -f2-

And decide on the century cut off date, and match month names case insensitively with:

<your-file awk -F- '
  {
    printf "%s%02d%s\t%s\n", \
      $3 + ($3 < 70 ? 2000 : 1900), \
      index("jan,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec", tolower($2)), \
      $1, \
      $0
  }' |
  sort |
  cut -f2-

¹ well a century runs from 2001-01-01 to 2100-12-31 for instance, I mean that if there's a 01-Sep-21 and 12-Jan-86 for instance, that means 2021 and 2086 or 1921 and 1986, not 1986 and 2021.

3

Using Python and dates file dates.txt:

from datetime import datetime
with open('dates.txt') as f:
    dts = [datetime.strptime(line.rstrip(), '%d-%b-%y') for line in f]
for k in sorted(dts):
    print(k.strftime('%d-%b-%y'))

Can also use dateutil.parser if you want to parse dates in different syntaxes:

from dateutil import parser
with open('dates.txt') as f:
    dts2 = [parser.parse(line) for line in f]
for k in sorted(dts2):
    print(k.strftime('%d-%b-%y'))

Both outputs the same, from oldest to newest:

12-Aug-21
01-Sep-21
24-Dec-21
02-Jan-22
11-Jul-22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.