HyCal — Hybrid ISO week–Gregorian calendar with color themes (Bash package)

Below you find the latest version of (1) the package's README and (2) its main source file.

For the git repository and issue tracker, see the project's page on sr.ht.

For more packages, see Software.


README.org

Overview

HyCal is a hybrid ISO week–Gregorian colored calendar for your terminal.

It has the layout of an ISO week calendar, yet the first day of each Gregorian calendar month is shown with a distinct color.

You can customize many of its features, including the color theme.

  • It ships with a few themes, and you can create as many others as you want.
  • There're more than 16.7 million colors to choose from — so you can customize its look to your heart's content.

Examples

Let's pick two dates, one of which is in the first day of a month.

Then let's pass both dates to:

  • the themes that ship with HyCal
  • a monochrome (-cn) alternative

HyCal's own themes

Default 24

Regular day:


     2042-04-02   Wednesday   12:42:42 +00                                                        2042-W14-3

Mon  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚
Tue  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Wed   □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □
Thu  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Fri  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sat  ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sun  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
            05        10        15        20        25        30        35        40        45        50

First of the month:


     2042-05-01   Thursday   12:42:42 +00                                                         2042-W18-4

Mon  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚
Tue  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Wed   ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Thu  □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □
Fri  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sat  ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sun  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
            05        10        15        20        25        30        35        40        45        50

Lighthearted

Regular day:


     2042-04-02   Wednesday   12:42:42 +00                                                        2042-W14-3

Mon  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚
Tue  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Wed   □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □
Thu  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Fri  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sat  ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sun  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
            05        10        15        20        25        30        35        40        45        50

First of the month:


     2042-05-01   Thursday   12:42:42 +00                                                         2042-W18-4

Mon  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚
Tue  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Wed   ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Thu  □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □
Fri  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sat  ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sun  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
            05        10        15        20        25        30        35        40        45        50

Palish

Regular day:


     2042-04-02   Wednesday   12:42:42 +00                                                        2042-W14-3

Mon  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚
Tue  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Wed   □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □
Thu  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Fri  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sat  ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sun  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
            05        10        15        20        25        30        35        40        45        50

First of the month:


     2042-05-01   Thursday   12:42:42 +00                                                         2042-W18-4

Mon  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚
Tue  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Wed   ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Thu  □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □
Fri  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sat  ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sun  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
            05        10        15        20        25        30        35        40        45        50

Pinkify

Regular day:


     2042-04-02   Wednesday   12:42:42 +00                                                        2042-W14-3

Mon  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚
Tue  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Wed   □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □
Thu  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Fri  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sat  ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sun  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
            05        10        15        20        25        30        35        40        45        50

First of the month:


     2042-05-01   Thursday   12:42:42 +00                                                         2042-W18-4

Mon  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚
Tue  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Wed   ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Thu  □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □
Fri  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sat  ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sun  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
            05        10        15        20        25        30        35        40        45        50

Seagreeny

Regular day:


     2042-04-02   Wednesday   12:42:42 +00                                                        2042-W14-3

Mon  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚
Tue  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Wed   □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □
Thu  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Fri  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sat  ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sun  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
            05        10        15        20        25        30        35        40        45        50

First of the month:


     2042-05-01   Thursday   12:42:42 +00                                                         2042-W18-4

Mon  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚
Tue  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Wed   ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Thu  □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □
Fri  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sat  ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sun  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
            05        10        15        20        25        30        35        40        45        50

Monochrome alternative

Regular day:


     2042-04-02   Wednesday   12:42:42 +00                                                        2042-W14-3

Mon  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ▫ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ▫ ⬚ ⬚ ⬚
Tue  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ▪ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ▫ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Wed  ▪ □ □ □ □ □ □ □ □ □ □ □ □ ■ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ ▪ □ □ □ □ □ □ □ □ □ □ □ □
Thu  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ▫ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Fri  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ▫ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sat  ⬚ ⬚ ⬚ ⬚ ▫ ⬚ ⬚ ⬚ ▫ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ▫ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sun  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ▫ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
            05        10        15        20        25        30        35        40        45        50

First of the month:


     2042-05-01   Thursday   12:42:42 +00                                                         2042-W18-4

Mon  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ▫ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ▫ ⬚ ⬚ ⬚
Tue  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ▫ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ▫ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Wed  ▫ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ▫ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Thu  □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ ■ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □
Fri  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ▫ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sat  ⬚ ⬚ ⬚ ⬚ ▫ ⬚ ⬚ ⬚ ▫ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ▫ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sun  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ▫ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
            05        10        15        20        25        30        35        40        45        50

Your own theme

Making your own theme is easy.

Look, here's all there is to seagreeny:

C_Y=1.seagreen1      # Year
C_m=1.seagreen       # Month
C_d=1.darkseagreen1  # Day
C_hyp=1.seashell4    # Hyphen

C_A=1.darkseagreen3  # Weekday name

C_H=1.seashell3      # Hour
C_M=1.seashell3      # Minute
C_S=1.seashell3      # Second
C_z=0.seashell4      # Timezone
C_col=0.seashell4    # Colon

C_G="$C_Y"           # ISO week year
C_V=1.lightseagreen  # ISO week number
C_u="$C_A"           # ISO week day

C_a="$C_A"           # Weekday abbreviation
C_now="$C_d"         # Square for today
C_1st="$C_m"         # Square for 1st of the month

Just replace these colors with some combination that you like.

When you're finished:

  • save it to /path/to/your/themes/name-of-the-theme
  • and add to your ~/.config/hycal.rc file:
    • a line HYCAL_THEMES_DIR_USER=/path/to/your/themes
    • a line HYCAL_THEME=name-of-the-theme (optional, if you want to set it as default)

Done. You have your own theme.

The color syntax is that of Ecos (see for details). Basically:

  • the 0 or 1 means regular or bold; the 0 can be omitted
  • the . means: use 24-bit colors (/ = 4-bit, : = 8-bit)
  • for 24-bit, you can enter either:
    • X11 color names (.seagreen1)
    • or RGB in dec (.84.255.159)
    • or RGB in hex (.#54ff9f)

If you want to simplify your color choices to 12 bits, short hex syntax is also supported: #ace instead of #aaccee.

To see the more than 500 X11 color names in their own color, run: ecos -u lnc.

Picking a random theme

Want to tell HyCal to pick a theme randomly? Try this:

hycal -t "$(hycal --tl a | shuf -n1)"

or replace a with:

  • u for it to pick only from your themes
  • h for it to pick only from its own

Going glocal

« Mais non ! C'est tout en anglais, ces jours-ci. Je déteste ça. Mon calendrier je le veux en français ! »

Got it. You want:

  • the advantages of a well-thought universal standard for representing and keeping track of time and
  • the flavor of your local culture.

Pas de problème : HyCal can be glocalized:

  • both Gregorian date and ISO Week date are shown in ISO 8601 format and
  • weekday names and their abbreviations are shown in your locale.

Inspired by those garden gnomes from Amélie, Pinkify went on a quick tour just to send you selfies.

(An incredibly fast flyer, Pinkify managed to take them all at the exact same local time!)

🇯🇵 日本


   2042-04-02   水曜日12:42:42 +09                                                            2042-W14-3
    
  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚
  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
   □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □
  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
  ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
           05        10        15        20        25        30        35        40        45        50

🇧🇬 България


    2042-04-02   сряда12:42:42 +03                                                            2042-W14-3
    
пн  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚
вт  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
ср   □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □
чт  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
пт  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
сб  ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
нд  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
           05        10        15        20        25        30        35        40        45        50

🇨🇭 Schweiz


    2042-04-02   Mittwoch12:42:42 +02                                                         2042-W14-3
    
Mo  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚
Di  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Mi   □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □
Do  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Fr  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sa  ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
So  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
           05        10        15        20        25        30        35        40        45        50

🏴󠁧󠁢󠁷󠁬󠁳󠁿 Cymru


     2042-04-02   Mercher12:42:42 +01                                                          2042-W14-3
     
Llu  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚
Maw  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Mer   □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □
Iau  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Gwe  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sad  ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
Sul  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
            05        10        15        20        25        30        35        40        45        50

🇬🇱 Kalaallit Nunaat


     2042-04-02   pingasunngorneq‎12:42:42 −02                                                  2042-W14-3

ata  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚
mar  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
pin   □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □
sis  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
tal  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
arf  ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
sap  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
            05        10        15        20        25        30        35        40        45        50

🇨🇦 Canada


     2042-04-02   mercredi12:42:42 −04                                                         2042-W14-3
     
lun  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚
mar  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
mer   □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □  □ □ □ □ □ □ □ □ □ □ □ □
jeu  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
ven  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
sam  ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
dim  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ □ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚  ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚
            05        10        15        20        25        30        35        40        45        50

Et voilà !

Troubleshooting

"I see a bunch of \xfu"

Pick UTF-8 as charmap.

HyCal is unlikely to work with locales that aren't UTF-8. (Try hycal -l foo and you'll see a bunch of \xfu.)

In most cases, .utf8 is appended to the locale name to indicate it, but some locales (e.g., sw_KE) are UTF-8 without this suffix.

"My calendar looks wavy"

Pick a good monospace font.

Two things cause alignment issues:

  • Inappropriate font. Your terminal should be using a monospace font. If you mix fonts, or if it's not internally consistent in its width — especially when it changes to another script —, then your calendar will look wavy. Some tests suggest that HyCal looks good in DejaVu Sans Mono Book and Noto Mono Regular.
  • Miscounted spaces. See below.

"My ISO week date isn't right-aligned to the calendar's last week"

This may be a problem of font choice: see above. If not, then it might be something I couldn't yet solve.

The amount of spacing between the timezone and the ISO week date needs to be calculated, which depends on the exact screen width of weekday names, which depends on the script, which depends on the chosen locale.

Here are some cases I identified and their status.

Solved
[X] Nynorsk
Weekday names in nn_NO. They have a trailing space for some reason. Trimmed.
[X] Alphabets
Weekday names in non-Latin alphabets (in the strict sense of the word). Straightforward from string length.
[X] Diacritics
Weekday names with NFC-normalized diacritics (e.g., "Miércoles"). Straightforward from string length.
[X] RTL scripts
Runs of right-to-left script inside left-to-right. Stabilized with a left-to-right mark.
[X] CJK scripts
Chinese, Japanese, and Korean: characters in Hang, Hani, Hans, Hant, and Hrkt are double-width. Detected and adjusted.
[X] Some abugidas
Unicode encodes as single characters every combination of Ethiopic and Canadian syllabics. So Ethi and Cans are solved.
Still unsolved
[ ] Most abugidas

Combining characters are zero-width, yet count as one for string length.
So an adjustment is needed when weekday names have them.

This affects most abugidas, for which vowels and markers are combining characters.

I tried enumerating these characters, but:

  • there're about 90 of them spread over a few Unicode blocks
  • PCRE doesn't work with \u
  • and pasting all of them jumbled on top of each other inside a bracket expression:
    • is an inelegant, awkward solution
    • that looked terribly fishy
    • and didn't seem to work for some cases.

What I'd like here is a simple non-expensive Bash way to count the number of Non-Spacing Marks in a string.

I had other things to do, so decided to drop this issue for now.

Completion

You can add completion to hycal, so that if you <tab><tab> with the cursor here:

hycal -t ★

you'll see the names of the available themes to choose from, and if you <tab><tab> with the cursor here:

hycal -l ★

you'll see all locales to choose from.

In the case of locales, you can complete for any part of it, not just the locale's beginning. See hycal -h for examples.

These are the most useful completions, but it also works when you <tab><tab> while in other parts of a hycal command.

Run hycal -h to see how to enable it.

Known limitations

Completion for themes with spaces in their filenames won't work.
That's ok: just avoid spaces in themes' filenames (or don't complete them).

Completion for --ec and --rc won't expand tildes to pick filenames from.
That's ok: you can manually expand your tilde with M-& (Alt-&). Then <tab><tab> to complete.

Usage

The docstring of hycal() will tell you all about it.

You can see it:

  • Online, at the package's page.
  • Or by running either hycal -h (with colors) or hycal -H (monochrome).

Installation

See my page Software for information about how to download and install my packages.

Dependencies

To run HyCal, you need:

Executable Package (usually¹)
ecos see ecos (same author)
column bsdextrautils or util-linux
date coreutils
getopt util-linux
grep grep
less less
sed sed
xargs findutils

¹ These are the usual package names that have these executables, but your distro may package them differently.

Contributing

See my page Software for information about how to contribute to my packages.

News

0.2.0

Release

See also

Other packages

To produce colors, HyCal depends on Ecos, another package of mine.
Ecos makes it easy to add colors and effects to text that is output to your terminal.

License

This project follows the REUSE Specification (FAQ), which in turn is built upon SPDX.

Therefore, license and copyright information can be found in:

  • each file's comment header, or
  • an adjacent file of the same name with the additional extension .license, or
  • the .reuse/dep5 file

The full text of the licenses can be found in the LICENSES subdirectory.


hycal

Structure

## HyCal --- Hybrid ISO week–Gregorian calendar with color themes
## Commentary
### See the README for more information
## Code
### Settings
### Functions
#### Main
#### Internal
##### Validate input
###### Validate date
###### Validate theme
###### Validate file
##### Set defaults
##### Source files
##### Output whole calendar
##### Output calendar parts
###### Calendar header
###### Calendar x-axis
###### Calendar y-axis
###### Calendar proper
##### Show or list themes
##### Utilities
##### Enable completion
#### Get help
### Run it and exit
## HyCal ends here

Contents

#!/usr/bin/env bash

## HyCal --- Hybrid ISO week–Gregorian calendar with color themes

# SPDX-FileCopyrightText: © flandrew <https://flandrew.srht.site/listful>
# SPDX-License-Identifier: GPL-3.0-or-later

#---------------------#
# Author:  flandrew   #
# Created: 2025-W51-3 #
# Updated: 2026-W02-6 #
#---------------------#
# Version: 0.2.0      #
#---------------------#

## Commentary
#
# HyCal is a hybrid ISO week–Gregorian calendar for your terminal.
#
# It has the layout of an ISO week calendar, yet the first day of each
# Gregorian calendar month is shown with a distinct color.
#
# You can customize many of its features, including the color theme.
# - It ships with a few themes, and you can create as many others as you want.
# - There're more than 16.7 million colors to choose from — so you can
#   customize its look to your heart's content.
#
# For help, run: hycal -h (or -H)
#
### See the README for more information
#
# A local README.org should be available in the same directory as this file.
#
# You can also read it online:
#   https://flandrew.srht.site/listful/sw-bash-hycal.html
#
#############################################################################

#⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
## Code
### Settings

LC_ALL=C.utf8
set -eo pipefail
hash column date getopt grep less sed || exit 127

#⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
### Functions
#### Main

hycal()
{ : _options <<_
HyCal --- Hybrid colored ISO week calendar for your terminal

Usage:
  hycal [-t THEME] [-l LO] [-c(y|n)] [--rc RC] [--ec EC] [[-d] WHEN]
        [--xf (weeknum|none)] [--xp (bottom|top|none)] [--xs NATNUM]
        [--yf (abbrev|none)]  [--yp (left|right|none)] [--hf (full|year|none)]

  hycal --t(l|s) (a|u|h)
  hycal --complete
  hycal -(h|H)

Options:
  | Flag | Description                    |
  |------+--------------------------------|
  | -h   | help (colors)                  |
  | -H   | help (monochrome)              |
  |------+--------------------------------|
  | --rc | path to your hycal config file |
  | --ec | path to ecos library file      |

And:
  | Flag | Desc.  | Default      | Alternatives                      |
  |------+--------+--------------+-----------------------------------|
  | -d   | date   | now          | some date accepted by date -d     |
  | -t   | theme  | default4     | name of theme; path to theme file |
  | -l   | locale | your current | other locale                      |

And:
  | Flag | Description   | Default | Alternatives           |
  |------+---------------+---------+------------------------|
  | -c   | colored?      | y       | n                      |
  |------+---------------+---------+------------------------|
  | --hf | header format | full    | none, year             |
  |------+---------------+---------+------------------------|
  | --xf | x-axis format | weeknum | none                   |
  | --xp | x-axis place  | bottom  | none, top              |
  | --xs | x-axis step   | 5       | (other natural number) |
  |------+---------------+---------+------------------------|
  | --yf | y-axis format | abbrev  | none                   |
  | --yp | y-axis place  | left    | none, right            |

And:
  | Flag | Description | Default | Alternatives               |
  |------+-------------+---------+----------------------------|
  | --tl | list themes |         | a, u, h (all, user, hycal) |
  | --ts | show themes |         | a, u, h (all, user, hycal) |

_____________________________________________________________________________

The defaults flags are, therefore:
hycal -dnow -cy --hf full --xf weeknum --xp bottom --xs 5 --yf abbrev --yp left

Flags are processed in order. If they conflict, the one given last wins.
_____________________________________________________________________________

Dates:

Anything you pass that isn't preceded by a dashed option will be considered to
be dates. In that case, the last one will be used instead of "now" and instead
of any date you may have previously passed to the -d option.

And although /usr/bin/date doesn't accept ISO week dates as input, HyCal does.
So these work:
  hycal  2042-W04-2
  hycal '2042-W04-2 71 days'
_____________________________________________________________________________

Dependencies:

HyCal needs Ecos, a color library by the same author.

It'll try to find and source these one by one until it succeeds:
- whatever you pass as a path to --ec in the command line
- PATH_TO_ECOS (as set in your hycal.rc file)
- some file named ecos anywhere in your PATH
_____________________________________________________________________________

Config:

HyCal will use your config file if available. It'll try these one by one:
- use the file at the path that you pass to --rc
- look for XDG_CONFIG_HOME/hycal.rc
- look for ~/.config/hycal.rc
- look for ~/hycal.rc
- don't use a config file, falling back to sane defaults

A config-examples/hycal.rc is provided — look into it.
_____________________________________________________________________________

Themes:

HyCal can use themes, of which it provides some.

To pick a theme, HyCal will try these until it succeeds:
- whatever you pass to -t in the command line
- HYCAL_THEME variable in your rc file

In either case:
- if it's a file with full or relative path, it'll try that first
- failing that, if it's just a name, it'll look for a file thus named in:
  - the directory HYCAL_THEMES_DIR_USER, if you set that in your rc file
  - hycal's directory's themes subdir, which is either:
    - the directory HYCAL_THEMES_DIR_HYCAL, if you set that in your rc file
    - subdir "themes" of hycal's executable's parent

If subdir "themes" is no longer under the same directory where you put hycal
executable, you must set HYCAL_THEMES_DIR_HYCAL for HyCal to find its themes.

And if you have themes, set HYCAL_THEMES_DIR_USER to point to where they are.

A config-examples/theme is provided — look into it.
_____________________________________________________________________________

Localization:

HyCal will already use your locale, yet you can pass a different one:
  hycal -l bg_BG.utf8   # Bulgarian
  hycal -l cy_GB.utf8   # Welsh
  hycal -l de_CH.utf8   # Swiss High German
  hycal -l fr_CA.utf8   # Canadian French
  hycal -l ja_JP.utf8   # Japanese
  hycal -l kl_GL.utf8   # Greenlandic

After -l, you can <tab><tab> to complete to all locale options
(completion here depends on /usr/bin/locale, part of libc-bin).

Below, ★ is where your cursor is.
Locale completion happens on any part of a locale, not just the beginning.
So if you <tab><tab> after typing:
  hycal -l fr★          # you'll see French-language locales.
  hycal -l utf8★        # you'll see UTF-8 locales.
  hycal -l FR★          # you'll see locales of France.
  hycal -l FR.utf8★     # you'll see UTF-8 locales of France
 (in this last case, five languages: br, ca, eu, fr, oc).

If your chosen locale offers an utf8 alternative, pick that one.

If you're not seeing any locales, you'd need to fetch them. Using your
distribution's package manager, install 'locales-all' or 'locales'.
_____________________________________________________________________________

Completion:

To enable it, add this line to your ~/.bash_aliases or ~/.bashrc:
  . <(hycal --complete)

or, if hycal executable is not in your PATH:
  . <(/path/to/hycal --complete)

and then, when writing a hycal command, press <tab><tab> to show completions.

Note that your interactive shell must be Bash for completions to work.
_____________________________________________________________________________

Read:  https://en.wikipedia.org/wiki/ISO_week_date
_____________________________________________________________________________

_
  local hf xf xp xs yf yp rc ec lo th when color
  opt=$(getopt -n hycal \
               -l 'hf:,xf:,xp:,xs:,yf:,yp:,rc:,ec:,tl:,ts:,complete' \
               -o 'l:t:d:c:=:h::H::' -- "$@")
  eval set -- "$opt"

  while :; do
      case "$1" in
          (--hf)    hf="$2"              ; shift     ;;
          (--xf)    xf="$2"              ; shift     ;;
          (--xp)    xp="$2"              ; shift     ;;
          (--xs)    xs="$2"              ; shift     ;;
          (--yf)    yf="$2"              ; shift     ;;
          (--yp)    yp="$2"              ; shift     ;;
          (--rc)    rc="$2"              ; shift     ;;
          (--ec)    ec="$2"              ; shift     ;;
          (  -l)    lo="$2"              ; shift     ;;
          (  -t)    th="$2"              ; shift     ;;
          (  -d)  when="$2"              ; shift     ;;
          (  -c) color="$2"              ; shift     ;;
          (  -=) hycal--"$2"    "${@:4}" ; exit "$?" ;;
          (  -h) hycal--doc         "$2" ; exit "$?" ;;
          (  -H) hycal--doc-nc      "$2" ; exit "$?" ;;
          (--tl) hycal--themes-list "$2" ; exit "$?" ;;
          (--ts) hycal--themes-show "$2" ; exit "$?" ;;
          --complete) hycal--complete    ; exit "$?" ;;
          ( --) shift                    ; break     ;;
          (  *) echo >&2 "Error"         ; exit 1    ;;
      esac;     shift                    ; continue
  done

  # If there're still args, use the last one as the input date
  if (("$#">0)); then when="${@: -1}"; fi

  # Set the date if it's still unset or null
  : "${when:=now}"

  # Although /usr/bin/date doesn't recognize ISO week inputs, HyCal does:
  when="$(hycal--replace-isoweek-date-with-gregorian-maybe "$when")"

  # Check if input date is valid — or fail now
  hycal--valid-input-date-p "$when"

  # Source user's rc file, if available
  hycal--source-rc "$rc" hycal.rc

  # Set place where HyCal's own themes can be found, if unset
  hycal--set-themes-dir-hycal

  # Source theme chosen by user, if available
  hycal--source-theme "$th" "$HYCAL_THEME"

  # Fall back to color and glyphs defaults if something is still unset
  hycal--load-fallback-theme

  # Source Ecos
  hycal--source-lib "$ec" "$PATH_TO_ECOS" ecos
  hash ecos || exit 127

  # Redefine color
  case "${color:=y}" in y) : color ;; *) : monochrome ;; esac; color="$_"

  # Make sure these params are set, or use default values
  : "${hf:=full}
     ${xf:=weeknum} ${xp:=bottom} ${xs:=5}
     ${yf:=abbrev}  ${yp:=left}"

  # Validate these params
  case  "$hf" in     full|year|none) ;;     *) exit 2 ;;          esac
  case  "$xf" in       weeknum|none) ;;     *) exit 3 ;;          esac
  case  "$yf" in        abbrev|none) ;;     *) exit 4 ;;          esac
  case  "$xp" in         bottom|top) ;;     *) exit 5 ;;          esac
  case  "$yp" in         left|right) ;;     *) exit 6 ;;          esac
  if [[ "$xs" =~ [0-9]+ ]]; then ((xs > 0)) || exit 7; else exit 8; fi

  # Display the calendar
  LC_TIME="${lo:-$LC_TIME}" \
         hycal--cal-"$color" "$when" "$hf" "$xf" "$xp" "$xs" "$yf" "$yp" ;}

#⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
#### Internal
##### Validate input
###### Validate date

hycal--replace-isoweek-date-with-gregorian-maybe()
{ : string <<_
If STRING has a match for ISO week date, replace it with standard Gregorian.
Otherwise just return STRING unmodified.
_
  if hycal--match-isoweek-date "$1"
  then declare G V u f
       read -r G V u <<< "${BASH_REMATCH[@]:2:3}"
       if ((V>53)); then echo >&2 "Invalid date: $1"; return 1; fi
       f="$G-01-04"
       ((_= 7*V-7 + u-"$(date +%u -d "$f")"))
       : "$(date -I -d "$f $_ days")"
       printf -- '%s%s%s' "${BASH_REMATCH[1]}" "$_" "${BASH_REMATCH[5]}"
  else printf -- '%s' "$1"
  fi ;}

hycal--match-isoweek-date()
{ : string <<_
Does STRING have a match for an ISO week date?
Set BASH_REMATCH indices to:
0=all 1=pre 2=%G 3=%V 4=%u 5=post
_
  [[ "$1" =~ ^(.*)([0-9]{4})-W([0-5][0-9])-([1-7])(.*)$ ]] ;}

hycal--valid-input-date-p()
{ : date <<_
Is that date valid?
_
  if ! date -d "$1" >/dev/null 2>&1
  then echo >&2 "Invalid date: $1"; return 1
  fi ;}

#⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
###### Validate theme

hycal--thfile-p()
{ : string <<_
Is STRING an existing, readable, regular file that looks like a theme?
The file must have something that looks like a color or glyph assignment.
It's a quick check to avoid sourcing non-theme files by mistake.
_
  hycal--xrfile-p "$1" && <"$1" grep -Eq '[CG]_[[:alnum:]_]+=' ;}

#⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
###### Validate file

hycal--xrfile-p()
{ : string <<_
Is STRING an existing, readable, regular file?
_
  [[ "$1" && -f "$1" && -r "$1" ]] ;}

#⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
##### Set defaults

hycal--set-themes-dir-hycal()
{ : <<_
Set place where HyCal's own themes can be found, if unset
_
  if [[ -z "$HYCAL_THEMES_DIR_HYCAL" ]]
  then : "$(realpath -m "${BASH_SOURCE[0]}")"
       : "${HYCAL_THEMES_DIR_HYCAL:=${_/%hycal/themes}}"
  fi ;}

hycal--load-fallback-theme()
{ : <<_
Default values to fall back to if empty or unset.
Using 4-bit colors to ensure it's displayable.
_
  # Colors
  : "${C_Y:=1/red}"      # Year
  : "${C_m:=1/blue}"     # Month
  : "${C_d:=1/green}"    # Day
  : "${C_hyp:=1/black}"  # Hyphen

  : "${C_A:=1/magenta}"  # Weekday name

  : "${C_H:=1/yellow}"   # Hour
  : "${C_M:=1/yellow}"   # Minute
  : "${C_S:=1/yellow}"   # Second
  : "${C_z:=0/yellow}"   # Timezone
  : "${C_col:=0/yellow}" # Colon

  : "${C_G:=$C_Y}"       # ISO week year
  : "${C_V:=1/cyan}"     # ISO week number
  : "${C_u:=$C_A}"       # ISO week day

  : "${C_a:=$C_A}"       # Weekday abbreviation
  : "${C_now:=$C_d}"     # Square for today
  : "${C_1st:=$C_m}"     # Square for 1st of the month

  # Glyphs for monochrome
  : "${G_now_t:=■}"      # Today
  : "${G_1st_y:=▪}"      # Some intersection
  : "${G_1st_n:=▫}" ;}   # No intersection

#⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
##### Source files

hycal--source-rc()
{ : rc base <<_
Source an rc file.
First try file RC, presumably passed directly at the command line.
If that fails, look up for file BASE in three places:
"XDG_CONFIG_HOME" (if set), ~/.config, and ~; source the first found.
_
  # See comment in hycal--source-theme for why realpath.
  local rc="$1" base="$2"
  if hycal--xrfile-p "$rc"; then . "$(realpath -m "$rc")"
  else for dir in "$XDG_CONFIG_HOME" ~/.config ~
       do rc="$dir/$base"
          if [[ "$dir" ]] && hycal--xrfile-p "$rc"
          then . "$rc" && return 0; fi
       done
  fi ;}

hycal--source-theme()
{ : files <<_
Source a theme from FILES candidates.
For every FILE, if relative or full path search fails, look for it:
- in user's themes dir, if set.
- in HyCal's own themes subdir.
Once a readable file is found, source it.
_
  # The use of realpath avoids an undesirable corner case: the argument is a
  # relative path that points to an existing file, which returns true for the
  # predicate. It'll then try to source it — but source (aka ".") does that by
  # searching PATH. It may then hit a file of the same name before it reaches
  # PWD, and try to source that file instead.
  #
  # As an example, running this in an empty temp dir:
  #   echo "echo foo" > cat; . cat; . "$(realpath -m cat)"
  #
  # returned:
  #   bash: .: /usr/bin/cat: cannot execute binary file
  #   foo
  #
  # So realpath fixes that, and you can now (file)name your theme "cat".
  local ud="$HYCAL_THEMES_DIR_USER"   # Possible user's themes' dir
  local hd="$HYCAL_THEMES_DIR_HYCAL"  # HyCal's own themes' dir
  for t
  do if [[ "$t" ]]
     then if hycal--thfile-p "$t"; then . "$(realpath -m "$t")"
          elif [[ "$ud" ]] && hycal--thfile-p "$ud/$t"; then . "$ud/$t"
          elif [[ "$hd" ]] && hycal--thfile-p "$hd/$t"; then . "$hd/$t"
          fi && return 0
     fi
  done ;}

hycal--source-lib()
{ : cl rc base <<_
Source a library.
First try file CL, presumably passed directly at the command line.
If that fails, try file RC, presumably a variable from an rc file.
If that fails, try file BASE to be found anywhere in PATH.
_
  # See comment in hycal--source-theme for why realpath.
  local cl="$1" rc="$2" base="$3"
  if   hycal--xrfile-p "$cl"; then . "$(realpath -m "$cl")"
  elif hycal--xrfile-p "$rc"; then . "$(realpath -m "$rc")"
  elif [[     "$base"     ]]; then . "$base"
  fi ;}

#⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
##### Output whole calendar

hycal--cal-color()
{ : when hf xf xp xs yf yp <<_
Assemble and display colored calendar.
WHEN is the date.

| Var | Meaning       | Default | Alternatives           |
|-----+---------------+---------+------------------------|
| HF  | header format | full    | none, year             |
|-----+---------------+---------+------------------------|
| XF  | x-axis format | weeknum | none                   |
| XP  | x-axis place  | bottom  | none, top              |
| XS  | x-axis step   | 5       | (other natural number) |
|-----+---------------+---------+------------------------|
| YF  | y-axis format | abbrev  | none                   |
| YP  | y-axis place  | left    | none, right            |

It's assumed that the values passed had already been validated.
_
  local when="$1" hf="$2" xf="$3" xp="$4" xs="$5" yf="$6" yp="$7" \
        head xaxs tops bots mids core side

  head=$(# The header string
         hycal--cal-header-"$hf" "$when")
  [[ "$head" ]] && head+="\n" ||:

  xaxs=$(# The x-axis string
         hycal--cal-x-axis-"$xf" "$xs")

  case "$xp" in
      bottom) [[ "$xaxs" ]] && xaxs+="\n" ||:
              tops="$head"; bots="$xaxs" ;;
      top)    [[ "$head" && "$xaxs" ]] && head+="\n"
              tops="$head$xaxs"; bots="" ;;
  esac;  [[ "$tops" ]] && tops+="\n" ||:

  mids=$(# The calendar squares
         hycal--cal-proper "$when")
  mids+="\n"

  core="$tops$mids$bots"; core="${core@E}"

  side=$(# The y-axis plus leading and trailing empty lines
         printf -- "%s" "${tops@E}" | sed 's/.*//'
         hycal--cal-y-axis-"$yf"
         printf -- "%s" "${bots@E}" | sed 's/.*//')

  if [[ "$side" ]]
  then case "$yp" in
           left)  paste <(printf -- "%s" "$side") <(printf -- "%s" "$core") ;;
           right) paste <(printf -- "%s" "$core") <(printf -- "%s" "$side") ;;
       esac | column -Lts$'\t'
  else printf -- "%s" "$core"
  fi ;}

hycal--cal-monochrome()
{ : args <<_
Display calendar without SGR (ANSI) colors or effects.
For ARGS, see hycal--cal-color.
_
  # Yes, adding more than a dozen colors to then remove them is inefficient.
  # Nevertheless:
  # - the colorized option had already been implemented
  # - it takes much less code to make it monochrome by using such a filter
  # - colors are the big thing here; the monochrome option was an afterthought
  hycal--cal-color "$@" | hycal--replace-glyphs | hycal--remove-colors ;}

hycal--replace-glyphs()
{ : <<_
Replace default intersection glyphs with alternatives suitable for monochrome.
_
  sed -E "s,[^ ]+⬚[^ ]+,$G_1st_n,g
          s,[^ ]+□[^ ]+,$G_1st_y,g
          s,[^ ]+■[^ ]+,$G_now_t," ;}

hycal--remove-colors()
{ : <<_
Remove colors and effects.
_
  sed -E "s,\x1b\[[0-9;]*m,,g" ;}

#⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
##### Output calendar parts
###### Calendar header

hycal--cal-header-none() { :;}

hycal--cal-header-year()
{ : _when <<_
Display the calendar's header — just the ISO week year, centered.
If optional WHEN is not passed, use "now".
_
  : "$(date -d "${1:-now}" +%G)"
  ecos -- 0 "$(hycal--rep 49)" "$C_G" "$_" ;}

hycal--cal-header-full()
{ : _when <<_
Display the calendar's header — full dates.
If optional WHEN is not passed, use "now".
_
  # Let's right-align the ISO week date with the calendar's squares
  local when="${1:-now}" A nA d1 sp

  :  "$(date -d "$when" +%A)"              # Weekday name in locale
  # ${_% } trims a trailing space in Nynorsk weekday names:
  #   LC_TIME=nn_NO.utf8 date +'_%A_'      # Bokmål is fine:
  #   LC_TIME=nb_NO.utf8 date +'_%A_'
  A="${_% }"; nA="${#A}"

  # In CJK weekday names, characters have double width:
  if [[ "$A" =~ [일日星週禮] ]]; then ((nA*=2)); fi

  d1="$(date -d "$when" +"%Y-%m-%d%T %:::z")"   #         Gregorian date
  :  "$(hycal--num-of-iso-weeks "$when")"       # Weeks in this ISO year
  :  "$((2*_-1 - "${#d1}" - nA - 6 - 10))"      #       Number of spaces
  sp="$(hycal--rep "$_")"                       #                 Spaces

  # Show the date string
  date -d "$when" +"%Y %m %d %H %M %S %:::z %G W%V %u %A" |
      # Why this parsing order?
      #
      # Because %A is the only locale-dependent date format among all these.
      # Weekday names in English happen to be a single word ("Wednesday").
      # But this isn't true for every language. In Albanian ("e mërkurë") and
      # in Irish ("Dé Céadaoin"), for example, they can take two words.
      #
      # By putting %A at the end of read, the whole weekday name is assigned
      # to var $A. (Arrays could have solved it, too, but more verbosely.)
      #
      # And \u200e is a left-to-right mark, used to correctly display runs of
      # RTL scripts inside LTR text. Here, it's after %A, which could be RTL.
      (read -r Y m d H M S z G V u A;  : $'\u200e'
       ecos -r --                          \
            "$C_Y" "$Y"     "$C_hyp" "-"   \
            "$C_m" "$m"     "$C_hyp" "-"   \
            "$C_d" "$d"        0    "   "  \
            "$C_A" "${A% }"    0   "$_   " \
            "$C_H" "$H"     "$C_col" ":"   \
            "$C_M" "$M"     "$C_col" ":"   \
            "$C_S" "$S"        0     " "   \
            "$C_z" "${z/#-/−}" 0    "$sp"  \
            "$C_G" "$G"     "$C_hyp" "-"   \
            "$C_V" "$V"     "$C_hyp" "-"   \
            "$C_u" "$u");}

#⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
###### Calendar x-axis

hycal--cal-x-axis-none() { :;}

hycal--cal-x-axis-weeknum()
{ : step <<_
Make an evenly-spaced sequence of numbers to label the weeks.
The argument is the STEP size.
_
  local st="$1" sp
  ((sp= st * 2 - 2))
  : "$(hycal--rep "$sp")"   # inter-number space-string
  seq -s' ' -w "$st" "$st" 52 | sed "s/ /$_/g; s/^/${_# }/" |
      ecos -f -- "$C_V" '.*' . . ;}

#⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
###### Calendar y-axis

hycal--cal-y-axis-none() { :;}

hycal--cal-y-axis-abbrev()
{ : <<_
Make seven lines with colored weekday abbrevs.
_
  printf "2042-09-0%s\n" {1..7} | date +'%a' -f - |
      ecos -f -- "$C_a" '.*' . . ;}

#⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
###### Calendar proper

hycal--cal-proper()
{ : _when <<_
Display the calendar part of the output.
If optional WHEN is not passed, use "now".
_
  local   u V G when="${1:-now}"
  read -r u V G < <(date -d "$when" "+%u %V %G")
  # Dec 28 is always on ISO year's last week.
  # With that, we get the number of weeks in the year.
  : "$(date -d "$G-12-28" +%V)"  # Number of weeks:
  : "$(hycal--rep "$_" " ⬚")"    # make that many spaced squares...
  hycal--rep 7 "${_# }\n" |      # ...in each of seven lines.
      sed "$u s/⬚/$(ecos -- "$C_now" ■)/$V
           $u s/⬚/□/g
              s/⬚/□/$V
           8d" | hycal--colorize-1st "$when" ;}

hycal--colorize-1st()
{ : _when <<_
Colorize the 1st day of each month of the calendar.
If optional WHEN is not passed, use "now".
_
  declare -a uVs
  read   -ra uVs < <(hycal--uVs "${1:-now}"       |
                         sed "s|^|$C_1st [⬚□■] |" | xargs)
  ecos -f -- "${uVs[@]}" ;}

hycal--uVs()
{ : _when <<_
Output pairs of %V and %u to determine first day of all months.

Each line has the weekday number, a space, and a ISO week number. These
correspond to the first day of each month. January 1st of the following year
may end up in this year's ISO calendar — check it as well.

If optional WHEN is not passed, use "now".
_
  local G
  G="$(date -d "${1:-now}" +%G)"
  printf '%s\n' "$G"-{01..12}-01 "$((G+1))"-01-01 |
      date +"%G:%u %V" -f - | grep -E "^$G:" | cut -f2 -d: ;}

#⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
##### Show or list themes

hycal--themes-show()
{ : type <<_
Show available themes.
TYPE is either a (all), u (user), or h (hycal).
_
  local th now="$EPOCHSECONDS"
  while read -r th
  do ecos -- 0.cyan4 "[$th]" 0 '\n'
     hycal -t "$th" -d "@$now"; echo
  done < <(hycal--themes-list "$1" 2>/dev/null) | \less -R ;}

hycal--themes-list()
{ : type <<_
Try to find available themes and list them.
TYPE is either a (all), u (user), or h (hycal).
_
  case "$1" in
      a) hycal--themes-list-user
         hycal--themes-list-hycal ;;
      u) hycal--themes-list-user  ;;
      h) hycal--themes-list-hycal ;;
  esac ;}

hycal--themes-list-user()
{ : <<_
Try to find available user themes and list them.
_
  local ud
  ud=$(hycal--source-rc "" hycal.rc
       printf -- '%s\n' "$HYCAL_THEMES_DIR_USER")
  if [[ "$ud" && -d "$ud" ]]
  then (cd "$ud" && printf -- '%s\n' *)
  fi | sort -V ;}

hycal--themes-list-hycal()
{ : <<_
Try to find available HyCal themes and list them.
_
  local hd
  hd=$(hycal--source-rc "" hycal.rc
       hycal--set-themes-dir-hycal
       printf -- '%s\n' "$HYCAL_THEMES_DIR_HYCAL")
  if [[ "$hd" && -d "$hd" ]]
  then (cd "$hd" && printf -- '%s\n' *)
  fi | sort -V ;}

#⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
##### Utilities

hycal--num-of-iso-weeks()
{ : when <<_
Given a date WHEN, check whether there're 52 or 53 weeks in the ISO year.
_
  : "$(date -d "$1" +"%G")"; date -d "$_-12-28" +%V ;}

hycal--rep()
{ : n _char <<_
Make string of CHAR repeated N times.
If CHAR is empty, use spaces.
_
  printf -- '%*s\n' "$1" "" |
      case "$#" in
          1) cat ;;
          *) sed -E "s/ /$2/g" ;;
      esac ;}

#⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
##### Enable completion

hycal--complete()
{ : <<_
Output commands necessary to enable completion.
_
  type _hycal | sed 1d
  echo "complete -o bashdefault -o filenames -F _hycal hycal" ;}

_hycal()
{ : <<_
Enable completion for hycal.

Add this line to your ~/.bash_aliases or ~/.bashrc:
  . <(hycal --complete)

or, if hycal executable is not in your PATH:
  . <(/path/to/hycal --complete)

and then, when writing a hycal command, press <tab><tab> to show completions.
_
  COMPREPLY=()
  local cur="$2" pre="$3" W="" \
        ops="-d -t -c -h -H -l \
             --hf --xf --xp --xs --yf --yp --rc --ec --tl --ts"

  # We want to quickly search any part of a locale, not just the beginning
  if [[ "$pre" == "-l" ]]
  then mapfile -t COMPREPLY < <(locale -a 2>/dev/null | \grep -E -- "$cur")
  else case "$pre" in
           -d)      : "YYYY-MM-DD YYYY-MM-DDThh:mm:ss
                       yesterday today tomorrow"   ;;
           -t)      : "$(hycal -=themes-list a)"   ;;
           --[er]c) : "$(compgen -f -- "$cur")"    ;;
           --t[ls]) : "a u h"                      ;;
           -h|-H)   : ""                           ;;
           --hf)    : "full year none"             ;;
           --xf)    : "weeknum none"               ;;
           --xp)    : "bottom top"                 ;;
           --xs)    : "$(seq 1 52)"                ;;
           --yf)    : "abbrev none"                ;;
           --yp)    : "left right"                 ;;
           -c)      : "y n"                        ;;
           *)       : "$ops"                       ;;
       esac; mapfile -t COMPREPLY < <(compgen -W "$_" -- "$cur")
  fi

  W=$(# Completion words
      if [[ "$cur" == "-c" ]]                           # whether color
      then compgen -P "$cur"        -W "y n"
      elif [[ "${cur:0:2}" =~ -[Hh] ]]                  # -[Hh]FUN (dev opt)
      then compgen -P "${cur:0:2}"  -W "$(hycal -=funs-list)"
           printf -- "%s\n" "${cur:0:2}"
      elif [[ "${cur:0:1}" == "-" ]]                    # any options
      then compgen                  -W "$ops"
      fi)
  if [[ "$W" ]]; then mapfile -t COMPREPLY < <(compgen -W "$W" -- "$cur"); fi ;}

hycal--funs-list()
{ : <<_
List internal functions that are completion candidates.
Remove common hycal-- prefix.
_
  : "${BASH_SOURCE[0]}"
  if [[ "$_" ]]
  then <"$_"        grep -oP '(?<=^hycal--).*(?=[(][)])'
  else declare -F | grep -oP '(?<= hycal--).*'
  fi ;}

#⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
#### Get help

hycal--doc()
{ : _fun <<_
Show a function's docstring. Colors.
If FUN is empty, show the docstring of hycal.
Otherwise, show the docstring of hycal--FUN.
_
  hycal--doc-no-colors "$@" | hycal--doc-colorize | \less -RF ;}

hycal--doc-nc()
{ : _fun <<_
Show a function's docstring. No colors.
If FUN is empty, show the docstring of hycal.
Otherwise, show the docstring of hycal--FUN.
_
  hycal--doc-no-colors "$@" | \less -RF ;}

hycal--doc-no-colors()
{ : _fun <<_
Output to stdout a function's docstring without colors.
_
  : hycal"${1:+--$1}"; type "$_" | sed -n "/<<_$/,/^_$/p" |
      sed "1 {s/ <<_.*/)/ ; s/[^:]*: */$_ (/}; $ d" ;}

hycal--doc-colorize()
{ : <<_
Filter to colorize hycal's docstrings.
_
  : hycal
  ecos -f -- \
       1.#fde028         '^[^ ]*'              1     .  \
       1.orange1         '\(.*'                1     .  \
       1.deepskyblue     '.*'                  2     .  \
       1.#b4fa70         '^[A-Z][a-z]+:'       3,$   .  \
       0.lightskyblue    "^ *([|]|[[]|$_).*"   .     .  \
       0.lightskyblue    "^ *[.] [<].*"        .     .  \
       1.darkslateblue   '^_+$'                .     .  ;}

#⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
### Run it and exit

hycal "$@"
exit 0

# Local Variables:
# coding:                     utf-8
# indent-tabs-mode:           nil
# sentence-end-double-space:  nil
# outline-regexp:             "###* "
# End:

## HyCal ends here
📆 2026-W04-5📆 2026-01-23