Long year?

From Rosetta Code
Task
Long year?
You are encouraged to solve this task according to the task description, using any language you may know.

Most years have 52 weeks, some have 53, according to ISO8601.


Task

Write a function which determines if a given year is long (53 weeks) or not, and demonstrate it.

ALGOL-M[edit]

BEGIN
 
COMMENT
FIND ISO CALENDAR YEARS HAVING 53 WEEKS. THE SIMPLEST
TEST IS THAT A GIVEN YEAR WILL BE "LONG" IF EITHER THE
FIRST OR LAST DAY IS A THURSDAY;
 
% CALCULATE P MOD Q %
INTEGER FUNCTION MOD(P, Q);
INTEGER P, Q;
BEGIN
MOD := P - Q * (P / Q);
END;
 
COMMENT
RETURN DAY OF WEEK (SUN=0, MON=1, ETC.) FOR A GIVEN
GREGORIAN CALENDAR DATE USING ZELLER'S CONGRUENCE;
INTEGER FUNCTION DAYOFWEEK(MO, DA, YR);
INTEGER MO, DA, YR;
BEGIN
INTEGER Y, C, Z;
IF MO < 3 THEN
BEGIN
MO := MO + 10;
YR := YR - 1;
END
ELSE MO := MO - 2;
Y := MOD(YR, 100);
C := YR / 100;
Z := (26 * MO - 2) / 10;
Z := Z + DA + Y + (Y / 4) + (C /4) - 2 * C + 777;
DAYOFWEEK := MOD(Z, 7);
END;
 
% RETURN 1 IF YEAR IS LONG, OTHERWISE 0 %
INTEGER FUNCTION ISLONGYEAR(YR);
INTEGER YR;
BEGIN
INTEGER THURSDAY;
THURSDAY := 4;
IF (DAYOFWEEK(1,1,YR) = THURSDAY) OR
(DAYOFWEEK(12,31,YR) = THURSDAY) THEN
ISLONGYEAR := 1
ELSE
ISLONGYEAR := 0;
END;
 
% MAIN PROGRAM STARTS HERE %
INTEGER YEAR;
WRITE("ISO YEARS THAT WILL BE LONG IN THIS CENTURY:");
WRITE("");
FOR YEAR := 2000 STEP 1 UNTIL 2099 DO
BEGIN
IF ISLONGYEAR(YEAR) = 1 THEN WRITEON(YEAR);
END;
 
END
 
Output:
ISO YEARS THAT WILL BE LONG IN THIS CENTURY:
  2004  2009  2015  2020  2026  2032  2037  2043  2048  2054  2060  2065  2071 2076
  2082  2088  2093  2099


AppleScript[edit]

on isLongYear(y)
-- ISO8601 weeks begin on Mondays and belong to the year in which they have the most days.
-- A year which begins on a Thursday, or which begins on a Wednesday and is a leap year,
-- has majority stakes in the weeks it overlaps at *both* ends and so has 53 weeks instead of 52.
-- Leap years divisible by 400 begin on Saturdays and so don't so need to be considered in the leap year check.
 
tell (current date) to set {Jan1, its day, its month, its year} to {it, 1, January, y}
set startWeekday to Jan1's weekday
 
return ((startWeekday is Thursday) or ((startWeekday is Wednesday) and (y mod 4 is 0) and (y mod 100 > 0)))
end isLongYear
 
set longYears to {}
repeat with y from 2001 to 2100
if (isLongYear(y)) then set end of longYears to y
end repeat
 
return longYears
Output:
{2004, 2009, 2015, 2020, 2026, 2032, 2037, 2043, 2048, 2054, 2060, 2065, 2071, 2076, 2082, 2088, 2093, 2099}

On the other hand, since the cycle repeats every 400 years, it's possible to cheat with a precalculated look-up list:

on isLongYear(y)
return (y mod 400 is in {4, 9, 15, 20, 26, 32, 37, 43, 48, 54, 60, 65, 71, 76, 82, 88, 93, 99, 105, 111, 116, 122, 128, 133, 139, 144, 150, 156, 161, 167, 172, 178, 184, 189, 195, 201, 207, 212, 218, 224, 229, 235, 240, 246, 252, 257, 263, 268, 274, 280, 285, 291, 296, 303, 308, 314, 320, 325, 331, 336, 342, 348, 353, 359, 364, 370, 376, 381, 387, 392, 398})
end isLongYear
 
set longYears to {}
repeat with y from 2001 to 2100
if (isLongYear(y)) then set end of longYears to y
end repeat
 
return longYears

AWK[edit]

 
# syntax: GAWK -f LONG_YEAR.AWK
BEGIN {
for (cc=19; cc<=21; cc++) {
printf("%2d00-%2d99: ",cc,cc)
for (yy=0; yy<=99; yy++) {
ccyy = sprintf("%02d%02d",cc,yy)
if (is_long_year(ccyy)) {
printf("%4d ",ccyy)
}
}
printf("\n")
}
#
printf("\n%4d-%4d: ",by=1970,ey=2037)
for (y=by; y<=ey; y++) {
if (strftime("%V",mktime(sprintf("%d 12 28 0 0 0",y))) == 53) {
printf("%4d ",y)
}
}
printf("\n")
exit(0)
}
function is_long_year(year, i) {
for (i=0; i<=1; i++) {
year -= i
if ((year + int(year/4) - int(year/100) + int(year/400)) % 7 == 4-i) {
return(1)
}
}
return(0)
}
 
Output:
1900-1999: 1903 1908 1914 1920 1925 1931 1936 1942 1948 1953 1959 1964 1970 1976 1981 1987 1992 1998
2000-2099: 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
2100-2199: 2105 2111 2116 2122 2128 2133 2139 2144 2150 2156 2161 2167 2172 2178 2184 2189 2195

1970-2037: 1970 1976 1981 1987 1992 1998 2004 2009 2015 2020 2026 2032 2037

C#[edit]

using static System.Console;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
 
public static class Program
{
public static void Main()
{
WriteLine("Long years in the 21st century:");
WriteLine(string.Join(" ", 2000.To(2100).Where(y => ISOWeek.GetWeeksInYear(y) == 53)));
}
 
public static IEnumerable<int> To(this int start, int end) {
for (int i = start; i < end; i++) yield return i;
}
 
}
Output:
Long years in the 21st century:
2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099

C++[edit]

// Reference:
// https://en.wikipedia.org/wiki/ISO_week_date#Weeks_per_year
 
#include <iostream>
 
inline int p(int year) {
return (year + (year/4) - (year/100) + (year/400)) % 7;
}
 
bool is_long_year(int year) {
return p(year) == 4 || p(year - 1) == 3;
}
 
void print_long_years(int from, int to) {
for (int year = from, count = 0; year <= to; ++year) {
if (is_long_year(year)) {
if (count > 0)
std::cout << ((count % 10 == 0) ? '\n' : ' ');
std::cout << year;
++count;
}
}
}
 
int main() {
std::cout << "Long years between 1800 and 2100:\n";
print_long_years(1800, 2100);
std::cout << '\n';
return 0;
}
Output:
Long years between 1800 and 2100:
1801 1807 1812 1818 1824 1829 1835 1840 1846 1852
1857 1863 1868 1874 1880 1885 1891 1896 1903 1908
1914 1920 1925 1931 1936 1942 1948 1953 1959 1964
1970 1976 1981 1987 1992 1998 2004 2009 2015 2020
2026 2032 2037 2043 2048 2054 2060 2065 2071 2076
2082 2088 2093 2099

Clojure[edit]

(defn long-year? [year] 
(-> (java.time.LocalDate/of year 12 28)
(.get (.weekOfYear (java.time.temporal.WeekFields/ISO)))
(= 53)))
 
(filter long-year? (range 2000 2100))
Output:
(2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099)

Dc[edit]

Translation of: Tcl
Works with: GNU dc version 1.3.95
[0q]s0
[1q]s1
[1r- r 1r- * 1r-]sO # O = logical OR
##.............................................................................
# C: for( initcode ; condcode ; incrcode ) {body}
# .[q] [1] [2] [3] [4]
# # [initcode] [condcode] [incrcode] [body] (for)
[ [q]S. 4:.3:.2:.x [2;.x 0=. 4;.x 3;.x 0;.x]d0:.x
Os.L.o
]sF # F = for
##.............................................................................
# [1] [0]
# (.) [cond_code] [then_code] [else_code] (if_CTE)
[ []S. 0:. 1:. x [0=0 1]x ;. s.L. x]sI # I = if
##-----------------------------------------------------------------------------
[S. l. l.4/+ l.100/- l.400/+ 7% s.L.]sp # p
##.............................................................................
[S. [l. lpx 4=1 0]x
[l. 1- lpx 3=1 0]x lOx
s.L.
]si # i = is_long_year
##.............................................................................
[
# f = from
# t = to
# y = year
# c = count
st sf # fetch args from stack
[lfsy 0sc]
[ly lt <0 1] # cond
[ly 1+ sy] # incr y
[
[ly lix] # is_long_year(y)
[
[lc 0 <1 0] # 0<c
[
[ lc 10% 0=1 0] # (c % 10) == 0
[ AP ]
[ [ ]P ]
lIx # if
]
[]
lIx # if
ly n
lc 1+ sc
]
[]
lIx # if
] lFx # for
]sD # D = doit = print_long_years
##.............................................................................
 
[Long years between 1800 and 2100:]P AP
1800 2100 lDx
AP
Output:
Long years between 1800 and 2100:
1801 1807 1812 1818 1824 1829 1835 1840 1846 1852
1857 1863 1868 1874 1880 1885 1891 1896 1903 1908
1914 1920 1925 1931 1936 1942 1948 1953 1959 1964
1970 1976 1981 1987 1992 1998 2004 2009 2015 2020
2026 2032 2037 2043 2048 2054 2060 2065 2071 2076
2082 2088 2093 2099

Factor[edit]

Works with: Factor version 0.99 2019-10-06
USING: calendar formatting io kernel math.ranges sequences ;
 
: long-year? ( n -- ? ) 12 28 <date> week-number 53 = ;
 
"Year Long?\n-----------" print 1990 2021 [a,b]
[ dup long-year? "yes" "no" ? "%d  %s\n" printf ] each
Output:
Year  Long?
-----------
1990  no
1991  no
1992  yes
1993  no
1994  no
1995  no
1996  no
1997  no
1998  yes
1999  no
2000  no
2001  no
2002  no
2003  no
2004  yes
2005  no
2006  no
2007  no
2008  no
2009  yes
2010  no
2011  no
2012  no
2013  no
2014  no
2015  yes
2016  no
2017  no
2018  no
2019  no
2020  yes
2021  no

Go[edit]

package main
 
import (
"fmt"
"time"
)
 
func main() {
centuries := []string{"20th", "21st", "22nd"}
starts := []int{1900, 2000, 2100}
for i := 0; i < len(centuries); i++ {
var longYears []int
fmt.Printf("\nLong years in the %s century:\n", centuries[i])
for j := starts[i]; j < starts[i] + 100; j++ {
t := time.Date(j, time.December, 28, 0, 0, 0, 0, time.UTC)
if _, week := t.ISOWeek(); week == 53 {
longYears = append(longYears, j)
}
}
fmt.Println(longYears)
}
}
Output:
Long years in the 20th century:
[1903 1908 1914 1920 1925 1931 1936 1942 1948 1953 1959 1964 1970 1976 1981 1987 1992 1998]

Long years in the 21st century:
[2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099]

Long years in the 22nd century:
[2105 2111 2116 2122 2128 2133 2139 2144 2150 2156 2161 2167 2172 2178 2184 2189 2195]

Haskell[edit]

import Data.Time.Calendar.WeekDate (toWeekDate)
import Data.Time.Calendar (fromGregorian)
 
longYear :: Integer -> Bool
longYear y = 52 < w
where
(_, w, _) = toWeekDate $ fromGregorian y 12 28
 
main :: IO ()
main = mapM_ print $ filter longYear [2000 .. 2100]
Output:
2004
2009
2015
2020
2026
2032
2037
2043
2048
2054
2060
2065
2071
2076
2082
2088
2093
2099

Java[edit]

 
import java.time.LocalDate;
import java.time.temporal.WeekFields;
 
public class LongYear {
 
public static void main(String[] args) {
System.out.printf("Long years this century:%n");
for (int year = 2000 ; year < 2100 ; year++ ) {
if ( longYear(year) ) {
System.out.print(year + " ");
}
}
}
 
private static boolean longYear(int year) {
return LocalDate.of(year, 12, 28).get(WeekFields.ISO.weekOfYear()) == 53;
}
 
}
 
Output:
Long years this century:
2004  2009  2015  2020  2026  2032  2037  2043  2048  2054  2060  2065  2071  2076  2082  2088  2093  2099  

Julia[edit]

using Dates
 
has53weeks(year) = week(Date(year, 12, 28)) == 53
 
println(" Year 53 weeks?\n----------------")
for year in 1990:2021
println(year, " ", has53weeks(year) ? "Yes" : "No")
end
 
Output:
 Year  53 weeks?
----------------
1990   No
1991   No
1992   Yes
1993   No
1994   No
1995   No
1996   No
1997   No
1998   Yes
1999   No
2000   No
2001   No
2002   No
2003   No
2004   Yes
2005   No
2006   No
2007   No
2008   No
2009   Yes
2010   No
2011   No
2012   No
2013   No
2014   No
2015   Yes
2016   No
2017   No
2018   No
2019   No
2020   Yes
2021   No

Perl[edit]

use strict;
use warnings;
use DateTime;
 
for my $century (19 .. 21) {
for my $year ($century*100 .. ++$century*100 - 1) {
print "$year " if DateTime->new(year => $year, month => 12, day => 28)->week_number > 52
}
print "\n";
}
Output:
1903 1908 1914 1920 1925 1931 1936 1942 1948 1953 1959 1964 1970 1976 1981 1987 1992 1998
2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
2105 2111 2116 2122 2128 2133 2139 2144 2150 2156 2161 2167 2172 2178 2184 2189 2195

Phix[edit]

Requires 0.8.1+

include builtins\ordinal.e 
 
function week_number(integer y,m,d)
integer doy = day_of_year(y,m,d),
dow = day_of_week(y,m,d),
week = floor((doy-dow+10)/7)
return week
end function
 
for c=20 to 22 do
sequence long_years = {}
integer century = (c-1)*100
for year=century to century+99 do
if week_number(year,12,28)=53 then
long_years &= year
end if
end for
printf(1,"Long years in the %d%s century:%v\n", {c,ord(c),long_years})
end for
Output:
Long years in the 20th century:{1903,1908,1914,1920,1925,1931,1936,1942,1948,1953,1959,1964,1970,1976,1981,1987,1992,1998}
Long years in the 21st century:{2004,2009,2015,2020,2026,2032,2037,2043,2048,2054,2060,2065,2071,2076,2082,2088,2093,2099}
Long years in the 22nd century:{2105,2111,2116,2122,2128,2133,2139,2144,2150,2156,2161,2167,2172,2178,2184,2189,2195}

Python[edit]

Works with: Python version 3.7
'''Long Year ?'''
 
from datetime import date
 
 
# longYear :: Year Int -> Bool
def longYear(y):
'''True if the ISO year y has 53 weeks.'''
return 52 < date(y, 12, 28).isocalendar()[1]
 
 
# --------------------------TEST---------------------------
# main :: IO ()
def main():
'''Longer (53 week) years in the range 2000-2100'''
for year in [
x for x in range(2000, 1 + 2100)
if longYear(x)
]:
print(year)
 
 
# MAIN ---
if __name__ == '__main__':
main()
Output:
2004
2009
2015
2020
2026
2032
2037
2043
2048
2054
2060
2065
2071
2076
2082
2088
2093
2099

Raku[edit]

(formerly Perl 6)

Works with: Rakudo version 2019.11

December 28 is always in the last week of the year. (By ISO8601)

sub is-long ($year) { Date.new("$year-12-28").week[1] == 53 }
 
# Testing
say "Long years in the 20th century:\n", (1900..^2000).grep: *.&is-long;
say "\nLong years in the 21st century:\n", (2000..^2100).grep: *.&is-long;
say "\nLong years in the 22nd century:\n", (2100..^2200).grep: *.&is-long;
Output:
Long years in the 20th century:
(1903 1908 1914 1920 1925 1931 1936 1942 1948 1953 1959 1964 1970 1976 1981 1987 1992 1998)

Long years in the 21st century:
(2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099)

Long years in the 22nd century:
(2105 2111 2116 2122 2128 2133 2139 2144 2150 2156 2161 2167 2172 2178 2184 2189 2195)

REXX[edit]

/*REXX program determines if a (calendar) year is a SHORT or LONG year (52 or 53 weeks).*/
parse arg LO HI . /*obtain optional args. */
if LO=='' | LO=="," | LO=='*' then LO= left( date('S'), 4) /*Not given? Use default.*/
if HI=='' | HI=="," then HI= LO /* " " " " */
if HI=='*' then HI= left( date('S'), 4) /*an asterisk ≡ current yr*/
do j=LO to HI /*process single yr or range of years.*/
say ' year ' j " is a " right( word('short long', weeks(j)-51),5) " year"
end /*j*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
pWeek: parse arg yr; return (yr + yr%4 - yr%100 + yr%400) // 7 /*calculate P*/
weeks: parse arg y; $= 52; if pWeek(y)==4 | pWeek(y-1)==3 then $= $ + 1; return $
output   when using the inputs of:     1990   2030

(Shown at three-quarter size.)

     year  1990  is a  short  year
     year  1991  is a  short  year
     year  1992  is a   long  year
     year  1993  is a  short  year
     year  1994  is a  short  year
     year  1995  is a  short  year
     year  1996  is a  short  year
     year  1997  is a  short  year
     year  1998  is a   long  year
     year  1999  is a  short  year
     year  2000  is a  short  year
     year  2001  is a  short  year
     year  2002  is a  short  year
     year  2003  is a  short  year
     year  2004  is a   long  year
     year  2005  is a  short  year
     year  2006  is a  short  year
     year  2007  is a  short  year
     year  2008  is a  short  year
     year  2009  is a   long  year
     year  2010  is a  short  year
     year  2011  is a  short  year
     year  2012  is a  short  year
     year  2013  is a  short  year
     year  2014  is a  short  year
     year  2015  is a   long  year
     year  2016  is a  short  year
     year  2017  is a  short  year
     year  2018  is a  short  year
     year  2019  is a  short  year
     year  2020  is a   long  year
     year  2021  is a  short  year
     year  2022  is a  short  year
     year  2023  is a  short  year
     year  2024  is a  short  year
     year  2025  is a  short  year
     year  2026  is a   long  year
     year  2027  is a  short  year
     year  2028  is a  short  year
     year  2029  is a  short  year
     year  2030  is a  short  year

Ruby[edit]

 
require 'date'
 
def long_year?(year = Date.today.year)
Date.new(year, 12, 28).cweek == 53
end
 
(2020..2030).each{|year| puts "#{year} is long? #{ long_year?(year) }." }
 
Output:
2020 is long? true.
2021 is long? false.
2022 is long? false.
2023 is long? false.
2024 is long? false.
2025 is long? false.
2026 is long? true.
2027 is long? false.
2028 is long? false.
2029 is long? false.
2030 is long? false.

S-Basic[edit]

 
$lines
 
rem - compute p mod q
function mod(p, q = integer) = integer
end = p - q * (p/q)
 
comment
return day of week (Sun = 0, Mon = 1, etc.) for a
given Gregorian calendar date using Zeller's congruence
end
function dayofweek (mo, da, yr = integer) = integer
var y, c, z = integer
if mo < 3 then
begin
mo = mo + 10
yr = yr - 1
end
else mo = mo - 2
y = mod(yr,100)
c = int(yr / 100)
z = int((26 * mo - 2) / 10)
z = z + da + y + int(y/4) + int(c/4) - 2 * c + 777
z = mod(z,7)
end = z
 
comment
The simplest of several possible tests is that
any calendar year starting or ending on a
Thursday is "long", i.e., has 53 ISO weeks
end
function islongyear(yr = integer) = integer
var thursday, result = integer
thursday = 4
if (dayofweek(1,1,yr) = thursday) or \
(dayofweek(12,31,yr) = thursday) then
result = -1 rem "true"
else
result = 0 rem "false"
end = result
 
rem - main program begins here
 
var year = integer
print "ISO years that will be long in this century:"
for year = 2000 to 2099
if islongyear(year) then print year;
next year
 
end
Output:
ISO years that will be long in this century:
 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088
 2093 2099

Scala[edit]

Output:
Best seen running in your browser by Scastie (remote JVM).
import java.time.temporal.TemporalAdjusters.firstInMonth
import java.time.temporal.{ChronoField, IsoFields}
import java.time.{DayOfWeek, LocalDate, Month}
 
import scala.util.{Failure, Try}
 
private object LongYear extends App {
private val (currentCentury, maxWeekNumber) = (LocalDate.now().getYear / 100, ChronoField.ALIGNED_WEEK_OF_YEAR.range().getMaximum)
private val centuries = currentCentury * 100 until (currentCentury + 1) * 100
private val results = List(
centuries.filter(isThursdayFirstOrLast),
centuries.filter(year => maxIsoWeeks(year) == maxWeekNumber),
centuries.filter(mostThursdaysInYear)
)
 
// Solution 1, the first or respectively last day of the year is a Thursday.
private def isThursdayFirstOrLast(_year: Int): Boolean = {
 
LocalDate.of(_year, Month.DECEMBER, 31).get(ChronoField.DAY_OF_WEEK) == DayOfWeek.THURSDAY.getValue ||
LocalDate.of(_year, Month.JANUARY, 1).get(ChronoField.DAY_OF_WEEK) == DayOfWeek.THURSDAY.getValue
}
 
// Solution 2, if last week that contains at least four days of the month of December.
private def maxIsoWeeks(_year: Int) = {
// The last week that contains at least four days of the month of December.
LocalDate.of(_year, Month.DECEMBER, 28).get(IsoFields.WEEK_OF_WEEK_BASED_YEAR)
}
 
// Solution 3, if there are 52 Thursdays in a year
private def mostThursdaysInYear(_year: Int) = {
val datum = LocalDate.of(_year, Month.JANUARY, 1).`with`(firstInMonth(DayOfWeek.THURSDAY))
 
datum.plusDays(52 * 7).getYear == _year
}
 
println(s"Years in this ${currentCentury + 1}st century having ISO week $maxWeekNumber :")
 
Try { // Testing the solutions
assert(results.tail.forall(_ == results.head), "Discrepancies in results.")
} match {
case Failure(ex) => Console.err.println(ex.getMessage)
case _ =>
}
 
results.zipWithIndex.foreach(solution => println(s"Solution ${solution._2}: ${solution._1.mkString(" ")}"))
 
}

Swift[edit]

func isLongYear(_ year: Int) -> Bool {
let year1 = year - 1
let p = (year + (year / 4) - (year / 100) + (year / 400)) % 7
let p1 = (year1 + (year1 / 4) - (year1 / 100) + (year1 / 400)) % 7
 
return p == 4 || p1 == 3
}
 
for range in [1900...1999, 2000...2099, 2100...2199] {
print("\(range): \(range.filter(isLongYear))")
}
Output:
1900...1999: [1903, 1908, 1914, 1920, 1925, 1931, 1936, 1942, 1948, 1953, 1959, 1964, 1970, 1976, 1981, 1987, 1992, 1998]
2000...2099: [2004, 2009, 2015, 2020, 2026, 2032, 2037, 2043, 2048, 2054, 2060, 2065, 2071, 2076, 2082, 2088, 2093, 2099]
2100...2199: [2105, 2111, 2116, 2122, 2128, 2133, 2139, 2144, 2150, 2156, 2161, 2167, 2172, 2178, 2184, 2189, 2195]

Tcl[edit]

Translation of: C++
 
## Reference: https://en.wikipedia.org/wiki/ISO_week_date#Weeks_per_year
 
proc p {year} {
return [expr {($year + ($year/4) - ($year/100) + ($year/400)) % 7}]
}
 
proc is_long_year {year} {
return [expr {[p $year] == 4 || [p [expr {$year - 1}]] == 3}]
}
 
proc print_long_years {from to} {
for {set year $from; set count 0} {$year <= $to} {incr year} {
if {[is_long_year $year]} {
if {$count > 0} {
puts -nonewline [expr {($count % 10 == 0) ? "\n" : " "}]
}
puts -nonewline $year
incr count
}
}
}
 
puts "Long years between 1800 and 2100:"
print_long_years 1800 2100
puts ""
Output:
Long years between 1800 and 2100:
1801 1807 1812 1818 1824 1829 1835 1840 1846 1852
1857 1863 1868 1874 1880 1885 1891 1896 1903 1908
1914 1920 1925 1931 1936 1942 1948 1953 1959 1964
1970 1976 1981 1987 1992 1998 2004 2009 2015 2020
2026 2032 2037 2043 2048 2054 2060 2065 2071 2076
2082 2088 2093 2099

Visual Basic[edit]

Works with: Visual Basic version 5
Works with: Visual Basic version 6
Works with: VBA version Access 97
Works with: VBA version 6.5
Works with: VBA version 7.1
Option Explicit
 
Function IsLongYear(ByVal Year As Integer) As Boolean
Select Case vbThursday
Case VBA.DatePart("w", VBA.DateSerial(Year, 1, 1)), _
VBA.DatePart("w", VBA.DateSerial(Year, 12, 31))
IsLongYear = True
End Select
End Function
 
Sub Main()
'test
Dim l As Long
For l = 1990 To 2021
Select Case l
Case 1992, 1998, 2004, 2009, 2015, 2020
Debug.Assert IsLongYear(l)
Case Else
Debug.Assert Not IsLongYear(l)
End Select
Next l
End Sub
 

zkl[edit]

fcn isLongYear(y){ Time.Date.weeksInYear(y)==53 }
foreach nm,y in (T(T("20th",1900), T("21st",2000), T("22nd",2100))){
println("\nLong years in the %s century:\n%s".fmt(nm,
[y..y+99].filter(isLongYear).concat(" ")));
}
Output:
Long years in the 20th century:
1903 1908 1914 1920 1925 1931 1936 1942 1948 1953 1959 1964 1970 1976 1981 1987 1992 1998

Long years in the 21st century:
2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099

Long years in the 22nd century:
2105 2111 2116 2122 2128 2133 2139 2144 2150 2156 2161 2167 2172 2178 2184 2189 2195