20

How can I find out which are leap years between 2014 and 2020 in a Linux terminal?

Is there any way using some code like $cal - anything to show which years are leap years between 2014 and 2020 straight away?

1

4 Answers 4

40

You can make use of date's exit code to check for a leap year, relying on date's behaviour of generating a non 0 exit code for an invalid date, obviosuly there's no 29th of Feb in a non-leap year:

date -d $year-02-29 &>/dev/null
echo $?

as a function:

isleap() { date -d $1-02-29 &>/dev/null && echo is leap || echo is not leap; }

Usage:

$ isleap 2019
is not leap

$ isleap 2020
is leap

Regarding your question:

How can I find out which are leap years between 2014 and 2020 in a Linux terminal?

echo "Leap years between 2014 and 2020:";
for y in {2014..2020}; do
    date -d $y-02-29 &>/dev/null && echo $y;
done
2
  • why this is not work in mac terminal
    – lee
    Oct 17, 2018 at 14:15
  • I hope you didn't ask for a solution for mac on askubuntu ... See this for osx date command.
    – pLumo
    Oct 17, 2018 at 14:22
9

Just a variant of @RoVo's answer ...

for a in {2014..2020}
do 
  date -d $a-02-29 +"%Y" 2>/dev/null
done

date -d $a-02-29 +"%Y" 2> /dev/null sets date to the 29th of Feb and prints the year, ignoring any errors that occur.

2
  • 3
    Or even seq -f "%g-02-29" 2014 2020 | date -f- +"%Y" 2>/dev/null Oct 5, 2018 at 20:08
  • @DigitalTrauma: very cool!
    – user216043
    Oct 5, 2018 at 22:43
7

Here on Stack Overflow, an elegant solution was provided by anubhava:

#!/bin/bash
(( !($1 % 4) && ( $1 % 100 || !( $1 % 400) ) )) &&
echo "leap year" || echo "not a leap"
exit 0

Save the above in a text files named isleap.

Don't forget to set execute permission:

chmod +x isleap

Test it:

$ ./isleap 1900
not a leap
$ ./isleap 2000
leap year
1
  • This is the correct answer. The others that depend on an arbitrary implementation in the date command are hacks. Oct 9, 2018 at 17:59
3

If you don’t want to rely on some incidental “arcane” properties of leap years (like their divisibility, the number of days in a year, or the existence of a specific day) you should use a programming language with an appropriate calendar library function. I recommend Python’s calendar.isleap()1, 2:

#!/usr/bin/python3
import sys
import traceback
import calendar

try:
    year = int(sys.argv[1])
    is_leap = calendar.isleap(year)
except:
    traceback.print_exc()
    sys.exit(2)

print(is_leap)  # Print the year’s leap status
sys.exit(not is_leap)  # Exit program with "success" if leap and "failure" otherwise

Usage:

$ python3 is_leap.py 2000
True
$ python3 is_leap.py 2100
False

Or as a one-liner (without proper error handling):

$ python3 -c 'import sys, calendar; print(calendar.isleap(int(sys.argv[1])))' 2000
True
$ python3 -c 'import sys, calendar; sys.exit(not calendar.isleap(int(sys.argv[1])))' 2000
$ echo $?
0

1 I’m sure there is a simple equivalent Perl solution.

2 Python’s calendar module uses the proleptic Gregorian calendar, i. e. it extends the G. calendar indefinitely into the past and future. It doesn’t take into account that the G. calendar only went into effect in 1582 or that some locales continue to use other calendars with different leap year rules. If you need support for other calendars, e. g. the Julian calendar, I recommend that you install and use an appropriate Python extension module.

2
  • From calendar.py: def isleap(year): """Return True for leap years, False for non-leap years.""" return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0). Same fct. as used in askubuntu.com/a/1081237/790920
    – abu_bua
    Oct 7, 2018 at 15:48
  • @abu_bua: Yes, but to not reinvent the wheel means that you won’t make the same mistakes (even typos) as its original inventor. That’s assuming that you trust in the work of that inventor. The Python core modules are generally well maintained. Oct 8, 2018 at 8:41

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .