% datemultical-format.def % % datemultical: Named dates with multi-calendar formatting for LaTeX. % % Copyright (C) 2026 Amer Amikhteh % % This file is part of the datemultical package. % % This work is free software: you may redistribute it and/or modify % it under the terms of the LaTeX Project Public License as published % by the LaTeX Project, either version 1.3c of the License, or % (at your option) any later version. % % This work is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty % of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. % % The full license text is available at: % https://www.latex-project.org/lppl/ % % This work is "maintained" by Amer Amikhteh. % % The current maintainer of this work is Amer Amikhteh. \NeedsTeXFormat{LaTeX2e} \ProvidesFile{datemultical-format.def} [2026/09/17 v0.1.0 Multi-calendar date formatting] \ExplSyntaxOn \makeatletter % ================================================= % Temporary variables % ================================================= \tl_new:N \l_dmc_format_tl \tl_new:N \l_dmc_style_tl \tl_new:N \l_dmc_calendar_tl \cs_new_protected:Npn \dmc_style_store:nnn #1 #2 #3 { \tl_set:Nx \l_dmc_calendar_tl { \tl_to_str:n {#1} } \cs_gset:cpn { g_dmc_style_ \l_dmc_calendar_tl _ \tl_to_str:n {#2} _tl } {#3} } \cs_new_protected:Npn \dmc_style_fetch:nnN #1 #2 #3 { \tl_set:Nx \l_dmc_calendar_tl { \tl_to_str:n {#1} } \cs_if_exist:cTF { g_dmc_style_ \l_dmc_calendar_tl _ \tl_to_str:n {#2} _tl } { \tl_set:Nx #3 { \use:c { g_dmc_style_ \l_dmc_calendar_tl _ \tl_to_str:n {#2} _tl } } } { \tl_clear:N #3 } } % ================================================= % Calendar-dependent month captions % ================================================= \cs_new:Npn \dmc_format_month_name:nn #1 #2 { \str_case:nnF {#1} { {gr} { \dmc_month_name_gr:n {#2} } {sh} { \dmc_month_name_sh:n {#2} } {lh} { \dmc_month_name_lh:n {#2} } } {} } \cs_new:Npn \dmc_format_month_persian:nn #1 #2 { \str_case:nnF {#1} { {gr} { \dmc_month_name_gr_persian:n {#2} } {sh} { \dmc_month_name_sh_persian:n {#2} } {lh} { \dmc_month_name_lh_persian:n {#2} } } {} } \cs_new:Npn \dmc_format_month_abbrev:nn #1 #2 { \str_case:nnF {#1} { {gr} { \dmc_month_abbrev_gr:n {#2} } {sh} { \dmc_month_abbrev_sh:n {#2} } {lh} { \dmc_month_abbrev_lh:n {#2} } } {} } % ================================================= % Multi-digit formatting % ================================================= \cs_new:Npn \dmc_format_two_digits:n #1 { \int_compare:nNnTF {#1} < {10} { 0#1 } { #1 } } \cs_new:Npn \dmc_format_four_digits:n #1 { \int_compare:nNnTF {#1} < {10} { 000#1 } { \int_compare:nNnTF {#1} < {100} { 00#1 } { \int_compare:nNnTF {#1} < {1000} { 0#1 } { #1 } } } } % ================================================= % Bool to intiger % ================================================= \cs_new:Npn \dmc_format_bool_to_int:n #1 { \exp_args:Nx \str_case:nnF {#1} { {true} {1} {false} {0} } {#1} } % ================================================= % Internal formatting command % ================================================= \cs_new_protected:Npn \dmc_format_replace_one:nnnnn #1 #2 #3 #4 #5 { \tl_replace_all:Nnn \l_dmc_format_tl {#3} { \tl_if_blank:nTF {#5} { \dmcget [#1] {#2} {#4} } { #5 { \dmcget [#1] {#2} {#4} } } } } \cs_new_protected:Npn \dmc_format_replace_two:nnnnn #1 #2 #3 #4 #5 { \tl_replace_all:Nnn \l_dmc_format_tl {#3} { \tl_if_blank:nTF {#5} { \dmcget [#1] {#2} {#4} } { #5 {#1} { \dmcget [#1] {#2} {#4} } } } } \cs_new_protected:Npn \dmc_format:nnn #1 #2 #3 { \group_begin: \tl_set:Nn \l_dmc_format_tl { #3 } % ================================================= % Year % ================================================= \dmc_format_replace_one:nnnnn {#1} {#2} {yyyy} {year} {\dmc_format_four_digits:n} \dmc_format_replace_one:nnnnn {#1} {#2} {yy} {year} {\dmc_format_two_digits:n} \dmc_format_replace_one:nnnnn {#1} {#2} {y} {year} {} % ================================================= % Leap % ================================================= \dmc_format_replace_one:nnnnn {#1} {#2} {lmi} {leap_month} {\dmc_format_bool_to_int:n} \dmc_format_replace_one:nnnnn {#1} {#2} {ldi} {leap_day} {\dmc_format_bool_to_int:n} \dmc_format_replace_one:nnnnn {#1} {#2} {li} {leap} {\dmc_format_bool_to_int:n} \dmc_format_replace_one:nnnnn {#1} {#2} {lm} {leap_month} {} \dmc_format_replace_one:nnnnn {#1} {#2} {ld} {leap_day} {} \dmc_format_replace_one:nnnnn {#1} {#2} {l} {leap} {} % ================================================= % Month % ================================================= \ifdmc@persian \dmc_format_replace_two:nnnnn {#1} {#2} {MMMMP} {month} {\dmc_format_month_persian:nn} \fi \dmc_format_replace_two:nnnnn {#1} {#2} {MMMM} {month} {\dmc_format_month_name:nn} \dmc_format_replace_two:nnnnn {#1} {#2} {MMM} {month} {\dmc_format_month_abbrev:nn} \dmc_format_replace_one:nnnnn {#1} {#2} {MM} {month} {\dmc_format_two_digits:n} \dmc_format_replace_one:nnnnn {#1} {#2} {M} {month} {} % ================================================= % Day % ================================================= \dmc_format_replace_one:nnnnn {#1} {#2} {dd} {day} {\dmc_format_two_digits:n} \dmc_format_replace_one:nnnnn {#1} {#2} {d} {day} {} % ================================================= % Week % ================================================= \dmc_format_replace_one:nnnnn {#1} {#2} {ww} {week} {\dmc_format_two_digits:n} \dmc_format_replace_one:nnnnn {#1} {#2} {w} {week} {} % ================================================= % Weekday % ================================================= \ifdmc@persian \dmc_format_replace_one:nnnnn {#1} {#2} {EEEEP} {weekday} {\dmc_weekday_persian:n} \fi \dmc_format_replace_one:nnnnn {#1} {#2} {u} {weekday} {} \dmc_format_replace_one:nnnnn {#1} {#2} {EEEE} {weekday} {\dmc_weekday_name:n} \dmc_format_replace_one:nnnnn {#1} {#2} {EEE} {weekday} {\dmc_weekday_abbrev:n} % ================================================= % Major and cycle % ================================================= \dmc_format_replace_one:nnnnn {#1} {#2} {R} {major} {} \dmc_format_replace_one:nnnnn {#1} {#2} {U} {cycle} {} % ================================================= % Output % ================================================= \tl_use:N \l_dmc_format_tl \group_end: } % ================================================= % Public formatting command % ================================================= \NewDocumentCommand \dmcformat { O{gr} m m } { \dmc_format:nnn {#1} {#2} {#3} } % ================================================= % Internal style setter % ================================================= \cs_new_protected:Npn \dmc_style_set:nnn #1 #2 #3 { \clist_map_inline:nn {#1} { \dmc_style_store:nnn {##1} {#2} {#3} } } \NewDocumentCommand \dmcstyle { O{gr} m m } { \dmc_style_set:nnn {#1} {#2} {#3} } % ================================================= % Resolve for style % ================================================= \cs_new_protected:Npn \dmc_style_resolve:nnN #1 #2 #3 { \dmc_style_fetch:nnN {#1} {#2} #3 \tl_if_blank:VTF #3 { \dmc_style_fetch:nnN {gr} {#2} #3 } { } } % ================================================= % Public styled-date command % ================================================= \NewDocumentCommand \dmc { O{gr} m m } { \dmc_style_resolve:nnN {#1} {#3} \l_dmc_style_tl \tl_if_blank:VTF \l_dmc_style_tl { \PackageError{datemultical} {Unknown date style '#3' for calendar '#1'} {The requested date style has not been defined for this calendar, and no Gregorian fallback style exists.} } { \exp_args:NnnV \dmc_format:nnn {#1} {#2} \l_dmc_style_tl } } % ================================================= % Standard date styles % ================================================= \dmcstyle{full}{EEEE,~MMMM~d,~y} \dmcstyle{long}{MMMM~d,~y} \dmcstyle{medium}{MMM~d,~y} \dmcstyle{short}{yy/MM/dd} \dmcstyle{short-use}{M/d/yy} \dmcstyle{ISO}{yyMMdd} \dmcstyle{ISOext}{yy-MM-dd} \dmcstyle{american}{MMMM~dd,~yy} \dmcstyle{shamerican}{MM/dd/yy} \dmcstyle{british}{dd~MMMM~yy} \dmcstyle{shbritish}{dd/MM/yy} \dmcstyle{shbritishdots}{dd.MM.yy} % ================================================= % Standard date styles for nonstandard calender % ================================================= \dmcstyle[iso]{short}{yy/ww/dd} \dmcstyle[mayan_haab,aztec_xihuitl]{short}{MM/dd} \dmcstyle[korean,old_hindu_lunar,babylonian]{short}{yy/MM/li/dd} \dmcstyle[hindu_lunar,hindu_lunar_astronomical,tibetan]{short}{yy/MM/lmi/dd/ldi} \dmcstyle[bahai,bahai_astronomical]{short}{R/U/yy/MM/dd} \dmcstyle[chinese,japanese]{short}{U/yy/MM/li/dd} \dmcstyle[olympiad]{short}{U/yy/MM/dd} % ================================================= % Persian convenience commands % ================================================= \NewDocumentCommand \ShortShamsi { m } {\rl{\dmcformat[sh]{#1}{yy/MM/dd}}} \NewDocumentCommand \ShortGhamari { m } {\rl{\dmcformat[lh]{#1}{yy/MM/dd}}} \NewDocumentCommand \ShortMiladi { m } {\lr{\dmcformat[gr]{#1}{yy/MM/dd}}} \NewDocumentCommand \Shamsi { m } {\rl{\dmcformat[sh]{#1}{d~MMMMP~y}}} \NewDocumentCommand \Ghamari { m } {\rl{\dmcformat[lh]{#1}{d~MMMMP~y}}} \NewDocumentCommand \Miladi { m } {\lr{\dmcformat[gr]{#1}{MMMM~d,~y}}} \NewDocumentCommand \FaMiladi { m } {\rl{\dmcformat[gr]{#1}{d~MMMMP~y}}} \NewDocumentCommand \Persianweekday { m } {\rl{\dmcformat{#1}{EEEEP}}} \makeatother \ExplSyntaxOff \endinput