I'm editing orgmode, a time-management mode for emacs. I'm adding some new time functions.
In my addition i need to determine the day of the week for a given date. I use the following code:
(defun org-day-of-week (day month year)
(nth-value 6 (decode-universal-time (encode-universal-time 0 0 0 day month year 0) 0)))
Executing this code gives me the error:
nth-value: Symbol's function definition is void: decode-universal-time
I'm new to lisp, and can't find any info related to this error. I presume some libraries aren't loaded or available.
Can anyone please shed a light on this?
Regards,
Erwin Vrolijk
Snow.nl
Essentially decode-universal-time is a Common Lisp function. These are not necessarily available in emacs-lisp. Some quick checking in a local emacs indicates that this is the fact.
Something close to your original implementation would be:
(defun org-day-of-week (year month day)
(nth 6
(decode-time
(date-to-time
(format "%d-%02d-%02dT00:00:00" year month day)))))
You should be able to use decode-time instead (maybe in conjuction with date-to-time):
decode-time is a built-in function in `C source code'.
(decode-time &optional specified-time)
Decode a time value as (SEC MINUTE HOUR DAY MONTH YEAR DOW DST ZONE).
The optional specified-time should be a list of (HIGH LOW . IGNORED),
as from `current-time' and `file-attributes', or nil to use the
current time. The obsolete form (HIGH . LOW) is also still accepted.
The list has the following nine members: SEC is an integer between 0
and 60; SEC is 60 for a leap second, which only some operating systems
support. MINUTE is an integer between 0 and 59. HOUR is an integer
between 0 and 23. DAY is an integer between 1 and 31. MONTH is an
integer between 1 and 12. YEAR is an integer indicating the
four-digit year. DOW is the day of week, an integer between 0 and 6,
where 0 is Sunday. DST is t if daylight saving time is in effect,
otherwise nil. ZONE is an integer indicating the number of seconds
east of Greenwich. (Note that Common Lisp has different meanings for
DOW and ZONE.)
A cleaner version of Vatine's answer is:
(defun day-of-week (year month day)
"Return the day of the week given a YEAR MONTH DAY"
(nth 6 (decode-time (encode-time 0 0 0 day month year))))
decode-time and encode-time are documented here.
I haven't found the source of this problem, but found a workaround:
(defun day-of-week (day month year)
"Returns the day of the week as an integer.
Sunday is 0. Works for years after 1752."
(let ((offset '(0 3 2 5 0 3 5 1 4 6 2 4)))
(when (< month 3)
(decf year 1))
(mod
(truncate (+ year
(/ year 4)
(/ (- year)
100)
(/ year 400)
(nth (1- month) offset)
day
-1))
7)))
Related
I'm looking to map a date/week to the Week number of the year.
I've thought about subtracting the start of the year, and dividing by 7 - however it might not line up correctly.
e.g.
2020.01.02 -> Week 1
2020.01.06 -> Week 2
I would suggest to use following function:
weekOfYear: {1+floor (x-`week$"d"$12 xbar"m"$x)%7}
This function
Finds the first Monday before or on 1st Jan. E.g. {(`week$"d"$12 xbar"m"$x)}2020.01.01 returns 2019.12.30
Then finds difference in days between x and the first Monday
Divides difference by 7 and adds 1, which returns result you are looking for
For example
weekOfYear 2019.12.31 2020.01.01 2020.01.02 2020.01.05 2020.01.06 2020.01.07
returns
53 1 1 1 2 2
Just to build on Antons great answer, you could also use the div function instead of flooring it, which would look something like
{1 + (x - `week $ `date $ 12 xbar `month $ x) div 7}
I have a scheduled start date of a task and the effort to complete the task in amount of days,
e.g in the case below N=5, start date is <2016-01-27 Wed>
How can the deadline be automatically calculated based upon scheduled_date+5days ?
such that in the end I have the following:
DEADLINE: <2016-02-03 Wed> SCHEDULED: <2016-01-27 Wed>
The following example calls org-schedule; the user inputs the date/time desired; then the timeshift of 5 days are added to the last inserted timestamp and that value is used programmatically by org-deadline. If the user wishes hours/minutes to appear in the timestamp for the deadline, then set with-hm to t.
[Some additional work would be needed if the users wishes the deadline to have the exact same time of day as the scheduled date. At the present time, the default is midnight for the deadline.]
(defun schedule-me ()
(interactive)
(org-schedule nil)
(let* (
(timeshift 5)
(time
(org-time-from-absolute
(+
timeshift
(org-time-string-to-absolute org-last-inserted-timestamp))))
(with-hm nil)
(fmt (funcall (if with-hm 'cdr 'car) org-time-stamp-formats)) )
(org-deadline nil (format-time-string fmt time))))
So, I'm reading Land of Lisp now, and Lisp is turning out to be quite different than other programming languages that I've seen.
Anyways, the book provides some code that we're meant to enter into the CLISP REPL:
(defparameter *small* 1)
(defparameter *big* 100)
(defun guess-my-number ()
(ash (+ *small* *big*) -1))
(defun smaller ()
(setf *big* (1- (guess-my-number)))
(guess-my-number))
(defun bigger ()
(setf *small* (1+ (guess-my-number)))
(guess-my-number))
Now, the basic goal is to create a number guessing game wherein the user/player chooses a number, and then the computer tries to guess the number. It performs a "binary search", to find the player's number, by having the player report whether the computer-guessed number is higher or lower than the player's number.
I'm a little bit confused about the ash function. It's my understanding that this is vital to the binary search, but I'm not really sure why. The book somewhat explains what it does, but it's a little confusing.
What does the ash function do? Why is it passed the parameters of *small* added to *big* and -1? How does it work? What purpose does it serve to the binary search?
Google gives you this page which explains that ash is an arithmetic shift operation. So (ash x -1) shift x by one bit to the right, so gives its integer half.
Thanks to Basile Starynkevitch for the help on this one...
Anyhow, ash performs an arithmetic shift operation.
In the case of (ash x -1) it shifts x by one bit to the right, which ultimately returns the integer half.
For example, consider the binary number 1101. 1101 in binary is equivalent to 13 in decimal, which can be calculated like so:
8 * 1 = 8
4 * 1 = 4
2 * 0 = 0
1 * 1 = 1
8 + 4 + 0 + 1 = 13
Running (ash 13 -1) would look at the binary representation of 13, and perform an arithmetic shift of -1, shifting all the bits to the right by 1. This would produce a binary output of 110 (chopping off the 1 at the end of the original number). 110 in binary is equivalent to 6 in decimal, which can be calculated like so:
4 * 1 = 4
2 * 1 = 2
1 * 0 = 0
4 + 2 + 0 = 6
Now, 13 divided by 2 is not equivalent to 6, it's equivalent to 6.5, however, since it will return the integer half, 6 is the acceptable answer.
This is because binary is base 2.
Q. What does the ash function do? Why is it passed the parameters of small added to big and -1? How does it work? What purpose does it serve to the binary search?
It does operation of of shifting bits, more precisely Arithmetic shifting as explained/represented graphically for particular case of Lisp:
> (ash 51 1)
102
When you do (ash 51 1) it will shift the binary of 51 i.e 110011 by 1 bit place towards left side and results in 1100110 which gives you 102 in decimal. (process of binary to decimal conversion is explained in this answer)
Here it adds 0 in the vacant most right place (called Least Significant Bit).
> (ash 51 -1)
25
When you do (ash 51 -1) it will shift the binary of 51 i.e 110011 by 1 bit place towards right side (negative value stands for opposite direction) and results in 11001 which gives you 102 in decimal.
Here it discards the redundant LSB.
In particular example of "guess-my-number" game illustrated in Land of Lisp, we are interested in halving the range or to average. So, (ash (+ *small* *big*) -1)) will do halving of 100+1 = 100 / 2 to result in 50. We can check it as follows:
> (defparameter *small* 1)
*SMALL*
> (defparameter *big* 100)
*BIG*
>
(defun guess-my-number ()
(ash (+ *small* *big*) -1))
GUESS-MY-NUMBER
> (guess-my-number)
50
An interesting thing to notice is you can double the value of integer by left shifting by 1 bit and (approximately) halve it by right shifting by 1 bit.
What's the proper way to store dates in Common Lisp? The closest thing I found to an answer is this, which doesn't really seem to cut it for me.
How about ENCODE-UNIVERSAL-TIME?
(defparameter *my-birth-date* (encode-universal-time 0 0 0 14 2 1984))
If you want to store a date converted to string, you can use the following:
(multiple-value-bind
(s m h d mm y dw dst-p tz) (get-decoded-time)
(format nil "~D\/~D\/~D" date month year))
If I've got a time_t value from gettimeofday() or compatible in a Unix environment (e.g., Linux, BSD), is there a compact algorithm available that would be able to tell me the corresponding week number within the month?
Ideally the return value would work in similar to the way %W behaves in strftime() , except giving the week within the month rather than the week within the year.
I think Java has a W formatting token that does something more or less like what I'm asking.
[Everything below written after answers were posted by David Nehme, Branan, and Sparr.]
I realized that to return this result in a similar way to %W, we want to count the number of Mondays that have occurred in the month so far. If that number is zero, then 0 should be returned.
Thanks to David Nehme and Branan in particular for their solutions which started things on the right track. The bit of code returning [using Branan's variable names] ((ts->mday - 1) / 7) tells the number of complete weeks that have occurred before the current day.
However, if we're counting the number of Mondays that have occurred so far, then we want to count the number of integral weeks, including today, then consider if the fractional week left over also contains any Mondays.
To figure out whether the fractional week left after taking out the whole weeks contains a Monday, we need to consider ts->mday % 7 and compare it to the day of the week, ts->wday. This is easy to see if you write out the combinations, but if we insure the day is not Sunday (wday > 0), then anytime ts->wday <= (ts->mday % 7) we need to increment the count of Mondays by 1. This comes from considering the number of days since the start of the month, and whether, based on the current day of the week within the the first fractional week, the fractional week contains a Monday.
So I would rewrite Branan's return statement as follows:
return (ts->tm_mday / 7) + ((ts->tm_wday > 0) && (ts->tm_wday <= (ts->tm_mday % 7)));
If you define the first week to be days 1-7 of the month, the second week days 8-14, ... then the following code will work.
int week_of_month( const time_t *my_time)
{
struct tm *timeinfo;
timeinfo =localtime(my_time);
return 1 + (timeinfo->tm_mday-1) / 7;
}
Assuming your first week is week 1:
int getWeekOfMonth()
{
time_t my_time;
struct tm *ts;
my_time = time(NULL);
ts = localtime(&my_time);
return ((ts->tm_mday -1) / 7) + 1;
}
For 0-index, drop the +1 in the return statement.
Consider this pseudo-code, since I am writing it in mostly C syntax but pretending I can borrow functionality from other languages (string->int assignment, string->time conversion). Adapt or expand for your language of choice.
int week_num_in_month(time_t timestamp) {
int first_weekday_of_month, day_of_month;
day_of_month = strftime(timestamp,"%d");
first_weekday_of_month = strftime(timefstr(strftime(timestamp,"%d/%m/01")),"%w");
return (day_of_month + first_weekday_of_month - 1 ) / 7 + 1;
}
Obviously I am assuming that you want to handle weeks of the month the way the standard time functions handle weeks of the year, as opposed to just days 1-7, 8-13, etc.