Categories
computers suck

Awk day of the week function

Yet another in my series of awk functions no-one but me will ever use:

function dow(year, month, day) {
# Modified from C Snippets "calsupp.c" public domain by Ray McVay 
# http://www8.cs.umu.se/~isak/snippets/calsupp.c
# returns 0-6 where 0 == sunday
# tested over 24000 days in range of unix timestamp, 1970-2035

    day_of_week = 0;

    if (month <= 2) {
        month += 12;
        year--;
    }
    day_of_week = (day + month * 2 + int(((month + 1) * 6) / 10) + year + int(year / 4) - int(year / 100) + int(year / 400) + 2);
    day_of_week = day_of_week % 7;
    return ((day_of_week ? day_of_week : 7) - 1);
}

Basically, all this does is calculate a Julian day number, then take its remainder modulo 7. I’d seen an example that parsed the output of ‘cal’. That’s one way of doing it; not necessarily mine.

4 replies on “Awk day of the week function”

Thank you so much.

I write nearly everything I do in awk and I needed the day of the week for my dates.

Scruss,
I got a Sunday instead of Monday.

2020 MAR 16 SUNDAY

week_day = (day_of_week ? day_of_week : 7) – 1
line = day_of_week ” ” week_day
printf(string_nl, day_of_week)
1 0

Are you sure? Don’t see enough of your code to tell what you’re doing. It did pass a test harness I just wrote:

 ./testdow.sh
Testing /usr/bin/awk from 2010-03-19 to 2030-03-19 ...
PASSED: interpreter /usr/bin/awk over 7306 days.
$ ./testdow.sh
Testing /usr/bin/gawk from 2010-03-19 to 2030-03-19 ...
PASSED: interpreter /usr/bin/gawk over 7306 days.
$ ./testdow.sh
Testing /usr/bin/mawk from 2010-03-19 to 2030-03-19 ...
PASSED: interpreter /usr/bin/mawk over 7306 days.
$ ./testdow.sh
Testing /usr/bin/original-awk from 2010-03-19 to 2030-03-19 ...
PASSED: interpreter /usr/bin/original-awk over 7306 days.

And yes, I gave it a quick Y2038 check by running from 2000-03-19 to 2040-03-19 (14611 days) with /usr/bin/awk.

Here’s the test harness bash script:

#!/bin/bash
# test awk date function for a decent time period
# scruss - 2020-03

# could be awk, gawk, mawk, original-awk
awkbin=$(which awk)
# awkscript is code from
#  https://scruss.com/blog/2012/02/15/awk-day-of-the-week-function/
# but with this line (uncommented) added:
#  { print dow($1, $2, $3); }
awkscript="./dow.awk"

# years, split evenly
period=20

# probably don't need to change these
count=0
fail=0
first=$(TZ='UTC0' date --date="$((period / 2)) years ago" +'%Y %m %d')
last=$(TZ='UTC0' date --date="$((period / 2)) years hence" +'%Y %m %d')
# initial value
today=$(TZ='UTC0' date --date="${first// /-} -1 day" +'%Y %m %d')

echo Testing "$awkbin" from "${first// /-}" to "${last// /-}" ...
# compare dates as numeric YYYMMDD instead of strings
while
    [ "${today// /}" -lt "${last// /}" ]
do
    today=$(TZ='UTC0' date --date="${today// /-} +1 day" +'%Y %m %d')
    ddow=$(TZ='UTC0' date --date="${today// /-}" +'%w')
    adow=$(echo "$today" | "$awkbin" -f "$awkscript")

    if
	[ "$ddow" -ne "$adow" ]
    then
	fail=1
	echo "FAILED:" "${today// /-}" "- date:" "$ddow" "- awk" "$adow" \
	     "interpreter" "$awkbin"
    fi
    count=$((count + 1))
done

if
    [ "$fail" -eq 0 ]
then
    echo "PASSED: interpreter" "$awkbin" "over" "$count" "days."
fi

Leave a Reply

Your email address will not be published. Required fields are marked *