In the summer of 1999 I reread *The Lord of the Rings* for perhaps the dozenth time. With that particular reading I studied, *really* studied, Appendix D on the calendrical systems in use in Middle-Earth in the Third Age. I was drawn, in particular, to the Hobbit calendar and decided to write a quick-and-dirty computer program to convert our dates into Hobbit dates.

Today, November 20th, is in Shire Reckoning, the first of Foreyule.

What made me think of this, today, of all days? Maybe it’s playing *The Third Age*, EA’s *Lord of the Rings* turn-based RPG on the XBox. How is the game? I’ll save that for another post.

But for those who want to see the program, after the cut is the BASIC source code. Yes, I wrote it in BASIC. You have a problem with that?

100 CLS

110 GOSUB 1000

120 GOSUB 2000

130 GOSUB 2500

140 REM PRINT “JULIAN DATE”; JL

150 REM PRINT “SHIRE JULIAN DATE”; SJ

160 GOSUB 3000

170 GOSUB 3500

180 GOSUB 4000

190 GOSUB 4500

200 PRINT “Your date is “;W$;”, “;D$

210 REM PRINT DT

999 END

1000 REM Input date

1010 PRINT “Year”;

1020 INPUT Y:Y=INT(Y)

1030 IF Y<0 THEN GOTO 1010

1040 GOSUB 1500

1050 PRINT “Month”;

1060 INPUT M:M=INT(M)

1070 IF M<1 OR M>12 THEN GOTO 1050

1080 PRINT “Day”;

1090 INPUT D:D=INT(D)

1100 IF D<1 THEN GOTO 1080

1110 IF M=2 AND D>28+LP THEN GOTO 1080

1120 IF (M=4 OR M=6 OR M=9 OR M=11) AND D>30 THEN GOTO 1080

1130 IF M>31 THEN GOTO 1080

1140 RETURN

1500 REM Leap Year Check

1510 LP=0

1520 IF Y/4=INT(Y/4) THEN LP=1

1530 IF Y/100=INT(Y/100) THEN LP=0

1540 IF Y/400=INT(Y/400) THEN LP=1

1550 RETURN

2000 REM Julian Date conversion

2010 JL=0

2020 IF M=2 THEN JL=31

2030 IF M=3 THEN JL=59

2040 IF M=4 THEN JL=90

2050 IF M=5 THEN JL=120

2060 IF M=6 THEN JL=151

2070 IF M=7 THEN JL=181

2080 IF M=8 THEN JL=212

2090 IF M=9 THEN JL=243

2100 IF M=10 THEN JL=273

2110 IF M=11 THEN JL=304

2120 IF M=12 THEN JL=334

2130 JL=JL+D

2140 IF M>2 THEN JL=JL+LP

2150 RETURN

2500 REM Shire Julian Date conversion

2510 SJ=0

2520 SJ=JL+11

2530 IF SJ>365+LP THEN SJ=SJ-(365+LP)

2540 RETURN

3000 REM Shire Date calculation

3010 SD=0:SM=0

3020 IF SJ=1 THEN SD=2:SM=13:RETURN

3030 IF SJ=182 THEN SD=1:SM=14:RETURN

3040 IF SJ=183 THEN SM=15:RETURN

3050 IF SJ=184+LP THEN SD=2:SM=14:RETURN

3060 IF SJ=184 AND LP=1 THEN SM=16:RETURN

3070 IF SJ=365+LP THEN SD=1:SM=13:RETURN

3080 SJ=SJ-1

3090 IF SJ>182+LP THEN SJ=SJ-(3+LP)

3100 SM=INT((SJ-1)/30)+1

3110 SD=SJ-((SM-1)*30)

3120 RETURN

3500 REM Shire month string

3510 IF SM=1 THEN M$=”Afteryule”

3520 IF SM=2 THEN M$=”Solmath”

3530 IF SM=3 THEN M$=”Rethe”

3540 IF SM=4 THEN M$=”Astron”

3550 IF SM=5 THEN M$=”Thrimidge”

3560 IF SM=6 THEN M$=”Forelithe”

3570 IF SM=7 THEN M$=”Afterlithe”

3580 IF SM=8 THEN M$=”Wedmath”

3590 IF SM=9 THEN M$=”Halimath”

3600 IF SM=10 THEN M$=”Winterfilth”

3610 IF SM=11 THEN M$=”Blotmath”

3620 IF SM=12 THEN M$=”Foreyule”

3630 IF SM=13 THEN M$=”Yule”

3640 IF SM=14 THEN M$=”Lithe”

3650 IF SM=15 THEN M$=”Midyear’s Day”

3660 IF SM=16 THEN M$=”Overlithe”

3670 RETURN

4000 REM Create date string

4010 D$=””

4020 IF SM>14 THEN D$=M$:RETURN

4030 D$=STR$(SD)+” “+M$

4040 RETURN

4500 REM Shire day of week calculation

4510 GOSUB 2500

4520 DT=0

4530 IF SJ=183 OR (SJ=184 AND LP=1) THEN DT=8:RETURN

4535 IF SJ>183 THEN SJ=SJ-LP-1

4540 DT=SJ-7*INT(SJ/7)

4550 IF DT=0 THEN W$=”Highday”

4560 IF DT=1 THEN W$=”Sterday”

4570 IF DT=2 THEN W$=”Sunday”

4580 IF DT=3 THEN W$=”Monday”

4590 IF DT=4 THEN W$=”Trewsday”

4600 IF DT=5 THEN W$=”Hevensday”

4610 IF DT=6 THEN W$=”Mersday”

4620 RETURN

Had a bit of a problem because you have some curly quotes in there, and QBasic isn’t too fond of that. But once I sorted those out with Notepad, I managed to learn that I was born on Hevensday, 18 Afterlithe. Which is somewhat disturbing. “Heaven” and “afterlife”?

Steve

Feh. I don’t think I even have QBasic on this machine. So I ported it to C++. Kinda. ‘Cause it doesn’t quite work. And I don’t feel like debugging it right now. 🙂

(BTW, line 1130 ought to be “d>31”. And you called the subroutine starting at 2500 twice, which won’t do anything. :))

Andrew, thank you for the error catch on line 1130. In five years I hadn’t noticed that. Shire.bas is now updated. 🙂

As for the subroutine at line 2500, I disagree strongly that it “won’t do anything.” I admit I’m biased, but I think the subroutine is absolutely vital for accuracy’s sake in the date conversion process.

Let’s examine what it does. The REM comment in line 2500 calls it “Shire Julian Date Conversion.” A cryptic comment, true. The subroutine at line 2000 converts the inputed date into a Julian number, counting forward from the beginning of the year. So, what is the conversion?

Let’s turn to Professor Tolkien. We writes in Appendix D, “It appears that Mid-Year’s Day was intended to correspond as nearly as possible to the summer solstice. In that case Shire Dates were actually in advance of ours by some ten days, and our New Year’s Day corresponded more or less to the Shire January 9.” On that assumption Mid-Year’s Day should be the equivalent of June 21st. I worked backwards from that–I knew what my output should be, and so generated some calculations to generate the pre-determined result–and found that Tolkien was incorrect–the calendars are off by eleven days, not ten.

Looking at the subroutine, line 2510 is pointless, as the variable SJ (Shire Julian) is defined in line 2520 by taking JL (our Julian date) and adding eleven days. Line 2530 then “rolls over” dates at the end of our year to the beginning of the Hobbit year. If you unREMark lines 140 and 150 the program will output the two Julian dates–ours and the Hobbit’s–for comparison’s sake.

Why call the subroutine twice? The simplest explanation–and I’m drawing back five years here–is that the Hobbit calendar has days that fall outside of both weeks and months, hence the need to remove days from the Shire Julian date to simplify both the Hobbit week and month calculations.

I wouldn’t call shire.bas an elegent program. It does what I wanted it to do–take our dates and make a reasonable calculation as to where they would fall on the Hobbit calendar. Which the program does. 🙂

Oh, I realized that the first call did something. It was the second call that I thought wouldn’t do anything–unless JL is changing, which I don’t see it doing after the initial call. *shrug* Then again, my version doesn’t work (albeit for other reasons), and yours does, so you win. 🙂

And you’re right, it’s not elegant–but then, very little BASIC is. 🙂

JL doesn’t change. SJ

doeschange, hence the two calls to subroutine 2500.The first time the subroutine is called the program pulls out the non-month days in subroutine 3000, subtracting from SJ in lines 3080 and 3090.

The second time the program calls subroutine 2500 occurs later, in subroutine 4500 when the program figures out the day of the week. Because the value for SJ was no longer accurate because of previous calculations, the program recalculates SJ from JL.

I’m trying to remember why I set the program up in such a fashion. I think the day of the week calculation was a late idea, something I hadn’t initially planned upon.

I always meant to rewrite the program in Pascal. One of these days….