## Tomohiko Sakamoto’s Day-Of-Week Algorithm

### June 17, 2016

Here is Sakamoto’s algorithm for calculating the day of the week, taken from the comment that introduces the code:

Jan 1st 1 AD is a Monday in Gregorian calendar.

So Jan 0th 1 AD is a Sunday [It does not exist technically].Every 4 years we have a leap year. But xy00 cannot be a leap unless xy divides 4 with reminder 0.

y/4 – y/100 + y/400 : this gives the number of leap years from 1AD to the given year. As each year has 365 days (divdes 7 with reminder 1), unless it is a leap year or the date is in Jan or Feb, the day of a given date changes by 1 each year. In other case it increases by 2.

y -= m So y + y/4 – y/100 + y/400 gives the day of Jan 0th (Dec 31st of prev year) of the year. (This gives the reminder with 7 of the number of days passed before the given year began.)

Array t: Number of days passed before the month ‘m+1’ begins.

So t[m-1]+d is the number of days passed in year ‘y’ upto the given date.

(y + y/4 – y/100 + y/400 + t[m-1] + d) % 7 is reminder of the number of days from Jan 0 1AD to the given date which will be the day (0=Sunday,6=Saturday).

int dow(int y, int m, int d) { static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; y -= m < 3; return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7; }

Another description is given here.

Your task is to write a program that implements the day-of-week algorithm shown above. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

Pages: 1 2

A Haskell version, with a variant (dow’) that provides a little more type safety.

Here’s a solution in x86 assembly.

/* dow.s */

.section .data

t:

.long 0,3,2,5,0,3,5,1,4,6,2,4

.section .text

.globl dow

.type dow,@function

# int dow(y, m, d);

dow:

# Save old base pointer

pushl %ebp

movl %esp, %ebp

# Create a local variable for

# the result.

# result: -4(%ebp)

subl $4, %esp

# Arguments:

# y: 8(%ebp)

# m: 12(%ebp)

# d: 16(%ebp)

# %ebp Offsets:

.equ result, -4

.equ y, 8

.equ m, 12

.equ d, 16

# if (m < 3) –y;

cmpl $3, m(%ebp)

jge proceed

decl y(%ebp)

proceed:

# result = y

movl y(%ebp), %ecx

movl %ecx, result(%ebp)

# result += y/4

movl $0, %edx

movl y(%ebp), %eax

movl $4, %ecx

divl %ecx

addl %eax, result(%ebp)

# result -= y/100

movl $0, %edx

movl y(%ebp), %eax

movl $100, %ecx

divl %ecx

subl %eax, result(%ebp)

# result += y/400

movl $0, %edx

movl y(%ebp), %eax

movl $400, %ecx

divl %ecx

addl %eax, result(%ebp)

# result += t[m-1]

movl m(%ebp), %ecx

decl %ecx

movl t(,%ecx,4), %ecx

addl %ecx, result(%ebp)

# result += d

movl d(%ebp), %ecx

addl %ecx, result(%ebp)

# result = result % 7

movl $0, %edx

movl result(%ebp), %eax

movl $7, %ecx

divl %ecx

movl %edx, result(%ebp)

# Save result

movl result(%ebp), %eax

# Restore old base pointer

movl %ebp, %esp

popl %ebp

ret

Here’s a C program that calls the day-of-week function.

Here’s example usage.

language=”asm” didn’t work for formatting my last post. Here’s the assembly code formatted with language=”text”.