Sprache || Language
Emacs-/Linux-Inhalte werden auf Englisch veröffentlicht.
Emacs-/Linux related content will be published in English.
Dealing with working days
I have x vacation days, by contract with my employer. How many did I take already? How many are left for the current year?
How many business days until deadline y, of course excluding holidays and leave days? Can I finish this project on time?
How many sick days did I have in 2020?
For my amusement (or for doing my taxes) I might need to know how many days I worked in 2021 - not counting public holidays, sick days or vacation days.
I want to schedule daily standups, jour fixes, reoccuring maintenance tasks - they should not clutter my agenda view when I'm on leave though.
Some org-mode
magic, some of elisp
, and all of this becomes easy.
Let me introduce to you: duty.el
(an Emacs package)!
Disclaimer
This sounded way more consequential than it should. This is basically my first published piece of elisp - it is way worse written than it could be, while doing way less than it should.
Consider it a WIP, because I do.
I stumbled across this (Counting working days again) blog post by Marcin Borkowski while reading the 2022-11-07 Emacs news by Sacha Chua. This teased me to write about and publish my own version of accomplishing similar things.
Please do not hesitate to contact me to suggest improvements, but also to try out if this packages works for you.
Examples of what I do using duty.el
-
counting days
- counting workdays in any given time frame
- counting non-workdays in any given time frame
- counting vacation days in any given time frame
-
scheduling tasks
- only on work days
- only on non-work days
- only on days before a work day
-
marking in
org-mode
- work days
- vacation days
- sick days
-
having an overview over
- how many vacation days I already took that year
- how many are left
-
planning vacations by
- selecting time frame in
M-x calendar
-
automatically creating/scheduling tasks for
- requesting that time frame as vacation with my employer
- awaiting acceptance/decline
- generating the elisp for the date range, which a lot of the magic here is built on
- setting up an absence note on the last workday before my absence
- inform colleagues about loose strings on the last workday before my absence
- selecting time frame in
How I do these things using duty.el
Counting days
In M-x calendar
, pressing M-=
counts days between point and mark
(Basically, what non emacs users know as a selection. In this case a
selection of dates).
Pressing C-u M-=
counts workdays in that same region.
Pressing C-u C-u M-=
counts non workdays in that same region.
Pressing C-u C-u C-u M-=
counts vacation days in that same region.
This may be updated to select type of days to count via list selection instead of stacking universal arguments C-u
.
Scheduling tasks and marking in org-mode
org-mode
supports diary-style expression entries. The following
entry would display the task "Important task" on 10. November 2022 (at
least with calendar-date-style
configured to 'iso
).
* Important task
<%%(diary-date 2022 11 10)>
These expressions can get arbitrarily complex. And since these are simply elisp functions, you can hide them behind your own function names:
* Work days
<%%(duty-work-days)>
* Vacation days
<%%(duty-vacation-days)>
* Sick days
<%%(duty-sick-days)>
* 9:00-9:15 Daily Standup
<%%(duty-work-days)>
* 20:00 Go to bed early
<%%(duty-days-where-next-day-is-a-work-day)>
Planning new vacation days
Pressing i v
("insert vacation" mnemonic) in M-x calendar
to
create a bunch of tasks for arranging to get time off in the selected
time range and things to work through for when I'll actually be able
to leave.
Overview over vacation days
Pressing C-c C-x C-c (M-x org-columns)
at the location of the
created tasks mentioned in the previous section displays the duration
of each leave while also adding them up for the info on how many one
took in total.
What's required to be able to do this
Package installation
I recommend the following.
Clone duty.el repo from github or download duty.el directly.
(add-to-list 'load-path "~/path/to/duty.el")
(require 'duty)
(keymap-set calendar-mode-map "M-=" 'duty-calendar-count-days-region)
(keymap-set calendar-mode-map "i v" 'duty-calendar-new-holidays)
I had issues with the package loading too late with use-package
and getting a buch of errors (bad s-exps) in my org files. If you
know how to circumvent this issue I'd be glad to hear from you.
General
It is mostly about maintaining the functions duty-work-days
,
duty-vacation-days
and duty-sick-days
, as well as an one time
effort to define duty-holiday-days
.
You can define arbitraty types of days next to work-days, vacation-days and sick-days to keep track of.
duty-holiday-days
uses the calendar-holidays
format, so you
could in theory (setq duty-holiday-days 'calendar-holidays)
. In
practice this is not a good idea, since it, by default, contains a lot of days
you'll most probably still have to work on.
The elisp to add into duty-vacation-days
is automatically generated
and added to a task when calling duty-calendar-new-holidays
.
But you could also write it yourself - or by pressing i d
or i b
in M-x calendar
to let emacs create a diary-date or diary-block
expression for you anytime.
This is also the easiest way to create expressions to add to
duty-sick-days
.
Examples
duty-work-days
(defun duty-work-days ()
(and
(not (duty-is-weekend-p date))
(not (duty-is-official-holiday-p date))
(not (duty-vacation-days))
(not (duty-sick-days))
(diary-block 2022 01 01 2025 12 31) ; time of employment
))
duty-vacation-days
(defun duty-vacation-days ()
(and
(not (duty-is-weekend-p date))
(not (duty-is-official-holiday-p date))
(or (diary-date 2022 02 14)
(diary-block 2022 04 15 2022 04 22))))
duty-sick-days
(defun duty-sick-days ()
(diary-block 2022 02 01 2022 02 08) ; Covid
(diary-date 2022 03 01) ; my finger hurt
)
Planning new vacation days
Create a new file like ~/vacation-planning.org
and set
duty-org-refile-target
accordingly.
After that pressing i v (M-x duty-calendar-new-holidays)
in
M-x calendar
does the trick for the most part.
It will append a set of tasks in duty-org-refile-target
.
You'll notice that these tasks are german, as well as specific to my
use case by default. As of writing this there is no good
customization workflow available, so you'll need to get your hands
dirty and change/overwrite the
duty-work-new-holidays-org-project-for
function.
The part at the end could look something like this for you:
(insert
"\n* TODO " days-string "\n"
":PROPERTIES:\n"
":DURATION: " (number-to-string day-count) "\n"
":END:\n"
"** NEXT request this period\n"
":PROPERTIES:\n"
":TRIGGER: " days-string-id "-reply(WAIT)\n"
":END:\n"
"** TODO await acceptance/decline\n"
":PROPERTIES:\n"
":ID: " days-string "-reply\n"
":TRIGGER: chain-siblings(NEXT)\n"
":END:\n"
"** TODO add to duty-vacation-days (when accepted)\n"
diary-date-string "\n"
"** TODO check responsibilities\n"
"SCHEDULED: <" work-day-before-string " 8:30>\n"
"Inform colleagues:\n"
"- something that did not get done?\n"
"- appointments I cannot attend?\n"
"** TODO enable absence notice\n"
"SCHEDULED: <" work-day-before-string " 15:30>\n")
Adapt to your needs.
Overview over vacation days
I add :COLUMNS: %7TODO(State) %65ITEM(When) %DURATION(Dur in d.){+}
to a heading I refile my tasks (created by M-x calendar i v
(duty-calendar-new-holidays)
) to. This uses the DURATION property
thats automatically calculated at task generation time.
* Vacation planning
:PROPERTIES:
:COLUMNS: %7TODO(State) %65ITEM(When) %DURATION(Dur in d.){+}
:CATEGORY: vacation
:END:
** 2022
*** left from 2021
:PROPERTIES:
:DURATION: -2
:END:
*** approved
entries created by duty-calendar-new-holidays, refiled again once approved
*** pending
entries created by duty-calendar-new-holidays
When now using org-columns
, you will have an overview about how many
actual days a vacation period takes, as well as a running total for
that year. You could add another heading with the negative amount of
your total vacation days like
*** Vacation days by contract
:PROPERTIES:
:DURATION: -30
:END:
to spare youself from the burden of calculating the days you have left yourself.
Hallo, Welt!
Handyhalterung im Mercedes W203 mit Kuda Halterung, foto-kontor Adapterplatte, Wicked Chili Universalhalter
Emacs