Tuesday, 2017 March 28 9:01 PM MDT — Arvada, Colorado UNITED STATES

So, the last time that I wrote anything here… was 2015. I think that it's about time to admit that my project of recreating PC Globe isn't happening.

I did make some progress. I managed to make a [map-projection demonstrator](/Features/MapSVG.html), and I managed to create (by hand!) SVG flags for many countries (despite the fact that [Wikipedia](https://en.wikipedia.org/wiki/Gallery_of_sovereign_state_flags) has a list of **every single flag that I would have ever needed**).

I've decided at this point that I'm never going to end up finishing it.

However, over the past… six months, I did start a new software project that's pretty much already done, so all that remains is to write blog posts about it.

Sunday, 2015 January 18 7:45 PM MST — Arvada, Colorado UNITED STATES

So, I've had computer trouble lately. My laptop died, and I had nothing backed up. Fortunately, I purchased a replacement, and I was able to recover my data in spite of the fact that I had nothing backed up. That is a mistake that I won't let happen again.

Anyway, we're well past the holidays at this point. However, due to the aforementioned computer problems and just general laziness on my part, I'm finally getting around to throwing up another blog post that I meant to throw up during the holidays. This Christmas, I managed to get three of my nieces a globe as a present. Perhaps the gift says more about me than it does my nieces: the oldest of the nieces is four years old. When I was about four years old (back in 1990), my father installed a neat computer program on our 25 MHz, 386 personal computer: [PC Globe](https://en.wikipedia.org/wiki/PC_Globe). That, combined with other geographic artifacts such as [Where In The World Is Carmen Sandiego?](https://en.wikipedia.org/wiki/Where_in_the_World_Is_Carmen_Sandiego?_(1985)) and a real globe that my grandmother bought for my brother, began a hopeless descent into the world of geography nerdism that still haunts me today.

Anyway, PC Globe: it was a DOS program that was a cross between an atlas and a statistics book containing data on various countries. It had a slick (for the time) point-and-shoot interface; you pointed the mouse cursor over a country on a map and clicked the mouse button. Up popped information about the country that you clicked on: population estimates, age distribution, GNP, languages spoken, ethnic groups, religions, imports, exports… you get the idea. One very neat feature was that you could even get it to display the country's flag while it simultaneously played that country's national anthem on [the computer's shitty internal speaker](https://en.wikipedia.org/wiki/PC_speaker).

I still have a copy of the program. However, it has to be run it through [DOSBox](http://www.dosbox.com/) because of technical issues. I run it purely for nostalgia purposes; it's entirely useless as a usable tool in this day of age mostly because it's out of date. Remember how I said 1990? If you remember correctly, that was during a period of transition. The [Berlin Wall](http://www.smithsonianmag.com/history/amazing-rare-photographs-berlin-wall-coming-down-180953278/) fell in 1989, and [the Soviet Union collapsed](https://en.wikipedia.org/wiki/Dissolution_of_the_Soviet_Union) in 1991. I remember, after being told that the USSR had broken up into smaller countries, calling my father at his workplace to ask him if he could “draw lines across Russia” in PC Globe once he came home from work.

He never did. As disappointed as I was then (*i.e.*, I wasn't), it's entirely understandable to me know how my father didn't want to spend hours hacking someone else's proprietary software… even though he was a computer programmer. Even if he wanted to, [writing software back then was incredibly different](http://thecodist.com/article/what_writing_and_selling_software_was_like_in_the_80_39_s); mainly, there was no World Wide Web to rely on: that means no Google, no Stack Overflow and no way to download all of the free programming tools… and then there's data. PC Globe wasn't just an electronic atlas: it was a database of *a ton* of information about each country. We don't appreciate enough the fact that, before Wikipedia, we had paper encyclopaedias. If you wanted up-to-date information, you had to purchase a new set.

Today, none of those limitations exist, so I can finally set out to break the Soviet Union apart. However, rather than tweak the original program, I'm going to recreate my own atlas and database. It's probably going to be an overwhelming task to begin with. Then, once I'm finished, I have the impossible task of… keeping the information up to date.

Yeah.

My finished result probably isn't going to be a perfect clone of PC Globe. I wouldn't want to recreate it exactly anyway even if I could. Besides, this project isn't about the product; it's more just for fun… and nostalgia.

![screenshot](/Media/Weblog/2015-01-18/PCGlobe0.png)

![screenshot](/Media/Weblog/2015-01-18/PCGlobe2.png)

![screenshot](/Media/Weblog/2015-01-18/PCGlobe3.png)

![screenshot](/Media/Weblog/2015-01-18/PCGlobe4.png)

![screenshot](/Media/Weblog/2015-01-18/PCGlobe5.png)

Saturday, 2014 November 22 10:18 PM MST — Arvada, Colorado UNITED STATES

Let's talk about math. If math scares you, don't worry: we're really going to talk about beer.

Beer (or any alcoholic drink for that matter) is mostly just water with some ethyl alcohol thrown in for good measure and trace amounts of other stuff that provides the flavor. Typically, about 5% of a beer is alcohol, so a 12 floz serving of beer will have 0.6 floz of alcohol. Now, I said that a beer is *typically* 5% alcohol: beer does come in many different strengths. For example, last night, at the [Wynkoop Brewing Company](http://www.wynkoop.com/), I had a beer that was 8.2% alcohol, and, because the content was so high, the bar gave me a “short pour” which means that they gave me a brandy snifter's worth of beer.

One common strength of beer that is seen especially in the retail area is 3.2% beer. In Colorado, where I live, beer can only be sold in a grocery store if its strength is less than 3.2%. If you're fine with drinking 3.2% beer, you can pick up your [watered-down, mass-marketed, American pale lager](https://en.wikipedia.org/wiki/Duff_Beer) at the same time you buy your milk and eggs. If you prefer wine, whisky or beer that's stronger than 3.2%, you need to make a special trip to the liquor store.

So, if we do the simple math on this and divide 3.2 by 5, 3.2% beer has only 64% percent of the amount of alcohol that a normal 5% beer has. That math would be fine except that it's **completely wrong**.

For some legal or historical oddity that I think has to do with taxation laws (but I am not sure), when a beer advertises itself as 3.2%, what it means is 3.2% **by weight** as in 3.2% of the total weight of the liquid is alcohol. Just about every other time you look at an alcoholic beverage label, the alcohol content is listed **by volume**… and they are most definitely not the same. Well, they are the same, but only in exactly two instances: 0% alcohol by weight is 0% by volume, and 100% by weight is also 100% by volume. However, between those two extremes, the relationship is not linear.

Most calculators that I come across on the Internet, however, do assume that the relationship is linear with the common assumption that the alcohol by weight (ABW) is 80% of the alcohol by volume (ABV). This may be close enough for the range of alcohol that covers most beers, but “close enough” only counts in horseshoes and handgrenades. We can do better.

So, let's think: how is alcohol by volume (or ABV) defined? Well, it's a ratio of the volume of alcohol divided by the total volume. Now, the total volume of an alcoholic beverage is alcohol and water… and some other stuff that provides the taste, but for our purposes, let's just ignore that other stuff—alcohol, water and nothing else. When we put it together, we get something like this:

$$$$

Okay, but we're dealing in weights—not volumes. Since a volume of something is equal to the weight of that something divided by its density, we can replace the volumes with weights, so let's consult Wikipedia (the most peer reviewed publication on the planet). If we look up the appropriate articles, we'd find that [ethyl alcohol](https://en.wikipedia.org/wiki/Ethanol_%28data_page%29) (the type used in alcoholic beverages) has a density of 0.78945 kilograms per liter at 20°C (68°F). At that same temperature, [water](https://en.wikipedia.org/wiki/Properties_of_water#Density_of_water_and_ice) has a density of 0.9982336 kilograms per liter. For this exercise, let's round it at 0.99823 kilograms per liter. If we replace the volumes in our equation, we end up with:

$$$$

…and if we simplify that, do the dimensional analysis and eliminate the decimals, we get:

$$$$

Our units cancel out in the dimensional analysis, which, since the ABV is a ratio, makes sense. Now, remember when I said that we're dealing with weights? I lied. What we actually know is the alcohol by weight (ABW), and we know the ABW is the ratio of the weight of the alcohol to the total weight. This is very similar to the equation that we started with for the volumes:

$$$$

Well, we could try to solve this all as a system of equations. Let's solve our ABW equation for either the weight of the alcohol or the weight of the water. (It won't matter which one in the end, but let's pick weight of water.) When we go through the steps to solve for the weight of water, we get:

$$$$

Let's plug that into tho ABV equation and simplify. If you've been following along on your TI-89 from high school, you should get:

$$$$

…and there's our formula. What's interesting is that when we plug in the weight of water from the ABW equation, the weight of the alcohol gets canceled out. If we would have plugged in the weight of alcohol instead, we get the same results.

If you need to convert the other way around (*i.e.*, obtain the ABW from an ABV), you just need to solve the above formula for ABW:

$$$$

So, when we put 3.2% into the equation for the ABW, we come within a rounding error of 4.0%. Remember how we did the math and we said that 3.2% beer is 64% as strong as regular beer? Well, it turns out that, since 3.2% beer should really be marketed as 4.0% beer, it's really 80% as strong as regular beer. Keep that in mind before you consider chugging down another 3.2% bottle after you've already had a few: it may be more potent that you think.

Monday, 2014 September 1 9:30 AM MDT — Arvada, Colorado UNITED STATES

I've had this blog since January of 2005. Every month for the past nine years and eight months, I've been pretty faithfully updating this blog by posting an entry at least once a month, but it's not the same as it used to be. In 2006, I managed to write 139 blog posts with no problem. So far, this year, I've only written nine… and we're already nine months into the year. In addition, the past few posts were written close to the end of the month. I somehow managed to be lazy for twenty-nine days of the month only to arrive at day thirty and hastily have to chalk up a blog entry in order to claim that I've kept my streak alive.

It's impressive to say that you've been blogging for the past ten years, but, for me, it's time to put an end to this blog. Essentially, I'm starting over on the blogging. Sometime within the next few days, I'll be removing all of my old posts and… starting over. For a few years, I've been toying with the idea of making a software-development blog, but I never felt that combining software-development topics here was appropriate given the topics of my other posts. If I'm starting over, I no longer have that constraint. However, I'm not sure if I really want to go towards software development as a theme. Looking at my bookshelf, I see books about not only software development but history, religion, linguistics and now homebrewing too. I think that any of these topics could be good material.

One thing that I'm sure of is that I want to write in a more professional manner. What really irritates me is that, when I go back to read old posts, I'm embarrassed about the quality. Many or most of my previous posts show little or no research effort; it's just somebody's incoherent ramblings put down on paper (metaphorically). After doing a short stint in graduate school (for the second time) and after looking at some other quality blogs carefully, I've come to appreciate the value of well-written prose. If I really need to ramble incoherently, I still have Facebook and Twitter to fall back on.

Back when I started blogging, it seemed that everyone had a blog. (Remember Xanga?) Now, it seems that fewer people still blog. Fortunately, I believe that the blogs that are still out there are better quality. If I'm choosing to continue blogging, I need to keep up with the times.

In summary, I don't know what I'll be writing about from here on out, but I can definitely say that I'll be focusing more on quality than quantity. Don't be too surprised if, ten months later, this is still the only post on the site. Fortunately, it means no more midnight writing on the last day of the month just to keep the streak alive.

Monday, 2019 December 30 8:53 PM MST — Arvada, Colorado UNITED STATES

A while back, my employer tried to switch from paying us monthly to paying us biweekly. It had to do with lower administration costs or some bureaucratic procedural details. The plan didn't go over well with the employees to the point where, eventually, the idea was scrapped. Overall, employees weren't happy with the change, but I was actually in favor of making the change. I had figured out that, considering the details in the implementation, once you added up all the paychecks, it meant that the employees actually got **more** money being paid biweekly.

On the surface, it's natural to assume that the pay would be the same either way. Let's use some examples. Mike and Brittany both get hired with the same company on the same day. (For convenience sake, we're going to say 2019 December 1 since that month began on a Sunday.) Both Mike and Brittany have negotiated their payrate to be $58,500.00 annually. The difference is that Mike elected to get paid every month on the last day of the month while Brittany elected to get paid biweekly (i.e., every fourteen days). For Mike's monthly salary, the employer naturally divided his annual rate by twelve.

$$$$

For Brittany's biweekly salary, since (naturally) there are fifty-two weeks in a year, there should be twenty-six paychecks.

$$$$

Let's suppose that both Mike and Brittany continue to work at this job (without getting a raise) until 2049 July 31—which, conveniently, is a payday for both of them. How much have each of them been paid total over the years if we were to count up each of their *individual* paychecks? We could either put the numbers on a spreadsheet or chalk up six lines of code in a scripting language and run it. If we were to do that, the results would be that Mike got a total of $1,735,500.00 over the course of his career while Brittany was paid $1,741,500.00 over that same course of time. Go ahead and try it yourself and see.

Brittany got paid **six thousand dollars** more than Mike did over the same course of time when they were supposed to have the same salary.

Now sure, over approximately thirty years, six thousand dollars comes out to just two hundred dollars each year (which is what Mike is saying to himself to psychologically minimize the discrepancy), but, hey… more money is more money. The question is: how did that happen.

Okay, earlier I said that there are fifty-two weeks in a year. That was… a lie. A fifty-two-week year has 364 days in it. However, actual years have 365 days or 366 days if it's a leap year. Brittany gets paid **every** fourteen days. Period. Every time another fourteen days pass and if Brittany hasn't managed to die, retire, do something to get herself fired or ragequit in frustration, she gets another paycheck. Mike, on the other hand, gets paid at the end of every month. Sometimes, that month can be as short as twenty-eight days; othertimes, it can be as much as thirty-one days. Mike gets paid the same amount regardless of the length of time.

That still shouldn't make a difference, right? Even though Mike gets paid monthly, at the end of the year it should even out. However, Mike's years are 365 or 366 days; Brittany's years are 364 days. Every year there is at least one day that Brittany gets paid for that Mike doesn't. In leap years, it's two days. Over a significant length of time (e.g., thirty years, perhaps?), that comes to a six-thousand-dollar discrepancy.

Brittany and Mike's employer could have also calculated the amounts better. Instead of dividing Brittany's annual rate by 26, a number of 26.08875 (i.e., the number of biweekly pay periods in a mean Gregorian year) would have closed the gap much more significantly and saved the employer some money. While my employer ultimately chose not to implement the switch, their course of action at the time was to stick with 26.

If you find yourself in this situation, I say take every advantage you can get.

Sunday, 2018 September 23 9:30 PM MDT — Arvada, Colorado UNITED STATES

I'm hungry. Now, I have one of those microwavable Asian meals; all I need to do is add water and put it in the microwave. The instructions are telling me to heat it up for ninety seconds. Okay, but my microwave won't accept ninety seconds. Instead, I have to express the value in components of minutes and seconds. Now, the answer is 1:30—I know this, and I didn't need a calculator to figure this out… but how would we program a computer to calculate this for us?

These type of problems come up frequently when working with calendars, so I want to talk about this before we delve further because different computer languages do different things and also come to different conclusions when you ask them to perform the same calculation.

When I first learned long division back in third grade, I was taught to compute remainders. For example, if I was asked to calculate nine divided by four, I would have told you that it was two with a remainder of one. The next year, in fourth grade, I was taught how to divide using decimals. Now, nine divided by four became 2.25.

In some computer languages like JavaScript or PHP, if I program it to divide two numbers, I will get the fourth-grade answer—that is, a floating-point number as a result. In JavaScript, `console.log(90 / 60)` gives me 1.5. Simple.

However, when working with calendars, it's typically the third-grade answer that we want. This is called(https://en.wikipedia.org/wiki/Division_(mathematics)#Of_integers). Other computer languages like C, C++, Java and C# will do integer division by default if we're dividing two integers. For example, in Java, evaluating `System.out.println(90 / 60);` will give a result of 1 and not 1.5 as we may expect. What about the remainder then? We would have to do something called a [modulo operation](https://en.wikipedia.org/wiki/Modulo_operation) to obtain that. In Java, the modulo operation would look like this: `System.out.println(90 % 60);`. That percent sign is essentially saying, “Divide 90 by 60, but return the *remainder* instead of the *quotient*”. The result that we get from that is 30. Combining those two results, we just split 90 seconds into its components of 1 minute and 30 seconds.

Integer division and modulo are two operations that have a special mathematical relationship. The general rule is this:

$$$$

Most computer languages follow this rule. If that's the case, how then can computer languages come to different results? Well, you'll notice that there's a `round` function in that formula. While each computer language may follow this general rule, computer languages **do not** necessarily round using the same method.

So let's talk about rounding now. In mathematics, there are *several* different ways to round numbers. We're going to focus on two: the *floor* function and the *ceiling* function. You'll typically find these in any programming language's standard library.

The ceiling function (sometimes spelled ceil), will round the parameter to the closest integer that is greater than or equal to the parameter. We don't use it that much for calendrical calculations. The floor function on the other hand gets used very much. It does the opposite of ceiling: it rounds the parameter to the closest integer that is less than or equal to the parameter. **When we do integer division and modulo, we almost always want to use the floor function as our rounding method.**

That is not what we get with C, C++, Java, C#, JavaScript or PHP. When these languages perform integer division, they simply get rid of the digits on the right side of the decimal point of the result. This is called *truncation*. Now, if you think about it, truncation sounds like it's the same as the floor function. That's because it is… *for positive numbers!* As soon as negative numbers get thrown into the mix, we end up with results consistent with performing the ceiling function. That's bad!

The consequences for modulo arithmetic are this: if we use the floor function when doing integer division, the result of the modulo operation will always have the same sign as the *divisor*. However, if we truncate the result of the integer division instead, the result of the modulo operation will always have the same sign of the *dividend*.

Here's an example. [Last week](/Home/Weblog/Entry_8), I talked about representing dates as linear numbers. I put all of my family members' birthdates into a table with the linear-date values. One benefit of representing dates like this is that it's easy to find out what day of the week a certain date is. You just divide the number by seven and take the remainder. The remainder will correspond to a day of the week. What happens if we do that to my family members' birthdates?

Name | Ordinal Date | Ordinal Date mod 7 | Day of the Week |
---|---|---|---|

Lance | 20368 | 5 | Thursday |

Lucy | 20559 | 0 | Saturday |

Samuel | 29728 | 6 | Friday |

Helena | 30227 | 1 | Sunday |

Nicholas | 30855 | 6 | Friday |

Susan | 31069 | 3 | Tuesday |

Daniel | 31475 | 3 | Tuesday |

Juliana | 37382 | 2 | Monday |

Ana | 39348 | 1 | Sunday |

Amy | 40466 | 6 | Friday |

Catherine | 41169 | 2 | Monday |

Anastasia | 41363 | 0 | Saturday |

Emily | 41731 | 4 | Wednesday |

Patricia | 42152 | 5 | Thursday |

Elisa | 42155 | 1 | Sunday |

It worked great. Now suppose that I want to add my great-grandmother to the list. She was born 1893 February 13. In the number system that we're using, that translates to -2511. That's a negative number, but the beauty of representing dates on a linear scale is that negative numbers aren't a problem. So what day of the week was my great-grandmother born on? Well, if we do the modulo operation in a computer language that uses the floor method like Ruby, Lua, Perl or Python, we get 2 which corresponds to Monday. However, what happens when we try that modulo operation in computer languages that use the truncate method like C, Java or PHP? Well, the dividend is negative and, in these programming languages, the result of the modulo operation has to have the same sign as the dividend, so we end up with… -5. Positive dividends can have positive results and negative dividends can have negative results. Since both positive and negative dividends are possible, the unfortunate consequence of this is that we need to program our code to handle negative and non-negative results.

With calendars, we consistently want to use the floor method, so how do we deal with the these problems?

One way is to use a computer language that has floor division right out of the box. Guido van Rossum, the creator of Python, once wrote [a blog post](http://python-history.blogspot.com/2010/08/why-pythons-integer-division-floors.html) about Python's use of the floor method instead of the truncate method. He made the right choice in my opinion.

Some computer languages provide give you options. For example, while Java's `/` and `%` operators use the truncate method, Java now has [`floorDiv`](https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#floorDiv-int-int-) and [`floorMod`](https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#floorMod-int-int-) functions that you can use when you need the floor method. Both Haskell and Lisp have a `rem` function that uses the truncate method and a `mod` function that uses the floor method.

Sometimes, we don't have a choice in what programming language that we use. In those instances, one thing that can help is to rewrite code to avoid negative numbers. Obviously, that isn't always an option.

The method that I see most often in production code is to check if the result of the modulo operation is negative and, if it is, add the divisor to it. Here's a C function that does just that.

`` int Modulo(int X, int Y) { int Result; Result = X % Y; if (Result < 0) { Result += Y; } return Result; } ```This works all of the time… unless your divisor is negative.

If you're using computer languages that don't have integer division (like PHP and JavaScript), there's a more straightforward solution.

`` function Modulo(X, Y) { return X - Y * Math.floor(X / Y); } ```The advantage with this method is that it works even when the divisor is negative.

Now that we have proper understanding of the nuances of integer division and modulo operations in programming languages, we can move on to applying these in converting calendar dates to linear dates. More on that to come.

Sunday, 2018 September 16 9:00 PM MDT — Arvada, Colorado UNITED STATES

By some accident of probability, I have exactly eight nieces and no nephews. The fact that they're all nieces isn't relevant to the story; it's just interesting. The fact that there are eight of them is relevant.

So, it's my job as the bachelor uncle to buy the cool toys for my nieces on their birthdays. Since there are eight of them, I'm going to need help remembering their birthdates. Yes, I know that they have calendars and apps for your phone that will tell you these sorts of things, but I want us to understand *how* those apps work.

First, I e-mail my sister in Mexico, Helena, and my sister-in-law across town, Susan, to get a list of all the birthdates in their families. I'm going to compile their responses into a table of some sort.

Amy | 10/15/10 |
---|---|

Ana | 23.9.2007 |

Anastasia | 30.3.2013 |

Catherine | 9/17/12 |

Daniel | March 4, 1986 |

Elisa | 31.5.2015 |

Emily | 4/2/14 |

Helena | 3.10.1982 |

Juliana | 6.5.2002 |

Lance | October 6, 1955 |

Lucy | April 14, 1956 |

Nicholas | 6/22/84 |

Patricia | 5/28/15 |

Samuel | 22.5.1981 |

Susan | 1/22/85 |

Yuck. The dates don't look the same. Helena lives in Mexico, so, as one would expect, she provided the dates with the day of the month first, the month next and the year last. Susan, on the other hand living in the United States, gave me the dates in the American format: the month, followed by the day of the month and then followed by the year. Helena used four-digit years while Susan gave me two-digit years. I myself entered in a few birthdates for family members that I already knew, but I spelled out the months. When I got the responses, I just threw them onto a table the same way that I got them. They need to be consistent.

Let's try putting them all in my format.

Amy | October 15, 2010 |
---|---|

Ana | September 23, 2007 |

Anastasia | March 30, 2013 |

Catherine | September 17, 2012 |

Daniel | March 4, 1986 |

Elisa | May 31, 2015 |

Emily | April 2, 2014 |

Helena | October 3, 1982 |

Juliana | May 6, 2002 |

Lance | October 6, 1955 |

Lucy | April 14, 1956 |

Nicholas | June 22, 1984 |

Patricia | May 28, 2015 |

Samuel | May 22, 1981 |

Susan | January 22, 1985 |

Now, it's sorted alphabetically by name. Here's the thing: I need to know who's birthday is coming up next. If the list were in order by birthday, I may be able to figure this out better. Let's tell the computer to sort it that way.

Lucy | April 14, 1956 |
---|---|

Emily | April 2, 2014 |

Susan | January 22, 1985 |

Nicholas | June 22, 1984 |

Anastasia | March 30, 2013 |

Daniel | March 4, 1986 |

Samuel | May 22, 1981 |

Patricia | May 28, 2015 |

Elisa | May 31, 2015 |

Juliana | May 6, 2002 |

Amy | October 15, 2010 |

Helena | October 3, 1982 |

Lance | October 6, 1955 |

Catherine | September 17, 2012 |

Ana | September 23, 2007 |

That didn't turn out the way that I expected it. It sorted it alphabetically by month. Also, it didn't even sort properly within the month. Look at the month of May: Samuel, Patricia and Elisa's birthdays seem to fall in order. However, Juliana's birthday is before any of theirs, but she's listed after. That's because ‘6’ comes after ‘2’ and ‘3’ when we sort alphabetically. **We need to make these numbers somehow.**

At my work, when we enter in dates into the computer system, we enter a two-digit month, a two-digit day of the month and then a two-digit year. For example, today, 2018 September 16 would be entered in as “091618”. Let's try entering the dates with this method and then sorting on that.

Susan | 012285 |
---|---|

Daniel | 030486 |

Anastasia | 033013 |

Emily | 040214 |

Lucy | 041456 |

Juliana | 050602 |

Samuel | 052281 |

Patricia | 052815 |

Elisa | 053115 |

Nicholas | 062284 |

Catherine | 091712 |

Ana | 092307 |

Helena | 100382 |

Lance | 100655 |

Amy | 101510 |

Yes, this really is how we enter the dates into the computer at work, and it's a bad way to do it. At least now, they're in the order that I want. Also, Catherine's having a birthday **tomorrow!** I need to get her a gift tonight! Before I can do that, I need to know how old she's going to be. Of course, I could just look at the number and deduce that she'll be six, but I need to get the computer to figure that out. Actually, what will be helpful would be to sort the list in such a way where the oldest people are on top and the youngest on the bottom. To do that, I need to change the date format again.

Lance | 19551006 |
---|---|

Lucy | 19560414 |

Samuel | 19810522 |

Helena | 19821003 |

Nicholas | 19840622 |

Susan | 19850122 |

Daniel | 19860304 |

Juliana | 20020506 |

Ana | 20070923 |

Amy | 20101015 |

Catherine | 20120917 |

Anastasia | 20130330 |

Emily | 20140402 |

Patricia | 20150528 |

Elisa | 20150531 |

Okay, we have a four-digit year, two-digit month and two-digit day of the month. This is still a bad way to do it in my opinion. However, there are computer systems that use this method. MySQL uses [a similar method](https://dev.mysql.com/doc/internals/en/date-and-time-data-type-representation.html) for storing its dates. Why is this bad then?

Let's take a moment to talk about time in the platonic sense. Not only do we perceive time in cycles, we order our lives around these cycles as well. Think of how often you wake up, attend religious ceremonies, get paid, pay the rent or the mortgage, pay taxes, vote or watch the Olympics. All of these events occur in cycles. The day is probably the most fundamental of these cycles, but even the day is broken up into smaller cycles. An analogue clock is the absolute perfect way to represent this. The instant that the second hand reaches the top of the clock, a new cycle of sixty seconds begins, and the number of these cycles that have passed is represented by the minute hand (and, similarly, the hour hand). Since we perceive time in cycles, it is natural that we represent time that way in our speech and our writing.

However, it is **exactly deplorable** to do mathematical calculations when time is represented in cycles. (It's *possible*… but it's also exactly deplorable.)

When dates get represented as numbers, they need to *act* like numbers. For example, if I'm travelling on the highway and if I'm at mile marker 269 and if I know my destination is at mile marker 116, I can easily subtract the two numbers to know that my destination is 153 miles away. This makes sense because… that's… just how numbers work!

Suppose that I want to know how much older Patricia is than Elisa. Using the numbers on our table, we can subtract Elisa's birthday (20150531) from Patricia's birthday (20150528). Doing the math tells us that Patricia is three days older than Elisa. Perfect right?

No! Let's try that again, except, let's see how much older Lance is than Nicholas. By doing the same subtraction, we get 289,616 days—which is close to 793 years. I happen to know that Lance was twenty-eight when Nicholas was born. Why did the math work for Patricia and Elisa but not for Lance and Nicholas? It's because Patricia and Elisa were both born in the same month—May of 2015. Lance and Nicholas weren't. This system has gaps in it—literally. For instance, the difference between 20171231 and 20180101 is only one day. However, if we subtract the two numbers, we get 8,870 and not… one (you know, kind of like we should). Also, what about a date like 20171581? That's not even a date that ever existed, but what would a computer program even do if it was given that input?

We want the dates to work the same way that our mile markers worked. In order to get that to happen, we have to abandon notating our dates in cycles and put them on a linear scale like the mile markers. (I do have to point out that the mile-marker analogy breaks down as soon as we realize that the mile markers reset at the state line.)

This is the way that most software that calculates dates already works! If you're a spreadsheet person, try this: open up your spreadsheet software—Excel, LibreOffice or, if you don't have any of these, [Google Sheets](https://sheets.google.com/). Select a cell and type in today's date (or press `Ctrl+;`). Select another cell and type in your birthdate. Select now a third cell and create a cell to subtract your birthdate from today's date. Once you press enter, the result that you should see is the number of days old you are. Divide that by 365.2425, and you should get your age in years.

The reason this works is because each cell in a spreadsheet has a value and a format. The format that you see is the date represented in the cycles that we humans are used to (i.e., years, months, days). However, the value that's in the cell is a number. If you want to see this number, select a cell and then change the number format for the cell to ‘General’ or ‘Automatic’. (This process is different in different spreadsheet programs.) It goes the other way around. Type ‘37045’ into a cell. Now, change the number format of the cell to a date. You'll end up with 2001 June 3.

If we take that table of dates from above and put it in a spreadsheet, we'd end up with this data:

Lance | 20368 |
---|---|

Lucy | 20559 |

Samuel | 29728 |

Helena | 30227 |

Nicholas | 30855 |

Susan | 31069 |

Daniel | 31475 |

Juliana | 37382 |

Ana | 39348 |

Amy | 40466 |

Catherine | 41169 |

Anastasia | 41363 |

Emily | 41731 |

Patricia | 42152 |

Elisa | 42155 |

While that's what the spreadsheet will actually store in the background, we can give the spreadsheet instructions to format the data however we want. It will convert the dates from these linear formats into the cyclical representations that we humans deal with. How those conversions are done is a topic for another time, but these dates on a linear scale are an improvement. Remember how I said that mathematical calculations are exactly deplorable with cyclical representations? Well, now, mathematical calculations are elegant and straightforward. Need to know what date it will be a hundred days from now? Tell the spreadsheet to add the days and let it do the math for you!

Sunday, 2018 September 9 4:38 PM MDT — Arvada, Colorado UNITED STATES

So, the last time that I wrote a blog post here—nearly a year and a half ago—I was talking about a new software project that I had been working on for, at the time, about six months. I had said that the project was “pretty much already done”.

That part about it being pretty much already done… was not exactly the truth. There was also another lie: the one about my starting the project six months before the last blog post. In truth, I started this project back in college. Untruths aside, I think that my software project—despite being still unfinished—is done enough that I can finally let you in on the secret.

So, context: I grew up in what could be described as an *evangelical* environment. Each religion seems to have its holidays—and Christianity is **no** exception to that rule. However, my particular brand of vodka of Christianity certainly hadn't gotten that memo. Growing up, I seem to remember three Christian holidays: Christmas, Easter and Palm Sunday—end of list. I make the joke that, despite being Pentecostals, we didn't even celebrate Pentecost. Of course, my church also celebrated Independence Day, Memorial Day or any other day set aside for nationalistic glorification with the same sincerity because it conflated nationalism and spirituality (a disturbing trend that's a topic for another time).

Anyway, despite having just three holidays, there was still this awareness that there were other holy days. Of course, you couldn't escape *Saint* Valentine and *Saint* Patrick's days. Some people reminded us that Halloween had it's origins in Christian tradition before being appropriated by… satanists or something ('cause, you know, satanists and their candy…). Around Christmas time, you neither can't escape the barrage of Christmas carols—among them, “The Twelve Days of Christmas”. This raises the question: *Twelve days? Well, which twelve days are these twelve days: the twelve before December 25 or the twelve after?* (Spoiler alert: [It's the twelve days after](https://en.wikipedia.org/wiki/Christmastide).)

Attending a Christian university, there was a little more exposure to these other holidays. Once, a professor asked us students if we were attending chapel on this particular day because it was “[Monday Thursday](https://en.wikipedia.org/wiki/Maundy_Thursday)”. *What the !@#$ is “Monday Thursday”?*, I thought to myself. Fortunately, that was the beginning of the Wikipedia age where, if you really want to know something, an answer was no further than the closest computer. (However, this was still before the smartphone age where answers now are no further than your pocket.)

Being a computer-science student, during my senior year, I chalked together a little one-page, PHP script that, for any year that you gave it, would spit out a liturgical calendar. It was pretty minimal; it showed just a few holidays, it marked the beginning and the end of the liturgical seasons and it showed each particular day on the calendar in its appropriate liturgical color, but that was about it. PHP has [a built-in function](http://www.php.net/manual/en/function.easter-days.php) that made calculating the date of Easter easy, so there wasn't a great deal of effort that went into it. After a bit of time, that calendar just stayed forgotten in the deep recesses of my website.

Let's jump ahead about eight years. I'm now in a new religious tradition. Specifically, it's a tradition that is overflowing with various “holy days” (which is the etymology of the word *holiday*). After a few months in my new church, I pulled out the old calendar that I made in college and *reworked* it.

By *reworked*, I mean I burned down the old PHP calendar script that I made and started fresh. I made a second “object-oriented” attempt that was more trouble than it was worth, so I burned that one down too and started over a second time.

Third time's a charm… as the saying says. It is still a work in progress, and I've spent countless (as in, I've literally lost count) hours working on this, and I anticipate that I'll be spending plenty more. I still don't feel that it's “ready”, but, if all goes according to plan… it'll never be ready. However, I just discovered that my calendar has started to show up in some Google searches, so I've decided that it's time to release it. Just yesterday, I registered **[liturgical-calendar.com](https://liturgical-calendar.com/)** and moved the calendar from this website over to its new domain.

My new website displays the liturgical calendar of the [Anglican Church of North America](http://anglicanchurch.net/?/main/texts_for_common_prayer) (which itself is a work in progress). In addition (while I haven't yet built any sort of way to switch between the two—it is a work in progress after all), I also included the liturgical calendar according to the Episcopal Church's [1979 Book of Common Prayer](https://liturgical-calendar.com/en/Episcopal).

I could really talk a while about the nice features that I put into it, but I will just mention a few:

One, in true linguistics-nerd fashion, the capability to have the calendar available in multiple languages was built in from the start, and, as such, I included translations into [Spanish](https://liturgical-calendar.com/es/ACNA/) and [French](https://liturgical-calendar.com/fr/ACNA/).

Two, the calendar provides links to other websites for scripture readings. However, Anglicans don't necessarily use ordinary Bible translations when reading the Psalms. Typically, a separate [psalter](https://en.wikipedia.org/wiki/Psalter) is provided within each of the various versions of the Book of Common Prayer. Since I couldn't find a decent website with the psalter, I created my [own website of the psalter](https://psalter.liturgical-calendar.com/en/). The psalter website still needs a *lot* of work, but that in itself was a monumental task for something that's kind of an afterthought.

Three, while the calendar was programmed in PHP, I also rewrote all of the functionality in JavaScript as well so that moving from page to page within the site becomes lightning quick! For this project, I actually programmed it [TypeScript](https://www.typescriptlang.org/), a computer language from Microsoft that adds static typing to JavaScript and then compiles to JavaScript. The lack of static typing is a frustration for me in both PHP and JavaScript (among other computer languages), and I'm thrilled that tools now exist for static typing.

Lastly, while Christians in “the West” all use the Gregorian calendar for their feasts and fasts, I included functionality for the use of calendars used by Christians in “the East” such as the Julian, Coptic, Ethiopic and Revised Julian calendars. For good measure, I also threw in the Hebrew calendar too. While I'm not actually using this functionality right now, it's… there. In the future, I may expand the website to include calendars from other traditions besides just the Anglican one. However, to include this functionality, I am indebted to Edward M. Reingold and Nachum Dershowiz for their fantastic book *[Calendrical Calculations](https://www.amazon.com/Calendrical-Calculations-Ultimate-Edward-Reingold/dp/1107683165)* which contained and explained all of the mathematics that I needed to support all of these calendars (except the Revised Julian calendar which I had to create myself). When it became clear that I needed something to help me with the calculations, I read online that Reingold and Dershowiz' book was the one to use. After reading it, I recommend it for anyone seeking an understanding of calendrical calculations.

It's been a good deal of work, and it's been a great deal of fun. Going forward, I hope to continue to work on this project, and I hope that it can be of use those who have great liturgical-calendar needs! Also, I hope that this gives me more things about which to write blog posts. I encounter a bit of frustration when I see examples of software development that don't properly compute dates and times correctly. I've gotten into more than a couple of arguments at work about this. Hopefully, I can write a few blog posts on this topic in the near future to inspire good coding practices. Right now, it's a miracle that I wrote this one.