Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

jdate

date for the Persian calendar.

Prints the Jalali (Hijri Shamsi) date — and the Hijri Qamari date — using the same flags and the same +FORMAT specifiers as date(1).

One POSIX shell script. No compiler, no runtime, no package manager.

License: MIT Shell: POSIX Dependencies: none


$ jdate
یکشنبه 04 مرداد 1405 12:30:00 +0330

$ jdate +%Y/%m/%d
1405/05/04

$ jdate --qamari +%Y/%m/%d
1448/02/10

Install

curl -fsSL https://raw.githubusercontent.com/malekpouri/jdate/main/install.sh | sh

or, with wget:

wget -qO- https://raw.githubusercontent.com/malekpouri/jdate/main/install.sh | sh

Note

Both flags matter. You need the raw.githubusercontent.com host, because github.com/... serves an HTML page rather than the script, and you need wget -qO- to send the script to stdout — plain wget URL | bash writes the file to disk and pipes nothing.

Installs to /usr/local/bin when you have permission, otherwise to ~/.local/bin. To choose:

curl -fsSL .../install.sh | sh -s -- --prefix="$HOME/.local"
curl -fsSL .../install.sh | sh -s -- --uninstall

Or skip the installer entirely — it is one file:

curl -fsSLO https://raw.githubusercontent.com/malekpouri/jdate/main/jdate
chmod +x jdate && sudo mv jdate /usr/local/bin/

Usage

jdate mirrors date(1), so most things you already know carry over.

Choosing a calendar

Flag Calendar Example
(default), -j, --jalali Jalali / Hijri Shamsi, solar 1405/05/04
-q, --qamari, --hijri Hijri Qamari, lunar 1448/02/10
-g, --gregorian Gregorian 2026/07/26

Choosing a script

Flag Output
(default), --fa-names یکشنبه 04 مرداد 1405 — Persian names, ASCII digits
--fa یکشنبه ۰۴ مرداد ۱۴۰۵ — Persian names and digits
--en Yekshanbeh 04 Mordad 1405 — Latin transliteration

The default keeps ASCII digits on purpose: the output still sorts, compares and parses as a plain number in a shell script.

Formatting

Every date(1) specifier works — %Y %m %d %H %M %S %A %B %j %s %z %Z, the shorthands %F %T %D %R %r, and the %-d / %_d / %0e / %^B modifiers.

$ jdate +'%A، %d %B %Y'
یکشنبه، 04 مرداد 1405

$ jdate --en +'%A %-d %B %Y at %I:%M %p'
Yekshanbeh 4 Mordad 1405 at 12:30 PM

jdate adds %E… specifiers that print the Gregorian value of the same day, so a single call can emit both calendars:

$ jdate +'%Y/%m/%d is %EY-%Em-%Ed'
1405/05/04 is 2026-07-26
Specifier Meaning
%G, %EY Gregorian year
%Em, %Ed Gregorian month number, day of month
%Eb, %EB Gregorian month name, short and full
%EF Gregorian %Y-%m-%d
%Ej Gregorian day of year

Converting a specific date

A bare YYYY/MM/DD given to -d is read in the calendar you are printing, so this asks "what Gregorian day was Nowruz 1404?":

$ jdate -d 1404/01/01 +%EF
2025-03-21

Use --from to go the other way, or between the two Hijri calendars:

$ jdate --from=gregorian -d 2025-03-21 +%F
1404-01-01

$ jdate --qamari --from=jalali -d 1404/01/01 +%F
1446-09-21

Anything that is not a bare date is handed to date(1), so relative expressions work wherever GNU date does:

$ jdate -d 'next friday' +'%A %d %B'
$ jdate -d '3 days ago' +%F
$ jdate -r /etc/passwd +%F        # a file's modification date

Everything else

-u, --utc              use UTC
-I[SPEC]               ISO 8601 output (date, hours, minutes, seconds, ns)
-R, --rfc-email        RFC 5322 output
-r, --reference=FILE   use a file's modification time
-h, --help             full option list
-V, --version          version

Full documentation is in man jdate, or jdate --help.

In scripts

# Date-stamped backups in the Persian calendar
tar czf "backup-$(jdate +%Y%m%d).tar.gz" ~/documents

# A Persian prompt segment
PS1='[\u@\h $(jdate +%m/%d) ]\$ '

# Is today Nowruz?
[ "$(jdate +%m%d)" = "0101" ] && echo 'نوروز مبارک'

Requirements

sh, awk and date — all three are already on any Linux, macOS or BSD system, including BusyBox-only containers.

Verified against dash, bash, zsh and busybox sh, with mawk, gawk and busybox awk. install.sh additionally needs either curl or wget.

Accuracy

Jalali uses the 2820-year arithmetic cycle with the observed leap-year breaks — the same algorithm as jalaali-js and Kazimierz Borkowski's tables. It is exact over the range the Iranian calendar is civilly defined for, about 1178–1633 Jalali (1799–2255 CE). The test suite round-trips every single day from 1200 to 1500 Jalali.

Hijri Qamari uses the tabular (arithmetic) Islamic calendar. The religious calendar depends on sighting the new moon, so the printed day can differ from a locally announced date by about a day. It is right for timestamps and filenames; do not use it to fix religious observances.

Tests

sh tests/run.sh

58 checks: known conversion pairs, leap years, every format specifier, option and error handling, and an exhaustive round-trip over 300 Jalali and 600 Hijri years. Set AWK=busybox awk to test another awk.

License

MIT — see LICENSE.

About

date(1) for the Persian calendar — Jalali (Hijri Shamsi) and Hijri Qamari dates with the same flags and +FORMAT specifiers as date. One POSIX shell script, zero dependencies.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages