% 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/10/18 v0.2.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}
}


% =================================================
% Japanese era formatting
% =================================================

\cs_new:Npn \dmc_format_japanese_era:n #1
{
    \exp_args:Nx \str_case:nnF {#1}
    {
        {meiji}  {1}
        {taisho} {2}
        {showa}  {3}
        {heisei} {4}
        {reiwa}  {5}
    }
    {#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 }

    % =================================================
    % Four-digit and two-digit 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}

    % =================================================
    % Longest leap and era tokens
    % =================================================

    \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} {lui} {luang}
    {\dmc_format_bool_to_int:n}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {Gi} {era}
    {\dmc_format_japanese_era:n}

    % =================================================
    % Two-character leap tokens
    % =================================================

    \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}
    {}

    % =================================================
    % Maya Long Count
    %
    % lui must precede ui.
    % =================================================

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {bt} {baktun}
    {}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {ka} {katun}
    {}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {tn} {tun}
    {}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {ui} {uinal}
    {}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {ki} {kin}
    {}

    % =================================================
    % Balinese cycles
    %
    % lui has already been replaced above.
    % =================================================

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {lu} {luang}
    {}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {di} {dwiwara}
    {}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {tr} {triwara}
    {}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {cw} {caturwara}
    {}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {pw} {pancawara}
    {}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {sw} {sadwara}
    {}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {sp} {saptawara}
    {}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {aw} {asatawara}
    {}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {sg} {sangawara}
    {}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {da} {dasawara}
    {}

    % =================================================
    % Month names and numeric 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}

    % =================================================
    % Day
    % =================================================

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {dd} {day}
    {\dmc_format_two_digits:n}

    % =================================================
    % Week
    % =================================================

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {ww} {week}
    {\dmc_format_two_digits:n}

    % =================================================
    % Weekday names
    % =================================================

    \ifdmc@persian
        \dmc_format_replace_one:nnnnn
        {#1} {#2} {EEEEP} {weekday}
        {\dmc_weekday_persian:n}
    \fi

    \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}
    {}

    % =================================================
    % Remaining one-character tokens
    % =================================================

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {y} {year}
    {}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {l} {leap}
    {}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {M} {month}
    {}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {d} {day}
    {}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {w} {week}
    {}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {u} {weekday}
    {}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {N} {name}
    {}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {S} {season}
    {}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {G} {era}
    {}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {E} {event}
    {}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {C} {count}
    {}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {p} {prefix}
    {}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {s} {stem}
    {}

    \dmc_format_replace_one:nnnnn
    {#1} {#2} {n} {number}
    {}

    % =================================================
    % 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 calendars
% =================================================

\dmcstyle[akan]{short}{p/s}
\dmcstyle[aztec-tonalpohualli,mayan-tzolkin]{short}{n/N}
\dmcstyle[aztec-xihuitl,mayan-haab]{short}{MM/dd}
\dmcstyle[babylonian,old-hindu-lunar]{short}{yy/MM/li/dd}
\dmcstyle[bahai,bahai-astronomical]{short}{R/U/yy/MM/dd}
\dmcstyle[balinese]{short}{lui/di/tr/cw/pw/sw/sp/aw/sg/da}
\dmcstyle[chinese,japanese,vietnamese]{short}{U/yy/MM/li/dd}
\dmcstyle[hindu-lunar,hindu-lunar-astronomical,tibetan]{short}{yy/MM/lmi/dd/ldi}
\dmcstyle[icelandic]{short}{yy/S/ww/u}
\dmcstyle[iso]{short}{yy/ww/dd}
\dmcstyle[japanese-era]{short}{Gi/yy/MM/dd}
\dmcstyle[korean]{short}{yy/MM/li/dd}
\dmcstyle[mayan-long-count]{short}{bt/ka/tn/ui/ki}
\dmcstyle[olympiad]{short}{U/yy/MM/dd}
\dmcstyle[roman]{short}{yy/MM/E/C/li}




% =================================================
% 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