1
$\begingroup$

My trash gets picked up every other Tuesday. Now it's easy to remember what day of the week it is, but not so easy to remember if it's a skip week or not - especially if you miss it sometimes. You have to count weeks from the last week you remember it being picked up, it's easy to lose count, and off-by-one errors are catastrophic.

I know there are various tricks (ie. arithmetic algorithms) for calculating what day of the week a certain future date would be, for example. Is it possible to derive such a function, so that given today's date (year, month, day) I could calculate if it's one of the skip weeks or one of the trash weeks?

Naturally the function would have to incorporate some sort of epoch, since the choice of skip week is arbitrary. Also, I am ideally looking for a function that would be easy to remember and calculate in my head. A probabilistic function would also be okay (eg. if it only correctly identifies the skip week, say, 95% of the time).


I can see that if I had some global week number (as in, not capped at 52), I could easily write such a function by taking mod 2. So I think this question reduces to finding a function that can calculate week number wrt to some reference "epoch" date. That is assuming there is not another way to do it without looking at the number of weeks at all.

$\endgroup$

1 Answer 1

2
$\begingroup$

There might be a more compact algorithm that's easier to memorize, and to do mentally, but here's something that works.

I've adapted a Julian day number algorithm from
RG Tantzen (1963), ACM. Algorithm 199: conversions between calendar date and Julian day number. 
doi: 10.1145/366707.390020.

I have Python code that uses this algorithm to do Julian day number conversion for the Gregorian and Julian calendars on Github.

I've simplified that code slightly to calculate week numbers for the 21st century, by doing simple division by 7 of the day number, counting Saturday 2000-Jan-01 as day 1. You might like to add an integer offset to shift the week cycle.

The year 2000 was a leap year, so we can treat this century as a Julian century, and do our calculations using the Julian calendar algorithm, which is slightly simpler than the Gregorian calendar one.


A common trick in calendar arithmetic is to shift the start of the year to March. This moves the mess of February to the end of the year, so it doesn't affect the day count of the other months. It also gives us a nice regular pattern of month lengths, with long and short months alternating in 5 month blocks, with 153 days per block.

Month Month Month Length
Mar Aug Jan long
Apr Sep Feb short
May Oct - long
Jun Nov - short
Jul Dec - long

I see from your profile that you're familiar with Python, so I'll post my algorithm as Python code, rather than using more standard mathematical notation. ;)

def weeknum(y, m, d):
    yy, m = divmod(m + 9, 12)
    y += yy - 1
    d += 4 + y + y // 4 + m * 2 + (m * 3 + 2) // 5
    w = 8 + y * 52 + m * 4
    return w + d // 7

The first two lines do the rotation to make March month zero, subtracting 1 from the year if the month is January or February. In the original function, the core of the day calculation is

d += offset + y * 1461 // 4 + (m * 153 + 2) // 5

The 153 and 5 I explained above, the 1461 and 4 come from the fact that there are 1461 days in the 4 year leapyear cycle.

In weeknum I've tried to simplify the arithmetic by moving multiples of 7 days to the w variable.

Here's a demo running on the SageMathCell server.

$\endgroup$

You must log in to answer this question.

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