Conky Calendar with Date Highlight

Since I got a new desktop a month or so ago, I’ve been running Ubuntu as my main operating system, and am using Conky for a nice heads-up-display. There are a lot of articles on the web about both Ubuntu and Conky, but one thing I couldn’t find a good, accurate how-to on was getting a calendar that highlighted the current date. While getting the calendar is easy using the cal command, actually getting the date highlighted is somewhat hard, and all of the articles I found suggested methods that broke in various situations. However, I managed to get it all worked out, and have a beautiful calendar that looks like this:

After the jump, I’ll give you the code and explain how it all works.

How it Works:

The code from ~/.conkyrc that makes this calendar is simple:

Edit: I’ve updated the code as Zacco suggested in the comments to fix a minor bug on certain dates.

${color orange}CALENDAR ${hr 2}$color
${execpi 60 DJS=`date +%_d`; cal | sed s/"\(^\|[^0-9]\)$DJS"'\b'/'\1${color orange}'"$DJS"'$color'/}}

This is a somewhat complicated expression, but what it does is fairly simple. The first line simply draws the title for the section, and it’s the second line that does the magic. Let me break it down and explain it.

${execpi 60

This command tells Conky to execute the next argument every 60 seconds, and, importantly, parse the output of that argument. This way, when we put in commands that change the text color, Conky will obey them instead of printing them.

DJS=`date +%_d`;

DJS (which stands for “date” followed by my initials) is a temporary variable that holds the current day of the month, padded with a leading space, if necessary (so that we’ll catch the first of the month, not every 1 in the calendar, for example).

cal |

cal simply prints out a simple calendar, and the pipe feeds that output through to the next commmand:

sed s/"\([^0-9]\)$DJS"'\b'/'${color orange}'"$DJS"'$color'/

This is one big mess of a command, but the main body is a regex that sed takes as an argument. The regex searches for the string “\([^0-9]\)$DJS”‘\b’, which means the contents of the variable DJS (which we set earlier) preceded by anything other than a digit, and followed by a word boundary – a change from printable characters to white space. This means that it will find the current date (one or two digits) but won’t find the 3 of the 30th on the third of the month. It also means that it will work correctly if the current date is on the far left or right column of the calendar.

The second half of the regex simply wraps what it found the first time around in a couple of Conky commands that change to color to orange, and then back to what it was before.

Lastly, the closing bracket (}) at the end of the line closes out the opening one that is required for all Conky commands with arguments.

Now go forth and cover your desktop in beautiful calendars.

Update: Erik in the comments has a modification to center the entire calendar, if left-aligning isn’t for you.

23 thoughts on “Conky Calendar with Date Highlight

  1. Erik

    Thanks for the conky calendar line, works great.
    I did make one slight modification to the main line to get the calendar to center in the conky space it was in. I piped it through sed again to replace the beginning of each line with ${alignc}(For some reason it didn’t work if you placed the ${alignc} at the beginning of the conky config line. It would only align the first line.) Anyways, thought you might like to see it so here it is. Thanks again… -Erik

    ${font DejaVu Sans Mono :size=8}${execpi 60 DJS=`date +%_d`; cal | sed s/”$DJS”‘\b’/’${color orange}'”$DJS”‘$color’/ | sed s/^/’${alignc}’/}

  2. sethjust Post author

    Very nice. I have my conky hug the left side of my screen, so I prefer the calendar left-aligned, but good job on getting the alignment to work. It looks like you’re using sed to insert an ${alignc} at the beginning of each line. Awesome.

  3. sethjust Post author

    First, because I have no knowledge of Lua or using it with conky. Second, because I figured it out without Lua – using the command line works perfectly well.

  4. Sean

    When using Erik’s modified code, I get an error and no calendar…

    “sh: Syntax error: Unterminated quoted string” any ideas?

  5. sethjust Post author

    There seems to be some problem with the quotes in his code, probably caused by posting to the web, then copy-pasting into a script. If I get a chance to hack through it I’ll post a fixed version, otherwise I think that the quotes just need to be jiggled to match properly.

  6. Zacco

    Thanks for this compact solution! There is a little problem with it however: depending on the location of the days, the year may also be coloured. E.g. today is 2010.12.10 and both the 10 in 2010 and 10 amongst the days are coloured. There is a relatively easy fix to that however: we do not colour if the match is preceded by a number:

    ${execpi 60 DJS=`date +%_d`; cal | sed s/”\([^0-9]\)$DJS”‘\b’/’\1${color orange}'”$DJS”‘$color’/}

  7. Zacco

    Hi,

    You’re welcome. As I was playing with this, I have found something that you may be interested in as well.
    I wanted to have several month visible. As date prints 3 months in the same row, your solution would higlight the current day in each, which is clearly not what we want. But if we print the previous and next month separately before and after the current month (vertically), respectively, without applying the highlighting, the result is what I needed. Maybe others will find it useful, too.

    ${execpi 60 YEAR=`date --date='1 month ago' +%_Y`; MONTH=`date --date='1 month ago' +%_m`; cal -m $MONTH $YEAR}

    ${execpi 60 DJS=`date +%_d`; cal | sed s/โ€\([^0-9]\)$DJSโ€โ€˜\bโ€™/'\1${color orange}โ€™โ€$DJSโ€โ€˜$colorโ€™/}

    ${execpi 60 YEAR=`date --date='next month' +%_Y`; MONTH=`date --date='next month' +%_m`; cal -m $MONTH $YEAR}

  8. Zacco

    For some reason, my previous comment was altered after submission: your command to display the current month with today’s highlighting should be placed in between the previous and next month (in the preceding comment) in order to get 3 months vertically.

  9. joeham

    The new 1.8.x conky breaks the old script.

    They “iixed” alignc in the newer conky and the ${alignc} that is used on every new line in your script to parse the cal output is now longer needed. I removed it and now the script works in newer rev of conky.

    Your script is quite popular and there are posts from people encountering this bug. Most just recommend reverting to older conky versions.

    I am hoping you make this available as a fix so people can continue using your conky calendar script.

  10. sethjust Post author

    I haven’t had a chance to check that out (I’m away from my Ubuntu box for the next few weeks), but thanks for the tip! I don’t use alignc anyway, but it’s good to know!

  11. Zacco

    On 27th Dec, I realized that my modification was not at all perfect :) I guess you noticed it, too! Here’s the fix:

    ${execpi 60 DJS=`date +%_d`; cal | sed s/โ€\(^\|[^0-9]\)$DJSโ€โ€˜\bโ€™/’\1${color orange}โ€™โ€$DJSโ€โ€˜$colorโ€™/}

    I.e. if the day appears in the first position in the calendar, it must be highlighted.

  12. sethjust Post author

    Good spot — I actually hadn’t seen that because I’m away from my Ubuntu box for the holidays. I’ve updated the code in the post. Thanks!

  13. Ernesto

    How about this one:
    ${color darkcyan}${voffset -2}${hr 1}
    ${color}${time %H:%Mh}${alignr}${time %m-%d-%y}
    ${voffset -16}${font :size=18}${color darkCyan}${alignc}${time %I:%M%P}${font}
    ${voffset 4}${color darkcyan}${alignc}${time %A %B %d, %Y}
    ${font}${voffset -4}${color darkcyan}${hr 1}
    ${color}${font Bitstream Vera Sans Mono:bold:size=09}${execpi 150 cal -h | grep -v b | grep -v J | grep -v Ma | grep -v A | sed s/” $(date +%e)”/\$\{“color tan1”}\&\$\{color}/ | sed s/”$(date +%e) “/\$\{“color cyan”}\&\$\{color}/ | sed s/”$(date +%a | cut -c1-2)”/\$\{“color tan1”}\&\$\{color}/}

  14. SStookey

    Hey guys… I know its been about a year since anybody has posted comments on this particular thread but i would like to add something that was giving me much headache over trying to get the date to highlight correctly in my version of Ubuntu 11.10. Hopefully if someone else is wanting this on there desktop it will save them the headache. Your guys code works wonderfully but instead of the day of the month being highlighted i would get this _[] []_ around the date. I soon realized that it was the block highlight from the cal command that was screwing everything up. I used cal -h instead of cal to fix this problem. It prints out just a standard calendar with no highlight. The code that seth wrote and that others have modified takes care of the highlighting like it should. LINUX_4_LIFE

  15. sethjust Post author

    I realize that I didn’t cover this in the post, but the calendar display relies on using a fixed-width font to align the text properly because conky only offers simple alignment tools. In your case, it looks like the font you’re using has spaces that are more narrow than the numbers, so things don’t line up properly. I use the line xftfont Bitstream Vera Sans Mono:size=8 to change my entire conky setup to use a fixed-width font, but the comment above by Ernesto shows an example of setting the font for only the calendar.

  16. Marco

    There are some circumstances in which the cal command highlights the current day by default (happens in debian 7), resulting in sed not properly parsing the current day. This is easily fixed by running “cal -h” instead of “cal”.

  17. thebeast5282

    Any advice if we were trying to Highlight the current date and also make it larger?
    As in, the calendar writes out in font size 11, but the current date is increased to font size 12. I’ve been stuck trying to do it for quite some time :/

  18. chris

    Hello from the future. For anyone looking to use Erik’s code to center the calendar, thankfully I was able to use ChatGPT to fix / finish it, and it works!

    Here is is (hopefully it pastes here properly):
    ${execpi 60 DJS=date +%_d; cal | sed s/”(^|[^0-9])$DJS”‘\b’/’\1${color yellow}'”$DJS”‘$color’/ | sed ‘s/^/${alignc}/’}

Leave a Reply

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