Greetings.  I made this change in two stages hence two commits, but I
think it makes more sense to combine them into one commit. 
Unfortunately, I am not a master of git and I don't know how.  I can use
git diff to combine the changes, but git format-patch wants to do one
patch per commit.

It is attached.

-- 
http://www.fastmail.com - Accessible with your email software
                          or over the web

From 715bf6068f98089a03ca2beb38facbe568ac07ff Mon Sep 17 00:00:00 2001
From: Greg Reagle <greg.rea...@umbc.edu>
Date: Thu, 8 Jan 2015 17:16:19 -0500
Subject: [PATCH 1/2] Julian when month is Sep 1752 or before. Gregorian when
 month is Oct 1752 or after.

---
 cal.1 |  1 +
 cal.c | 22 +++++++++++++++++-----
 2 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/cal.1 b/cal.1
index c215340..659d46a 100644
--- a/cal.1
+++ b/cal.1
@@ -28,6 +28,7 @@ of calendars side by side. Each row of calendars contains at most
 .IR columns
 number of calendars. The defaults are obtained using
 .IR localtime (3).
+The Julian calendar is used for Septmeber 1752 and before.  Starting with October 1752, the Gregorian calendar is used.
 .SH OPTIONS
 .TP
 .B \-1
diff --git a/cal.c b/cal.c
index 53c6022..a000843 100644
--- a/cal.c
+++ b/cal.c
@@ -5,6 +5,9 @@
 
 #include "util.h"
 
+enum caltype {Julian, Gregorian};
+enum {Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec};
+
 static int
 isleap(int year)
 {
@@ -19,27 +22,36 @@ static int
 monthlength(int year, int month)
 {
 	int mdays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-	return (month==1 && isleap(year))  ?  29  :  mdays[month];
+	return (month==Feb && isleap(year))  ?  29  :  mdays[month];
 }
 
 /* From http://www.tondering.dk/claus/cal/chrweek.php#calcdow */
 static int
-dayofweek(int year, int month, int dom)
+dayofweek(int year, int month, int dom, enum caltype cal)
 {
 	int m, y, a;
 	month += 1;  /*  in this formula, 1 <= month <= 12  */
 	a = (14 - month) / 12;
 	y = year - a;
 	m = month + 12*a - 2;
-	return (dom + y + y/4 - y/100 + y/400 +((31*m)/12)) % 7;
+
+	if (cal == Gregorian)
+		return (dom + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
+	else  /* cal == Julian */
+		return (5 + dom + y + y/4 + (31*m)/12) % 7;
 }
 
 static void
 printgrid(int year, int month, int fday, int line)
 {
-	int dom, offset, d=0;
+	enum caltype cal, offset, dom, d=0;
+
+	if (year < 1752 || (year == 1752 && month <= Sep))
+		cal = Julian;
+	else 
+		cal = Gregorian;
+	offset = dayofweek(year, month, 1, cal) - fday;
 
-	offset = dayofweek(year, month, 1) - fday;
 	if (offset < 0)
 		offset += 7;
 	if (line==1) {
-- 
2.2.1


From 3520c5cccb9958a056e4885108060bdf8ed03526 Mon Sep 17 00:00:00 2001
From: Greg Reagle <greg.rea...@umbc.edu>
Date: Tue, 13 Jan 2015 12:37:30 -0500
Subject: [PATCH 2/2] Using the Julian calendar for dates through September 2,
 1752 and the Gregorian calendar for dates from September 14, 1752.

---
 cal.1 |  4 +++-
 cal.c | 39 ++++++++++++++++++++++++++-------------
 2 files changed, 29 insertions(+), 14 deletions(-)

diff --git a/cal.1 b/cal.1
index 659d46a..8619460 100644
--- a/cal.1
+++ b/cal.1
@@ -28,7 +28,7 @@ of calendars side by side. Each row of calendars contains at most
 .IR columns
 number of calendars. The defaults are obtained using
 .IR localtime (3).
-The Julian calendar is used for Septmeber 1752 and before.  Starting with October 1752, the Gregorian calendar is used.
+The Julian calendar is used through Sep 2, 1752, and the Gregorian calendar is used starting the next day with Sep 14, 1752.
 .SH OPTIONS
 .TP
 .B \-1
@@ -58,3 +58,5 @@ Specify the first day of the week. 0 is Sunday and 6 is Saturday.
 Specify the number months to print. The default is 1.
 .SH SEE ALSO
 .IR localtime (3)
+.SH STANDARDS
+This program tries to conform to IEEE Std 1003.1, 2013 Edition, q.v. http://pubs.opengroup.org/onlinepubs/9699919799/utilities/cal.html.
diff --git a/cal.c b/cal.c
index a000843..a493ec9 100644
--- a/cal.c
+++ b/cal.c
@@ -5,24 +5,30 @@
 
 #include "util.h"
 
-enum caltype {Julian, Gregorian};
 enum {Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec};
+enum caltype {Julian, Gregorian};
+enum {TRANS_YEAR = 1752, TRANS_MONTH = Sep, TRANS_DAY = 2};
 
 static int
-isleap(int year)
+isleap(int year, enum caltype cal)
 {
-	if (year % 400 == 0)
-		return 1;
-	if (year % 100 == 0)
-		return 0;
-	return (year % 4 == 0);
+	if (cal == Gregorian) {
+		if (year % 400 == 0)
+			return 1;
+		if (year % 100 == 0)
+			return 0;
+		return (year % 4 == 0);
+	}
+	else { /* cal == Julian */
+		return (year % 4 == 0);
+	}
 }
 
 static int
-monthlength(int year, int month)
+monthlength(int year, int month, enum caltype cal)
 {
 	int mdays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-	return (month==Feb && isleap(year))  ?  29  :  mdays[month];
+	return (month==Feb && isleap(year,cal))  ?  29  :  mdays[month];
 }
 
 /* From http://www.tondering.dk/claus/cal/chrweek.php#calcdow */
@@ -44,14 +50,16 @@ dayofweek(int year, int month, int dom, enum caltype cal)
 static void
 printgrid(int year, int month, int fday, int line)
 {
-	enum caltype cal, offset, dom, d=0;
+	enum caltype cal;
+	int trans; /* are we in the transition from Julian to Gregorian? */
+	int offset, dom, d=0;
 
-	if (year < 1752 || (year == 1752 && month <= Sep))
+	if (year < TRANS_YEAR || (year == TRANS_YEAR && month <= TRANS_MONTH))
 		cal = Julian;
 	else 
 		cal = Gregorian;
+	trans = (year == TRANS_YEAR && month == TRANS_MONTH);
 	offset = dayofweek(year, month, 1, cal) - fday;
-
 	if (offset < 0)
 		offset += 7;
 	if (line==1) {
@@ -60,9 +68,14 @@ printgrid(int year, int month, int fday, int line)
 		dom = 1;
 	} else {
 		dom = 8-offset + (line-2)*7;
+		if (trans && !(line==2 && fday==3))
+			dom += 11;
 	}
-	for ( ; d < 7 && dom <= monthlength(year, month); ++d, ++dom)
+	for ( ; d < 7 && dom <= monthlength(year, month, cal); ++d, ++dom) {
 		printf("%2d ", dom);
+		if (trans && dom==TRANS_DAY)
+			dom += 11;
+	}
 	for ( ; d < 7; ++d)
 		printf("   ");
 }
-- 
2.2.1

Reply via email to