HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Calculate the weekday from a date (M-D-Y)

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
theweekdaydatecalculatefrom

Problem

This Common Lisp exercise is to write a program that can calculate the weekday given a string of the format "M-D-Y." It was more challenging than I expected. If you have suggestions about how to simplify this code, I will be very grateful.

```
;; 2.7 Day of Week. A program for converting Gregorian dates in the form month-day-year to day of the
;; week is the following. Let the Gregorian date be represented by M-D-Y where we have the following
;; definitions:
;; M is the month of the year. Let m be the month number derived from M by the rule m is M - 2 if M >= 3
;; and m is M + 10 otherwise.
;; d is the day of the month.
;; y is the year of the century.
;; c is the number of the previous century.
;; The algorithm is as follows:
;; (a) A is the integer part of (13m - 1)/5.
;; (b) B is the integer parg of y/4.
;; (c) C is the integer part of c/4.
;; (d) D = A + B + C + d + y - 2c.
;; (e) Make R equal to the remainder of D/7.
;; (f ) Interpret R as Sunday if R = 0, Monday if R is 1, etc

(defun read-date () (format t "Enter the gregorian date in the format (M-D-Y): ~%") (read))

(defun flatten (the-list)
(cond ((null the-list) nil)
((atom the-list) (list the-list))
(t (concatenate 'list (flatten (car the-list)) (flatten (cdr the-list))))))

(defun split (split-char string-to-split)
(let ((next-split-char (position split-char string-to-split)))
(if next-split-char (flatten (list (safely-read-from-string (subseq string-to-split 0 next-split-char))
(split split-char (subseq string-to-split (+ 1 next-split-char)))))
(list (safely-read-from-string string-to-split)))))

(defun weekday-code (bigM bigD bigY)
(let* ((m (if (>= bigM 3) (- bigM 2) (+ bigM 10)))
(y (mod bigY 100))
(littleC (/ (- bigY y) 100))
(A (floor (- (* 13 m) 1) 5))
(B (floor y 4))
(C (floor littleC 4))
(D (- (+ A B C bigD y) (* 2 littleC)))
(R (mod D 7)))

Solution

If you're allowed to use library functions, split already exists as part of cl-ppcre.

There's a pretty rich set of date/time functions in the Lisp core that make this trivial. If it's for learning purposes, by all means, go ahead and do it by hand. But if you're thinking "What's the best way to get the day-of-week in Lisp?", that's actually ridiculously simple.

(defun day-of-week (day month year)
   (nth-value 6 (decode-universal-time (encode-universal-time 0 0 0 day month year 0))))


Re-arrange order of argumnents to taste. Monday is 0 by default, so you'd need to re-jig your format directive. If you need to be able to handle dates before 1900, there's a more robust version at the Common Lisp Cookbook.

Code Snippets

(defun day-of-week (day month year)
   (nth-value 6 (decode-universal-time (encode-universal-time 0 0 0 day month year 0))))

Context

StackExchange Code Review Q#1206, answer score: 3

Revisions (0)

No revisions yet.