%%
%% This is file `datatool-base.sty',
%% generated with the docstrip utility.
%%
%% The original source files were:
%%
%% datatool.dtx  (with options: `datatool-base.sty,package')
%% 
%%  datatool.dtx
%%  Copyright 2025 Nicola Talbot
%% 
%%  This work may be distributed and/or modified under the
%%  conditions of the LaTeX Project Public License, either version 1.3
%%  of this license or (at your option) any later version.
%%  The latest version of this license is in
%%    http://www.latex-project.org/lppl.txt
%%  and version 1.3 or later is part of all distributions of LaTeX
%%  version 2005/12/01 or later.
%% 
%%  This work has the LPPL maintenance status `maintained'.
%% 
%%  The Current Maintainer of this work is Nicola Talbot.
%% 
%%  This work consists of the files datatool.dtx and datatool.ins and the derived files datatool-base.sty, datatool-undetermined.ldf, datatool-latin1.ldf, datatool-utf8.ldf, datatool-l3fp.def, datatool-lua.def, datatool-fp.def, datatool-fp.sty, datatool-pgfmath.def, datatool-pgfmath.sty, datatool.sty, datagidx.sty, databib.sty, databar.sty, datapie.sty, dataplot.sty, person.sty, databib.bst, databar-2019-09-27.sty, databib-2019-09-27.sty, datagidx-2019-09-27.sty, datapie-2019-09-27.sty, dataplot-2019-09-27.sty, datatool-2019-09-27.sty, datatool-base-2019-09-27.sty, datatool-fp-2019-09-27.sty, datatool-pgfmath-2019-09-27.sty, person-2019-09-27.sty.
%% 
%% \CharacterTable
%%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
%%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
%%   Digits        \0\1\2\3\4\5\6\7\8\9
%%   Exclamation   \!     Double quote  \"     Hash (number) \#
%%   Dollar        \$     Percent       \%     Ampersand     \&
%%   Acute accent  \'     Left paren    \(     Right paren   \)
%%   Asterisk      \*     Plus          \+     Comma         \,
%%   Minus         \-     Point         \.     Solidus       \/
%%   Colon         \:     Semicolon     \;     Less than     \<
%%   Equals        \=     Greater than  \>     Question mark \?
%%   Commercial at \@     Left bracket  \[     Backslash     \\
%%   Right bracket \]     Circumflex    \^     Underscore    \_
%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
%%   Right brace   \}     Tilde         \~}
\NeedsTeXFormat{LaTeX2e}
\DeclareRelease{v2.32}{2019-09-27}{datatool-base-2019-09-27.sty}
\DeclareCurrentRelease{v3.4.1}{2025-04-25}
\ProvidesPackage{datatool-base}[2025/04/25 v3.4.1 (NLCT)]
\RequirePackage{etoolbox}
\RequirePackage{amsmath}
\RequirePackage{xfor}
\RequirePackage{ifthen}
\RequirePackage{tracklang}[2022/12/13]
\newif\ifdtlverbose
\expandafter\newif\csname if@dtl@utf8\endcsname
\ExplSyntaxOn
\cs_if_exist:NF \TrackLangEncodingName
{
  \cs_if_exist:NTF \inputencodingname
  { \tl_set:NN \TrackLangEncodingName \inputencodingname }
  { \tl_set:Nn \TrackLangEncodingName { utf8 } }
}
\bool_lazy_any:nTF
 {
  { \sys_if_engine_luatex_p: }
  { \sys_if_engine_xetex_p: }
  { \sys_if_engine_uptex_p: }
 }
 {
   \cs_set_eq:NN \datatool_if_unicode_engine:TF \use_i:nn
   \cs_set_eq:NN \datatool_if_unicode_engine:T \use:n
   \cs_set_eq:NN \datatool_if_unicode_engine:F \use_none:n
 }
 {
   \cs_set_eq:NN \datatool_if_unicode_engine:TF \use_ii:nn
   \cs_set_eq:NN \datatool_if_unicode_engine:T \use_none:n
   \cs_set_eq:NN \datatool_if_unicode_engine:F \use:n
 }
\ifdef\directlua
{\providecommand*{\@dtl@mathprocessor}{lua}}
{\providecommand*{\@dtl@mathprocessor}{l3fp}}
\newcommand\datatool@load@locales[1]{#1}
\clist_new:N \l__datatool_extra_locales_clist
\bool_new:N \l__datatool_initial_purify_early_bool
\bool_set_true:N \l__datatool_initial_purify_early_bool
\seq_new:N \l__datatool_auto_reformat_types_seq
\seq_set_from_clist:Nn \l__datatool_auto_reformat_types_seq
 { integer , decimal , si , currency , datetime , date , time }
\cs_new:Nn \__datatool_auto_reformat_types_do:n
 {
   \tl_if_eq:nnTF { #1 } { integer }
    {
      \seq_put_right:Nn \l__datatool_auto_reformat_types_seq
        { #1 }
    }
    {
      \tl_if_eq:nnTF { #1 } { decimal }
       {
         \seq_put_right:Nn \l__datatool_auto_reformat_types_seq
           { #1 }
       }
       {
         \tl_if_eq:nnTF { #1 } { si }
          {
            \seq_put_right:Nn \l__datatool_auto_reformat_types_seq
              { #1 }
          }
          {
            \tl_if_eq:nnTF { #1 } { datetime }
             {
               \seq_put_right:Nn \l__datatool_auto_reformat_types_seq
                 { #1 }
             }
             {
               \tl_if_eq:nnTF { #1 } { date }
                {
                  \seq_put_right:Nn \l__datatool_auto_reformat_types_seq
                    { #1 }
                }
                {
                  \tl_if_eq:nnTF { #1 } { time }
                   {
                     \seq_put_right:Nn \l__datatool_auto_reformat_types_seq
                       { #1 }
                   }
                   {
                     \PackageError { datatool-base }
                      {
                        Unsupported ~ auto-reformat ~ data ~ type ~
                         identifier  ~ ` #1 '
                      }
                      {
                        Supported ~ identifiers: ~
                        `integer', ~ `decimal', ~ `si', ~
                        `datetime', ~ `date', ~ `time'
                      }
                   }
                }
             }
          }
       }
    }
 }
\prg_new_conditional:Npnn \__datatool_if_auto_reformat_on:n #1
   { T, F, TF }
 {
   \seq_if_in:NnTF
      \l__datatool_auto_reformat_types_seq
     { #1 }
    {
       \tl_if_eq:nnTF { #1 } { si }
        {
           \bool_if:NTF \l__datatool_reformat_numeric_bool
            { \prg_return_true: }
            { \prg_return_false: }
        }
        {
          \int_if_exist:cTF { c_datatool_ #1 _int }
           {
             \exp_args:Nc \datatool_if_temporal_datum_type:nTF
               { c_datatool_ #1 _int }
              {
                \bool_if:NTF \l__datatool_reformat_datetime_bool
                 { \prg_return_true: }
                 { \prg_return_false: }
              }
              {
                \exp_args:Nc \datatool_if_numeric_datum_type:nTF
                  { c_datatool_ #1 _int }
                 {
                   \bool_if:NTF \l__datatool_reformat_numeric_bool
                    { \prg_return_true: }
                    { \prg_return_false: }
                 }
                 { \prg_return_false: }
              }
           }
           { \prg_return_false: }
        }
    }
    { \prg_return_false: }
 }
\prg_new_conditional:Npnn \__datatool_if_auto_reformat_on:
   { T, F, TF }
 {
   \int_case:nnF { \@dtl@datatype }
    {
      { \c_datatool_integer_int }
       {
         \seq_if_in:NnTF
            \l__datatool_auto_reformat_types_seq
           { integer }
          {
            \bool_if:NTF \l__datatool_reformat_numeric_bool
             { \prg_return_true: }
             { \prg_return_false: }
          }
          { \prg_return_false: }
       }
      { \c_datatool_decimal_int }
       {
         \seq_if_in:NnTF
            \l__datatool_auto_reformat_types_seq
           { decimal }
          {
            \bool_if:NTF \l__datatool_reformat_numeric_bool
             { \prg_return_true: }
             { \prg_return_false: }
          }
          { \prg_return_false: }
       }
      { \c_datatool_currency_int }
       {
         \seq_if_in:NnTF
            \l__datatool_auto_reformat_types_seq
           { currency }
          {
            \bool_if:NTF \l__datatool_reformat_numeric_bool
             { \prg_return_true: }
             { \prg_return_false: }
          }
          { \prg_return_false: }
       }
      { \c_datatool_datetime_int }
       {
         \seq_if_in:NnTF
            \l__datatool_auto_reformat_types_seq
           { datetime }
          {
            \bool_if:NTF \l__datatool_reformat_datetime_bool
             { \prg_return_true: }
             { \prg_return_false: }
          }
          { \prg_return_false: }
       }
      { \c_datatool_date_int }
       {
         \seq_if_in:NnTF
            \l__datatool_auto_reformat_types_seq
           { date }
          {
            \bool_if:NTF \l__datatool_reformat_datetime_bool
             { \prg_return_true: }
             { \prg_return_false: }
          }
          { \prg_return_false: }
       }
      { \c_datatool_time_int }
       {
         \seq_if_in:NnTF
            \l__datatool_auto_reformat_types_seq
           { time }
          {
            \bool_if:NTF \l__datatool_reformat_datetime_bool
             { \prg_return_true: }
             { \prg_return_false: }
          }
          { \prg_return_false: }
       }
    }
    { \prg_return_false: }
 }
\keys_define:nn { datatool }
{
   verbose .legacy_if_set:n = dtlverbose,
   utf8 .legacy_if_set:n = @dtl@utf8,
   math .choices:nn = { fp, pgfmath, l3fp, lua }
                      { \tl_set_eq:NN \@dtl@mathprocessor \l_keys_choice_tl },
   math .usage:n = load,
   lang-warn .choice: ,
   lang-warn / true .code:n =
    {
      \cs_set_eq:NN \datatool_locale_warn:nn \PackageWarning
    } ,
   lang-warn / false .code:n =
    {
      \PackageInfo
        {datatool-base}
        {
         localisation ~ warnings ~ switched ~
         off ~ (including ~ tracklang ~ warnings)
        }
      \cs_set_eq:NN  \datatool_locale_warn:nn \use_none:nn
      \TrackLangShowWarningsfalse
    } ,
   lang-warn .default:n = true ,
   lang-warn .initial:n = true ,
   lang-warn .usage:n = load ,
   nolocale .code:n =
    {
      \cs_set_eq:NN \datatool@load@locales \use_none:n
      \clist_clear:N \l__datatool_extra_locales_clist
    },
   nolocale .value_forbidden:n = true,
   nolocale .usage:n = load,
   locales .code:n =
     {
        \cs_set_eq:NN \datatool@load@locales \use:n
        \clist_set:Nn \l__datatool_extra_locales_clist { #1 }
     },
   locales .usage:n = load,
   lang .code:n =
     {
        \cs_set_eq:NN \datatool@load@locales \use:n
        \clist_set:Nn \l__datatool_extra_locales_clist { #1 }
     },
   lang .usage:n = load,
   lists .code:n = { \keys_set:nn { datatool / lists } { #1 } },
   initial-purify .choice:,
   initial-purify / early .code:n =
      { \bool_set_true:N \l__datatool_initial_purify_early_bool },
   initial-purify / late .code:n =
      { \bool_set_false:N \l__datatool_initial_purify_early_bool },
   auto-reformat-types .code:n =
     {
       \seq_clear:N \l__datatool_auto_reformat_types_seq
       \exp_args:Ne \clist_map_function:nN { #1 }
          \__datatool_auto_reformat_types_do:n
     } ,
   compare .code:n = { \keys_set:nn { datatool / compare } { #1 } },
   datetime .code:n = { \keys_set:nn { datatool / datetime } { #1 } },
   numeric .code:n = { \keys_set:nn { datatool / numeric } { #1 } },
}
\bool_new:N \l__datatool_reformat_numeric_bool
\bool_set_false:N \l__datatool_reformat_numeric_bool
\IfPackageLoadedTF { siunitx }
 {
   \newcommand \DTLscinum [ 1 ] { \num { #1 } }
 }
 {
   \newcommand \DTLscinum [ 1 ] { #1 }
   \AddToHook
     { package / siunitx / after }
     {
       \renewcommand \DTLscinum [ 1 ] { \num { #1 } }
     }
 }
\bool_new:N \l_datatool_region_set_numberchars_bool
\bool_set_true:N \l_datatool_region_set_numberchars_bool
\bool_new:N \l_datatool_region_set_currency_bool
\bool_set_true:N \l_datatool_region_set_currency_bool
\newcommand{\datatoolcurrencysymbolprefixfmt}[1]{#1}
\newcommand{\DTLcurrCodeOrSymOrChar}[3]{#2}
\keys_define:nn { datatool / numeric }
{
   auto-reformat .bool_set:N = \l__datatool_reformat_numeric_bool ,
   set-number-chars .code:n =
    {
      \DTLsetnumberchars #1
      \bool_set_false:N \l_datatool_region_set_numberchars_bool
    } ,
   region-number-chars .choice: ,
   region-number-chars / true .code:n =
    {
      \bool_set_true:N \l_datatool_region_set_numberchars_bool
      \tl_if_empty:NF \l_datatool_current_region_tl
       {
         \cs_if_exist_use:cF
          { datatool \l_datatool_current_region_tl SetNumberChars }
          {
            \PackageWarning { datatool-base }
             {
               No ~ numberchars ~ hook ~ found ~ for ~ region ~
                 ` \l_datatool_current_region_tl '
             }
          }
       }
    } ,
   region-number-chars / false .code:n =
    {
      \bool_set_false:N \l_datatool_region_set_numberchars_bool
    } ,
   region-number-chars .default:n = true ,
   set-currency .code:n =
    {
      \tl_if_exist:cTF { dtl@curr@ \tl_to_str:n { #1 } @sym }
       {
         \tl_set:Ne \@dtl@currency { \exp_not:c { DTLcurr #1 } }
         \tl_set:Ne \DTLCurrencyCode { #1 }
         \tl_set:Ne \DTLfmtcurrency
           { \exp_not:c { dtl@curr@ #1 @fmt } }
         \bool_false:N \l_datatool_region_set_currency_bool
       }
       {
         \PackageError { datatool-base }
          {
            Currency ~ ` #1 ' ~ has ~ not ~ been ~ defined
          }
          {
            Currency ~ must ~ first ~ be ~ defined ~ with ~
            \tl_to_str:N \DTLdefcurrency
          }
       }
    } ,
   region-currency .choice: ,
   region-currency / true .code:n =
    {
      \bool_set_true:N \l_datatool_region_set_currency_bool
      \tl_if_empty:NF \l_datatool_current_region_tl
       {
         \cs_if_exist_use:cF
          { datatool \l_datatool_current_region_tl SetCurrency }
          {
            \PackageWarning { datatool-base }
             {
               No ~ currency ~ hook ~ found ~ for ~ region ~
                 ` \l_datatool_current_region_tl '
             }
          }
       }
    } ,
   region-currency / false .code:n =
    {
      \bool_set_false:N \l_datatool_region_set_currency_bool
    } ,
   region-currency .default:n = true ,
   region-currency-prefix .choice: ,
   region-currency-prefix / normal .code:n =
    {
      \cs_set_eq:NN \datatoolcurrencysymbolprefixfmt \use:n
    } ,
   region-currency-prefix / smallcaps .code:n =
    {
      \renewcommand \datatoolcurrencysymbolprefixfmt [ 1 ]
       {
         \exp_args:Ne \textsc { \text_lowercase:n { ##1 } }
       }
    } ,
   region-currency-prefix / smaller .code:n =
    {
      \renewcommand \datatoolcurrencysymbolprefixfmt [ 1 ]
       {
         \textsmaller { ##1 }
       }
    } ,
   currency-symbol-style .choice:,
   currency-symbol-style / iso .code:n =
    {
      \cs_set_eq:NN \DTLcurrCodeOrSymOrChar \use_i:nnn
    },
   currency-symbol-style / symbol .code:n =
    {
      \cs_set_eq:NN \DTLcurrCodeOrSymOrChar \use_ii:nnn
    },
   currency-symbol-style / string .code:n =
    {
      \cs_set_eq:NN \DTLcurrCodeOrSymOrChar \use_iii:nnn
    },
}
\bool_new:N \l__datatool_parse_datetime_bool
\bool_set_false:N \l__datatool_parse_datetime_bool
\bool_new:N \l__datatool_parse_datetime_iso_bool
\bool_set_true:N \l__datatool_parse_datetime_iso_bool
\bool_new:N \l__datatool_parse_datetime_regional_bool
\bool_set_true:N \l__datatool_parse_datetime_regional_bool
\bool_new:N \l__datatool_reformat_datetime_bool
\bool_set_false:N \l__datatool_reformat_datetime_bool
\newcommand \DTLCurrentLocaleFormatDate [4]
 {
   \datatool_default_date_fmt:nnnn { #1 } { #2 } { #3 } { #4 }
 }
\cs_new_nopar:Nn \datatool_default_date_fmt:nnnn
 {
   \cs_if_exist:NTF \DTMdisplaydate
    {
      \tl_if_empty:nTF { #4 }
       {
         \DTMdisplaydate { #1 } { #2 } { #3 } { -1 }
       }
       {
         \DTMdisplaydate { #1 } { #2 } { #3 } { #4 }
       }
    }
    {
      \datatool_date_iso_fmt:nnnn { #1 } { #2 } { #3 } { #4 }
    }
 }
\newcommand \DataToolDateFmt [4]
 {
   \DTLCurrentLocaleFormatDate { #1 } { #2 } { #3 } { #4 }
 }
\cs_new_nopar:Nn \datatool_date_iso_fmt:nnnn
 {
   \datatool_date_iso_fmt:nnn { #1 } { #2 } { #3 }
 }
\cs_new_nopar:Nn \datatool_date_iso_fmt:nnn
 {
   \int_eval:n { #1 }
    - \datatool_two_digits:n { #2 }
    - \datatool_two_digits:n { #3 }
 }
\newcommand \DTLCurrentLocaleFormatTime [3]
 {
   \datatool_default_time_fmt:nnn { #1 } { #2 } { #3 }
 }
\cs_new_nopar:Nn \datatool_default_time_fmt:nnn
 {
   \cs_if_exist:NTF \DTMdisplaytime
    {
      \tl_if_empty:nTF { #3 }
       {
         \DTMdisplaytime { #1 } { #2 } { 0 }
       }
       {
         \DTMdisplaytime { #1 } { #2 } { #3 }
       }
    }
    {
      \datatool_time_iso_fmt:nnn { #1 } { #2 } { #3 }
    }
 }
\newcommand \DataToolTimeFmt [3]
 {
   \DTLCurrentLocaleFormatTime { #1 } { #2 } { #3 }
 }
\cs_new_nopar:Nn \datatool_time_iso_fmt:nnn
 {
   \datatool_two_digits:n { #1 }
   \c_colon_str
   \datatool_two_digits:n { #2 }
   \tl_if_empty:nF { #3 }
    {
      \c_colon_str
      \datatool_two_digits:n { #3 }
    }
 }
\newcommand \DTLCurrentLocaleFormatTimeZone [2]
 {
   \datatool_default_timezone_fmt:nn { #1 } { #2 }
 }
\cs_new:Nn \datatool_default_timezone_fmt:nn
 {
   \cs_if_exist:NTF \DTMdisplayzone
    {
      \DTMdisplayzone { #1 } { #2 }
    }
    {
      \datatool_timezone_iso_fmt:nn { #1 } { #2 }
    }
 }
\newcommand \DataToolTimeZoneFmt [2]
 {
   \DTLCurrentLocaleFormatTimeZone { #1 } { #2 }
 }
\cs_new_nopar:Nn \datatool_timezone_iso_fmt:nn
 {
   \datatool_signed_two_digits:n { #1 }
   \c_colon_str
   \datatool_two_digits:n { #2 }
 }
\newcommand \DTLCurrentLocaleTimeStampFmtSep { ~ }
\newcommand \DataToolTimeStampFmtSep
 {
   \DTLCurrentLocaleTimeStampFmtSep
 }
\newcommand* \DataToolDateTimeFmt [3]
 {
   \tl_if_empty:nTF { #1 }
    {
     \tl_if_empty:nF { #2 }
      {
        \DataToolTimeFmt #2
      }
     \tl_if_empty:nF { #3 }
      {
        \DataToolTimeZoneFmt #3
      }
    }
    {
      \tl_if_empty:nTF { #2 }
      {
        \DataToolDateFmt #1
      }
      {
       \tl_if_empty:nTF { #3 }
        {
          \DataToolTimeStampNoZoneFmt #1 #2
        }
        {
          \DataToolTimeStampWithZoneFmt #1 #2 #3
        }
      }
    }
 }
\newcommand \DataToolTimeStampWithZoneFmt [9]
 {
   \DTLCurrentLocaleFormatTimeStampWithZone
     { #1 } { #2 } { #3 } { #4 } { #5 } { #6 } { #7 } { #8 } { #9 }
 }
\newcommand \DataToolTimeStampNoZoneFmt [7]
 {
   \DTLCurrentLocaleFormatTimeStampNoZone
     { #1 } { #2 } { #3 } { #4 } { #5 } { #6 } { #7 }
 }
\cs_new_nopar:Nn \datatool_default_timestamp_fmt:nnnnnnn
 {
   \cs_if_exist:NTF \DTMdisplay
    {
      \tl_if_empty:nTF { #4 }
       {
         \DTMdisplay
           { #1 } { #2 } { #3 } { -1 }
           { #5 } { #6 } { #7 }
           { 0 } { 0 }
       }
       {
         \DTMdisplay
           { #1 } { #2 } { #3 } { #4 }
           { #5 } { #6 } { #7 }
           { 0 } { 0 }
       }
    }
    {
      \datatool_default_date_fmt:nnnn
        { #1 } { #2 } { #3 } { #4 }
      \DataToolTimeStampFmtSep
      \datatool_default_time_fmt:nnn
        { #5 } { #6 } { #7 }
    }
 }
\cs_new_nopar:Nn \datatool_default_timestamp_fmt:nnnnnnnnn
 {
   \cs_if_exist:NTF \DTMdisplay
    {
      \tl_if_empty:nTF { #4 }
       {
         \DTMdisplay
           { #1 } { #2 } { #3 } { -1 }
           { #5 } { #6 } { #7 }
           { #8 } { #9 }
       }
       {
         \DTMdisplay
           { #1 } { #2 } { #3 } { #4 }
           { #5 } { #6 } { #7 }
           { #8 } { #9 }
       }
    }
    {
      \datatool_default_timestamp_fmt:nnnnnnn
        { #1 } { #2 } { #3 } { #4 }
        { #5 } { #6 } { #7 }
      \datatool_default_timezone_fmt:nn
        { #8 } { #9 }
    }
 }
\cs_new_nopar:Nn \datatool_timestamp_iso_fmt:nnnnnnn
 {
   \datatool_date_iso_fmt:nnnn { #1 } { #2 } { #3 } { #4 }
   T
   \datatool_time_iso_fmt:nnn { #5 } { #6 } { #7 }
 }
\cs_new_nopar:Nn \datatool_timestamp_iso_fmt:nnnnnnnnn
 {
   \datatool_timestamp_iso_fmt:nnnnnnn
    { #1 } { #2 } { #3 } { #4 }
    { #5 } { #6 } { #7 }
   \datatool_timezone_iso_fmt:nn { #8 } { #9 }
 }
\newcommand \DTLCurrentLocaleFormatTimeStampWithZone [9]
 {
   \datatool_default_timestamp_fmt:nnnnnnnnn
    { #1 } { #2 } { #3 } { #4 } { #5 } { #6 } { #7 } { #8 } { #9 }
 }
\newcommand \DTLCurrentLocaleFormatTimeStampNoZone [7]
 {
   \datatool_default_timestamp_fmt:nnnnnnn
      { #1 } { #2 } { #3 } { #4 } { #5 } { #6 } { #7 }
 }
\keys_define:nn { datatool / datetime }
{
   parse .choice:,
   parse / false .code:n =
    {
      \bool_set_false:N \l__datatool_parse_datetime_bool
    } ,
   parse / true .code:n =
    {
      \bool_set_true:N \l__datatool_parse_datetime_bool
    } ,
   parse / parse-only .code:n =
    {
      \bool_set_true:N \l__datatool_parse_datetime_bool
      \bool_set_false:N \l__datatool_reformat_datetime_bool
    } ,
   parse / auto-reformat .code:n =
    {
      \bool_set_true:N \l__datatool_parse_datetime_bool
      \bool_set_true:N \l__datatool_reformat_datetime_bool
    } ,
   parse / iso-only .code:n =
    {
      \bool_set_true:N \l__datatool_parse_datetime_bool
      \bool_set_true:N \l__datatool_parse_datetime_iso_bool
      \bool_set_false:N \l__datatool_parse_datetime_regional_bool
    } ,
   parse / region-only .code:n =
    {
      \bool_set_true:N \l__datatool_parse_datetime_bool
      \bool_set_false:N \l__datatool_parse_datetime_iso_bool
      \bool_set_true:N \l__datatool_parse_datetime_regional_bool
    } ,
   parse / iso + region .code:n =
    {
      \bool_set_true:N \l__datatool_parse_datetime_bool
      \bool_set_true:N \l__datatool_parse_datetime_iso_bool
      \bool_set_true:N \l__datatool_parse_datetime_regional_bool
    } ,
   parse .default:n = true ,
   auto-reformat .choice: ,
   auto-reformat / false .code:n =
    {
      \bool_set_false:N \l__datatool_reformat_datetime_bool
    } ,
   auto-reformat / true .code:n =
    {
      \bool_set_true:N \l__datatool_reformat_datetime_bool
    } ,
   auto-reformat / region .code:n =
    {
      \bool_set_true:N \l__datatool_reformat_datetime_bool
      \renewcommand \DataToolDateFmt [ 4 ]
       {
         \DTLCurrentLocaleFormatDate { ##1 } { ##2 } { ##3 } { ##4 }
       }
      \renewcommand \DataToolTimeFmt [ 3 ]
       {
         \DTLCurrentLocaleFormatTime { ##1 } { ##2 } { ##3 }
       }
      \renewcommand \DataToolTimeZoneFmt [ 2 ]
       {
         \DTLCurrentLocaleFormatTimeZone { ##1 } { ##2 }
       }
      \renewcommand \DataToolTimeStampWithZoneFmt [ 9 ]
       {
         \DTLCurrentLocaleFormatTimeStampWithZone
           { ##1 } { ##2 } { ##3 } { ##4 }
           { ##5 } { ##6 } { ##7 }
           { ##8 } { ##9 }
       }
      \renewcommand \DataToolTimeStampNoZoneFmt [ 7 ]
       {
         \DTLCurrentLocaleFormatTimeStampNoZone
           { ##1 } { ##2 } { ##3 } { ##4 }
           { ##5 } { ##6 } { ##7 }
       }
      \renewcommand \DataToolTimeStampFmtSep
       {
        \DTLCurrentLocaleTimeStampFmtSep
       }
    } ,
   auto-reformat / iso .code:n =
    {
      \bool_set_true:N \l__datatool_reformat_datetime_bool
      \renewcommand \DataToolDateFmt [ 4 ]
       {
         \datatool_date_iso_fmt:nnnn
           { ##1 } { ##2 } { ##3 } { ##4 }
       }
      \renewcommand \DataToolTimeFmt [ 3 ]
       {
         \datatool_time_iso_fmt:nnn
           { ##1 } { ##2 } { ##3 }
       }
      \renewcommand \DataToolTimeZoneFmt [ 2 ]
       {
         \datatool_timezone_iso_fmt:nn
           { ##1 } { ##2 }
       }
      \renewcommand \DataToolTimeStampWithZoneFmt [ 9 ]
       {
         \datatool_timestamp_iso_fmt:nnnnnnnnn
           { ##1 } { ##2 } { ##3 } { ##4 }
           { ##5 } { ##6 } { ##7 }
           { ##8 } { ##9 }
       }
      \renewcommand \DataToolTimeStampNoZoneFmt [ 7 ]
       {
         \datatool_timestamp_iso_fmt:nnnnnnn
           { ##1 } { ##2 } { ##3 } { ##4 }
           { ##5 } { ##6 } { ##7 }
       }
    } ,
   auto-reformat / datetime2 .code:n =
    {
      \cs_if_exist:NTF \DTLdisplay
       {
         \bool_set_true:N \l__datatool_reformat_datetime_bool
         \renewcommand \DataToolDateFmt [ 4 ]
          {
            \tl_if_empty:nTF { ##4 }
             {
               \DTMdisplaydate { ##1 } { ##2 } { ##3 } { -1 }
             }
             {
               \DTMdisplaydate { ##1 } { ##2 } { ##3 } { ##4 }
             }
          }
         \renewcommand \DataToolTimeFmt [ 3 ]
          {
            \tl_if_empty:nTF { ##3 }
             {
               \DTMdisplaytime { ##1 } { ##2 } { 0 }
             }
             {
               \DTMdisplaytime { ##1 } { ##2 } { ##3 }
             }
          }
         \renewcommand \DataToolTimeZoneFmt [ 2 ]
          {
            \DTMdisplayzone { ##1 } { ##2 }
          }
         \renewcommand \DataToolTimeStampWithZoneFmt [ 9 ]
          {
            \tl_if_empty:nTF { ##4 }
             {
               \DTMdisplay
                 { ##1 } { ##2 } { ##3 } {-1 }
                 { ##5 } { ##6 } { ##7 }
                 { ##8 } { ##9 }
             }
             {
               \DTMdisplay
                 { ##1 } { ##2 } { ##3 } { ##4 }
                 { ##5 } { ##6 } { ##7 }
                 { ##8 } { ##9 }
             }
          }
         \renewcommand \DataToolTimeStampNoZoneFmt [ 7 ]
          {
            \tl_if_empty:nTF { ##4 }
             {
               \DTMdisplay
                 { ##1 } { ##2 } { ##3 } {-1 }
                 { ##5 } { ##6 } { ##7 }
                 { 0 } { 0 }
             }
             {
               \DTMdisplay
                 { ##1 } { ##2 } { ##3 } { ##4 }
                 { ##5 } { ##6 } { ##7 }
                 { 0 } { 0 }
             }
          }
       }
       {
          \PackageError { datatool-base }
           {
              Option ~ datetime ~ = ~ { ~ auto-reformat ~ = ~ datetime2 ~ } ~
              requires ~ datetime2 ~ package
           }
           {
             You ~ need ~ to ~ load ~ datetime2.sty ~ before ~ you ~
             set ~ this ~ option
           }
       }
    } ,
   auto-reformat .default:n = false ,
}
\bool_new:N \l__datatool_list_trim_bool
\bool_new:N \l__datatool_sort_reverse_bool
\bool_new:N \l__datatool_sort_datum_bool
\bool_new:N \l_datatool_list_and_bool
\bool_set_true:N \l_datatool_list_and_bool
\newcommand \DTLlistand
 {
   \bool_if:NTF \l_datatool_list_and_bool
    { \DTLandname }
    { \& }
 }
\newif\ifDTLlistskipempty
\DTLlistskipemptytrue
\keys_define:nn { datatool / lists }
{
   skip-empty .legacy_if_set:n = DTLlistskipempty ,
   trim .bool_set:N = \l__datatool_list_trim_bool ,
   trim .initial:n = true ,
   sort-reverse .bool_set:N = \l__datatool_sort_reverse_bool ,
   sort-reverse .initial:n = false ,
   sort-datum .bool_set:N = \l__datatool_sort_datum_bool ,
   sort-datum .initial:n = false ,
   and .choice: ,
   and / word .code:n =
    {
      \bool_true:N \l_datatool_list_and_bool
    } ,
   and / symbol .code:n =
    {
      \bool_false:N \l_datatool_list_and_bool
    } ,
}
\newif\ifdtlcompareskipcs
\dtlcompareskipcsfalse
\bool_new:N \l__datatool_compare_expand_cs_bool
\keys_define:nn { datatool / compare }
{
   expand-cs .bool_set:N = \l__datatool_compare_expand_cs_bool,
   skip-cs .legacy_if_set:n = dtlcompareskipcs,
}
\DeclareDocumentCommand \DTLsetup { m }
 { \keys_set:nn { datatool } { #1 } }
\ExplSyntaxOff
\ProcessKeyOptions[datatool]
\InputIfFileExists
 {datatool-\@dtl@mathprocessor.def}
 {}
 {
   \InputIfFileExists
    {datatool-l3fp.def}
    {
       \PackageError{datatool}
       {%
         Missing file `datatool-\@dtl@mathprocessor.def'
         for math=\@dtl@mathprocessor. Falling back on
         math=l3fp
       }
       {%
         Check that your TeX distribution contains the file
         `datatool-\@dtl@mathprocessor.def'
       }
    }
    {
       \PackageError{datatool}
       {%
         Missing file `datatool-\@dtl@mathprocessor.def'
         for math=\@dtl@mathprocessor. No math commands
         available!
       }
       {%
         Something is wrong with the datatool installation
       }
    }
 }
\newcommand*{\dtl@message}[1]{%
  \ifdtlverbose\typeout{#1}\fi
}
\newtoks\@dtl@toks
\newcount\@dtl@tmpcount
\newlength\dtl@tmplength
\ExplSyntaxOn
\cs_new:Nn \datatool_measure_height:Nn
{
  \settoheight #1 { \l_datatool_measure_hook_tl #2 }
}
\cs_new:Nn \datatool_measure_width:Nn
{
  \settowidth #1 { \l_datatool_measure_hook_tl #2 }
}
\cs_new:Nn \datatool_measure_depth:Nn
{
  \settodepth #1 { \l_datatool_measure_hook_tl #2 }
}
\cs_new:Nn \datatool_measure:NNNn
 {
   \hbox_set:Nn \l__datatool_measure_box
    { \l_datatool_measure_hook_tl #4 }
   \dim_set:Nn #1 { \box_wd:N \l__datatool_measure_box }
   \dim_set:Nn #2 {\box_ht:N \l__datatool_measure_box }
   \dim_set:Nn #3 { \box_dp:N \l__datatool_measure_box }
 }
\cs_new:Nn \datatool_measure_ht_plus_dp:Nn
 {
   \hbox_set:Nn \l__datatool_measure_box
    { \l_datatool_measure_hook_tl #2 }
   \dim_set:Nn #1
    {
      \box_ht:N \l__datatool_measure_box
      + \box_dp:N \l__datatool_measure_box
    }
 }
\box_new:N \l__datatool_measure_box
\tl_new:N \l_datatool_measure_hook_tl
\tl_set:Nn \l_datatool_measure_hook_tl
{
  \cs_set_eq:NN \label \use_none:n
  \cs_set_eq:NN \ref \use_none:n
  \cs_set_eq:NN \pageref \use_none:n
  \cs_set_eq:NN \refstepcounter \__datatool_local_stepcounter:n
  \cs_set_eq:NN \stepcounter \__datatool_local_stepcounter:n
  \cs_set_eq:NN \hypertarget \use_ii:nn
  \cs_set_eq:NN \hyperlink \use_ii:nn
}
\cs_new:Nn \__datatool_local_stepcounter:n
{
  \int_if_exist:cT { c@ #1 } { \int_incr:c { c@ #1 } }
}
\cs_new:Nn \datatool_swap_ints:NN
{
  \exp_args:Nee \__datatool_swap_ints:nnNN
    { \int_use:N #1 } { \int_use:N #2 } #1 #2
}
\cs_new:Nn \__datatool_swap_ints:nnNN
{
  \int_set:Nn #3 { #2 }
  \int_set:Nn #4 { #1 }
}
\newcommand{\dtlifintopenbetween}[5]{%
  \bool_lazy_and:nnTF
    { \int_compare_p:nNn { #1 } > { #2 } }
    { \int_compare_p:nNn { #1 } < { #3 } }
  { #4 } { #5 }
}
\newcommand{\dtlifintclosedbetween}[5]{%
  \bool_lazy_or:nnTF
    { \int_compare_p:nNn { #1 } < { #2 } }
    { \int_compare_p:nNn { #1 } > { #3 } }
  { #5 } { #4 }
}
\cs_new:Nn \datatool_signed_two_digits:n
 {
   \int_compare:nNnTF { #1 } < { \c_zero_int }
    {
      - \datatool_two_digits:e { \int_abs:n { #1 } }
    }
    {
      + \datatool_two_digits:n { #1 }
    }
 }
\cs_generate_variant:Nn \datatool_signed_two_digits:n { e, V }
\cs_new:Nn \datatool_signed_two_digits:N
 {
   \int_compare:nNnTF { #1 } < { \c_zero_int }
    {
      - \datatool_two_digits:e { \int_abs:n { #1 } }
    }
    {
      + \datatool_two_digits:N #1
    }
 }
\cs_new:Nn \datatool_two_digits:n
 {
   \int_compare:nNnTF { #1 } < { \c_zero_int }
    {
      - \datatool_two_digits:e { \int_abs:n { #1 } }
    }
    {
      \int_compare:nNnT { #1 } < { 10 } { 0 }
      \int_eval:n { #1 }
    }
 }
\cs_generate_variant:Nn \datatool_two_digits:n { e, V }
\cs_new:Nn \datatool_two_digits:N
 {
   \int_compare:nNnTF { #1 } < { \c_zero_int }
    {
      - \datatool_two_digits:e { \int_abs:n { #1 } }
    }
    {
      \int_compare:nNnT { #1 } < { 10 } { 0 }
      \int_use:N #1
    }
 }
\newcommand{\dtlpadleadingzeros}[2]{
  \fp_compare:nNnTF { #2 } < { \c_zero_fp }
  { \dtlpadleadingzerosminus } { \dtlpadleadingzerosplus }
  \__datatool_int_leading_zeros:ee
    { \int_eval:n { #1 } }
    { \fp_to_int:n { floor ( abs ( #2 ) ) } }
  \fp_to_decimal:n { abs ( #2 ) }
}
\newcommand{\dtlpadleadingzerosminus}{-}
\newcommand{\dtlpadleadingzerosplus}{}
\cs_new:Nn \__datatool_int_leading_zeros:nn
{
 \bool_lazy_and:nnTF
    { \int_compare_p:nNn { #1 } > { \c_one_int } }
    { \int_compare_p:nNn { #2 } < { 10 } }
  { \prg_replicate:nn { #1 - \c_one_int } { 0 } }
  {
    \bool_lazy_and:nnTF
      { \int_compare_p:nNn { #1 } > { 2 } }
      { \int_compare_p:nNn { #2 } < { 100 } }
     { \prg_replicate:nn { #1 - 2 } { 0 } }
     {
       \bool_lazy_and:nnTF
         { \int_compare_p:nNn { #1 } > { 3 } }
         { \int_compare_p:nNn { #2 } < { 1000 } }
        { \prg_replicate:nn { #1 - 3 } { 0 } }
        {
          \bool_lazy_and:nnTF
            { \int_compare_p:nNn { #1 } > { 4 } }
            { \int_compare_p:nNn { #2 } < { 10000 } }
           { \prg_replicate:nn { #1 - 4 } { 0 } }
           {
             \bool_lazy_and:nnTF
               { \int_compare_p:nNn { #1 } > { 5 } }
               { \int_compare_p:nNn { #2 } < { 100000 } }
              { \prg_replicate:nn { #1 - 5 } { 0 } }
              {
                \bool_lazy_and:nnT
                  { \int_compare_p:nNn { #1 } > { 6 } }
                  { \int_compare_p:nNn { #2 } < { 1000000 } }
                 { \prg_replicate:nn { #1 - 6 } { 0 } }
              }
           }
        }
     }
  }
}
\cs_generate_variant:Nn \__datatool_int_leading_zeros:nn { en, ee }
\cs_new:Nn \datatool_pad_trailing_zeros:Nn
{
  \int_compare:nNnT { #2 } > { \c_zero_int }
  {
    \tl_if_in:NnTF #1 { . }
    {
      \exp_after:wN \__datatool_split_decimal:wNN #1 \q_stop
        \l__datatool_prefix_tl
        \l__datatool_suffix_tl
      \int_step_inline:nnn { \tl_count:N \l__datatool_suffix_tl + 1 } { #2 }
       {
         \tl_put_right:Nn #1 { 0 }
       }
    }
    {
      \tl_put_right:Nn #1 { . }
      \int_step_inline:nn { #2 }
       {
         \tl_put_right:Nn #1 { 0 }
       }
    }
  }
}
\cs_generate_variant:Nn \datatool_pad_trailing_zeros:Nn { cn }
\cs_new:Npn \__datatool_split_decimal:wNN #1 . #2 \q_stop #3 #4
{
  \tl_set:Nn #3 { #1 }
  \tl_set:Nn #4 { #2 }
}
\newcommand{\@dtl@assigntmpseq}[1]{
  \tl_if_single_token:nTF { #1 }
  {
    \exp_args:No \__datatool_create_tmp_list:n { #1 }
  }
  {
    \__datatool_create_tmp_list:n { #1 }
  }
}
\cs_new:Nn \__datatool_create_tmp_list:n
 {
   \bool_if:NTF \l__datatool_list_trim_bool
   {
     \seq_set_from_clist:Nn \l__datatool_tmp_seq { #1 }
   }
   {
     \seq_set_split_keep_spaces:Nnn \l__datatool_tmp_seq { , } { #1 }
   }
   \ifDTLlistskipempty
    \seq_remove_all:Nn \l__datatool_tmp_seq {}
   \fi
 }
\newcommand*{\DTLifinlist}[4]{
 \@dtl@assigntmpseq{#2}
 \seq_if_in:NnTF \l__datatool_tmp_seq { #1 } { #3 } { #4 }
}
\newrobustcmd{\DTLlistelement}[2]{%
 \@dtl@assigntmpseq{#1}
 \seq_item:Nn \l__datatool_tmp_seq { #2 }
}
\newrobustcmd{\DTLfetchlistelement}[3]{%
 \@dtl@assigntmpseq{#1}
 \tl_set:Nx #3 { \seq_item:Nn \l__datatool_tmp_seq { #2 } }
}
\newrobustcmd{\DTLnumitemsinlist}[2]{%
  \@dtl@assigntmpseq{#1}
  \tl_set:Nx #2 { \seq_count:N \l__datatool_tmp_seq }
}
\newcommand{\DTLDefaultLocaleWordHandler}[1]{%
  \DTLCurrentLocaleWordHandler{#1}%
  \appto#1{\datatoolctrlboundary}%
}
\newcommand{\DTLCurrentLocaleWordHandler}[1]{}
\ExplSyntaxOff
\newcommand*{\dtlSortWordCommands}{%
 \begingroup\makeatletter
 \dtl@SortWordCommands
}
\newcommand{\dtl@SortWordCommands}[1]{%
  \gappto\dtl@SortWordCommands@hook{#1}%
  \endgroup
}
\newcommand{\datatoolasciistart}{}
\newcommand{\datatoolasciiend}{}
\newcommand{\datatoolctrlboundary}{}
\newcommand{\dtltexorsort}[2]{#1}
\begingroup
\ExplSyntaxOn
\char_set_catcode_other:n {0}
\char_set_catcode_other:n {28}
\char_set_catcode_other:n {29}
\char_set_catcode_other:n {30}
\char_set_catcode_other:n {31}
\char_set_catcode_other:n {127}
\ExplSyntaxOff
\gdef\dtl@SortWordCommands@hook{%
  \def\datatoolasciistart{^^@}%
  \def\datatoolpersoncomma{^^1c}%
  \def\datatoolplacecomma{^^1d}%
  \def\datatoolsubjectcomma{^^1e}%
  \def\datatoolparenstart{^^1f}%
  \def\datatoolctrlboundary{^^1f}%
  \def\datatoolparen{\datatoolctrlboundary\@gobble}%
  \def\datatoolasciiend{^^7f}%
  \let\nobreakspace\space
  \let\ \space
  \edef\${\expandafter\@gobble\string\$}%
  \edef\_{\expandafter\@gobble\string\_}%
  \edef\#{\expandafter\@gobble\string\#}%
  \edef\%{\expandafter\@gobble\string\%}%
  \edef\&{\expandafter\@gobble\string\&}%
  \let\dtltexorsort\@secondoftwo
  \def\TeX{TeX}%
  \def\LaTeX{LaTeX}%
  \datatoolSetCurrencySort
}
\endgroup
\ExplSyntaxOn
\cs_new:Nn \datatool_sort_preprocess:Nn
 {
   \datatool_sort_preprocess:NnN #1 { #2 }
    \l_datatool_sort_to_lowercase_bool
 }
\cs_new:Nn \datatool_sort_preprocess:NnN
 {
   \group_begin:
    \dtl@SortWordCommands@hook
    \bool_if:NTF #3
     {
       \datatool_sort_handler_preprocess:Nn #1 { \text_lowercase:n { #2 } }
     }
     {
       \datatool_sort_handler_preprocess:Nn #1 { #2 }
     }
    \exp_args:NNNe
   \group_end:
    \tl_set:Nn #1 { \exp_args:NV \text_purify:n #1 }
 }
\seq_new:N \l__datatool_wordlist_seq
\tl_new:N \l__datatool_word_tl
\NewDocumentCommand \DTLsortwordlist { m m }
{
  \datatool_sortwordlist:NNN #1 #2 \__datatool_append_sorteditem:w
}
\cs_new:Nn \datatool_sortwordlist:NNN
 {
  \__datatool_sortword_list:NN #1 #2
  \__datatool_finish_sortword_list:NN #1 #3
 }
\cs_new:Nn \__datatool_sortword_list:NN
{
  \group_begin:
  \dtl@SortWordCommands@hook
  \seq_clear:N \l__datatool_wordlist_seq
  \exp_args:No \__datatool_create_tmp_list:n { #1 }
  \__datatool_sortword_seq:NN \l__datatool_tmp_seq #2
  \exp_args:No
   \__datatool_start_sortword_list:n
     { \l__datatool_wordlist_seq }
}
\cs_new:Nn \datatool_sortwordseq:NN
 {
   \datatool_sortwordseq:NNN #1 #2 \__datatool_append_sorted_seq_item:w
 }
\cs_new:Nn \datatool_sortwordseq:NNN
 {
  \__datatool_sortword_seqlist:NN #1 #2
  \__datatool_finish_sortword_seq:NN #1 #3
 }
\cs_new:Nn \__datatool_sortword_seqlist:NN
{
  \group_begin:
  \dtl@SortWordCommands@hook
  \seq_clear:N \l__datatool_wordlist_seq
  \__datatool_sortword_seq:NN #1 #2
  \exp_args:No
   \__datatool_start_sortword_list:n
     { \l__datatool_wordlist_seq }
}
\cs_new:Nn \__datatool_sortword_seq:NN
{
  \seq_map_inline:Nn #1
   {
     \bool_if:NTF \l__datatool_sort_datum_bool
     {
       \DTLparse \l__datatool_tmpa_tl { ##1 }
       \tl_set:No \l__datatool_word_tl { ##1 }
       #2 { ##1 } { \l__datatool_word_tl }
       \exp_args:Noo \__datatool_sortword_append:nn
        { \l__datatool_word_tl }
        { \l__datatool_tmpa_tl }
     }
     {
       \tl_set:Nn \l__datatool_word_tl { ##1 }
       #2 { ##1 } { \l__datatool_word_tl }
       \exp_args:No \__datatool_sortword_append:nn
        { \l__datatool_word_tl } { ##1 }
     }
   }
}
\cs_new:Nn \__datatool_start_sortword_list:n
{
   \group_end:
   \tl_set:Nn \l__datatool_wordlist_seq { #1 }
   \seq_sort:Nn \l__datatool_wordlist_seq
   {
     \__datatool_compare_sortitem:w ##1 ##2
   }
}
\cs_new:Nn \__datatool_sortword_append:nn
 {
    \seq_put_right:Nn \l__datatool_wordlist_seq
     { #1 \q_mark #2 \q_stop }
 }
\cs_new:Npn \__datatool_compare_sortitem:w
 #1\q_mark#2\q_stop#3\q_mark#4\q_stop
 {
   \__datatool_compare_sortitem:nnnn
    { #1 } { #2 } { #3 } { #4 }
   \int_compare:nNnTF
       { \dtl@sortresult } < { \c_zero_int }
    {
      \sort_return_same:
    }
    {
      \int_compare:nNnTF
         { \dtl@sortresult } > { \c_zero_int }
       {
         \sort_return_swapped:
       }
       {
         \bool_if:NTF \l__datatool_sort_reverse_bool
          {
            \__datatool_fallback_action:nnnn { #4 } { #2 }
             { \sort_return_swapped: }
             { \sort_return_same: }
          }
          {
            \__datatool_fallback_action:nnnn { #2 } { #4 }
             { \sort_return_swapped: }
             { \sort_return_same: }
          }
       }
    }
 }
\cs_new:Nn \__datatool_compare_sortitem:nnnn
{
  \tl_clear:N \l__datatool_tmpc_tl
  \tl_clear:N \l__datatool_tmpd_tl
  \int_set_eq:NN \@dtl@datatype \c_datatool_string_int
  \tl_if_head_eq_meaning:nNTF { #2 }  \__datatool_datum:nnnn
   {
     \__datatool_get_datum:w #2 \q_nil \q_stop
     \int_set_eq:NN
       \l__datatool_tmp_datatype_int
       \@dtl@datatype
     \tl_set:No \l__datatool_tmpc_tl
       { \datatool_datum_currency:Nnnnn #2 }
   }
   {
     \datatool_if_null:nT { #2 }
      {
        \int_set_eq:NN
          \l__datatool_tmp_datatype_int
          \c_datatool_unknown_int
      }
   }
  \tl_if_head_eq_meaning:nNTF { #4 }  \__datatool_datum:nnnn
   {
     \__datatool_get_datum:w #4 \q_nil \q_stop
     \tl_set:No \l__datatool_tmpd_tl
       { \datatool_datum_currency:Nnnnn #4 }
   }
   {
     \datatool_if_null:nT { #4 }
      {
        \int_set_eq:NN
          \@dtl@datatype
          \c_datatool_unknown_int
      }
   }
  \tl_if_eq:NNF \l__datatool_tmpc_tl \l__datatool_tmpd_tl
   {
     \int_set_eq:NN
       \l__datatool_tmp_datatype_int \c_datatool_string_int
     \int_set_eq:NN
       \@dtl@datatype \c_datatool_string_int
   }
  \int_compare:nNnTF
    { \l__datatool_tmp_datatype_int }
      =
    { \c_datatool_unknown_int }
   {
     \int_compare:nNnTF
      { \@dtl@datatype } > { \c_datatool_string_int }
     {
       \__datatool_numcmp:Nnn \dtl@sortresult
        { 0 }
        { \datatool_datum_value:Nnnnn #4 }
     }
     {
       \__datatool_strcmp:Nnn \dtl@sortresult { #1 } { #3 }
     }
   }
   {
     \int_case:nnF { \@dtl@datatype }
     {
       { \c_datatool_unknown_int }
         {
           \int_compare:nNnTF
              { \l__datatool_tmp_datatype_int }
                >
              { \c_datatool_string_int }
            {
              \__datatool_numcmp:Nnn \dtl@sortresult
               { \datatool_datum_value:Nnnnn #2 }
               { 0 }
            }
            {
              \__datatool_strcmp:Nnn \dtl@sortresult { #1 } { #3 }
            }
         }
       { \c_datatool_string_int }
         {
            \__datatool_strcmp:Nnn \dtl@sortresult { #1 } { #3 }
         }
     }
     {
       \int_compare:nNnTF
          { \l__datatool_tmp_datatype_int }
           >
          { \c_datatool_string_int }
        {
          \__datatool_numcmp:Nnn \dtl@sortresult
           { \datatool_datum_value:Nnnnn #2 }
           { \datatool_datum_value:Nnnnn #4 }
        }
        {
          \__datatool_strcmp:Nnn \dtl@sortresult { #1 } { #3 }
        }
     }
   }
  \bool_if:NT \l__datatool_sort_reverse_bool
   {
     \int_compare:nNnTF
       { \dtl@sortresult } < { \c_zero_int }
      {
        \int_set:Nn \dtl@sortresult { \c_one_int }
      }
      {
        \int_set:Nn \dtl@sortresult { - \dtl@sortresult }
      }
   }
}
\cs_new:Nn \__datatool_finish_sortword_list:NN
 {
   \clist_clear:N #1
   \seq_map_inline:Nn \l__datatool_wordlist_seq
   {
     #2 ##1 #1
   }
 }
\cs_new:Nn \__datatool_finish_sortword_seq:NN
 {
   \seq_clear:N #1
   \seq_map_inline:Nn \l__datatool_wordlist_seq
   {
     #2 ##1 #1
   }
 }
\cs_new:Nn \__datatool_sorted:nnn { \exp_not:n { #1 }}
\newcommand{\DTLsortedactual} [1] { \use_ii:nnnn #1 }
\newcommand{\DTLsortedvalue} [1] { \use_iii:nnnn #1 }
\newcommand{\DTLsortedletter} [1] { \use_iv:nnnn #1 }
\cs_new:Npn \__datatool_append_sorteditem:w
  #1 \q_mark #2 \q_stop #3
{
  \tl_clear:N \l__datatool_tmpa_tl
  \DTLassignlettergroup { #2 } { #1 } { \l__datatool_tmpa_tl }
  \clist_put_right:Nx #3
    { \exp_not:N \__datatool_sorted:nnn
        { \exp_not:n { #2 } } { \exp_not:n { #1 } }
        { \exp_not:o { \l__datatool_tmpa_tl } }
    }
}
\cs_new:Npn \__datatool_append_sorted_seq_item:w
  #1 \q_mark #2 \q_stop #3
{
  \tl_clear:N \l__datatool_tmpa_tl
  \DTLassignlettergroup { #2 } { #1 } { \l__datatool_tmpa_tl }
  \seq_put_right:Nx #3
    { \exp_not:N \__datatool_sorted:nnn
        { \exp_not:n { #2 } } { \exp_not:n { #1 } }
        { \exp_not:o { \l__datatool_tmpa_tl } }
    }
}
\newcommand{\DTLassignlettergroup} [3]
 {
   \@dtl@datatype = \c_datatool_string_int
   \tl_if_head_eq_meaning:nNT { #1 } \__datatool_datum:nnnn
    {
      \__datatool_get_datum:w #1 \q_nil \q_stop
    }
   \int_case:nn { \@dtl@datatype }
   {
     { \c_datatool_string_int }
      {
       \DTLCurrentLocaleGetGroupString { #1 } { #2 } #3
       \exp_args:NV \datatool_get_first_grapheme:nN #3 #3
       \exp_args:NV \datatool_if_letter:nTF #3
        {
           \exp_args:NV \DTLCurrentLocaleGetInitialLetter #3 { #3 }
           \DTLPreProcessLetterGroup { #3 }
           \tl_set:Nx #3 { \exp_not:N \dtllettergroup { #3 } }
        }
        {
          \DTLPreProcessNonLetterGroup { #3 }
          \tl_set:Nx #3 { \exp_not:N \dtlnonlettergroup { #3 } }
        }
      }
     { \c_datatool_integer_int }
      {
        \DTLPreProcessIntegerGroup
          { \l__datatool_datum_value_tl } { #1 }
        \tl_set:Nx #3
         { \exp_not:N \dtlnumbergroup { \l__datatool_datum_value_tl } }
      }
     { \c_datatool_decimal_int }
      {
        \DTLPreProcessDecimalGroup
          { \l__datatool_datum_value_tl } { #1 }
        \tl_set:Nx #3
         { \exp_not:N \dtlnumbergroup { \l__datatool_datum_value_tl } }
      }
     { \c_datatool_currency_int }
      {
        \DTLPreProcessCurrencyGroup
          { \l__datatool_datum_currency_tl }
          { \l__datatool_datum_value_tl }
          { #1 }
        \tl_set:Nx #3
         {
           \exp_not:N \dtlcurrencygroup
             { \exp_not:o { \l__datatool_datum_currency_tl } }
             { \l__datatool_datum_value_tl }
         }
      }
     { \c_datatool_datetime_int }
      {
        \DTLPreProcessDateTimeGroup
          { \l__datatool_datum_value_tl } { #1 }
        \tl_set:Nx #3
         { \exp_not:N \dtldatetimegroup { \l__datatool_datum_value_tl } }
      }
     { \c_datatool_date_int }
      {
        \DTLPreProcessDateGroup
          { \l__datatool_datum_value_tl } { #1 }
        \tl_set:Nx #3
         { \exp_not:N \dtldategroup { \l__datatool_datum_value_tl } }
      }
     { \c_datatool_time_int }
      {
        \DTLPreProcessTimeGroup
          { \l__datatool_datum_value_tl } { #1 }
        \tl_set:Nx #3
         { \exp_not:N \dtltimegroup { \l__datatool_datum_value_tl } }
      }
   }
 }
\newcommand{\DTLCurrentLocaleGetGroupString}[3]
{
  \tl_set:Nn #3 { #1 }
}
\newcommand{\DTLPreProcessLetterGroup}[1]{}
\newcommand{\DTLPreProcessNonLetterGroup}[1]{}
\newcommand{\DTLPreProcessIntegerGroup}[2]{}
\newcommand{\DTLPreProcessDecimalGroup}[2]{}
\newcommand{\DTLPreProcessCurrencyGroup}[3]{}
\newcommand{\DTLPreProcessDateTimeGroup}[2]{}
\newcommand{\DTLPreProcessDateGroup}[2]{}
\newcommand{\DTLPreProcessTimeGroup}[2]{}
\newcommand{\dtllettergroup}[1]{ \text_titlecase_first:n { #1 } }
\newcommand{\dtlnonlettergroup}[1]{\detokenize{#1}}
\newcommand{\dtlnumbergroup}[1]{#1}
\newcommand{\dtlcurrencygroup}[2]{#1}
\newcommand{\dtldatetimegroup}[1]{#1}
\newcommand{\dtldategroup}[1]{#1}
\newcommand{\dtltimegroup}[1]{#1}
\newcommand{\dtlfallbackaction}[4]{
  \DTLifstringgt { #1 } { #2 } { #3 } { #4 }
}
\cs_new:Nn \__datatool_fallback_action:nnnn
{
  \dtlfallbackaction { #1 } { #2 } { #3 } { #4 }
}
\cs_new:Nn \datatool_sort_handler_preprocess:Nn
{
  \protected@edef #1 { #2 }
}
\bool_new:N \l_datatool_sort_to_lowercase_bool
\bool_set_true:N \l_datatool_sort_to_lowercase_bool
\newcommand{\DTLsortwordhandler}[2]{
  \bool_set_true:N \l_datatool_sort_to_lowercase_bool
  \datatool_sort_handler_preprocess:Nn
     #2 { #1 }
  \DTLDefaultLocaleWordHandler { #2 }
  \tl_set:Ne #2 { \text_lowercase:n { \text_purify:n { #2 } } }
}
\newcommand{\DTLsortwordcasehandler}[2]{
  \bool_set_false:N \l_datatool_sort_to_lowercase_bool
  \datatool_sort_handler_preprocess:Nn
    #2 { #1 }
  \DTLDefaultLocaleWordHandler { #2 }
  \tl_set:Ne #2 { \text_purify:n { #2 } }
}
\regex_new:N \l_datatool_letter_regex
\regex_set:Nn \l_datatool_letter_regex { [\-[:space:]] }
\newcommand{\DTLsortletterhandler}[2]{
  \bool_set_true:N \l_datatool_sort_to_lowercase_bool
  \datatool_sort_handler_preprocess:Nn
    #2 { #1 }
  \regex_replace_all:NnN \l_datatool_letter_regex {} #2
  \DTLDefaultLocaleWordHandler { #2 }
  \tl_set:Ne #2 { \text_lowercase:n { \text_purify:n { #2 } } }
}
\newcommand{\DTLsortlettercasehandler}[2]{
  \bool_set_false:N \l_datatool_sort_to_lowercase_bool
  \datatool_sort_handler_preprocess:Nn
    #2 { #1 }
  \regex_replace_all:NnN \l_datatool_letter_regex {} #2
  \DTLDefaultLocaleWordHandler { #2 }
  \tl_set:Ne #2 { \text_purify:n { #2 } }
}
\newcommand{\dtlsortlist}[2]{%
  \exp_args:No \__datatool_create_tmp_list:n { #1 }
  \seq_set_eq:NN \l__datatool_wordlist_seq \l__datatool_tmp_seq
  \seq_sort:Nn \l__datatool_wordlist_seq
  {
    \bool_if:NTF \l__datatool_sort_reverse_bool
    {
      #2 { \dtl@sortresult } { ##2 } { ##1 }
    }
    {
      #2 { \dtl@sortresult } { ##1 } { ##2 }
    }
    \ifnum\dtl@sortresult > 0\relax
      \sort_return_swapped:
    \else
      \sort_return_same:
    \fi
  }
  \tl_clear:N #1
  \seq_map_inline:Nn \l__datatool_wordlist_seq
  {
    \tl_if_empty:NF #1
     {
       \tl_put_right:Nn #1 { , }
     }
    \tl_if_in:nnTF { ##1 } { , }
    {
      \tl_put_right:Nn #1 { { ##1 } }
    }
    {
      \tl_put_right:Nn #1 { ##1 }
    }
  }
}
\newrobustcmd{\dtlinsertinto}[3]{%
  \exp_args:No \__datatool_create_tmp_list:n { #2 }
  \seq_set_eq:NN \l__datatool_wordlist_seq \l__datatool_tmp_seq
  \tl_gclear:N #2
  \@dtl@insertdonefalse
  \seq_map_inline:Nn \l__datatool_wordlist_seq
  {
    \tl_if_empty:NF #2
     {
       \tl_gput_right:Nn #2 { , }
     }
    \if@dtl@insertdone
    \else
      #3 { \dtl@sortresult } { ##1 } { #1 }
      \ifnum\dtl@sortresult > 0\relax
        \@dtl@insertdonetrue
        \tl_if_in:nnTF { #1 } { , }
        {
          \tl_gput_right:Nn #2 { { #1 } , }
        }
        {
          \tl_gput_right:Nn #2 { #1 , }
        }
      \fi
    \fi
    \tl_if_in:nnTF { ##1 } { , }
    {
      \tl_gput_right:Nn #2 { { ##1 } }
    }
    {
      \tl_gput_right:Nn #2 { ##1 }
    }
  }
  \if@dtl@insertdone
  \else
    \tl_if_empty:NF #2
     {
       \tl_gput_right:Nn #2 { , }
     }
    \tl_if_in:nnTF { #1 } { , }
     {
       \tl_gput_right:Nn #2 { { #1 } }
     }
     {
       \tl_gput_right:Nn #2 { #1 }
     }
  \fi
}
\newcommand*{\edtlinsertinto}[3]{%
  \exp_args:Nx \dtlinsertinto {#1} {#2} {#3}%
}
\ExplSyntaxOff
\newif\if@dtl@insertdone
\newcount\dtl@sortresult
\ExplSyntaxOn
\NewDocumentCommand \DTLshufflelist { m }
{
  \group_begin:
  \exp_args:No \__datatool_create_tmp_list:n { #1 }
  \seq_shuffle:N \l__datatool_tmp_seq
  \clist_clear:N \l__datatool_tmp_clist
  \seq_map_inline:Nn \l__datatool_tmp_seq
   {
     \clist_put_right:Nn \l__datatool_tmp_clist { ##1 }
   }
  \exp_args:NNNV
  \group_end:
  \tl_set:Nn #1 \l__datatool_tmp_clist
}
\ExplSyntaxOff
\newcommand*{\DTLlistformatsep}{, }
\newcommand*{\DTLlistformatoxford}{}
\ifdef\andname
{\newcommand*{\DTLandname}{\andname}}
{\newcommand*{\DTLandname}{\&}}
\newcommand*{\DTLlistformatlastsep}{ \DTLlistand\space}
\newcommand*{\DTLlistformatitem}[1]{#1}
\newcommand*{\@dtl@formatlist@handler}[1]{%
  \@dtl@formatlist@itemsep
  \@dtl@formatlist@lastitem
  \renewcommand{\@dtl@formatlist@lastitem}{%
    \renewcommand{\@dtl@formatlist@itemsep}{%
      \DTLlistformatsep
      \renewcommand*{\@dtl@formatlist@prelastitemsep}{%
        \DTLlistformatoxford}}%
    \renewcommand{\@dtl@formatlist@prelastitem}{%
      \@dtl@formatlist@prelastitemsep
       \DTLlistformatlastsep}%
    \DTLlistformatitem{#1}%
  }%
}%
\newrobustcmd*{\DTLformatlist}{%
 \@ifstar{\s@dtlformatlist}{\@dtlformatlist}%
}
\ExplSyntaxOn
\newcommand*{\s@dtlformatlist}[1]{%
  \def\@dtl@formatlist@itemsep{}%
  \def\@dtl@formatlist@lastitem{}%
  \def\@dtl@formatlist@prelastitem{}%
  \def\@dtl@formatlist@prelastitemsep{}%
  \@dtl@assigntmpseq{#1}%
  \seq_map_function:NN \l__datatool_tmp_seq \@dtl@formatlist@handler
  \@dtl@formatlist@prelastitem\@dtl@formatlist@lastitem
}
\ExplSyntaxOff
\newcommand*{\@dtlformatlist}[1]{{\s@dtlformatlist{#1}}}
\ExplSyntaxOn
\newcommand{\@dtl@toks@gput@right@cx}[2]{%
 \__datatool_token_register_gput_right:cx #1 { #2 }
}
\newcommand{\@dtl@toks@gconcat@middle@cx}[4]{%
  \__datatool_token_register_gset:cx
    { #1 } { \the #2 #3 \the #4 }
}
\cs_new:Nn \__datatool_token_register_use:N
{
  \the #1
}
\cs_generate_variant:Nn
  \__datatool_token_register_use:N { c }
\cs_new:Nn \__datatool_token_register_set_eq:NN
{
  #1 = #2
}
\cs_generate_variant:Nn
   \__datatool_token_register_set_eq:NN
 { cN, Nc, cc }
\cs_new:Nn \__datatool_token_register_gset_eq:NN
{
  \global #1 = #2
}
\cs_generate_variant:Nn
   \__datatool_token_register_gset_eq:NN
 { cN, Nc, cc }
\cs_new:Nn \__datatool_token_register_set:Nn
{
  #1 = { #2 }
}
\cs_generate_variant:Nn
   \__datatool_token_register_set:Nn
   { cn, cx, co, cV, No, Nx, NV }
\cs_new:Nn \__datatool_token_register_gset:Nn
{
  \global #1 = { #2 }
}
\cs_generate_variant:Nn
   \__datatool_token_register_gset:Nn
   { cn, cx, co, cV, No, Nx }
\cs_new:Nn \__datatool_token_register_put_right:Nn
{
  \__datatool_token_register_set:No #1
   { \the #1  #2 }
}
\cs_generate_variant:Nn
   \__datatool_token_register_put_right:Nn
   { cn, cx, co, cV, No, Nx }
\cs_new:Nn \__datatool_token_register_gput_right:Nn
{
  \__datatool_token_register_gset:No #1
   { \the #1  #2 }
}
\cs_generate_variant:Nn
   \__datatool_token_register_gput_right:Nn
   { cn, cx, co, cV, No, Nx }
\cs_new:Nn \__datatool_token_register_concat_middle:NNnN
{
  \__datatool_token_register_set:Nx
    #1 { \the #2 \exp_not:n { #3 } \the #4 }
}
\cs_generate_variant:Nn
   \__datatool_token_register_concat_middle:NNnN
   { cNnN, cNxN, NNxN }
\cs_new:Nn \__datatool_token_register_gconcat_middle:NNnN
{
  \__datatool_token_register_gset:Nx
    #1 { \the #2 \exp_not:n { #3 } \the #4 }
}
\cs_generate_variant:Nn
   \__datatool_token_register_gconcat_middle:NNnN
   { cNnN, cNxN, NNxN }
\regex_new:N \l_datatool_apos_regex
\regex_set:Nn \l_datatool_apos_regex { \' }
\cs_new:Nn \__datatool_new_symbol:nn
 {
   \__datatool_new_symbol:nnn { #1 } { #2 } { #2 }
 }
\cs_new:Nn \__datatool_new_symbol:nnn
 {
   \tl_new:c { l_datatool_ #1 _tl }
   \tl_set:cn { l_datatool_ #1 _tl } { #2 }
   \str_new:c { l_datatool_ #1 _str }
   \str_set:cn { l_datatool_ #1 _str } { #3 }
 }
\cs_generate_variant:Nn \__datatool_new_symbol:nnn { nnV }
\regex_new:N \l_datatool_currencysigns_regex
\regex_set:Nn \l_datatool_currencysigns_regex { \$ }
\cs_new:Nn \datatool_set_symbol:nn
 {
   \str_set:cn { l_datatool_ #1 _str } { #2 }
   \tl_set:cn { l_datatool_ #1 _tl } { #2 }
 }
\cs_generate_variant:Nn \datatool_set_symbol:nn { ne }
\cs_new:Nn \datatool_set_symbol_from_charcode:nn
 {
   \str_set:ce { l_datatool_ #1 _str }
    { \char_generate:nn { #2 } { 12 } }
   \exp_args:Nno \tl_set:co { l_datatool_ #1 _tl }
    { \char_generate:nn { #2 } { 13 } }
 }
\cs_new:Nn \datatool_set_currencysign:nn
 {
   \datatool_set_symbol:nn { #1 } { #2 }
   \regex_set:Nn \l_datatool_currencysigns_regex
     {
        \ur { l_datatool_currencysigns_regex }
       | \u { l_datatool_ #1 _str }
     }
   \DTLnewcurrencysymbol { #2 }
 }
\cs_generate_variant:Nn \datatool_set_currencysign:nn { ne }
\cs_new:Nn \datatool_set_currencysign_from_charcode:nn
 {
   \datatool_set_symbol_from_charcode:nn { #1 } { #2 }
   \regex_set:Nn \l_datatool_currencysigns_regex
     {
        \ur { l_datatool_currencysigns_regex }
       | \u { l_datatool_ #1 _str }
     }
 }
\__datatool_new_symbol:nn { cent } { c }
\__datatool_new_symbol:nn { pound } { L }
\__datatool_new_symbol:nnV { currency } { \# } \c_hash_str
\__datatool_new_symbol:nn { yen } { Y }
\__datatool_new_symbol:nn { middot } { . }
\__datatool_new_symbol:nn { florin } { f }
\__datatool_new_symbol:nn { baht } { B }
\__datatool_new_symbol:nn { ecu } { CE }
\__datatool_new_symbol:nn { colonsign } { C }
\__datatool_new_symbol:nn { cruzerio } { Cr }
\__datatool_new_symbol:nn { frenchfranc } { F }
\__datatool_new_symbol:nn { lira } { L }
\__datatool_new_symbol:nn { mill } { m }
\__datatool_new_symbol:nn { naira } { N }
\__datatool_new_symbol:nn { peseta } { Pts }
\__datatool_new_symbol:nn { rupee } { Rs }
\__datatool_new_symbol:nn { won } { W }
\__datatool_new_symbol:nn { shekel } { S }
\__datatool_new_symbol:nn { dong } { d }
\__datatool_new_symbol:nn { euro } { E }
\__datatool_new_symbol:nn { kip } { K }
\__datatool_new_symbol:nn { tugrik } { T }
\__datatool_new_symbol:nn { drachma } { Dr }
\__datatool_new_symbol:nn { germanpenny } { p }
\__datatool_new_symbol:nn { peso } { P }
\__datatool_new_symbol:nn { guarani } { G. }
\__datatool_new_symbol:nn { austral } { A }
\__datatool_new_symbol:nn { hryvnia } { S }
\__datatool_new_symbol:nn { cedi } { C }
\__datatool_new_symbol:nn { livretournois } { lt }
\__datatool_new_symbol:nn { spesmilo } { Sm }
\__datatool_new_symbol:nn { tenge } { T }
\__datatool_new_symbol:nn { indianrupee } { R }
\__datatool_new_symbol:nn { turkishlira } { L }
\__datatool_new_symbol:nn { nordicmark } { M }
\__datatool_new_symbol:nn { manat } { M }
\__datatool_new_symbol:nn { ruble } { R }
\__datatool_new_symbol:nn { lari } { L }
\__datatool_new_symbol:nn { bitcoin } { B }
\__datatool_new_symbol:nn { som } { c }
\seq_new:N \l__datatool_known_currencies_seq
\seq_new:N \l_datatool_currencies_seq
\seq_new:N \l_datatool_regional_currencies_seq
\prop_new:N \l_datatool_regional_currencies_prop
\NewDocumentCommand \DTLnewcurrencysymbol { m }
{
  \seq_if_in:NnF \l__datatool_known_currencies_seq { #1 }
   {
     \seq_put_right:Nn \l__datatool_known_currencies_seq { #1 }
   }
}
\ExplSyntaxOff
\InputIfFileExists
 {datatool-\TrackLangEncodingName .ldf}
{}
{
  \PackageInfo{datatool-base}
   {Missing file `datatool-\TrackLangEncodingName .ldf'.
    Falling back on US-ASCII for \string\datatool\string_...\string_str commands}
}
\ExplSyntaxOn
\tl_new:N \__datatool_decimal_tl
\tl_new:N \__datatool_decimal_parse_tl
\regex_new:N \__datatool_decimal_parse_regex
\tl_new:N \__datatool_numbergroup_tl
\tl_new:N \__datatool_numbergroup_parse_tl
\regex_new:N \__datatool_numbergroup_parse_regex
\regex_new:N \l_datatool_locale_numeric_regex
\regex_new:N \l_datatool_locale_fractional_regex
\regex_new:N \l_datatool_locale_fractional_nozero_regex
\regex_new:N \l_datatool_locale_bigint_regex
\regex_const:Nn \c_datatool_decimal_grps_regex
  { \A ([+\-])? 0* (\d{1,3}) \. (\d+) \Z }
\regex_const:Nn \c_datatool_decimal_grps_i_regex
  { \A ([+\-])? 0* (\d{1,3}) (\d{3}) \. (\d+) \Z }
\regex_const:Nn \c_datatool_decimal_grps_ii_regex
  { \A ([+\-])? 0* (\d{1,3}) (\d{3}) (\d{3}) \. (\d+) \Z }
\regex_const:Nn \c_datatool_decimal_grps_iii_regex
  { \A ([+\-])? 0* (\d+) (\d{3}) (\d{3}) (\d{3}) \. (\d+) \Z }
\regex_const:Nn \c_datatool_integer_grps_i_regex
  { \A ([+\-])? 0* (\d{1,3}) (\d{3}) \Z }
\regex_const:Nn \c_datatool_integer_grps_ii_regex
  { \A ([+\-])? 0* (\d{1,3}) (\d{3}) (\d{3}) \Z }
\regex_const:Nn \c_datatool_integer_grps_iii_regex
  { \A ([+\-])? 0* (\d+) (\d{3}) (\d{3}) (\d{3}) \Z }
\regex_const:Nn \c_datatool_integer_no_grps_regex
  { \A ([+\-])? (\d{1,3}) \Z }
\regex_const:Nn \c_datatool_numeric_leading_zeros_regex
  { \A ([+\-])? 0* (\d+ (?: (\.\d+) )? ) \Z }
\regex_const:Nn \c_datatool_integer_leading_zeros_regex
  { \A ([+\-])? 0* (\d+ ) \Z }
\regex_const:Nn \c_datatool_decimal_redundant_zeros_regex
  { \A ([+\-])? 0* (\d+ \. \d+ ) 0* \Z }
\regex_const:Nn \c_datatool_decimal_implicit_zero_regex
  { \A ([+\-])? ( \. \d+ ) 0* \Z }
\regex_const:Nn \c_datatool_any_numeric_regex
  { \A ([+\-])? \d* \. ? \d+ ( [eE] [+\-]? \d+ ) ? \Z }
\cs_new:Nn \datatool_decimal_frac:n
 {
   \__datatool_decimal_frac:w #1 . 0 . 0 \q_stop
 }
\cs_generate_variant:Nn \datatool_decimal_frac:n { e , o }
\cs_new:Npn \__datatool_decimal_frac:w #1.#2.#3 \q_stop
{
  \tl_if_head_eq_meaning:nNT { #1 } - { - }
  0 . #2
}
\cs_new:Npn \__datatool_decimal_places_i:w #1.#2#3\q_stop
 {
   #1.#2
 }
\cs_new:Npn \__datatool_decimal_places_ii:w #1.#2#3#4\q_stop
 {
   #1.#2#3
 }
\cs_new:Npn \__datatool_decimal_places_iii:w #1.#2#3#4#5\q_stop
 {
   #1.#2#3#4
 }
\cs_new:Npn \__datatool_decimal_places_iv:w #1.#2#3#4#5#6\q_stop
 {
   #1.#2#3#4#5
 }
\cs_new:Npn \__datatool_decimal_places_v:w #1.#2#3#4#5#6#7\q_stop
 {
   #1.#2#3#4#5#6
 }
\cs_new:Npn \__datatool_decimal_places_vi:w #1.#2#3#4#5#6#7#8\q_stop
 {
   #1.#2#3#4#5#6#7
 }
\cs_new:Npn \__datatool_decimal_places_vii:w #1.#2#3#4#5#6#7#8#9\q_stop
 {
   #1.#2#3#4#5#6#7#8
 }
\cs_new:Nn \__datatool_decimal_trunc_pad_zeros:nn
 {
   \int_case:nnF { #2 }
    {
      { 1 }
        { \__datatool_decimal_places_i:w #1 0 \q_stop }
      { 2 }
        { \__datatool_decimal_places_ii:w #1 00 \q_stop }
      { 3 }
        { \__datatool_decimal_places_iii:w #1 000 \q_stop }
      { 4 }
        { \__datatool_decimal_places_iv:w #1 0000 \q_stop }
      { 5 }
        { \__datatool_decimal_places_v:w #1 00000 \q_stop }
      { 6 }
        { \__datatool_decimal_places_vi:w #1 000000 \q_stop }
    }
    {
      \__datatool_decimal_places_vii:w #1 0000000 \q_stop
    }
 }
\NewDocumentCommand \DTLsetnumberchars { m m }
 {
   \datatool_set_numberchars:nn { #1 } { #2 }
 }
\cs_new:Nn \datatool_set_numberchars:nn
 {
   \datatool_set_numberchars:nnnn { #1 } { #2 } { #1 } { #2 }
 }
\cs_generate_variant:Nn \datatool_set_numberchars:nn
 { nV , Vn , VV }
\cs_new:Nn \datatool_set_numberchars:nnnn
 {
  \tl_set:Nn \__datatool_numbergroup_tl { #1 }
  \tl_set:Nn \__datatool_numbergroup_parse_tl { #3 }
  \tl_set:Nn \__datatool_decimal_tl { #2 }
  \tl_set:Nn \__datatool_decimal_parse_tl { #4 }
  \regex_set:Nn \l_datatool_locale_bigint_regex
    {
       \A [+\-]?\d* [2-9]
         \u{__datatool_numbergroup_parse_tl}? \d{3}
         \u{__datatool_numbergroup_parse_tl}? \d{3}
         \u{__datatool_numbergroup_parse_tl}? \d{3}
          \Z
    }
  \regex_set:Nn \l_datatool_locale_numeric_regex
    {
       \A ([+\-]?\d+)
         (?:\u{__datatool_numbergroup_parse_tl}(\d{3}))?
         (?:\u{__datatool_numbergroup_parse_tl}(\d{3}))?
         (?:\u{__datatool_numbergroup_parse_tl}(\d{3}))?
         (?:\u{__datatool_decimal_parse_tl}(\d+))? \Z
    }
  \regex_set:Nn \l_datatool_locale_fractional_regex
    {
       \A ([+\-]?\d+) \u{__datatool_decimal_parse_tl} (\d+) \Z
    }
  \regex_set:Nn \l_datatool_locale_fractional_nozero_regex
    {
       \A ([+\-]?) \u{__datatool_decimal_parse_tl} (\d+) \Z
    }
}
\cs_generate_variant:Nn \datatool_set_numberchars:nnnn
 { VVVV , eeee , VnVn , nnVn }
\DTLsetnumberchars{,}{.}
\cs_new:Nn \datatool_set_numberchars_regex:nnnn
 {
  \tl_set:Nn \__datatool_numbergroup_tl { #1 }
  \tl_clear:N \__datatool_numbergroup_parse_tl
  \regex_set:Nn \__datatool_numbergroup_parse_regex { #3 }
  \tl_set:Nn \__datatool_decimal_tl { #2 }
  \tl_clear:N \__datatool_decimal_parse_tl
  \regex_set:Nn \__datatool_decimal_parse_regex { #4 }
  \regex_set:Nn \l_datatool_locale_bigint_regex
    {
       \A [+\-]?\d* [2-9]
         \ur{__datatool_numbergroup_parse_regex}? \d{3}
         \ur{__datatool_numbergroup_parse_regex}? \d{3}
         \ur{__datatool_numbergroup_parse_regex}? \d{3}
          \Z
    }
  \regex_set:Nn \l_datatool_locale_numeric_regex
    {
       \A ([+\-]?\d+)
         (?:\ur{__datatool_numbergroup_parse_regex}(\d{3}))?
         (?:\ur{__datatool_numbergroup_parse_regex}(\d{3}))?
         (?:\ur{__datatool_numbergroup_parse_regex}(\d{3}))?
         (?:\ur{__datatool_decimal_parse_regex}(\d+))? \Z
    }
  \regex_set:Nn \l_datatool_locale_fractional_regex
    {
       \A ([+\-]?\d+) \ur{__datatool_decimal_parse_regex} (\d+) \Z
    }
  \regex_set:Nn \l_datatool_locale_fractional_nozero_regex
    {
       \A ([+\-]?) \ur{__datatool_decimal_parse_regex} (\d+) \Z
    }
}
\cs_generate_variant:Nn \datatool_set_numberchars_regex:nnnn
 { VVnn , Vnnn , nVnn }
\cs_new:Nn \datatool_set_numberchars_regex_tl:nnnn
 {
  \tl_set:Nn \__datatool_numbergroup_tl { #1 }
  \tl_clear:N \__datatool_numbergroup_parse_tl
  \regex_set:Nn \__datatool_numbergroup_parse_regex { #3 }
  \tl_set:Nn \__datatool_decimal_tl { #2 }
  \tl_set:Nn \__datatool_decimal_parse_tl { #4 }
  \regex_set:Nn \l_datatool_locale_bigint_regex
    {
       \A [+\-]?\d* [2-9]
         \ur{__datatool_numbergroup_parse_regex}? \d{3}
         \ur{__datatool_numbergroup_parse_regex}? \d{3}
         \ur{__datatool_numbergroup_parse_regex}? \d{3}
          \Z
    }
  \regex_set:Nn \l_datatool_locale_numeric_regex
    {
       \A ([+\-]?\d+)
         (?:\ur{__datatool_numbergroup_parse_regex}(\d{3}))?
         (?:\ur{__datatool_numbergroup_parse_regex}(\d{3}))?
         (?:\ur{__datatool_numbergroup_parse_regex}(\d{3}))?
         (?:\u{__datatool_decimal_parse_tl}(\d+))? \Z
    }
  \regex_set:Nn \l_datatool_locale_fractional_regex
    {
       \A ([+\-]?\d+) \u{__datatool_decimal_parse_tl} (\d+) \Z
    }
  \regex_set:Nn \l_datatool_locale_fractional_nozero_regex
    {
       \A ([+\-]?) \u{__datatool_decimal_parse_tl} (\d+) \Z
    }
}
\cs_generate_variant:Nn \datatool_set_numberchars_regex_tl:nnnn
 { VVnn , Vnnn , nVnn , nVnV , nnnV }
\cs_new:Nn \datatool_set_numberchars_tl_regex:nnnn
 {
  \tl_set:Nn \__datatool_numbergroup_tl { #1 }
  \tl_set:Nn \__datatool_numbergroup_parse_tl { #3 }
  \tl_set:Nn \__datatool_decimal_tl { #2 }
  \tl_clear:N \__datatool_decimal_parse_tl
  \regex_set:Nn \__datatool_decimal_parse_regex { #4 }
  \regex_set:Nn \l_datatool_locale_bigint_regex
    {
       \A [+\-]?\d* [2-9]
         \u{__datatool_numbergroup_parse_tl}? \d{3}
         \u{__datatool_numbergroup_parse_tl}? \d{3}
         \u{__datatool_numbergroup_parse_tl}? \d{3}
          \Z
    }
  \regex_set:Nn \l_datatool_locale_numeric_regex
    {
       \A ([+\-]?\d+)
         (?:\u{__datatool_numbergroup_parse_tl}(\d{3}))?
         (?:\u{__datatool_numbergroup_parse_tl}(\d{3}))?
         (?:\u{__datatool_numbergroup_parse_tl}(\d{3}))?
         (?:\ur{__datatool_decimal_parse_regex}(\d+))? \Z
    }
  \regex_set:Nn \l_datatool_locale_fractional_regex
    {
       \A ([+\-]?\d+) \ur{__datatool_decimal_parse_regex} (\d+) \Z
    }
  \regex_set:Nn \l_datatool_locale_fractional_nozero_regex
    {
       \A ([+\-]?) \ur{__datatool_decimal_parse_regex} (\d+) \Z
    }
}
\cs_generate_variant:Nn \datatool_set_numberchars_tl_regex:nnnn
 { VVnn , Vnnn , nVnn , VnVn , nnVn }
\datatool_if_unicode_engine:TF
 {
  \cs_new:Nn \datatool_set_thinspace_group_decimal_char:n
   {
     \datatool_set_numberchars_regex_tl:nnnn
       { \, } { #1 } { \c{,} | \s | \x{2009} } { #1 }
   }
 }
 {
  \cs_new:Nn \datatool_set_thinspace_group_decimal_char:n
   {
     \datatool_set_numberchars_regex_tl:nnnn
       { \, } { #1 } { \c{,} | \s | \x{E2} \x{80} \x{89} } { #1 }
   }
 }
\cs_generate_variant:Nn \datatool_set_thinspace_group_decimal_char:n { V }
\datatool_if_unicode_engine:TF
 {
  \regex_const:Nn \c_datatool_apostrophe_regex
    { \x{27} | \x{2019} }
 }
 {
  \regex_const:Nn \c_datatool_apostrophe_regex
    { \x{27} | \x{E2} \x{80} \x{99} }
 }
\cs_new:Nn \datatool_set_apos_group_decimal_char:n
 {
   \datatool_set_numberchars_regex_tl:nnnn
     { ' } { #1 } { \ur{c_datatool_apostrophe_regex} } { #1 }
 }
\cs_generate_variant:Nn \datatool_set_apos_group_decimal_char:n { V }
\cs_new:Nn \datatool_set_underscore_group_decimal_char:n
 {
   \datatool_set_numberchars_regex_tl:nnnn
    { \_ } { #1 } { \c{_} | \x{5F} } { #1 }
 }
\cs_generate_variant:Nn \datatool_set_underscore_group_decimal_char:n { V }
\newcount\@dtl@datatype
\int_new:N \l__datatool_tmpa_int
\int_new:N \l__datatool_tmpb_int
\int_new:N \l__datatool_tmpc_int
\int_new:N \l__datatool_tmpd_int
\int_new:N \l__datatool_count_int
\int_new:N \l__datatool_tmp_datatype_int
\tl_clear_new:N \l__datatool_tmpa_tl
\tl_new:N \l__datatool_tmpb_tl
\tl_new:N \l__datatool_tmpc_tl
\tl_new:N \l__datatool_tmpd_tl
\tl_new:N \l__datatool_tmp_currency_tl
\tl_new:N \l__datatool_tmp_initial_tl
\tl_new:N \l__datatool_result_tl
\tl_new:N \l__datatool_resulta_tl
\tl_new:N \l__datatool_resultb_tl
\tl_new:N \l__datatool_dialect_tl
\fp_new:N \l__datatool_tmpa_fp
\fp_new:N \l__datatool_tmpb_fp
\fp_new:N \l__datatool_tmpc_fp
\fp_new:N \l__datatool_tmpd_fp
\fp_new:N \l__datatool_mean_fp
\fp_new:N \l__datatool_total_fp
\fp_new:N \l__datatool_datum_value_fp
\dim_new:N \l__datatool_tmpa_dim
\dim_new:N \l__datatool_tmpb_dim
\str_new:N \l__datatool_tmpa_str
\str_new:N \l__datatool_tmpb_str
\str_new:N \l__datatool_tmpc_str
\clist_new:N \l__datatool_tmp_clist
\seq_new:N \l__datatool_tmp_seq
\seq_new:N \l__datatool_tmpa_seq
\seq_new:N \l__datatool_tmpb_seq
\seq_new:N \l_datatool_regex_match_seq
\seq_new:N \l_datatool_timestamp_match_seq
\regex_new:N \l__datatool_tmpa_regex
\regex_new:N \l__datatool_tmpb_regex
\int_const:Nn \c_datatool_unknown_int {-1}
\int_const:Nn \c_datatool_string_int {0}
\int_const:Nn \c_datatool_integer_int {1}
\int_const:Nn \c_datatool_decimal_int {2}
\int_const:Nn \c_datatool_currency_int {3}
\int_const:Nn \c_datatool_datetime_int {4}
\int_const:Nn \c_datatool_date_int {5}
\int_const:Nn \c_datatool_time_int {6}
\cs_new:Nn \datatool_max_known_type:
 {
   \c_datatool_time_int
 }
\newcommand*{\DTLgetDataTypeName}[1]
{
  \int_case:nnF { #1 }
   {
     { \c_datatool_unknown_int }
       { \DTLdatatypeunsetname }
     { \c_datatool_string_int }
       { \DTLdatatypestringname }
     { \c_datatool_integer_int }
       { \DTLdatatypeintegername }
     { \c_datatool_decimal_int }
       { \DTLdatatypedecimalname }
     { \c_datatool_currency_int }
       { \DTLdatatypecurrencyname }
     { \c_datatool_datetime_int }
       { \DTLdatatypedatetimename }
     { \c_datatool_date_int }
       { \DTLdatatypedatename }
     { \c_datatool_time_int }
       { \DTLdatatypetimename }
   }
   {
     \DTLdatatypeinvalidname
   }
}
\newcommand \DTLdatatypeunsetname { unset }
\newcommand \DTLdatatypestringname { string }
\newcommand \DTLdatatypeintegername { integer }
\newcommand \DTLdatatypedecimalname { decimal }
\newcommand \DTLdatatypecurrencyname { currency }
\newcommand \DTLdatatypedatetimename { date-time }
\newcommand \DTLdatatypedatename { date }
\newcommand \DTLdatatypetimename { time }
\newcommand \DTLdatatypeinvalidname { invalid }
\prg_new_conditional:Npnn \datatool_if_valid_datum_type:n #1
   { p, T, F, TF }
 {
    \bool_lazy_or:nnTF
      { \int_compare_p:nNn { #1 } < { \c_datatool_unknown_int } }
      { \int_compare_p:nNn { #1 } > { \datatool_max_known_type: } }
    { \prg_return_false: }
    { \prg_return_true: }
 }
\prg_new_conditional:Npnn \datatool_if_numeric_datum_type:n #1
   { p, T, F, TF }
 {
    \bool_lazy_or:nnTF
      { \int_compare_p:nNn { #1 } < { \c_datatool_integer_int } }
      { \int_compare_p:nNn { #1 } > { \c_datatool_time_int } }
    { \prg_return_false: }
    { \prg_return_true: }
 }
\prg_new_conditional:Npnn \datatool_if_temporal_datum_type:n #1
   { p, T, F, TF }
 {
    \bool_lazy_or:nnTF
      { \int_compare_p:nNn { #1 } < { \c_datatool_datetime_int } }
      { \int_compare_p:nNn { #1 } > { \c_datatool_time_int } }
    { \prg_return_false: }
    { \prg_return_true: }
 }
\prg_new_conditional:Npnn \datatool_if_number_only_datum_type:n #1
   { p, T, F, TF }
 {
    \bool_lazy_or:nnTF
      { \int_compare_p:nNn { #1 } = { \c_datatool_integer_int } }
      { \int_compare_p:nNn { #1 } = { \c_datatool_decimal_int } }
    { \prg_return_true: }
    { \prg_return_false: }
 }
\prg_new_conditional:Npnn \datatool_if_any_int_datum_type:n #1
   { p, T, F, TF }
 {
    \bool_lazy_or:nnTF
      { \int_compare_p:nNn { #1 } = { \c_datatool_integer_int } }
      { \int_compare_p:nNn { #1 } = { \c_datatool_date_int } }
    { \prg_return_true: }
    { \prg_return_false: }
 }
\tl_const:Nx \c_datatool_nullvalue_tl
 {
   \c_catcode_other_space_tl
   \tl_to_str:n { Undefined }
   \c_catcode_other_space_tl
   \tl_to_str:n { Value }
   \char_generate:nn { 32 } { 11 }
 }
\newcommand* \dtlnovalue { \c_datatool_nullvalue_tl }
\newcommand* \DTLstringnull { \@dtlstringnull }
\newcommand* \@dtlstringnull {NULL}
\newcommand* \DTLnumbernull { \@dtlnumbernull }
\newcommand*{\@dtlnumbernull}{0}
\tl_const:Nn \c_datatool_empty_datum_tl
 {
   \__datatool_datum:nnnn { } { } { } { \c_datatool_unknown_int }
 }
\prg_new_conditional:Npnn \datatool_if_null:N #1
  { p, T, F, TF }
{
  \bool_lazy_any:nTF
   {
     { \tl_if_eq_p:NN #1 \dtlnovalue }
     { \tl_if_eq_p:NN #1 \DTLstringnull }
     { \tl_if_eq_p:NN #1 \DTLnumbernull }
     { \tl_if_eq_p:NN #1 \c_datatool_nullvalue_tl }
   }
   { \prg_return_true: }
   { \prg_return_false: }
}
\cs_generate_variant:Nn \datatool_if_null:NTF { cTF }
\prg_new_conditional:Npnn \datatool_if_null:n #1
  { T, F, TF }
{
  \tl_if_single_token:nTF { #1 }
  {
    \bool_lazy_any:nTF
     {
       { \tl_if_eq_p:NN #1 \dtlnovalue }
       { \tl_if_eq_p:NN #1 \DTLstringnull }
       { \tl_if_eq_p:NN #1 \DTLnumbernull }
       { \tl_if_eq_p:NN #1 \c_datatool_nullvalue_tl }
     }
     { \prg_return_true: }
     {
       \tl_if_eq:NnTF \dtlnovalue { #1 }
       { \prg_return_true: }
       {
         \tl_if_eq:NnTF \DTLstringnull { #1 }
         { \prg_return_true: }
         {
           \tl_if_eq:NnTF \DTLnumbernull { #1 }
           { \prg_return_true: }
           { \prg_return_false: }
         }
       }
     }
  }
  {
    \tl_if_eq:NnTF \c_datatool_nullvalue_tl { #1 }
     { \prg_return_true: }
     { \prg_return_false: }
  }
}
\prg_new_conditional:Npnn \datatool_if_null_or_empty:N #1
  { p, T, F, TF }
{
  \bool_lazy_any:nTF
   {
     { \tl_if_empty_p:N #1 }
     { \tl_if_eq_p:NN #1 \dtlnovalue }
     { \tl_if_eq_p:NN #1 \DTLstringnull }
     { \tl_if_eq_p:NN #1 \DTLnumbernull }
     { \tl_if_eq_p:NN #1 \c_datatool_nullvalue_tl }
     { \tl_if_eq_p:NN #1 \c_datatool_empty_datum_tl }
   }
   { \prg_return_true: }
   { \prg_return_false: }
}
\prg_new_conditional:Npnn \datatool_if_null_or_empty:n #1
  { T, F, TF }
{
  \tl_if_single_token:nTF { #1 }
  {
    \bool_lazy_any:nTF
     {
       { \tl_if_empty_p:N #1 }
       { \tl_if_eq_p:NN #1 \dtlnovalue }
       { \tl_if_eq_p:NN #1 \DTLstringnull }
       { \tl_if_eq_p:NN #1 \DTLnumbernull }
       { \tl_if_eq_p:NN #1 \c_datatool_nullvalue_tl }
       { \tl_if_eq_p:NN #1 \c_datatool_empty_datum_tl }
     }
     { \prg_return_true: }
     {
       \tl_if_eq:NnTF \dtlnovalue { #1 }
       { \prg_return_true: }
       {
         \tl_if_eq:NnTF \DTLstringnull { #1 }
         { \prg_return_true: }
         {
           \tl_if_eq:NnTF \DTLnumbernull { #1 }
           { \prg_return_true: }
           { \prg_return_false: }
         }
       }
     }
  }
  {
    \tl_if_empty:nTF { #1 }
    { \prg_return_true: }
    {
      \tl_if_eq:NnTF \c_datatool_nullvalue_tl { #1 }
       { \prg_return_true: }
       {
         \tl_if_eq:NnTF \c_datatool_empty_datum_tl { #1 }
         { \prg_return_true: }
         { \prg_return_false: }
       }
    }
  }
}
\cs_new:Nn \__datatool_datum:nnnn { \exp_not:n { #1 } }
\group_begin:
 \char_set_catcode_math_toggle:N \|
 \tl_const:Nn \c__datatool_datum_weird_marker_tl { | }
 \cs_new:Npn \__datatool_datum:w | #1 | #2 | #3 | #4 |
  {
    \exp_not:N \__datatool_datum:nnnn
     { \exp_not:n { #1 } }
     { \exp_not:n { #2 } }
     { \exp_not:n { #3 } }
     { \exp_not:n { #4 } }
  }
 \cs_new:Npn \__datatool_datum_use:w | #1 | #2 | #3 | #4 |
  {
    \__datatool_datum:nnnn
      { #1 } { #2 } { #3 } { #4 }
  }
 \cs_new:Npn \__datatool_datum_use_i:w | #1 | #2 | #3 | #4 |
  {
    \exp_not:n { #1 }
  }
 \cs_new:Nn \__datatool_weird_datum:nnnn
  {
    \exp_not:N \__datatool_datum:w
      | \exp_not:n { #1 }
      | #2
      | \exp_not:n { #3 }
      | #4 |
  }
 \cs_new:Nn \__datatool_weird_datum:Nnnnn
  {
    \exp_not:N \__datatool_datum:w
      | \exp_not:n { #2 }
      | \exp_not:n { #3 }
      | \exp_not:n { #4 }
      | \exp_not:n { #5 } |
  }
\cs_new:Npn \__datatool_get_weird_datum:w
  \__datatool_datum:w | #1 | #2 | #3 | #4 | #5 \q_stop
 {
   \quark_if_nil:nTF { #5 }
   {
     \@dtl@datatype = #4
     \tl_set:Nn \l__datatool_datum_original_value_tl { #1 }
     \tl_set:Nn \l__datatool_datum_value_tl { #2 }
     \tl_set:Nn \l__datatool_datum_currency_tl { #3 }
   }
   {
     \@dtl@datatype = \c_datatool_string_int
   }
 }
\group_end:
\prg_new_conditional:Npnn \datatool_if_value_eq:NN #1 #2
   { T, F, TF }
 {
   \exp_args:NV \tl_if_head_eq_meaning:nNTF
      #1 \__datatool_datum:w
    {
      \exp_args:NV \tl_if_head_eq_meaning:nNTF
         #2 \__datatool_datum:w
       {
         \datatool_if_value_eq:eeTF
          { #1 } { #2 }
          { \prg_return_true: }
          { \prg_return_false: }
       }
       {
         \datatool_if_value_eq:eVTF
          { #1 } #2
          { \prg_return_true: }
          { \prg_return_false: }
       }
    }
    {
      \exp_args:NV \tl_if_head_eq_meaning:nNTF
         #2 \__datatool_datum:w
       {
         \datatool_if_value_eq:VeTF
           #1 { #2 }
          { \prg_return_true: }
          { \prg_return_false: }
       }
       {
         \datatool_if_value_eq:VVTF #1 #2
          { \prg_return_true: }
          { \prg_return_false: }
       }
    }
 }
\prg_new_conditional:Npnn \datatool_if_value_eq:Nn #1 #2
   { T, F, TF }
 {
   \exp_args:NV \tl_if_head_eq_meaning:nNTF
      #1 \__datatool_datum:w
    {
      \datatool_if_value_eq:enTF
       { #1 } { #2 }
       { \prg_return_true: }
       { \prg_return_false: }
    }
    {
      \datatool_if_value_eq:VnTF #1 { #2 }
       { \prg_return_true: }
       { \prg_return_false: }
    }
 }
\prg_new_conditional:Npnn \datatool_if_value_eq:nN #1 #2
   { T, F, TF }
 {
   \exp_args:NV \tl_if_head_eq_meaning:nNTF
      #2 \__datatool_datum:w
    {
      \datatool_if_value_eq:neTF
       { #1 } { #2 }
       { \prg_return_true: }
       { \prg_return_false: }
    }
    {
      \datatool_if_value_eq:nVTF { #1 } #2
       { \prg_return_true: }
       { \prg_return_false: }
    }
 }
\prg_new_conditional:Npnn \datatool_if_value_eq:nn #1 #2
   { T, F, TF }
 {
   \tl_if_eq:nnTF { #1 } { #2 }
    { \prg_return_true: }
    {
      \tl_if_head_eq_meaning:nNTF { #1 } \__datatool_datum:nnnn
       {
         \tl_if_head_eq_meaning:nNTF { #2 } \__datatool_datum:nnnn
          {
            \bool_lazy_and:nnTF
             {
               \int_compare_p:nNn
                 { \__datatool_datum_type:n { #1 } }
                   >
                 { \c_datatool_string_int }
             }
             {
               \int_compare_p:nNn
                 { \__datatool_datum_type:n { #2 } }
                   >
                 { \c_datatool_string_int }
             }
             {
               \tl_if_eq:eeTF
                { \__datatool_datum_currency:n { #1 } }
                { \__datatool_datum_currency:n { #2 } }
                {
                  \fp_compare:nNnTF
                    { \__datatool_datum_value:n { #1 } }
                    =
                    { \__datatool_datum_value:n { #2 } }
                   { \prg_return_true: }
                   { \prg_return_false: }
                }
                { \prg_return_false: }
             }
             {
               \tl_if_eq:eeTF
                 { \__datatool_datum_string:n { #1 } }
                 { \__datatool_datum_string:n { #2 } }
                { \prg_return_true: }
                { \prg_return_false: }
             }
          }
          {
            \tl_if_eq:enTF { #1 } { #2 }
             { \prg_return_true: }
             { \prg_return_false: }
          }
       }
       {
         \tl_if_eq:enTF { #1 } { #2 }
          { \prg_return_true: }
          { \prg_return_false: }
       }
    }
 }
\cs_generate_variant:Nn \datatool_if_value_eq:nnTF
 { VVTF , VnTF , nVTF, eeTF, neTF, enTF, eVTF, VeTF }
\cs_new:Nn \__datatool_to_weird_datum_no_parse:N
{
  \exp_args:NV \__datatool_to_weird_datum_no_parse:nN #1 #1
}
\cs_new:Nn \__datatool_to_weird_datum_no_parse:nN
{
  \tl_if_head_eq_meaning:nNTF
    { #1 } \__datatool_datum:nnnn
   {
     \tl_set:Nx #2 { \__datatool_weird_datum:Nnnnn #1 }
   }
   {
     \tl_set:Nn #2 { #1 }
   }
}
\cs_new:Nn \__datatool_to_weird_datum:N
{
  \exp_args:NV \__datatool_to_weird_datum:nN #1 #1
}
\cs_new:Nn \__datatool_to_weird_datum:nN
{
  \tl_if_head_eq_meaning:nNTF
     { #1 } \__datatool_datum:w
   {
     \tl_set:Nn #2 { #1 }
   }
   {
     \__datatool_to_datum:nN { #1 } #2
     \datatool_if_null:NF #2
      {
        \tl_if_head_eq_meaning:nNT
          { #1 } \__datatool_datum:nnnn
         {
           \tl_put_left:Nn #2 { \__datatool_weird_datum:Nnnnn }
           \tl_set:Nx #2 { #2 }
         }
      }
  }
}
\cs_new:Nn \__datatool_to_datum:N
 {
   \exp_args:NV \__datatool_to_datum:nN #1 #1
 }
\cs_new:Nn \__datatool_to_datum:nN
{
 \datatool_if_null:nTF { #1 }
  {
    \tl_set_eq:NN #2 \dtlnovalue
  }
  {
   \tl_if_head_eq_meaning:nNTF
      { #1 } \__datatool_datum:w
    {
      \tl_set:Nx #2 { #1 }
    }
    {
      \tl_if_head_eq_meaning:nNTF
        { #1 } \__datatool_datum:nnnn
       {
         \tl_set:Nn #2 { #1 }
       }
       {
         \__datatool_parse_datum:n { #1 }
         \tl_if_empty:NTF \l__datatool_datum_update_value_tl
          {
            \int_compare:nNnTF
              { \@dtl@datatype }
                =
              { \c_datatool_unknown_int }
            {
              \tl_set:Nn #2
               {
                 \__datatool_datum:nnnn { #1 } { } { }
                 { \c_datatool_unknown_int }
               }
            }
            {
              \tl_set_eq:NN #2 \l__datatool_datum_original_value_tl
            }
         }
         {
           \tl_set_eq:NN #2 \l__datatool_datum_update_value_tl
         }
      }
    }
  }
}
\cs_new:Nn \__datatool_rm_weird_datum:N
{
  \exp_args:NV \__datatool_rm_weird_datum:nN #1 #1
}
\cs_new:Nn \__datatool_rm_weird_datum:nN
{
 \tl_if_head_eq_meaning:nNTF
    { #1 } \__datatool_datum:w
  {
    \tl_set:Nx #2 { #1 }
  }
  {
    \tl_set:Nn #2 { #1 }
  }
}
\cs_new:Nn \__datatool_rm_datum:N
{
  \exp_args:NV \__datatool_rm_datum:nN #1 #1
}
\cs_new:Nn \__datatool_rm_datum:nN
{
 \__datatool_rm_weird_datum:nN { #1 } #2
 \exp_args:NV \tl_if_head_eq_meaning:nNT
    #2 \__datatool_datum:nnnn
  {
    \tl_set:Nx #2 { #2 }
  }
}
\tl_if_eq:NnTF \@dtl@mathprocessor { fp }
 {
   \cs_new:Nn \datatool_datum_fp:nnn { #3 }
 }
 {
   \cs_new:Nn \datatool_datum_fp:nnn { #1 }
 }
\cs_new:Nn \datatool_datum_fp:Nnnn { \exp_not:n { #3 } }
\cs_new:Nn \datatool_set_fp:Nn
 {
  \tl_if_single_token:nTF { #2 }
   {
     \exp_args:No \tl_if_head_eq_meaning:nNTF { #2 } \__datatool_datum:nnnn
      {
        \exp_last_unbraced:NV \__datatool_get_datum:w #2 \q_nil \q_stop
      }
      {
        \exp_args:No \tl_if_head_eq_meaning:nNTF { #2 }  \__datatool_datum:w
         {
           \exp_last_unbraced:NV \__datatool_get_weird_datum:w #2 \q_nil \q_stop
         }
         {
           \exp_args:No \__datatool_parse_datum:n { #2 }
         }
      }
   }
   {
      \tl_if_head_eq_meaning:nNTF { #2 } \__datatool_datum:nnnn
      {
        \__datatool_get_datum:w #2 \q_nil \q_stop
      }
      {
        \tl_if_head_eq_meaning:nNTF { #2 } \__datatool_datum:w
         {
           \__datatool_get_weird_datum:w #2 \q_nil \q_stop
         }
         {
           \__datatool_parse_datum:n { #2 }
         }
      }
   }
  \datatool_if_numeric_datum_type:nF { \@dtl@datatype }
   {
     \exp_args:Nx \__datatool_parse_datum:n
      { \tl_trim_spaces:e { \text_expand:n { #2 } } }
   }
  \tl_if_empty:NTF \l__datatool_datum_value_tl
   {
     \fp_zero:N #1
   }
   {
     \exp_args:NV \tl_if_head_eq_meaning:nNTF
       \l__datatool_datum_value_tl
       { \datatool_datum_fp:nnn }
      {
        \tl_set:Nx #1
         {
           \exp_after:wN \datatool_datum_fp:Nnnn \l__datatool_datum_value_tl
         }
      }
      {
        \fp_set:Nn #1 { \l__datatool_datum_value_tl }
      }
   }
 }
\cs_generate_variant:Nn \datatool_set_fp:Nn { NV, No }
\cs_new:Nn \__datatool_datum_string:n { \datatool_datum_string:Nnnnn #1 }
\newcommand{\DTLusedatum} [1]
 {
   \tl_if_eq:NNTF #1 \dtlnovalue
   { \dtlnovalue }
   { \exp_args:NV \__datatool_datum_string:n #1 }
 }
\cs_new:Nn \datatool_datum_string:Nnnnn { #2 }
\cs_new:Nn \__datatool_datum_value:n { \datatool_datum_value:Nnnnn #1 }
\newcommand{\DTLdatumvalue} [1]
 {
   \tl_if_eq:NNTF #1 \dtlnovalue
   { \DTLnumbernull }
   { \exp_args:NV \__datatool_datum_value:n #1 }
 }
\cs_new:Nn \datatool_datum_value:Nnnnn { #3 }
\cs_new:Nn \__datatool_datum_currency:n { \datatool_datum_currency:Nnnnn #1 }
\newcommand{\DTLdatumcurrency} [1]
 {
   \tl_if_eq:NNTF #1 \dtlnovalue
   { \dtlnovalue }
   { \exp_args:NV \__datatool_datum_currency:n #1 }
 }
\cs_new:Nn \datatool_datum_currency:Nnnnn { \exp_not:n { #4 } }
\cs_new:Nn \__datatool_datum_type:n { \datatool_datum_type:Nnnnn #1 }
\newcommand{\DTLdatumtype} [1]
 {
   \tl_if_eq:NNTF #1 \dtlnovalue
   { \int_use:N \c_datatool_unknown_int }
   { \int_eval:n { \exp_args:NV \__datatool_datum_type:n #1 } }
 }
\cs_new:Nn \datatool_datum_type:Nnnnn { #5 }
\cs_new:Nn \datatool_datum_show:N
 {
  \int_compare:nNnTF { \tl_count:N #1 } = { 5 }
   {
     \exp_after:wN \__datatool_datum_show:NNnnnn
      \exp_after:wN #1 #1
   }
   {
    \datatool_if_null:NTF #1
     {
       \msg_show:nnnV
        { datatool-base }
        { show-datum-var-null }
        { #1 }
        #1
     }
     {
       \tl_if_empty:NTF #1
        {
          \msg_show:nnn
           { datatool-base }
           { show-datum-var-empty }
           { #1 }
        }
        {
         \PackageError { datatool-base }
          { \tl_to_str:N #1 \c_space_tl is ~ not ~ a ~ datum ~ variable }
          { }
        }
     }
   }
 }
\cs_new:Nn \__datatool_datum_show:NNnnnn
 {
  \tl_if_eq:NNTF #2 \__datatool_datum:nnnn
   {
     \int_case:nnF { #6 }
      {
        { \c_datatool_unknown_int }
         {
           \msg_show:nnnn
             { datatool-base }
             { show-datum-var-unset }
             { #1 }
             { #3 }
         }
        { \c_datatool_string_int }
         {
           \msg_show:nnnn
             { datatool-base }
             { show-datum-var-string }
             { #1 }
             { #3 }
         }
        { \c_datatool_integer_int }
         {
           \msg_show:nnnnn
             { datatool-base }
             { show-datum-var-integer }
             { #1 }
             { #3 }
             { #4 }
         }
        { \c_datatool_decimal_int }
         {
           \msg_show:nnnnn
             { datatool-base }
             { show-datum-var-decimal }
             { #1 }
             { #3 }
             { #4 }
         }
        { \c_datatool_currency_int }
         {
           \msg_show:nnnnnn
             { datatool-base }
             { show-datum-var-currency }
             { #1 }
             { #3 }
             { #4 }
             { #5 }
         }
        { \c_datatool_datetime_int }
         {
           \msg_show:nnnnn
             { datatool-base }
             { show-datum-var-datetime }
             { #1 }
             { #3 }
             { #4 }
         }
        { \c_datatool_date_int }
         {
           \msg_show:nnnnn
             { datatool-base }
             { show-datum-var-date }
             { #1 }
             { #3 }
             { #4 }
         }
        { \c_datatool_time_int }
         {
           \msg_show:nnnnn
             { datatool-base }
             { show-datum-var-time }
             { #1 }
             { #3 }
             { #4 }
         }
      }
      {
        \PackageError { datatool-base }
         {
           datum ~ variable ~
           \tl_to_str:N #1 \c_space_tl has ~ invalid ~ data ~ type: ~
           \int_eval:n { #6 }
         }
         { }
      }
   }
   {
    \tl_if_eq:NNTF #2  \__datatool_datum:w
      {
        \int_case:nnF { #6 }
         {
           { \c_datatool_unknown_int }
            {
              \msg_show:nnnn
                { datatool-base }
                { show-weird-datum-var-unset }
                { #1 }
                { #3 }
            }
           { \c_datatool_string_int }
            {
              \msg_show:nnnn
                { datatool-base }
                { show-weird-datum-var-string }
                { #1 }
                { #3 }
            }
           { \c_datatool_integer_int }
            {
              \msg_show:nnnnn
                { datatool-base }
                { show-weird-datum-var-integer }
                { #1 }
                { #3 }
                { #4 }
            }
           { \c_datatool_decimal_int }
            {
              \msg_show:nnnnn
                { datatool-base }
                { show-weird-datum-var-decimal }
                { #1 }
                { #3 }
                { #4 }
            }
           { \c_datatool_currency_int }
            {
              \msg_show:nnnnnn
                { datatool-base }
                { show-weird-datum-var-currency }
                { #1 }
                { #3 }
                { #4 }
                { #5 }
            }
           { \c_datatool_datetime_int }
            {
              \msg_show:nnnnn
                { datatool-base }
                { show-weird-datum-var-datetime }
                { #1 }
                { #3 }
                { #4 }
            }
           { \c_datatool_date_int }
            {
              \msg_show:nnnnn
                { datatool-base }
                { show-weird-datum-var-date }
                { #1 }
                { #3 }
                { #4 }
            }
           { \c_datatool_time_int }
            {
              \msg_show:nnnnn
                { datatool-base }
                { show-weird-datum-var-time }
                { #1 }
                { #3 }
                { #4 }
            }
         }
         {
           \PackageError { datatool-base }
            {
              weird ~ datum ~ variable ~
              \tl_to_str:N #1 \c_space_tl has ~ invalid ~ data ~ type: ~
              \int_eval:n { #6 }
            }
            { }
         }
      }
      {
        \PackageError { datatool-base }
         {
           Can't ~ show ~ \tl_to_str:N #1 : ~
           \tl_to_str:N #2 \c_space_tl is ~ not ~ a ~ datum ~ marker
         }
         { }
      }
   }
 }
\msg_new:nnn { datatool-base }
 { show-datum-var-null }
 {
   variable ~ \tl_to_str:N #1 \c_space_tl is ~ null \\
   > ~ #2
 }
\msg_new:nnn { datatool-base }
 { show-datum-var-empty }
 {
   variable ~ \tl_to_str:N #1 \c_space_tl is ~ empty
 }
\msg_new:nnn { datatool-base }
 { show-datum-var-unset }
 {
   Showing ~ unset ~ datum ~ variable ~ \tl_to_str:N #1 \\
   > ~ string ~ value ~ ` #2 '
 }
\msg_new:nnn { datatool-base }
 { show-weird-datum-var-unset }
 {
   Showing ~ unset ~ weird ~ datum ~ variable ~ \tl_to_str:N #1 \\
   > ~ string ~ value ~ ` #2 '
 }
\msg_new:nnn { datatool-base }
 { show-datum-var-string }
 {
   Showing ~ string ~ datum ~ variable ~ \tl_to_str:N #1 \\
   > ~ string ~ value ~ #2
 }
\msg_new:nnn { datatool-base }
 { show-weird-datum-var-string }
 {
   Showing ~ string ~ weird ~ datum ~ variable ~ \tl_to_str:N #1 \\
   > ~ string ~ value ~ #2
 }
\msg_new:nnn { datatool-base }
 { show-datum-var-integer }
 {
   Showing ~ integer ~ datum ~ variable ~ \tl_to_str:N #1 \\
   > ~ string ~ value ~ #2 \\
   > ~ numeric ~ value ~ #3
 }
\msg_new:nnn { datatool-base }
 { show-weird-datum-var-integer }
 {
   Showing ~ integer ~ weird ~ datum ~ variable ~ \tl_to_str:N #1 \\
   > ~ string ~ value ~ #2 \\
   > ~ numeric ~ value ~ #3
 }
\msg_new:nnn { datatool-base }
 { show-datum-var-decimal }
 {
   Showing ~ decimal ~ datum ~ variable ~ \tl_to_str:N #1 \\
   > ~ string ~ value ~ #2 \\
   > ~ numeric ~ value ~ #3
 }
\msg_new:nnn { datatool-base }
 { show-weird-datum-var-decimal }
 {
   Showing ~ decimal ~ weird ~ datum ~ variable ~ \tl_to_str:N #1 \\
   > ~ string ~ value ~ #2 \\
   > ~ numeric ~ value ~ #3
 }
\msg_new:nnn { datatool-base }
 { show-datum-var-currency }
 {
   Showing ~ currency ~ datum ~ variable ~ \tl_to_str:N #1 \\
   > ~ string ~ value ~ #2 \\
   > ~ numeric ~ value ~ #3 \\
   > ~ currency ~ symbol ~ #4
 }
\msg_new:nnn { datatool-base }
 { show-weird-datum-var-currency }
 {
   Showing ~ currency ~ weird ~ datum ~ variable ~ \tl_to_str:N #1 \\
   > ~ string ~ value ~ #2 \\
   > ~ numeric ~ value ~ #3 \\
   > ~ currency ~ symbol ~ #4
 }
\msg_new:nnn { datatool-base }
 { show-datum-var-datetime }
 {
   Showing ~ datetime ~ datum ~ variable ~ \tl_to_str:N #1 \\
   > ~ string ~ value ~ #2 \\
   > ~ numeric ~ value ~ #3
 }
\msg_new:nnn { datatool-base }
 { show-weird-datum-var-datetime }
 {
   Showing ~ datetime ~ weird ~ datum ~ variable ~ \tl_to_str:N #1 \\
   > ~ string ~ value ~ #2 \\
   > ~ numeric ~ value ~ #3
 }
\msg_new:nnn { datatool-base }
 { show-datum-var-date }
 {
   Showing ~ date ~ datum ~ variable ~ \tl_to_str:N #1 \\
   > ~ string ~ value ~ #2 \\
   > ~ numeric ~ value ~ #3
 }
\msg_new:nnn { datatool-base }
 { show-weird-datum-var-date }
 {
   Showing ~ date ~ weird ~ datum ~ variable ~ \tl_to_str:N #1 \\
   > ~ string ~ value ~ #2 \\
   > ~ numeric ~ value ~ #3
 }
\msg_new:nnn { datatool-base }
 { show-datum-var-time }
 {
   Showing ~ time ~ datum ~ variable ~ \tl_to_str:N #1 \\
   > ~ string ~ value ~ #2 \\
   > ~ numeric ~ value ~ #3
 }
\msg_new:nnn { datatool-base }
 { show-weird-datum-var-time }
 {
   Showing ~ time ~ weird ~ datum ~ variable ~ \tl_to_str:N #1 \\
   > ~ string ~ value ~ #2 \\
   > ~ numeric ~ value ~ #3
 }
\NewDocumentCommand \DTLparse { m m }
 {
   \__datatool_parse:Nn #1 { #2 }
 }
\cs_new:Nn \__datatool_parse:Nn
{
  \tl_clear:N \l__datatool_datum_value_tl
  \tl_clear:N \l__datatool_datum_currency_tl
  \tl_clear:N \l__datatool_datum_update_value_tl
  \datatool_if_null:nTF { #2 }
   {
     \tl_set_eq:NN #1 \dtlnovalue
     \tl_set:Nn \l__datatool_datum_original_value_tl { #2 }
     \int_set_eq:NN \@dtl@datatype \c_datatool_unknown_int
   }
   {
     \tl_if_head_eq_meaning:nNTF
       { #2 } \__datatool_datum:w
      {
        \tl_set:Nx #1 { #2 }
      }
      {
        \tl_set:Nn #1 { #2 }
      }
     \exp_args:NV \tl_if_head_eq_meaning:nNTF
       #1 \__datatool_datum:nnnn
      {
        \int_set:Nn \@dtl@datatype
          { \exp_args:NV \__datatool_datum_type:n #1 }
        \tl_set:Nx \l__datatool_datum_original_value_tl { #1 }
        \tl_set:Nx \l__datatool_datum_currency_tl
          { \exp_args:NV \__datatool_datum_currency:n #1  }
        \tl_set:Nx \l__datatool_datum_value_tl
          { \exp_args:NV \__datatool_datum_value:n #1 }
      }
      {
       \exp_args:NV \__datatool_parse_datum:n #1
       \tl_if_empty:NTF \l__datatool_datum_update_value_tl
        {
           \int_compare:nNnTF
             { \@dtl@datatype }
               =
             { \c_datatool_unknown_int }
           {
             \tl_set:Nn #1
              {
                \__datatool_datum:nnnn { #2 } { } { }
                { \c_datatool_unknown_int }
              }
           }
           {
             \tl_set_eq:NN #1 \l__datatool_datum_original_value_tl
           }
        }
        {
          \tl_set_eq:NN #1 \l__datatool_datum_update_value_tl
        }
     }
   }
 }
\cs_generate_variant:Nn \__datatool_parse:Nn
  { NV }
\cs_new:Nn \__datatool_parse:N
 {
   \exp_args:NNV \__datatool_parse:Nn #1 #1
 }
\NewDocumentCommand \DTLxparse { m m }
 {
   \exp_args:NNx \__datatool_parse:Nn #1 { #2 }
 }
\cs_new:Nn \datatool_set_datum:Nnnnn
 {
   \int_case:nnF { #5 }
    {
      { \c_datatool_unknown_int }
       {
         \tl_set:Nn #1
          {
            \__datatool_datum:nnnn
              { #2 } { } { } { \c_datatool_unknown_int }
          }
       }
      { \c_datatool_string_int }
       {
         \tl_set:Nn #1
          {
            \__datatool_datum:nnnn
              { #2 } { } { } { \c_datatool_string_int }
          }
       }
      { \c_datatool_integer_int }
       {
         \tl_set:Nn #1
          {
            \__datatool_datum:nnnn
              { #2 } { #3 } { } { \c_datatool_integer_int }
          }
       }
      { \c_datatool_decimal_int }
       {
         \tl_set:Nn #1
          {
            \__datatool_datum:nnnn
              { #2 } { #3 } { } { \c_datatool_decimal_int }
          }
       }
      { \c_datatool_currency_int }
       {
         \tl_set:Nn #1
          {
            \__datatool_datum:nnnn
              { #2 } { #3 } { #4 } { \c_datatool_currency_int }
          }
       }
      { \c_datatool_datetime_int }
       {
         \tl_set:Nn #1
          {
            \__datatool_datum:nnnn
              { #2 } { #3 } { } { \c_datatool_datetime_int }
          }
       }
      { \c_datatool_date_int }
       {
         \tl_set:Nn #1
          {
            \__datatool_datum:nnnn
              { #2 } { #3 } { } { \c_datatool_date_int }
          }
       }
      { \c_datatool_time_int }
       {
         \tl_set:Nn #1
          {
            \__datatool_datum:nnnn
              { #2 } { #3 } { } { \c_datatool_time_int }
          }
       }
    }
    {
      \PackageError { datatool-base }
        { Unsupported ~ datum ~ type ~ \int_eval:n { #5 } }
        { }
    }
 }
\cs_generate_variant:Nn \datatool_set_datum:Nnnnn
  { Neeen , Nnenn , NnVVn , NnVnn }
\cs_new:Nn \__datatool_set_datum:Nnnnn
 {
  \tl_set:Nn #1
   {
     \__datatool_datum:nnnn { #2 } { #3 } { #4 } { #5 }
   }
 }
\cs_generate_variant:Nn \__datatool_set_datum:Nnnnn
  { Neeen , NnVnn , NeVnn }
\NewDocumentCommand \DTLsetintegerdatum { m m m }
 {
   \tl_set:Nn #1
    {
      \__datatool_datum:nnnn
        { #2 } { #3 } { }
        { \c_datatool_integer_int }
    }
 }
\NewDocumentCommand \DTLxsetintegerdatum { m m m }
 {
   \exp_args:Neee \DTLsetintegerdatum { \exp_not:N #1 }
    { #2 } { #3 }
 }
\NewDocumentCommand \DTLsetfpdatum { m m m }
 {
   \fp_set:Nn \l__datatool_datum_value_fp { #3 }
   \tl_set:Nx #1
    {
      \exp_not:N \__datatool_datum:nnnn
       { \exp_not:n { #2 } }
       {
         \exp_not:N \datatool_datum_fp:nnn
          { #3 }
          { \exp_not:V \l__datatool_datum_value_fp }
          { \fp_to_decimal:N \l__datatool_datum_value_fp }
       }
       { }
       { \c_datatool_decimal_int }
    }
 }
\NewDocumentCommand \DTLsetdecimaldatum { m m m }
 {
   \tl_set:Nn #1
    {
      \__datatool_datum:nnnn
       { #2 } { #3 } { }
       { \c_datatool_decimal_int }
    }
 }
\NewDocumentCommand \DTLxsetdecimaldatum { m m m }
 {
   \exp_args:Neee \DTLsetdecimaldatum { \exp_not:N #1 }
    { #2 } { #3 }
 }
\NewDocumentCommand \DTLsetcurrencydatum { m m m m }
 {
   \tl_set:Nn #1
    {
      \__datatool_datum:nnnn
       { #2 } { #3 } { #4 }
       { \c_datatool_currency_int }
    }
 }
\NewDocumentCommand \DTLxsetcurrencydatum { m m m m }
 {
   \exp_args:Neee \DTLsetcurrencydatum { \exp_not:N #1 }
    { #2 } { #3 } { #4 }
 }
\NewDocumentCommand \DTLsettemporaldatum { m m m }
 {
   \__datatool_parse_datetime:nTF { #3 }
    {
       \__datatool_set_datetime_value:Nn #1 { #2 }
    }
    {
       \PackageError { datatool-base }
        { Invalid ~ date/time format ~ ` \tl_to_str:n { #3 } '}
        {
          The ~ date/time ~ value ~ needs ~ to ~ be ~ a ~
          date ~ in ~ the ~ form ~ YYYY-MM-DD ~ or ~ a ~
          time ~ in ~ the ~ form ~ hh:mm ~ or ~ hh:mm:ss ~ or ~ a ~
          timestamp ~ in ~ the ~ form ~ YYYY-MM-DD ~ hh:mm:ssTZ ~
          where ~ the ~ timezone ~ TZ ~ is ~ optional ~
          and ~ may ~ be ~ the ~ letter ~
          `Z' ~ or ~ in ~ the ~ form ~ [+-]hh:mm ~
          (if ~ omitted ~ `Z' ~ is ~ assumed). ~ The ~
          separator ~ may ~ either ~ be ~ a ~ space ~ or ~
          the ~ letter ~ `T'
        }
    }
 }
\NewDocumentCommand \DTLxsettemporaldatum { m m m }
 {
   \exp_args:Neee \DTLsettemporaldatum { \exp_not:N #1 }
    { #2 } { #3 }
 }
\NewDocumentCommand \DTLsetstringdatum { m m }
 {
   \tl_set:Nn #1
    {
      \__datatool_datum:nnnn
      { #2 } { } { }
      { \c_datatool_string_int }
    }
 }
\NewDocumentCommand \DTLxsetstringdatum { m m }
 {
   \exp_args:NNe \DTLxsetstringdatum #1 { #2 }
 }
\tl_new:N \l__datatool_datum_original_value_tl
\tl_new:N \l__datatool_datum_value_tl
\tl_new:N \l__datatool_datum_currency_tl
\tl_new:N \l__datatool_datum_currency_code_tl
\tl_new:N \l__datatool_datum_update_value_tl
\regex_const:Nn \c_datatool_sci_regex
 { \A [+\-]? [0-9]* \.? [0-9]+ \s* [eE] [+\-]? [0-9]+ \Z }
\cs_new:Nn \__datatool_parse_datum:n
 {
   \@dtl@datatype = \c_datatool_unknown_int
   \tl_set:Nn \l__datatool_datum_original_value_tl { #1 }
   \tl_clear:N \l__datatool_datum_value_tl
   \tl_clear:N \l__datatool_datum_currency_tl
   \tl_clear:N \l__datatool_datum_currency_code_tl
   \tl_clear:N \l__datatool_datum_update_value_tl
   \tl_if_blank:nF { #1 }
   {
     \tl_if_head_eq_meaning:nNTF { #1 }  \__datatool_datum:nnnn
     { \__datatool_get_datum:w #1 \q_nil \q_stop }
     {
       \tl_if_head_eq_meaning:nNTF { #1 }  \__datatool_datum:w
       { \__datatool_get_weird_datum:w #1 \q_nil \q_stop }
       {
        \regex_match:NnTF \c_datatool_sci_regex { #1 }
         {
           \fp_set:Nn \l__datatool_datum_value_fp { #1 }
           \@dtl@datatype = \c_datatool_decimal_int
           \tl_set:Nx \l__datatool_datum_value_tl
            {
              \exp_not:N \datatool_datum_fp:nnn
               { #1 }
               { \exp_not:V \l__datatool_datum_value_fp }
               { \fp_to_decimal:N \l__datatool_datum_value_fp }
            }
           \__datatool_if_auto_reformat_on:nTF { si }
            {
              \tl_set:Nx \l__datatool_datum_update_value_tl
               {
                 \exp_not:N \__datatool_datum:nnnn
                  {
                    \exp_not:N \DTLscinum
                      { \exp_not:n { #1 } }
                  }
                  { \exp_not:V \l__datatool_datum_value_tl }
                  { }
                  { \exp_not:N \c_datatool_decimal_int }
               }
            }
            {
              \tl_set:Nx \l__datatool_datum_update_value_tl
               {
                 \exp_not:N \__datatool_datum:nnnn
                  { \exp_not:n { #1 } }
                  { \exp_not:V \l__datatool_datum_value_tl }
                  { }
                  { \exp_not:N \c_datatool_decimal_int }
               }
            }
         }
         {
          \__datatool_parse_datetime_if_enabled:nTF { #1 }
           {
             \__datatool_if_auto_reformat_on:TF
              { \__datatool_set_datetime_value: }
              { \__datatool_set_datetime_value:n { #1 } }
           }
           {
            \bool_lazy_or:nnTF
              { \tl_if_head_eq_meaning_p:nN { #1 } + }
              { \tl_if_head_eq_meaning_p:nN { #1 } - }
             {
               \exp_args:Nxx \__datatool_parse_item:nn
                { \tl_tail:n { #1 } }
                { \tl_head:n { #1 } }
             }
             {
               \__datatool_parse_item:nn { #1 } { }
             }
           }
         }
       }
     }
   }
 }
\cs_new:Nn \__datatool_parse_item:nn
{
  \tl_set:Nn \l__datatool_datum_original_value_tl { #1 }
  \tl_if_head_eq_meaning:nNTF { #1 } { \DTLcurrency }
   { \__datatool_get_currency_datum:w #1 \q_nil \q_stop }
   {
     \tl_if_head_eq_meaning:nNTF { #1 } { \DTLfmtcurrency }
     { \__datatool_get_fmtcurrency_datum:w #1 \q_nil \q_stop }
     {
       \tl_if_head_eq_meaning:nNTF { #1 } { \DTLfmtcurr }
       { \__datatool_get_fmtcurr_datum:w #1 \q_nil \q_stop }
       {
          \__datatool_check_known_currencies:
          \tl_if_empty:NTF \l__datatool_datum_currency_tl
          {
            \__datatool_parse_numeric:n { #1 }
            \int_compare:nNnT
              { \@dtl@datatype } = { \c_datatool_unknown_int }
            {
              \int_set_eq:NN \@dtl@datatype \c_datatool_string_int
            }
          }
          {
            \tl_trim_spaces:N \l__datatool_suffix_tl
            \__datatool_parse_numeric:N \l__datatool_suffix_tl
            \int_compare:nNnTF
              { \@dtl@datatype } = { \c_datatool_string_int }
            {
              \tl_clear:N \l__datatool_datum_currency_tl
            }
            {
              \int_set_eq:NN \@dtl@datatype \c_datatool_currency_int
            }
          }
        }
     }
   }
   \tl_if_empty:nF { #2 }
    {
      \int_compare:nNnT
        { \@dtl@datatype } > { \c_datatool_string_int }
      {
        \bool_lazy_or:nnTF
          { \tl_if_head_eq_meaning_p:nN { #1 } + }
          { \tl_if_head_eq_meaning_p:nN { #1 } - }
         {
           \int_set_eq:NN \@dtl@datatype \c_datatool_string_int
         }
         {
           \tl_if_eq:nnT { #2 } { - }
            {
              \tl_set:Nx \l__datatool_datum_value_tl
               { \fp_to_tl:n { - ( \l__datatool_datum_value_tl ) } }
            }
         }
      }
    }
   \int_case:nn { \@dtl@datatype }
   {
     { \c_datatool_string_int }
      {
       \tl_set:Nn \l__datatool_datum_update_value_tl
        {
          \__datatool_datum:nnnn { #2 #1 } { } { }
            { \c_datatool_string_int }
        }
      }
     { \c_datatool_integer_int }
      {
       \__datatool_if_auto_reformat_on:nTF { integer }
        {
         \tl_set:Nx
           \l__datatool_datum_update_value_tl
           { \int_eval:n { \l__datatool_datum_value_tl } }
         \regex_replace_case_once:nN
          {
            \c_datatool_integer_grps_i_regex
               { \1 \2 \u{__datatool_numbergroup_tl} \3 }
            \c_datatool_integer_grps_ii_regex
               { \1 \2 \u{__datatool_numbergroup_tl} \3
                    \u{__datatool_numbergroup_tl} \4 }
            \c_datatool_integer_grps_iii_regex
               { \1 \2 \u{__datatool_numbergroup_tl} \3
                    \u{__datatool_numbergroup_tl} \4
                    \u{__datatool_numbergroup_tl} \5 }
          }
         \l__datatool_datum_update_value_tl
         \tl_set:Ne \l__datatool_datum_update_value_tl
          {
            \exp_not:N \__datatool_datum:nnnn
             {
               \exp_not:V \l__datatool_datum_update_value_tl
             }
             { \int_eval:n { \l__datatool_datum_value_tl } } { }
             { \c_datatool_integer_int }
          }
        }
        {
         \tl_set:Nx \l__datatool_datum_update_value_tl
          {
            \exp_not:N \__datatool_datum:nnnn
             { \exp_not:n { #2 #1 } }
             { \int_eval:n { \l__datatool_datum_value_tl } } { }
             { \c_datatool_integer_int }
          }
        }
      }
     { \c_datatool_decimal_int }
      {
        \tl_set_eq:NN
          \l__datatool_datum_update_value_tl
          \l__datatool_datum_value_tl
        \fp_set:Nn \l__datatool_datum_value_fp
          { \l__datatool_datum_value_tl }
        \tl_set:Nx \l__datatool_datum_value_tl
         {
          \exp_not:N \datatool_datum_fp:nnn
           { \exp_not:V \l__datatool_datum_value_tl }
           { \exp_not:V \l__datatool_datum_value_fp }
           { \fp_to_decimal:N \l__datatool_datum_value_fp }
         }
        \__datatool_if_auto_reformat_on:nTF { decimal }
         {
           \regex_replace_case_once:nN
             {
               \c_datatool_decimal_grps_regex
                 { \1 \2 \u{__datatool_decimal_tl} \3 }
               \c_datatool_decimal_grps_i_regex
                  { \1 \2 \u{__datatool_numbergroup_tl} \3 \u{__datatool_decimal_tl} \4 }
               \c_datatool_decimal_grps_ii_regex
                  { \1 \2 \u{__datatool_numbergroup_tl} \3
                       \u{__datatool_numbergroup_tl} \4
                       \u{__datatool_decimal_tl} \5 }
               \c_datatool_decimal_grps_iii_regex
                  { \1 \2 \u{__datatool_numbergroup_tl} \3
                       \u{__datatool_numbergroup_tl} \4
                       \u{__datatool_numbergroup_tl} \5
                       \u{__datatool_decimal_tl} \6 }
             }
            \l__datatool_datum_update_value_tl
           \tl_set:Ne \l__datatool_datum_update_value_tl
            {
              \exp_not:N \__datatool_datum:nnnn
               {
                 \exp_not:V \l__datatool_datum_update_value_tl
               }
               { \exp_not:V \l__datatool_datum_value_tl }
               { }
               { \c_datatool_decimal_int }
            }
         }
         {
           \tl_set:Nx \l__datatool_datum_update_value_tl
            {
              \exp_not:N \__datatool_datum:nnnn
               { \exp_not:n { #2 #1 } }
               { \exp_not:V \l__datatool_datum_value_tl }
               { }
               { \c_datatool_decimal_int }
            }
         }
      }
     { \c_datatool_currency_int }
      {
        \__datatool_if_auto_reformat_on:nTF { currency }
        {
          \__datatool_decimal_to_currency:VVNV
            \l__datatool_datum_currency_tl
            \l__datatool_datum_value_tl
            \l__datatool_datum_update_value_tl
            \l__datatool_datum_currency_code_tl
        }
        {
         \tl_set:Nx \l__datatool_datum_update_value_tl
          {
            \exp_not:N \__datatool_datum:nnnn
              { \exp_not:n { #2 #1 } }
              { \l__datatool_datum_value_tl }
              { \exp_not:V \l__datatool_datum_currency_tl }
              { \c_datatool_currency_int }
          }
        }
      }
   }
  \tl_set:Nn \l__datatool_datum_original_value_tl { #2 #1 }
}
\tl_new:N \l__datatool_parser_num_tl
\cs_new:Nn \__datatool_parse_numeric:N
 {
   \exp_args:No \__datatool_parse_numeric:n { #1 }
 }
\cs_new:Nn \__datatool_parse_numeric:n
 {
   \tl_set:Nn \l__datatool_parser_num_tl { #1 }
   \tl_if_empty:nF { #1 }
   {
     \regex_match:NnTF \l_datatool_locale_bigint_regex { #1 }
      {
        \@dtl@datatype = \c_datatool_string_int
      }
      {
        \regex_replace_case_once:nNTF
         {
           \l_datatool_locale_numeric_regex
           { \c{q_mark} \1 \2 \3 \4 . \5 \c{q_stop}}
           \l_datatool_locale_fractional_regex
           { \c{q_mark} \1 . \2 \c{q_stop}}
           \l_datatool_locale_fractional_nozero_regex
           { \c{q_mark} \1 0 . \2 \c{q_stop}}
         }
         \l__datatool_parser_num_tl
         { \exp_after:wN \__datatool_parse_number:w \l__datatool_parser_num_tl }
         { \@dtl@datatype = \c_datatool_string_int }
      }
   }
 }
\cs_new:Npn \__datatool_parse_number:w \q_mark #1.#2\q_stop
{
  \tl_if_empty:nTF { #2 }
  {
    \@dtl@datatype = \c_datatool_integer_int
    \tl_set:Nn \l__datatool_datum_value_tl { #1 }
  }
  {
    \@dtl@datatype = \c_datatool_decimal_int
    \tl_if_empty:nTF { #1 }
     { \tl_set:Nn \l__datatool_datum_value_tl { 0.#2 } }
     { \tl_set:Nn \l__datatool_datum_value_tl { #1.#2 } }
  }
}
\cs_new:Nn \__datatool_check_known_currencies:
 {
   \tl_clear:N \l__datatool_datum_currency_code_tl
   \prop_map_function:NN \l_datatool_regional_currencies_prop
     \__datatool_prop_parse_currency_do:nn
   \tl_if_empty:NT \l__datatool_datum_currency_tl
    {
     \seq_map_function:NN
      \l__datatool_known_currencies_seq
      \__datatool_seq_parse_currency_do:n
    }
   \exp_args:NV \tl_if_blank:nT \l__datatool_suffix_tl
    {
      \tl_clear:N \l__datatool_datum_currency_tl
    }
 }
\cs_new:Nn \__datatool_prop_parse_currency_do:nn
 {
   \__datatool_if_starts_or_ends_with:VvTF
       \l__datatool_datum_original_value_tl
       { dtl@curr@ #2 @tl }
    {
      \tl_set_eq:NN \l__datatool_datum_currency_tl \l__datatool_prefix_tl
      \tl_set:Nn \l__datatool_datum_currency_code_tl { #2 }
    }
    {
      \__datatool_if_starts_or_ends_with:VvTF
         \l__datatool_datum_original_value_tl
         { dtl@curr@ #2 @sym }
       {
         \tl_set_eq:NN \l__datatool_datum_currency_tl \l__datatool_prefix_tl
         \tl_set:Nn \l__datatool_datum_currency_code_tl { #2 }
       }
       {
         \cs_if_exist:cT { datatool #1 symbolprefix }
          {
            \__datatool_if_starts_or_ends_with:VeTF
               \l__datatool_datum_original_value_tl
               { #1 \exp_not:v { dtl@curr@ #2 @tl } }
             {
               \tl_set_eq:NN \l__datatool_datum_currency_tl \l__datatool_prefix_tl
               \tl_set:Nn \l__datatool_datum_currency_code_tl { #2 }
             }
             {
               \__datatool_if_starts_or_ends_with:VeTF
                   \l__datatool_datum_original_value_tl
                   { #1 \exp_not:v { dtl@curr@ #2 @sym } }
                {
                  \tl_set_eq:NN \l__datatool_datum_currency_tl \l__datatool_prefix_tl
                  \tl_set:Nn \l__datatool_datum_currency_code_tl { #2 }
                }
             }
         }
       }
    }
   \tl_if_empty:NF \l__datatool_datum_currency_tl
    {
      \prop_map_break:
    }
 }
\cs_new:Nn \__datatool_seq_parse_currency_do:n
 {
   \__datatool_if_starts_or_ends_with:VnTF
      \l__datatool_datum_original_value_tl { #1 }
     {
       \tl_set_eq:NN \l__datatool_datum_currency_tl \l__datatool_prefix_tl
       \seq_map_break:
     }
 }
\cs_new:Npn \__datatool_get_datum:w
  \__datatool_datum:nnnn #1 #2 #3 #4 #5 \q_stop
 {
   \quark_if_nil:nTF { #5 }
   {
     \@dtl@datatype = #4
     \tl_set:Nn \l__datatool_datum_original_value_tl { #1 }
     \tl_set:Nn \l__datatool_datum_value_tl { #2 }
     \tl_set:Nn \l__datatool_datum_currency_tl { #3 }
   }
   {
     \@dtl@datatype = \c_datatool_string_int
   }
 }
\cs_new:Npn \__datatool_get_currency_datum:w
  \DTLcurrency #1 #2 \q_stop
 {
   \quark_if_nil:nTF { #2 }
   {
     \__datatool_parse_numeric:n { #1 }
     \ifnum\@dtl@datatype = \c_datatool_string_int
     \else
       \tl_set:Nn \l__datatool_datum_currency_tl { \@dtl@currency }
       \@dtl@datatype = \c_datatool_currency_int
     \fi
   }
   {
     \@dtl@datatype = \c_datatool_string_int
   }
 }
\cs_new:Npn \__datatool_get_fmtcurrency_datum:w
  \DTLfmtcurrency #1 #2 #3 \q_stop
 {
   \quark_if_nil:nTF { #3 }
   {
     \__datatool_parse_numeric:n { #2 }
     \ifnum\@dtl@datatype = \c_datatool_string_int
     \else
       \@dtl@datatype = \c_datatool_currency_int
       \tl_set:Nn \l__datatool_datum_currency_tl { #1 }
     \fi
   }
   {
     \@dtl@datatype = \c_datatool_string_int
   }
 }
\cs_new:Npn \__datatool_get_fmtcurr_datum:w
  \DTLfmtcurr #1 #2 #3 \q_stop
 {
   \quark_if_nil:nTF { #3 }
   {
     \__datatool_parse_numeric:n { #2 }
     \ifnum\@dtl@datatype = \c_datatool_string_int
     \else
       \tl_set:Nn \l__datatool_datum_currency_code_tl { #1 }
       \@dtl@datatype = \c_datatool_currency_int
       \tl_set:Nn \l__datatool_datum_currency_tl { \DTLcurr { #1 } }
     \fi
   }
   {
     \@dtl@datatype = \c_datatool_string_int
   }
 }
\prg_new_conditional:Npnn \__datatool_parse_datetime_if_enabled:n #1
  { T, F, TF }
{
  \bool_if:NTF \l__datatool_parse_datetime_bool
   {
     \__datatool_parse_datetime:nTF { #1 }
      { \prg_return_true: }
      { \prg_return_false: }
   }
   { \prg_return_false: }
}
\cs_new:Nn \__datatool_if_datum_tl:nTF
 {
   \tl_if_single_token:nTF { #1 }
   {
     \exp_args:No \tl_if_head_eq_meaning:nNTF { #1 } \__datatool_datum:nnnn
     { #2 }
     { #3 }
   }
   { #3 }
 }
\cs_new:Nn \datatool_warn_not_number:n
 {
   \PackageWarning { datatool-base } { #1 }
 }
\NewDocumentCommand \DTLconverttodecimal { m m }
{
  \tl_if_single_token:nTF { #1 }
   {
     \exp_args:No \__datatool_parse_datum:n { #1 }
   }
   {
     \__datatool_parse_datum:n { #1 }
   }
  \datatool_if_numeric_datum_type:nF { \@dtl@datatype }
   {
     \datatool_warn_not_number:n
      { Can't ~ convert ~ non-numerical ~ ` #1 ' ~ to ~ decimal }
   }
  \tl_if_empty:NTF \l__datatool_datum_value_tl
   { \tl_set:Nn #2 { 0 } }
   { \tl_set_eq:NN #2 \l__datatool_datum_value_tl }
}
\newrobustcmd*{\DTLdecimaltolocale}[2]{%
 \tl_set:Nn #2 { #1 }
 \regex_replace_case_once:nN
 {
   \c_datatool_numeric_leading_zeros_regex { \1 \2 }
   \c_datatool_decimal_redundant_zeros_regex { \1 \2 }
   \c_datatool_decimal_implicit_zero_regex { \1 0 \2 }
 }
 #2
 \regex_replace_case_once:nNTF
 {
    \c_datatool_decimal_grps_regex
      { \1 \2 \u{__datatool_decimal_tl} \3 }
    \c_datatool_decimal_grps_i_regex
       { \1 \2 \u{__datatool_numbergroup_tl} \3 \u{__datatool_decimal_tl} \4 }
    \c_datatool_decimal_grps_ii_regex
       { \1 \2 \u{__datatool_numbergroup_tl} \3
            \u{__datatool_numbergroup_tl} \4
            \u{__datatool_decimal_tl} \5 }
    \c_datatool_decimal_grps_iii_regex
       { \1 \2 \u{__datatool_numbergroup_tl} \3
            \u{__datatool_numbergroup_tl} \4
            \u{__datatool_numbergroup_tl} \5
            \u{__datatool_decimal_tl} \6 }
 }
 #2
 {
   \tl_set:Ne #2
    {
     \exp_not:N \__datatool_datum:nnnn
      { \exp_not:V #2 }
      { #1 }
      {  }
      { \exp_not:N \c_datatool_decimal_int }
    }
  }
  {
    \regex_replace_case_once:nNTF
    {
      \c_datatool_integer_grps_i_regex
         { \1 \2 \u{__datatool_numbergroup_tl} \3 }
      \c_datatool_integer_grps_ii_regex
         { \1 \2 \u{__datatool_numbergroup_tl} \3
              \u{__datatool_numbergroup_tl} \4 }
      \c_datatool_integer_grps_iii_regex
         { \1 \2 \u{__datatool_numbergroup_tl} \3
              \u{__datatool_numbergroup_tl} \4
              \u{__datatool_numbergroup_tl} \5 }
      \c_datatool_integer_no_grps_regex { \1 \2 }
    }
    #2
    {
      \tl_set:Ne #2
       {
        \exp_not:N \__datatool_datum:nnnn
         { \exp_not:V #2 }
         { #1 }
         {  }
         { \exp_not:N \c_datatool_integer_int }
       }
    }
    {
      \datatool_warn_not_number:n
       {
         Can't ~ convert ~ `#1' ~ to ~ decimal: ~ not ~ a ~ number
       }
      \tl_set:Nn #2
       {
         \__datatool_datum:nnnn
          { #1 }
          {  }
          {  }
          { \c_datatool_string_int }
       }
    }
  }
}
\NewDocumentCommand{\DTLdecimaltocurrency} { O{} m m }
{
   \__datatool_decimal_to_currency:nnN { #1 } { #2 } { #3 }
}
\newcommand\DTLCurrentLocaleCurrencyDP{2}
\cs_new:Nn \__datatool_decimal_to_currency:nnN
{
  \__datatool_decimal_to_currency:nnNn { #1 } { #2 } #3 { }
}
\cs_generate_variant:Nn \__datatool_decimal_to_currency:nnN { VVN , nVN }
\cs_new:Nn \__datatool_decimal_to_currency:nnNn
{
 \regex_match:NnTF \c_datatool_any_numeric_regex { #2 }
  {
   \tl_if_empty:NTF \DTLCurrentLocaleCurrencyDP
    {
      \tl_set:Nn #3 { #2 }
      \tl_if_empty:NTF #3
       {
         \tl_set:Nn #3 { 0 }
       }
       {
         \regex_replace_once:NnN
          \c_datatool_integer_leading_zeros_regex { \1 \2 } #3
       }
    }
    {
      \tl_if_empty:nTF { #2 }
       {
         \dtlround { #3 } { 0 } { \DTLCurrentLocaleCurrencyDP }
       }
       {
         \dtlround { #3 } { #2 } { \DTLCurrentLocaleCurrencyDP }
       }
      \tl_set:Ne #3
        {
          \exp_args:Ne \__datatool_decimal_trunc_pad_zeros:nn
           { #3 }
           { \DTLCurrentLocaleCurrencyDP }
        }
    }
   \regex_replace_case_once:nN
    {
      \c_datatool_decimal_grps_regex { \1 \2 \u{__datatool_decimal_tl} \3 }
      \c_datatool_decimal_grps_i_regex
         { \1 \2 \u{__datatool_numbergroup_tl} \3 \u{__datatool_decimal_tl} \4 }
      \c_datatool_decimal_grps_ii_regex
         { \1 \2 \u{__datatool_numbergroup_tl} \3
              \u{__datatool_numbergroup_tl} \4
              \u{__datatool_decimal_tl} \5 }
      \c_datatool_decimal_grps_iii_regex
         { \1 \2 \u{__datatool_numbergroup_tl} \3
              \u{__datatool_numbergroup_tl} \4
              \u{__datatool_numbergroup_tl} \5
              \u{__datatool_decimal_tl} \6 }
      \c_datatool_integer_grps_i_regex
         { \1 \2 \u{__datatool_numbergroup_tl} \3 }
      \c_datatool_integer_grps_ii_regex
         { \1 \2 \u{__datatool_numbergroup_tl} \3
              \u{__datatool_numbergroup_tl} \4 }
      \c_datatool_integer_grps_iii_regex
         { \1 \2 \u{__datatool_numbergroup_tl} \3
              \u{__datatool_numbergroup_tl} \4
              \u{__datatool_numbergroup_tl} \5 }
    }
    #3
    \tl_set:Ne \l__datatool_datum_currency_code_tl { #4 }
    \tl_if_blank:nTF { #1 }
     {
       \tl_if_empty:NTF \l__datatool_datum_currency_code_tl
        {
         \seq_if_in:NVTF
            \l_datatool_regional_currencies_seq
            \DTLCurrencyCode
          {
           \tl_set:Ne #3
            {
             \exp_not:N \__datatool_datum:nnnn
              {
                \exp_not:N \DTLfmtcurr
                  { \DTLCurrencyCode }
                  { \exp_not:V #3 }
              }
              { #2 }
              { \exp_not:V \@dtl@currency }
              { \exp_not:N \c_datatool_currency_int }
            }
          }
          {
           \tl_set:Ne #3
            {
             \exp_not:N \__datatool_datum:nnnn
              {
                \exp_not:N \DTLfmtcurrency
                  { \exp_not:V \@dtl@currency }
                  { \exp_not:V #3 }
              }
              { #2 }
              { \exp_not:V \@dtl@currency }
              { \exp_not:N \c_datatool_currency_int }
            }
          }
        }
        {
         \tl_set:Ne #3
          {
           \exp_not:N \__datatool_datum:nnnn
            {
              \exp_not:N \DTLfmtcurr
                { \l__datatool_datum_currency_code_tl }
                { \exp_not:V #3 }
            }
            { #2 }
            {
              \exp_not:N \DTLcurr
               { \l__datatool_datum_currency_code_tl }
            }
            { \exp_not:N \c_datatool_currency_int }
          }
        }
     }
     {
       \tl_if_empty:NT \l__datatool_datum_currency_code_tl
        {
          \datatool_get_currency_code:NV
           \l__datatool_datum_currency_code_tl
           \l__datatool_datum_currency_tl
          \tl_if_eq:NnT
           \l__datatool_datum_currency_code_tl { XXX }
           {
             \tl_clear:N \l__datatool_datum_currency_code_tl
           }
        }
       \tl_if_empty:NTF \l__datatool_datum_currency_code_tl
        {
          \tl_set:Ne #3
           {
             \exp_not:N \__datatool_datum:nnnn
             {
               \exp_not:N \DTLfmtcurrency
                { \exp_not:n { #1 } }
                { \exp_not:V #3 }
             }
             { #2 }
             { \exp_not:n { #1 } }
             { \exp_not:N \c_datatool_currency_int }
           }
        }
        {
         \tl_set:Ne #3
          {
           \exp_not:N \__datatool_datum:nnnn
            {
               \exp_not:N \DTLfmtcurr
                { \l__datatool_datum_currency_code_tl }
                { \exp_not:V #3 }
            }
            { #2 }
            { \exp_not:n { #1 } }
            { \exp_not:N \c_datatool_currency_int }
          }
        }
      }
  }
  {
    \datatool_warn_not_number:n
     {
       Can't ~ convert ~ `#2' ~ to ~ currency: ~ not ~ a ~ number
     }
    \tl_set:Nn #3
     {
      \__datatool_datum:nnnn
       { #2 }
       {  }
       {  }
       { \c_datatool_string_int }
     }
  }
}
\cs_generate_variant:Nn \__datatool_decimal_to_currency:nnNn
  { VVNV , nVNV }
\NewDocumentCommand \DTLdecimaltodatetime { m m }
 {
   \datatool_decimal_to_temporal:Nnn
     #2 { \c_datatool_datetime_int } { #1 }
 }
\NewDocumentCommand \DTLdecimaltodate { m m }
 {
   \datatool_decimal_to_temporal:Nnn
     #2 { \c_datatool_date_int } { #1 }
 }
\NewDocumentCommand \DTLdecimaltotime { m m }
 {
   \datatool_decimal_to_temporal:Nnn
     #2 { \c_datatool_time_int } { #1 }
 }
\newcommand \DTLtemporalvalue [2] { #1 }
\cs_new_nopar:Nn \datatool_decimal_to_temporal:Nnn
{
  \int_case:nnF { #2 }
   {
     { \c_datatool_datetime_int }
       {
         \datatool_from_julian_date:nN { #3 }
           \l__datatool_datetime_seq
         \datatool_timestamp_to_datetime_datum:NeN
          \l__datatool_datetime_seq
          { #3 }
          #1
       }
     { \c_datatool_date_int }
       {
         \int_set:Nn \l__datatool_julian_int { \fp_to_int:n { #3 } }
         \datatool_from_julian_day:VNNN \l__datatool_julian_int
          \l__datatool_year_int
          \l__datatool_month_int
          \l__datatool_day_int
         \tl_set:Ne #1
          {
            \exp_not:N \__datatool_datum:nnnn
             {% formatted string
               \exp_not:N \DataToolDateFmt
                 { \int_use:N \l__datatool_year_int }
                 { \int_use:N \l__datatool_month_int }
                 { \int_use:N \l__datatool_day_int }
                 {
                   \datatool_julian_day_to_dow:n { \l__datatool_julian_int }
                 }
             }
             {% value
               \exp_not:N \DTLtemporalvalue
                { \int_use:N \l__datatool_julian_int }
                {
                  \int_use:N \l__datatool_year_int
                   -
                  \datatool_two_digits:N \l__datatool_month_int
                   -
                  \datatool_two_digits:N \l__datatool_day_int
                }
             }
             { }% no currency symbol
             { \exp_not:N \c_datatool_date_int }
          }
       }
     { \c_datatool_time_int }
       {
         \datatool_from_julian_time:eNNN { #3 }
          \l__datatool_hour_int
          \l__datatool_minute_int
          \l__datatool_second_int
         \tl_set:Ne #1
          {
            \exp_not:N \__datatool_datum:nnnn
             {% formatted string
               \exp_not:N \DataToolTimeFmt
                 { \int_use:N \l__datatool_hour_int }
                 { \int_use:N \l__datatool_minute_int }
                 { \int_use:N \l__datatool_second_int }
             }
             {% value
               \exp_not:N \DTLtemporalvalue
                { #3 }
                {
                  \datatool_two_digits:n { \l__datatool_hour_int }
                  \c_colon_str
                  \datatool_two_digits:N \l__datatool_minute_int
                  \c_colon_str
                  \datatool_two_digits:N \l__datatool_second_int
                }
             }
             { }% no currency symbol
             { \exp_not:N \c_datatool_time_int }
          }
       }
   }
   {
     \PackageError { datatool-base }
      { Invalid ~ data ~ type ~ \int_eval:n { #2 }: ~ not ~ a ~ temporal ~ type }
      {
        The ~ second ~ argument ~ of
        \token_to_str:N \datatool_decimal_to_temporal:Nnn ~
        \c_space_tl ~ should ~ be ~ one ~ of: ~
        \exp_not:N \c_datatool_datetime_int , ~
        \exp_not:N \c_datatool_date_int , ~ or ~
        \exp_not:N \c_datatool_time_int
      }
   }
}
\cs_generate_variant:Nn \datatool_decimal_to_temporal:Nnn
 { NnV }
\cs_new:Nn \datatool_extract_timestamp:NN
 {
   \tl_clear:N #2
   \group_begin:
    \cs_set_eq:NN \DTLtemporalvalue \use_ii:nn
    \tl_set:Ne \l__datatool_tmpa_tl
      { \DTLdatumvalue { #1 } }
    \regex_match:NVTF
      \c_datatool_temporal_regex \l__datatool_tmpa_tl
     {
       \tl_set:Ne \l__datatool_tmpa_tl
         { \exp_not:N \tl_set:Nn \exp_not:N #2 { \l__datatool_tmpa_tl } }
     }
     {
       \tl_clear:N \l__datatool_tmpa_tl
     }
    \exp_after:wN
    \group_end:
       \l__datatool_tmpa_tl
 }
\NewDocumentCommand \DTLdatumtoDTM { m m }
{
 \cs_if_exist:NTF \DTMsavetimestamp
  {
   \group_begin:
    \cs_set_eq:NN \DTLtemporalvalue \use_ii:nn
    \tl_set:Ne \l__datatool_tmpa_tl
      { \DTLdatumvalue { #1 } }
    \regex_match:NVTF
      \c_datatool_timestamp_regex \l__datatool_tmpa_tl
     {
       \tl_set:Ne \l__datatool_tmpa_tl
        { \exp_not:N \DTMsavetimestamp { #2 } { \l__datatool_tmpa_tl } }
     }
     {
       \regex_match:NVTF
         \c_datatool_date_regex \l__datatool_tmpa_tl
        {
          \tl_set:Ne \l__datatool_tmpa_tl
            { \exp_not:N \DTMsavedate { #2 } { \l__datatool_tmpa_tl } }
        }
        {
          \regex_extract_once:NVNTF
            \c_datatool_time_regex
            \l__datatool_tmpa_tl
            \l_datatool_timestamp_match_seq
           {
             \tl_if_empty:eTF
               { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
              {
                \tl_set:Ne \l__datatool_tmpa_tl
                  { \exp_not:N \DTMsavetime { #2 } { \l__datatool_tmpa_tl : 00 } }
              }
              {
                \tl_set:Ne \l__datatool_tmpa_tl
                  { \exp_not:N \DTMsavetime { #2 } { \l__datatool_tmpa_tl } }
              }
           }
           {
             \tl_if_empty:NTF \l__datatool_tmpa_tl
              {
                \PackageError { datatool-base }
                {
                   Can't ~ obtain ~ timestamp. ~
                   No ~ value ~ associated with ` \token_to_str:N #1 '
                }
                {
                  The ~ provided ~ value ~ doesn't ~ seem ~ to ~
                  be ~ numeric. ~ If ~ you ~ were ~ expecting ~ it ~
                  to ~ be ~ parsed ~ as ~ a ~ date/time ~ then ~
                  \bool_if:NTF \l__datatool_parse_datetime_bool
                   {
                     use ~ \token_to_str:N \DTLsetup { datetime=parse-only } ~
                     or ~ \token_to_str:N \DTLsetup { datetime=reformat }
                   }
                   {
                    check ~ the ~ original ~ source ~ matched ~
                    the ~ correct ~ format
                   }
                }
              }
              {
                \int_set:Nn \@dtl@datatype { \DTLdatumtype { #1 } }
                \int_case:nn { \@dtl@datatype }
                {
                  { \c_datatool_integer_int }
                   {
                     \int_set_eq:NN \@dtl@datatype \c_datatool_date_int
                   }
                  { \c_datatool_decimal_int }
                   {
                     \fp_compare:nNnTF
                       { \fp_abs:n { \l__datatool_tmpa_tl } }
                         < { \c_one_fp }
                      {
                        \int_set_eq:NN \@dtl@datatype \c_datatool_time_int
                      }
                      {
                        \int_set_eq:NN \@dtl@datatype \c_datatool_datetime_int
                      }
                   }
                }
                \int_case:nnF { \@dtl@datatype }
                {
                  { \c_datatool_datetime_int }
                   {
                     \PackageWarning { datatool-base }
                     {
                       No ~ timestamp ~ could ~ be ~ found ~ in ~ the ~
                       provided ~ datum ~ command. ~ Value ~ found: ~
                       \l__datatool_tmpa_tl . ~ I'm ~ going ~
                       to ~ assume ~ this ~ is ~ a ~ Julian ~ Date
                     }
                    \datatool_from_julian_date:VN
                     \l__datatool_tmpa_tl
                     \l__datatool_datetime_seq
                    \tl_set:Ne \l__datatool_tmpa_tl
                     {
                       \exp_not:N \DTMsavetimestamp { #2 }
                        {
                          \datatool_timestamp_to_iso:N
                            \l__datatool_datetime_seq
                        }
                      }
                   }
                  { \c_datatool_date_int }
                   {
                     \PackageWarning { datatool-base }
                     {
                       No ~ timestamp ~ could ~ be ~ found ~ in ~ the ~
                       provided ~ datum ~ command. ~ Value ~ found: ~
                       \l__datatool_tmpa_tl . ~ I'm ~ going ~
                       to ~ assume ~ this ~ is ~ a ~ Julian ~ Day ~ Number
                     }
                    \int_set:Nn \l__datatool_julian_int
                      { \l__datatool_tmpa_tl }
                    \datatool_from_julian_day:VNNN
                     \l__datatool_julian_int
                     \l__datatool_year_int
                     \l__datatool_month_int
                     \l__datatool_day_int
                    \tl_set:Ne \l__datatool_tmpa_tl
                     {
                       \exp_not:N \DTMsavenoparsedate { #2 }
                        { \int_use:N \l__datatool_year_int }
                        { \int_use:N \l__datatool_month_int }
                        { \int_use:N \l__datatool_day_int }
                        {
                          \datatool_julian_day_to_dow:n
                           { \l__datatool_julian_int }
                        }
                      }
                   }
                  { \c_datatool_time_int }
                   {
                     \PackageWarning { datatool-base }
                     {
                       No ~ timestamp ~ could ~ be ~ found ~ in ~ the ~
                       provided ~ datum ~ command. ~ Value ~ found: ~
                       \l__datatool_tmpa_tl . ~ I'm ~ going ~
                       to ~ assume ~ this ~ is ~ a ~ Julian ~
                       time ~ of ~ day ~ fraction
                     }
                    \fp_set:Nn \l__datatool_julian_fp
                      { \l__datatool_tmpa_tl }
                    \datatool_from_julian_time:nNNN
                     { \l__datatool_julian_fp }
                     \l__datatool_hour_int
                     \l__datatool_minute_int
                     \l__datatool_second_int
                    \tl_set:Ne \l__datatool_tmpa_tl
                     {
                       \exp_not:N \DTMsavetime { #2 }
                        {
                         \int_use:N \l__datatool_year_int
                         \c_colon_str
                         \int_use:N \l__datatool_month_int
                         \c_colon_str
                         \int_use:N \l__datatool_day_int
                        }
                      }
                   }
                }
                {

                  \PackageError { datatool-base }
                   {
                     No ~ timestamp ~ could ~ be ~ found ~ in ~ the ~
                     provided ~ datum ~ command. ~ Value ~ found: ~
                     \l__datatool_tmpa_tl
                   }
                   {
                     The ~ datum ~ value ~ supplied ~ can't ~ be ~
                     interpreted ~ as ~ a ~ timestamp, ~ date ~ or ~ time.
                   }
                }
              }
           }
        }
     }
    \exp_after:wN
   \group_end: \l__datatool_tmpa_tl
  }
  {
   \PackageError { datatool-base }
    {
      \token_to_str:N \DTLdatumtoDTM ~ \c_space_tl ~
      can't ~ save ~ time ~ stamp. ~
      Command ~ \token_to_str:N \DTMsavetimestamp ~ \c_space_tl ~
      undefined ~ (datetime2 ~ required)
    }
    { You ~ need ~ to ~ load ~ datetime2.sty }
  }
}
\cs_new:Nn \__datatool_set_datetime_value:NNn
 {
   \int_case:nn { \@dtl@datatype }
    {
      { \c_datatool_datetime_int }
      {
        \tl_set:Ne #2
         {
           \exp_not:N \DTLtemporalvalue
            { \fp_use:N \l__datatool_julian_fp }
            {
              \__datatool_tm_iso:
            }
         }
        \tl_if_empty:nTF { #3 }
         {
           \__datatool_set_datum:NeVnn #1
               {
                 \exp_not:N \DataToolDateTimeFmt
                  {
                    { \__datatool_tm_yr: }
                    { \__datatool_tm_mn: }
                    { \__datatool_tm_dy: }
                    { \__datatool_tm_dow: }
                  }
                  {
                    { \__datatool_tm_hr: }
                    { \__datatool_tm_mi: }
                    { \__datatool_tm_se: }
                  }
                  {
                    { \__datatool_tm_tzh: }
                    { \__datatool_tm_tzm: }
                  }
               }
               #2
               { }
               { \c_datatool_datetime_int }
         }
         {
           \__datatool_set_datum:NnVnn #1
             { #3 }
             #2
             { }
             { \c_datatool_datetime_int }
         }
      }
      { \c_datatool_date_int }
      {
        \tl_set:Ne #2
         {
           \exp_not:N \DTLtemporalvalue
            { \int_use:N \l__datatool_julian_int }
            {
              \__datatool_tm_iso_date:
            }
         }
        \tl_if_empty:nTF { #3 }
         {
           \__datatool_set_datum:NeVnn #1
               {
                 \exp_not:N \DataToolDateFmt
                  { \__datatool_tm_yr: }
                  { \__datatool_tm_mn: }
                  { \__datatool_tm_dy: }
                  { \__datatool_tm_dow: }
               }
               #2
               { }
               { \c_datatool_date_int }
         }
         {
           \__datatool_set_datum:NnVnn #1
              { #3 }
              #2
              { }
              { \c_datatool_date_int }
         }
      }
      { \c_datatool_time_int }
      {
        \tl_set:Ne #2
         {
           \exp_not:N \DTLtemporalvalue
            { \fp_use:N \l__datatool_time_fp }
            {
              \__datatool_tm_iso_time:
            }
         }
        \tl_if_empty:nTF { #3 }
         {
           \__datatool_set_datum:NeVnn #1
               {
                 \exp_not:N \DataToolTimeFmt
                  { \__datatool_tm_hr: }
                  { \__datatool_tm_mi: }
                  { \__datatool_tm_se: }
               }
               #2
               { }
               { \c_datatool_time_int }
         }
         {
           \__datatool_set_datum:NnVnn #1
               { #3 }
               #2
               { }
               { \c_datatool_time_int }
         }
      }
    }
 }
\seq_new:N \l__datatool_datetime_seq
\int_new:N \l__datatool_year_int
\int_new:N \l__datatool_month_int
\int_new:N \l__datatool_day_int
\int_new:N \l__datatool_hour_int
\int_new:N \l__datatool_minute_int
\int_new:N \l__datatool_second_int
\int_new:N \l__datatool_tzhour_int
\int_new:N \l__datatool_tzminute_int
\int_new:N \l__datatool_julian_int
\int_new:N \l__datatool_local_julian_int
\fp_new:N \l__datatool_julian_fp
\fp_new:N \l__datatool_time_fp
\cs_new:Nn \__datatool_tm_var_init:
{
  \int_zero:N \l__datatool_year_int
  \int_zero:N \l__datatool_month_int
  \int_zero:N \l__datatool_day_int
  \int_zero:N \l__datatool_hour_int
  \int_zero:N \l__datatool_minute_int
  \int_zero:N \l__datatool_second_int
  \int_zero:N \l__datatool_tzhour_int
  \int_zero:N \l__datatool_tzminute_int
  \int_zero:N \l__datatool_julian_int
  \fp_zero:N \l__datatool_julian_fp
  \fp_zero:N \l__datatool_time_fp
}
\regex_const:Nn \c_datatool_timestamp_regex
 {
   \A \s*
   ( \d+ ) \x { 2D } ( \d{2} ) \x { 2D } ( \d{2} )
   (?: \x { 54 } | \s+ )
   ( \d{2} ) \x { 3A } ( \d{2} ) \x { 3A } ( \d{2} )
   ( \x { 5A } | [\+\-]? \d{2} \x { 3A } ? \d{2} ) ?
   \s* \Z
 }
\regex_const:Nn \c_datatool_date_regex
 {
   \A \s*
   ( \d+ ) \x { 2D } ( \d{2} )\x { 2D } ( \d{2} )
   \s* \Z
 }
\regex_const:Nn \c_datatool_time_regex
 {
   \A \s*
   ( [\+\-]? \d{2} ) \x { 3A } ( \d{2} ) (?: \x { 3A } ( \d{2} ) )?
   \s* \Z
 }
\regex_const:Nn \c_datatool_temporal_regex
 {
   (?:
      (?: \d+ ) \x { 2D } (?: \d{2} ) \x { 2D } (?: \d{2} )
      (?:
         (?: \x { 54 } | \s+ )
         (?: \d{2} ) \x { 3A } (?: \d{2} ) \x { 3A } (?: \d{2} )
         (?: \x { 5A } | [\+\-]? \d{2} \x { 3A } ? \d{2} ) ?
      ) ?
   ) |
   (?:
     (?: \d{2} ) \x { 3A } (?: \d{2} ) (?: \x { 3A } (?: \d{2} ) )?
   )
 }
\cs_new:Nn \datatool_timestamp_new:N
{
  \seq_new:N #1
  \datatool_timestamp_zero:N #1
}
\seq_const_from_clist:Nn \c_datatool_timestamp_zero_seq
 { 0000 , 00 , 00 , 00 , 00 , 00 , +00 , 00, -1 }
\cs_new:Nn \datatool_timestamp_zero:N
{
  \seq_set_eq:NN #1 \c_datatool_timestamp_zero_seq
}
\cs_new:Nn \__datatool_tm_seq_init:
{
  \datatool_timestamp_zero:N
    \l__datatool_datetime_seq
}
\cs_new:Nn \datatool_timestamp_get_year:N
 {
   \seq_item:Nn #1 { 1 }
 }
\cs_new:Nn \__datatool_tm_yr:
 {
    \datatool_timestamp_get_year:N
      \l__datatool_datetime_seq
 }
\cs_new:Nn \datatool_timestamp_set_year:Nn
 {
   \tl_if_empty:nTF { #2 }
    {
      \exp_args:NNne \seq_set_item:Nnn #1
        { 1 } { \int_use:N \c_sys_year_int }
    }
    {
      \seq_set_item:Nnn #1 { 1 } { #2 }
    }
 }
\cs_generate_variant:Nn \datatool_timestamp_set_year:Nn
  { Ne, NV }
\cs_new:Nn \datatool_timestamp_set_year_add_century:Nn
 {
   \tl_if_empty:nTF { #2 }
    {
      \exp_args:NNne \seq_set_item:Nnn #1
        { 1 } { \int_use:N \c_sys_year_int }
    }
    {
      \bool_lazy_or:nnTF
         { \int_compare_p:nNn { #2 } < { \c_zero_int } }
         { \int_compare_p:nNn { #2 } > { 99 } }
       {
         \seq_set_item:Nnn #1 { 1 } { #2 }
       }
       {
         \datatool_timestamp_set_year:Ne #1
          {
           \int_eval:n
            {
              ( \int_div_truncate:nn { \c_sys_year_int } { 100 } ) * 100
              + #2
            }
          }
       }
    }
 }
\cs_generate_variant:Nn \datatool_timestamp_set_year_add_century:Nn
  { Ne, NV }
\cs_new:Nn \__datatool_tm_set_yr:n
 {
   \datatool_timestamp_set_year:Nn
     \l__datatool_datetime_seq { #1 }
 }
\cs_generate_variant:Nn \__datatool_tm_set_yr:n { e }
\cs_new:Nn \datatool_timestamp_get_month:N
 {
   \seq_item:Nn #1 { 2 }
 }
\cs_new:Nn \__datatool_tm_mn:
 {
   \datatool_timestamp_get_month:N
     \l__datatool_datetime_seq
 }
\cs_new:Nn \datatool_timestamp_set_month:Nn
 {
   \tl_if_empty:nTF { #2 }
    {
      \seq_set_item:Nnn #1 { 2 } { 00 }
    }
    {
      \exp_args:NNne \seq_set_item:Nnn
       #1 { 2 } { \datatool_two_digits:n { #2 } }
    }
 }
\cs_generate_variant:Nn \datatool_timestamp_set_month:Nn
  { Ne, NV }
\cs_new:Nn \__datatool_tm_set_mn:n
 {
   \datatool_timestamp_set_month:Nn
    \l__datatool_datetime_seq { #1 }
 }
\cs_generate_variant:Nn \__datatool_tm_set_mn:n { e }
\cs_new:Nn \datatool_timestamp_get_day:N
 {
   \seq_item:Nn #1 { 3 }
 }
\cs_new:Nn \__datatool_tm_dy:
 {
   \datatool_timestamp_get_day:N
     \l__datatool_datetime_seq
 }
\cs_new:Nn \datatool_timestamp_set_day:Nn
 {
   \tl_if_empty:nTF { #2 }
    {
      \seq_set_item:Nnn #1 { 3 } { 00 }
    }
    {
      \exp_args:NNne \seq_set_item:Nnn
       #1 { 3 } { \datatool_two_digits:n { #2 } }
    }
 }
\cs_generate_variant:Nn \datatool_timestamp_set_day:Nn
  { Ne, NV }
\cs_new:Nn \__datatool_tm_set_dy:n
 {
   \datatool_timestamp_set_day:Nn
    \l__datatool_datetime_seq { #1 }
 }
\cs_generate_variant:Nn \__datatool_tm_set_dy:n { e }
\cs_new:Nn \datatool_timestamp_get_hour:N
 {
   \seq_item:Nn #1 { 4 }
 }
\cs_new:Nn \__datatool_tm_hr:
 {
   \datatool_timestamp_get_hour:N
     \l__datatool_datetime_seq
 }
\cs_new:Nn \datatool_timestamp_set_hour:Nn
 {
   \tl_if_empty:nTF { #2 }
    {
      \seq_set_item:Nnn #1 { 4 } { 00 }
    }
    {
      \exp_args:NNne \seq_set_item:Nnn
       #1 { 4 } { \datatool_two_digits:n { #2 } }
    }
 }
\cs_generate_variant:Nn \datatool_timestamp_set_hour:Nn
  { Ne, NV }
\cs_new:Nn \__datatool_tm_set_hr:n
 {
   \datatool_timestamp_set_hour:Nn
      \l__datatool_datetime_seq { #1 }
 }
\cs_generate_variant:Nn \__datatool_tm_set_hr:n { e }
\cs_new:Nn \datatool_timestamp_get_minute:N
 {
   \seq_item:Nn #1 { 5 }
 }
\cs_new:Nn \__datatool_tm_mi:
 {
   \datatool_timestamp_get_minute:N
     \l__datatool_datetime_seq
 }
\cs_new:Nn \datatool_timestamp_set_minute:Nn
 {
   \tl_if_empty:nTF { #2 }
    {
      \seq_set_item:Nnn #1 { 5 } { 00 }
    }
    {
      \exp_args:NNne \seq_set_item:Nnn
       #1 { 5 } { \datatool_two_digits:n { #2 } }
    }
 }
\cs_generate_variant:Nn \datatool_timestamp_set_minute:Nn
  { Ne, NV }
\cs_new:Nn \__datatool_tm_set_mi:n
 {
   \datatool_timestamp_set_minute:Nn
     \l__datatool_datetime_seq { #1 }
 }
\cs_generate_variant:Nn \__datatool_tm_set_mi:n { e }
\cs_new:Nn \datatool_timestamp_get_second:N
 {
   \seq_item:Nn #1 { 6 }
 }
\cs_new:Nn \__datatool_tm_se:
 {
   \datatool_timestamp_get_second:N
     \l__datatool_datetime_seq
 }
\cs_new:Nn \datatool_timestamp_set_second:Nn
 {
   \tl_if_empty:nTF { #2 }
    {
      \seq_set_item:Nnn #1 { 6 } { 00 }
    }
    {
      \exp_args:NNne \seq_set_item:Nnn
       #1 { 6 } { \datatool_two_digits:n { #2 } }
    }
 }
\cs_generate_variant:Nn \datatool_timestamp_set_second:Nn
  { Ne, NV }
\cs_new:Nn \__datatool_tm_set_se:n
 {
   \datatool_timestamp_set_second:Nn
     \l__datatool_datetime_seq { #1 }
 }
\cs_generate_variant:Nn \__datatool_tm_set_se:n { e }
\cs_new:Nn \datatool_timestamp_get_tzhour:N
 {
   \seq_item:Nn #1 { 7 }
 }
\cs_new:Nn \__datatool_tm_tzh:
 {
   \datatool_timestamp_get_tzhour:N
    \l__datatool_datetime_seq
 }
\cs_new:Nn \datatool_timestamp_set_tzhour:Nn
 {
   \tl_if_empty:nTF { #2 }
    {
      \seq_set_item:Nnn #1 { 7 } { +00 }
    }
    {
      \exp_args:NNne \seq_set_item:Nnn
       #1 { 7 }
       { \datatool_signed_two_digits:n { #2 } }
    }
 }
\cs_generate_variant:Nn \datatool_timestamp_set_tzhour:Nn
  { Ne, NV }
\cs_new:Nn \__datatool_tm_set_tzh:n
 {
   \datatool_timestamp_set_tzhour:Nn
     \l__datatool_datetime_seq { #1 }
 }
\cs_generate_variant:Nn \__datatool_tm_set_tzh:n { e }
\cs_new:Nn \datatool_timestamp_get_tzminute:N
 {
   \seq_item:Nn #1 { 8 }
 }
\cs_new:Nn \__datatool_tm_tzm:
 {
   \datatool_timestamp_get_tzminute:N
    \l__datatool_datetime_seq
 }
\cs_new:Nn \datatool_timestamp_set_tzminute:Nn
 {
   \tl_if_empty:nTF { #2 }
    {
      \seq_set_item:Nnn #1 { 8 } { 00 }
    }
    {
      \exp_args:NNne \seq_set_item:Nnn
       #1 { 8 } { \datatool_two_digits:n { #2 } }
    }
 }
\cs_generate_variant:Nn \datatool_timestamp_set_tzminute:Nn
  { Ne, NV }
\cs_new:Nn \__datatool_tm_set_tzm:n
 {
   \datatool_timestamp_set_tzminute:Nn
     \l__datatool_datetime_seq { #1 }
 }
\cs_generate_variant:Nn \__datatool_tm_set_tzm:n { e }
\cs_new:Nn \datatool_timestamp_get_dow:N
 {
   \seq_item:Nn #1 { 9 }
 }
\cs_new:Nn \__datatool_tm_dow:
 {
   \datatool_timestamp_get_dow:N
    \l__datatool_datetime_seq
 }
\cs_new:Nn \datatool_timestamp_set_dow:Nn
 {
   \tl_if_empty:nTF { #2 }
    {
      \seq_set_item:Nnn #1 { 9 } { -1 }
    }
    {
      \exp_args:NNne \seq_set_item:Nnn
       #1 { 9 } { #2 }
    }
 }
\cs_generate_variant:Nn \datatool_timestamp_set_dow:Nn
  { Ne, NV }
\cs_new:Nn \__datatool_tm_set_dow:n
 {
   \datatool_timestamp_set_dow:Nn
     \l__datatool_datetime_seq { #1 }
 }
\cs_generate_variant:Nn \__datatool_tm_set_dow:n { e, V }
\cs_new:Nn \datatool_timestamp_to_iso:N
 {
   \datatool_timestamp_get_year:N #1
   -
   \datatool_timestamp_get_month:N #1
   -
   \datatool_timestamp_get_day:N #1
   T
   \datatool_timestamp_get_hour:N #1
   \c_colon_str
   \datatool_timestamp_get_minute:N #1
   \c_colon_str
   \datatool_timestamp_get_second:N #1
   \datatool_timestamp_get_tzhour:N #1
   \c_colon_str
   \datatool_timestamp_get_tzminute:N #1
 }
\cs_new:Nn \__datatool_tm_iso:
 {
   \datatool_timestamp_to_iso:N
     \l__datatool_datetime_seq
 }
\cs_new:Nn \datatool_timestamp_to_iso_date:N
 {
   \datatool_timestamp_get_year:N #1
   -
   \datatool_timestamp_get_month:N #1
   -
   \datatool_timestamp_get_day:N #1
 }
\cs_new:Nn \__datatool_tm_iso_date:
 {
   \datatool_timestamp_to_iso_date:N
     \l__datatool_datetime_seq
 }
\cs_new:Nn \datatool_timestamp_to_iso_time:N
 {
   \datatool_timestamp_get_hour:N #1
   \c_colon_str
   \datatool_timestamp_get_minute:N #1
   \c_colon_str
   \datatool_timestamp_get_second:N #1
 }
\cs_new:Nn \__datatool_tm_iso_time:
 {
   \datatool_timestamp_to_iso_time:N
     \l__datatool_datetime_seq
 }
\cs_new:Nn \datatool_timestamp_to_datetime_datum:NnN
 {
   \tl_set:Ne #3
    {
      \exp_not:N \__datatool_datum:nnnn
       {% formatted string
         \exp_not:N \DataToolDateTimeFmt
           {
             { \datatool_timestamp_get_year:N #1 }
             { \datatool_timestamp_get_month:N #1 }
             { \datatool_timestamp_get_day:N #1 }
             { \datatool_timestamp_get_dow:N #1 }
           }
           {
             { \datatool_timestamp_get_hour:N #1 }
             { \datatool_timestamp_get_minute:N #1 }
             { \datatool_timestamp_get_second:N #1 }
           }
           {
             { \datatool_timestamp_get_tzhour:N #1 }
             { \datatool_timestamp_get_tzminute:N #1 }
           }
       }
       {% value
         \exp_not:N \DTLtemporalvalue
          { #2 }
          {
            \datatool_timestamp_to_iso:N #1
          }
       }
       { }% no currency symbol
       { \exp_not:N \c_datatool_datetime_int }
    }
 }
\cs_generate_variant:Nn \datatool_timestamp_to_datetime_datum:NnN
 { NeN, NVN }
\cs_new:Nn \datatool_timestamp_to_date_datum:NnN
 {
   \tl_set:Ne #3
    {
      \exp_not:N \__datatool_datum:nnnn
       {% formatted string
         \exp_not:N \DataToolDateFmt
           { \datatool_timestamp_get_year:N #1 }
           { \datatool_timestamp_get_month:N #1 }
           { \datatool_timestamp_get_day:N #1 }
           {
             \datatool_julian_day_to_dow:n { #2 }
           }
       }
       {% value
         \exp_not:N \DTLtemporalvalue
          { #2 }
          {
            \datatool_timestamp_to_iso_date:N #1
          }
       }
       { }% no currency symbol
       { \exp_not:N \c_datatool_date_int }
    }
 }
\cs_generate_variant:Nn \datatool_timestamp_to_date_datum:NnN
 { NeN, NVN }
\cs_new:Nn \datatool_timestamp_to_time_datum:NnN
 {
   \tl_set:Ne #3
    {
      \exp_not:N \__datatool_datum:nnnn
       {% formatted string
         \exp_not:N \DataToolTimeFmt
           { \datatool_timestamp_get_hour:N #1 }
           { \datatool_timestamp_get_minute:N #1 }
           { \datatool_timestamp_get_second:N #1 }
       }
       {% value
         \exp_not:N \DTLtemporalvalue
          { #2 }
          {
            \datatool_timestamp_to_iso_time:N #1
          }
       }
       { }% no currency symbol
       { \exp_not:N \c_datatool_time_int }
    }
 }
\cs_generate_variant:Nn \datatool_timestamp_to_time_datum:NnN
 { NeN, NVN }
\cs_new:Nn \datatool_unix_to_julian:n
 {
   \fp_eval:n { #1 / 86400 + 2440587.5 }
 }
\cs_new:Nn \datatool_julian_to_unix:n
 {
   \fp_eval:n { (#1 - 2440587.5 ) * 86400 }
 }
\cs_new:Nn \datatool_julian_day_to_dow:n
 {
   \int_mod:nn { #1 } { 7 }
 }
\cs_new:Nn \datatool_calc_julian_date:NN
 {
   \int_compare:nNnTF { \seq_count:N #2 } = { 8 }
    {
      \seq_set_eq:NN \l__datatool_datetime_seq #2
      \_datatool_calc_julian_date:
      \fp_set_eq:NN #1 \l__datatool_julian_fp
    }
    {
      \PackageError { datatool-base }
        {
           Not ~ a ~ timestamp ~ sequence: ~
           \token_to_str:N #2
        }
        {
           The ~ second ~ argument ~ of ~
           \token_to_str:N \datatool_calc_julian_date:NN ~
           \c_string_tl ~ must ~ be ~ a ~ sequence ~ containing ~
           8 ~ integer ~ elements
        }
    }
 }
\cs_new:Nn \datatool_calc_julian_day:Nnnn
{
  \int_set:Nn #1
   {
     #4 - 32075
      +
         \int_div_truncate:nn
          {
             1461
             *
              ( #2 + 4800 + \int_div_truncate:nn { #3 - 14 } { 12 } )
          }
          { 4 }
      +
         \int_div_truncate:nn
          {
            367
             *
             ( #3 - 2
               - \int_div_truncate:nn { #3 - 14 } { 12 } * 12 )
          }
          { 12 }
      -
         \int_div_truncate:nn
          {
            3
            *
            (
              \int_div_truncate:nn
              {
                #2 + 4900
                + \int_div_truncate:nn { #3 - 14 } { 12 }
              }
              { 100 }
            )
          }
          { 4 }
   }
}
\cs_generate_variant:Nn \datatool_calc_julian_day:Nnnn
  { NVVV , Neee }
\cs_new:Nn \datatool_from_julian_time:nNNN
{
  \int_set:Nn #4 { 43200 + \fp_to_int:n { #1 * 86400 } }
  \int_set:Nn #3
    {
      \int_mod:nn { \int_div_truncate:nn { #4 } { 60 } } { 60 }
    }
  \int_set:Nn #2
    {
      \int_div_truncate:nn { #4 } { 3600 }
    }
  \int_set:Nn #4 { \int_mod:nn { #4 } { 60 } }
}
\cs_generate_variant:Nn \datatool_from_julian_time:nNNN
  { VNNN, eNNN }
\cs_new:Nn \datatool_from_julian_day:nNNN
{
  \int_set:Nn \l__datatool_tmpa_int { #1 + 68569 }
  \int_set:Nn \l__datatool_tmpb_int
    { \int_div_truncate:nn { 4 * \l__datatool_tmpa_int } { 146097 } }
  \int_set:Nn \l__datatool_tmpa_int
    {
      \l__datatool_tmpa_int
       - \int_div_truncate:nn { 146097 * \l__datatool_tmpb_int + 3 } { 4 }
    }
  \int_set:Nn \l__datatool_tmpc_int
    {
      \int_div_truncate:nn { 4000 * \l__datatool_tmpa_int + 1 } { 1461001 }
    }
  \int_set:Nn \l__datatool_tmpa_int
    {
      \l__datatool_tmpa_int
      - \int_div_truncate:nn { 1461 * \l__datatool_tmpc_int } { 4 }
      + 31
    }
  \int_set:Nn \l__datatool_tmpd_int
    {
      \int_div_truncate:nn { 80 * \l__datatool_tmpa_int } { 2447 }
    }
  \int_set:Nn #4
    {
      \l__datatool_tmpa_int
      - \int_div_truncate:nn { 2447 * \l__datatool_tmpd_int } { 80 }
    }
  \int_set:Nn \l__datatool_tmpa_int
    {
      \int_div_truncate:nn { \l__datatool_tmpd_int } { 11 }
    }
  \int_set:Nn \l__datatool_tmpd_int
    {
      \l__datatool_tmpd_int + 2 - 12 * \l__datatool_tmpa_int
    }
  \int_set:Nn \l__datatool_tmpc_int
    {
      100 * ( \l__datatool_tmpb_int - 49 )
      + \l__datatool_tmpc_int + \l__datatool_tmpa_int
    }
  \int_set_eq:NN #2 \l__datatool_tmpc_int
  \int_set_eq:NN #3 \l__datatool_tmpd_int
}
\cs_generate_variant:Nn \datatool_from_julian_day:nNNN
  { VNNN , eNNN }
\cs_new:Nn \datatool_from_julian_date:nNNNNNN
 {
   \int_set:Nn \l__datatool_julian_int
      { \fp_to_int:n { round ( #1 ) } }
   \datatool_from_julian_day:nNNN
      { \l__datatool_julian_int }
      #2 #3 #4
   \exp_args:Ne \datatool_from_julian_time:nNNN
      { \fp_eval:n { #1 - \l__datatool_julian_int } }
      #5 #6 #7
 }
\cs_generate_variant:Nn \datatool_from_julian_date:nNNNNNN
 { VNNNNNN, eNNNNNN }
\cs_new:Nn \datatool_from_julian_date:nN
 {
   \datatool_from_julian_date:nNNNNNN
    { #1 }
    \l__datatool_year_int
    \l__datatool_month_int
    \l__datatool_day_int
    \l__datatool_hour_int
    \l__datatool_minute_int
    \l__datatool_second_int
   \datatool_timestamp_zero:N #2
   \datatool_timestamp_set_year:NV #2 \l__datatool_year_int
   \datatool_timestamp_set_month:NV #2 \l__datatool_month_int
   \datatool_timestamp_set_day:NV #2 \l__datatool_day_int
   \datatool_timestamp_set_hour:NV #2 \l__datatool_hour_int
   \datatool_timestamp_set_minute:NV #2 \l__datatool_minute_int
   \datatool_timestamp_set_second:NV #2 \l__datatool_second_int
   \datatool_timestamp_set_dow:Ne #2
    {
      \datatool_julian_day_to_dow:n
       { \fp_eval:n { round ( #1 ) } }
    }
 }
\cs_generate_variant:Nn \datatool_from_julian_date:nN { VN , eN }
\cs_new:Nn \__datatool_calc_julian_day_tmz:
{
  \__datatool_calc_julian_day:
  \int_set_eq:NN \l__datatool_local_julian_int \l__datatool_julian_int
  \int_if_zero:nF { \l__datatool_tzminute_int }
    {
      \int_sub:Nn \l__datatool_minute_int { \l__datatool_tzminute_int }
      \int_compare:nNnTF { \l__datatool_minute_int } < { \c_zero_int }
       {
         \int_add:Nn \l__datatool_minute_int { 60 }
         \int_decr:N \l__datatool_hour_int
       }
       {
         \int_compare:nNnT { \l__datatool_minute_int } > { 59 }
          {
            \int_sub:Nn \l__datatool_minute_int { 60 }
            \int_incr:N \l__datatool_hour_int
          }
       }
    }
  \int_if_zero:nF { \l__datatool_tzhour_int }
    {
      \int_sub:Nn \l__datatool_hour_int { \l__datatool_tzhour_int }
    }
  \int_compare:nNnTF { \l__datatool_hour_int } < { \c_zero_int }
    {
      \int_add:Nn \l__datatool_hour_int { 23 }
      \int_decr:N \l__datatool_julian_int
    }
    {
      \int_compare:nNnT { \l__datatool_hour_int } > { 23 }
        {
          \int_decr:Nn \l__datatool_hour_int { 24 }
          \int_incr:N \l__datatool_julian_int
        }
    }
}
\cs_new:Nn \__datatool_calc_julian_day:
{
  \datatool_calc_julian_day:Nnnn
    \l__datatool_julian_int
    { \l__datatool_year_int }
    { \l__datatool_month_int }
    { \l__datatool_day_int }
}
\cs_new:Nn \__datatool_calc_julian_time:
{
  \fp_set:Nn \l__datatool_time_fp
   {
      ( \l__datatool_hour_int - 12) / 24
     + \l__datatool_minute_int / 1440
     + \l__datatool_second_int / 86400
   }
}
\cs_new:Nn \__datatool_from_julian_time:
{
  \__datatool_from_julian_time:n { \l__datatool_time_fp }
}
\cs_new:Nn \__datatool_from_julian_time:n
{
  \datatool_from_julian_time:nNNN { #1 }
    \l__datatool_hour_int
    \l__datatool_minute_int
    \l__datatool_second_int
}
\cs_new:Nn \__datatool_from_julian_day:
{
  \__datatool_from_julian_day:n { \l__datatool_julian_int }
}
\cs_new:Nn \__datatool_from_julian_day:n
{
   \datatool_from_julian_day:nNNN { #1 }
    \l__datatool_year_int
    \l__datatool_month_int
    \l__datatool_day_int
}
\cs_new:Nn \__datatool_from_julian_date:
{
  \__datatool_from_julian_date:n { \l__datatool_julian_int }
}
\cs_new:Nn \__datatool_from_julian_date:n
{
   \datatool_from_julian_date:nNNNNNN { #1 }
    \l__datatool_year_int
    \l__datatool_month_int
    \l__datatool_day_int
    \l__datatool_hour_int
    \l__datatool_minute_int
    \l__datatool_second_int
}
\prg_new_conditional:Npnn \datatool_parse_timestamp:Nn #1 #2
  { T, F, TF }
{
  \__datatool_parse_timestamp:nTF { #2 }
   {
     \seq_set_eq:NN #1 \l__datatool_datetime_seq
     \prg_return_true:
   }
   { \prg_return_false: }
}
\prg_new_conditional:Npnn \datatool_parse_date:Nn #1 #2
  { T, F, TF }
{
  \__datatool_parse_date:nTF { #2 }
   {
     \seq_if_empty:NTF #1
      {
        \seq_set_eq:NN #1 \l__datatool_datetime_seq
      }
      {
         \datatool_timestamp_set_year:Ne #1
           { \__datatool_tm_yr: }
         \datatool_timestamp_set_month:Ne #1
           { \__datatool_tm_mn: }
         \datatool_timestamp_set_day:Ne #1
           { \__datatool_tm_day: }
      }
     \prg_return_true:
   }
   { \prg_return_false: }
}
\prg_new_conditional:Npnn \datatool_parse_time:Nn #1 #2
  { T, F, TF }
{
  \__datatool_parse_time:nTF { #2 }
   {
     \seq_if_empty:NTF #1
      {
        \seq_set_eq:NN #1 \l__datatool_datetime_seq
      }
      {
         \datatool_timestamp_set_hour:Ne #1
           { \__datatool_tm_hr: }
         \datatool_timestamp_set_minute:Ne #1
           { \__datatool_tm_mi: }
         \datatool_timestamp_set_second:Ne #1
           { \__datatool_tm_se: }
      }
     \prg_return_true:
   }
   { \prg_return_false: }
}
\prg_new_conditional:Npnn \__datatool_parse_timestamp:n #1
  { T, F, TF }
{
 \bool_if:NTF \l__datatool_parse_datetime_iso_bool
  {
   \regex_extract_once:NnNTF
     \c_datatool_timestamp_regex { #1 }
     \l_datatool_timestamp_match_seq
    {
     \__datatool_tm_seq_init:
      \__datatool_tm_set_yr:e
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
      \__datatool_tm_set_mn:e
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
      \__datatool_tm_set_dy:e
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
      \__datatool_tm_set_hr:e
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 5 } }
      \__datatool_tm_set_mi:e
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 6 } }
      \__datatool_tm_set_se:e
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 7 } }
      \tl_if_empty:eF
        { \seq_item:Nn \l_datatool_timestamp_match_seq { 8 } }
       {
         \exp_args:NNe \regex_extract_once:NnNT
            \c_datatool_time_regex
            { \seq_item:Nn \l_datatool_timestamp_match_seq { 8 } }
            \l_datatool_timestamp_match_seq
          {
            \__datatool_tm_set_tzh:e
             { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
            \__datatool_tm_set_tzm:e
             { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
          }
       }
      \prg_return_true:
    }
    {
     \bool_if:NTF \l__datatool_parse_datetime_regional_bool
      {
        \DTLCurrentLocaleParseTimeStamp
          \l__datatool_datetime_seq
          { #1 }
          { \prg_return_true: }
          { \prg_return_false: }
      }
      { \prg_return_false: }
   }
 }
 {
   \bool_if:NTF \l__datatool_parse_datetime_regional_bool
    {
      \DTLCurrentLocaleParseTimeStamp
        \l__datatool_datetime_seq
        { #1 }
        { \prg_return_true: }
        { \prg_return_false: }
    }
    { \prg_return_false: }
 }
}
\newcommand{\DTLCurrentLocaleParseTimeStamp}[4]{#4}
\prg_new_conditional:Npnn \__datatool_parse_date:n #1
  { T, F, TF }
{
 \bool_if:NTF \l__datatool_parse_datetime_iso_bool
  {
   \regex_extract_once:NnNTF
     \c_datatool_date_regex { #1 }
     \l_datatool_timestamp_match_seq
    {
      \__datatool_tm_seq_init:
      \__datatool_tm_set_yr:e
        { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
      \__datatool_tm_set_mn:e
        { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
      \__datatool_tm_set_dy:e
        { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
      \prg_return_true:
    }
    {
      \bool_if:NTF \l__datatool_parse_datetime_regional_bool
       {
         \DTLCurrentLocaleParseDate
          \l__datatool_datetime_seq
          { #1 }
          { \prg_return_true: }
          { \prg_return_false: }
       }
       { \prg_return_false: }
    }
 }
 {
   \bool_if:NTF \l__datatool_parse_datetime_regional_bool
    {
      \DTLCurrentLocaleParseDate
       \l__datatool_datetime_seq
       { #1 }
       { \prg_return_true: }
       { \prg_return_false: }
    }
    { \prg_return_false: }
 }
}
\newcommand{\DTLCurrentLocaleParseDate}[4]{#4}
\prg_new_conditional:Npnn \__datatool_parse_time:n #1
  { T, F, TF }
{
 \bool_if:NTF \l__datatool_parse_datetime_iso_bool
  {
   \regex_extract_once:NnNTF
     \c_datatool_time_regex { #1 }
     \l_datatool_timestamp_match_seq
    {
      \__datatool_tm_seq_init:
      \__datatool_tm_set_hr:e
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
      \__datatool_tm_set_mi:e
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
      \__datatool_tm_set_se:e
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
      \prg_return_true:
    }
    {
      \bool_if:NTF \l__datatool_parse_datetime_regional_bool
       {
         \DTLCurrentLocaleParseTime
           \l__datatool_datetime_seq
           { #1 }
           { \prg_return_true: }
           { \prg_return_false: }
       }
       { \prg_return_false: }
    }
   }
   {
    \bool_if:NTF \l__datatool_parse_datetime_regional_bool
     {
       \DTLCurrentLocaleParseTime
         \l__datatool_datetime_seq
         { #1 }
         { \prg_return_true: }
         { \prg_return_false: }
     }
     { \prg_return_false: }
   }
}
\newcommand{\DTLCurrentLocaleParseTime}[4]{#4}
\prg_new_conditional:Npnn \__datatool_parse_datetime:n #1
  { T, F, TF }
{
  \seq_clear:N \l__datatool_datetime_seq
  \fp_zero:N \l__datatool_julian_fp
  \fp_zero:N \l__datatool_time_fp
  \int_zero:N \l__datatool_local_julian_int
  \int_zero:N \l__datatool_julian_int
  \__datatool_parse_timestamp:nTF { #1 }
   {
     \@dtl@datatype = \c_datatool_datetime_int
   }
   {
     \__datatool_parse_date:nTF { #1 }
      {
        \@dtl@datatype = \c_datatool_date_int
      }
      {
        \__datatool_parse_time:nT { #1 }
         {
           \@dtl@datatype = \c_datatool_time_int
         }
      }
   }
  \seq_if_empty:NTF \l__datatool_datetime_seq
   { \prg_return_false: }
   {
     \_datatool_calc_julian_date:
     \prg_return_true:
   }
}
\cs_new:Nn \_datatool_calc_julian_date:
 {
     \int_set:Nn \l__datatool_year_int { \__datatool_tm_yr: }
     \int_set:Nn \l__datatool_month_int { \__datatool_tm_mn: }
     \int_set:Nn \l__datatool_day_int { \__datatool_tm_dy: }
     \int_set:Nn \l__datatool_hour_int { \__datatool_tm_hr: }
     \int_set:Nn \l__datatool_minute_int { \__datatool_tm_mi: }
     \int_set:Nn \l__datatool_second_int { \__datatool_tm_se: }
     \int_set:Nn \l__datatool_tzhour_int { \__datatool_tm_tzh: }
     \int_set:Nn \l__datatool_tzminute_int { \__datatool_tm_tzm: }
     \__datatool_calc_julian_day_tmz:
     \__datatool_tm_set_dow:e
      {
        \datatool_julian_day_to_dow:n
         { \l__datatool_local_julian_int }
      }
     \__datatool_calc_julian_time:
     \fp_set:Nn \l__datatool_julian_fp
      {
        \int_use:N \l__datatool_julian_int
        + \l__datatool_time_fp
      }
 }
\cs_new:Nn \__datatool_set_datetime_value:
 {
   \__datatool_set_datetime_value:n { }
 }
\cs_new:Nn \__datatool_set_datetime_value:n
 {
   \__datatool_set_datetime_value:NNn
       \l__datatool_datum_update_value_tl
       \l__datatool_datum_value_tl
       { #1 }
 }
\cs_new:Nn \__datatool_set_datetime_value:Nn
 {
   \__datatool_set_datetime_value:NNn
       #1 \l__datatool_datum_value_tl { #2 }
 }
\prop_new:N \l_datatool_timezone_map_prop
\tl_new:N \l_datatool_timezone_map_value_tl
\cs_new:Nn \datatool_region_set_timezone_map:nn
 {
   \prop_put:Nnn \l_datatool_timezone_map_prop { #1 } { #2 }
 }
\cs_new:Nn \datatool_region_get_timezone_map:n
 {
   \prop_get:NnN \l_datatool_timezone_map_prop
     { #1 }
     \l_datatool_timezone_map_value_tl
 }
\datatool_region_set_timezone_map:nn { UTC } { +00:00 }
\datatool_region_set_timezone_map:nn { Z } { +00:00 }
\newcommand{\DTLCurrentLocaleGetTimeZoneMap}[1]{
  \tl_set_eq:NN \l_datatool_timezone_map_value_tl \q_no_value
}
\prop_new:N \l_datatool_monthname_map_prop
\tl_new:N \l_datatool_monthname_map_value_tl
\cs_new:Nn \datatool_region_set_monthname_map:nn
 {
   \prop_put:Nnn \l_datatool_monthname_map_prop { #1 } { #2 }
 }
\cs_new:Nn \datatool_region_get_monthname_map:n
 {
   \prop_get:NnN \l_datatool_monthname_map_prop
     { #1 }
     \l_datatool_monthname_map_value_tl
 }
\newcommand{\DTLCurrentLocaleGetMonthNameMap}[1]{
  \tl_set_eq:NN \l_datatool_monthname_map_value_tl \q_no_value
}
\regex_const:Nn \c_datatool_day_of_month_regex
 {
   ( 0?[1-9] | [12][0-9] | 30 | 31 )
 }
\regex_const:Nn \c_datatool_month_number_regex
 {
  ( 0?[1-9] | 10 | 11 | 12 )
 }
\regex_const:Nn \c_datatool_hour_regex
 {
  ( 0?[0-9] | 1[0-9] | 2[0-4] )
 }
\regex_const:Nn \c_datatool_minsec_regex
 {
   [0-5][0-9]
 }
\regex_const:Nn \c_datatool_timezone_regex
 {
   (?:GMT|UTC?)?
   ( [\+\-]? \ur{c_datatool_hour_regex} )
   (?: \: ? ( \ur{c_datatool_minsec_regex} ) ) ?
 }
\regex_const:Nn \c_datatool_timezone_id_regex
 {
   [A-Z]+ | \ur{c_datatool_timezone_regex}
 }
\newcommand \DTLCurrentLocaleIfpmTF [ 3 ]
 {
   \tl_if_eq:nnTF { #1 } { pm } { #2 } { #3 }
 }
\regex_const:Nn \c_datatool_slash_ddmmyyyy_date_regex
 {
   ( \ur{c_datatool_day_of_month_regex} )
    \/
   ( \ur{c_datatool_month_number_regex}  )
    \/ ( \d+ )
 }
\regex_const:Nn \c_datatool_slash_anchored_ddmmyyyy_date_regex
 {
   \A \s*
   ( \ur{c_datatool_day_of_month_regex} )
    \/
   ( \ur{c_datatool_month_number_regex}  )
    \/ ( \d+ )
   \s* \Z
 }
\regex_const:Nn \c_datatool_slash_ddmmyy_date_regex
 {
   ( \ur{c_datatool_day_of_month_regex} )
    \/
   ( \ur{c_datatool_month_number_regex}  )
    \/ ( \d{2} )
 }
\regex_const:Nn \c_datatool_slash_anchored_ddmmyy_date_regex
 {
   \A \s*
   ( \ur{c_datatool_day_of_month_regex} )
    \/
   ( \ur{c_datatool_month_number_regex}  )
    \/ ( \d{2} )
   \s* \Z
 }
\regex_const:Nn \c_datatool_hyphen_ddmmyyyy_date_regex
 {
   ( \ur{c_datatool_day_of_month_regex} )
    \-
   ( \ur{c_datatool_month_number_regex}  )
    \- ( \d+ )
 }
\regex_const:Nn \c_datatool_hyphen_anchored_ddmmyyyy_date_regex
 {
   \A \s*
   ( \ur{c_datatool_day_of_month_regex} )
    \-
   ( \ur{c_datatool_month_number_regex}  )
    \- ( \d+ )
   \s* \Z
 }
\regex_const:Nn \c_datatool_hyphen_ddmmyy_date_regex
 {
   ( \ur{c_datatool_day_of_month_regex} )
    \-
   ( \ur{c_datatool_month_number_regex} )
    \- ( \d{2} )
 }
\regex_const:Nn \c_datatool_hyphen_anchored_ddmmyy_date_regex
 {
   \A \s*
   ( \ur{c_datatool_day_of_month_regex} )
    \-
   ( \ur{c_datatool_month_number_regex} )
    \- ( \d{2} )
   \s* \Z
 }
\regex_const:Nn \c_datatool_dot_ddmmyyyy_date_regex
 {
   ( \ur{c_datatool_day_of_month_regex} )
    \.
   ( \ur{c_datatool_month_number_regex} )
    \. ( \d+ )
 }
\regex_const:Nn \c_datatool_dot_anchored_ddmmyyyy_date_regex
 {
   \A \s*
   ( \ur{c_datatool_day_of_month_regex} )
    \.
   ( \ur{c_datatool_month_number_regex} )
    \. ( \d+ )
   \s* \Z
 }
\regex_const:Nn \c_datatool_dot_ddmmyy_date_regex
 {
   ( \ur{c_datatool_day_of_month_regex} )
    \.
   ( \ur{c_datatool_month_number_regex} )
    \. ( \d{2} )
 }
\regex_const:Nn \c_datatool_dot_anchored_ddmmyy_date_regex
 {
   \A \s*
   ( \ur{c_datatool_day_of_month_regex} )
    \.
   ( \ur{c_datatool_month_number_regex} )
    \. ( \d{2} )
   \s* \Z
 }
\regex_const:Nn \c_datatool_slash_mmddyyyy_date_regex
 {
   ( \ur{c_datatool_month_number_regex} )
    \/
   ( \ur{c_datatool_day_of_month_regex} )
    \/ ( \d+ )
 }
\regex_const:Nn \c_datatool_slash_anchored_mmddyyyy_date_regex
 {
   \A \s*
   ( \ur{c_datatool_month_number_regex} )
    \/
   ( \ur{c_datatool_day_of_month_regex} )
    \/ ( \d+ )
   \s* \Z
 }
\regex_const:Nn \c_datatool_slash_mmddyy_date_regex
 {
   ( \ur{c_datatool_month_number_regex} )
    \/
   ( \ur{c_datatool_day_of_month_regex} )
    \/ ( \d{2} )
 }
\regex_const:Nn \c_datatool_slash_anchored_mmddyy_date_regex
 {
   \A \s*
   ( \ur{c_datatool_month_number_regex} )
    \/
   ( \ur{c_datatool_day_of_month_regex} )
    \/ ( \d{2} )
   \s* \Z
 }
\regex_const:Nn \c_datatool_hyphen_mmddyyyy_date_regex
 {
   ( \ur{c_datatool_month_number_regex} )
    \-
   ( \ur{c_datatool_day_of_month_regex} )
    \- ( \d+ )
 }
\regex_const:Nn \c_datatool_hyphen_anchored_mmddyyyy_date_regex
 {
   \A \s*
   ( \ur{c_datatool_month_number_regex} )
    \-
   ( \ur{c_datatool_day_of_month_regex} )
    \- ( \d+ )
   \s* \Z
 }
\regex_const:Nn \c_datatool_hyphen_mmddyy_date_regex
 {
   ( \ur{c_datatool_month_number_regex} )
    \-
   ( \ur{c_datatool_day_of_month_regex} )
    \- ( \d{2} )
 }
\regex_const:Nn \c_datatool_hyphen_anchored_mmddyy_date_regex
 {
   \A \s*
   ( \ur{c_datatool_month_number_regex} )
    \-
   ( \ur{c_datatool_day_of_month_regex} )
    \- ( \d{2} )
   \s* \Z
 }
\regex_const:Nn \c_datatool_dot_mmddyyyy_date_regex
 {
   ( \ur{c_datatool_month_number_regex} )
    \.
   ( \ur{c_datatool_day_of_month_regex} )
    \. ( \d+ )
 }
\regex_const:Nn \c_datatool_dot_anchored_mmddyyyy_date_regex
 {
   \A \s*
   ( \ur{c_datatool_month_number_regex} )
    \.
   ( \ur{c_datatool_day_of_month_regex} )
    \. ( \d+ )
   \s* \Z
 }
\regex_const:Nn \c_datatool_dot_mmddyy_date_regex
 {
   ( \ur{c_datatool_month_number_regex} )
    \.
   ( \ur{c_datatool_day_of_month_regex} )
    \. ( \d{2} )
 }
\regex_const:Nn \c_datatool_dot_anchored_mmddyy_date_regex
 {
   \A \s*
   ( \ur{c_datatool_month_number_regex} )
    \.
   ( \ur{c_datatool_day_of_month_regex} )
    \. ( \d{2} )
   \s* \Z
 }
\regex_const:Nn \c_datatool_slash_yyyymmdd_date_regex
 {
   ( \d+ ) \/
   ( \ur{c_datatool_month_number_regex} )
    \/
   ( \ur{c_datatool_day_of_month_regex} )
 }
\regex_const:Nn \c_datatool_slash_anchored_yyyymmdd_date_regex
 {
   \A \s*
   ( \d+ ) \/
   ( \ur{c_datatool_month_number_regex} )
    \/
   ( \ur{c_datatool_day_of_month_regex} )
   \s* \Z
 }
\regex_const:Nn \c_datatool_slash_yymmdd_date_regex
 {
   ( \d{2} ) \/
   ( \ur{c_datatool_month_number_regex} )
    \/
   ( \ur{c_datatool_day_of_month_regex} )
 }
\regex_const:Nn \c_datatool_slash_anchored_yymmdd_date_regex
 {
   \A \s*
   ( \d{2} ) \/
   ( \ur{c_datatool_month_number_regex} )
    \/
   ( \ur{c_datatool_day_of_month_regex} )
   \s* \Z
 }
\regex_const:Nn \c_datatool_hyphen_yyyymmdd_date_regex
 {
   ( \d+ ) \-
   ( \ur{c_datatool_month_number_regex} )
    \-
   ( \ur{c_datatool_day_of_month_regex} )
 }
\regex_const:Nn \c_datatool_hyphen_anchored_yyyymmdd_date_regex
 {
   \A \s*
   ( \d+ ) \-
   ( \ur{c_datatool_month_number_regex} )
    \-
   ( \ur{c_datatool_day_of_month_regex} )
   \s* \Z
 }
\regex_const:Nn \c_datatool_hyphen_yymmdd_date_regex
 {
   ( \d{2} ) \-
   ( \ur{c_datatool_month_number_regex} )
    \-
   ( \ur{c_datatool_day_of_month_regex} )
 }
\regex_const:Nn \c_datatool_hyphen_anchored_yymmdd_date_regex
 {
   \A \s*
   ( \d{2} ) \-
   ( \ur{c_datatool_month_number_regex} )
    \-
   ( \ur{c_datatool_day_of_month_regex} )
   \s* \Z
 }
\regex_const:Nn \c_datatool_dot_yyyymmdd_date_regex
 {
   ( \d+ ) \.
   ( \ur{c_datatool_month_number_regex} )
    \.
   ( \ur{c_datatool_day_of_month_regex} )
 }
\regex_const:Nn \c_datatool_dot_anchored_yyyymmdd_date_regex
 {
   \A \s*
   ( \d+ ) \.
   ( \ur{c_datatool_month_number_regex} )
    \.
   ( \ur{c_datatool_day_of_month_regex} )
   \s* \Z
 }
\regex_const:Nn \c_datatool_dot_yymmdd_date_regex
 {
   ( \d{2} ) \.
   ( \ur{c_datatool_month_number_regex} )
    \.
   ( \ur{c_datatool_day_of_month_regex} )
 }
\regex_const:Nn \c_datatool_dot_anchored_yymmdd_date_regex
 {
   \A \s*
   ( \d{2} ) \.
   ( \ur{c_datatool_month_number_regex} )
    \.
   ( \ur{c_datatool_day_of_month_regex} )
   \s* \Z
 }
\regex_const:Nn \c_datatool_colon_hhmmss_time_regex
 {
   ( \ur{c_datatool_hour_regex} )
   \: ( \ur{c_datatool_minsec_regex} )
   (?: \: ( \ur{c_datatool_minsec_regex} ) ) ?
   (?: \s* ( am | pm ) ) ?
 }
\regex_const:Nn \c_datatool_colon_anchored_hhmmss_time_regex
 {
   \A \s*
   ( \ur{c_datatool_hour_regex} )
   \: ( \ur{c_datatool_minsec_regex} )
   (?: \: ( \ur{c_datatool_minsec_regex} ) ) ?
   (?: \s* ( am | pm ) ) ?
   \s* \Z
 }
\regex_const:Nn \c_datatool_dot_hhmmss_time_regex
 {
   ( \ur{c_datatool_hour_regex} )
   \. ( \ur{c_datatool_minsec_regex} )
   (?: \. ( \ur{c_datatool_minsec_regex} ) ) ?
   (?: \s* ( am | pm ) ) ?
 }
\regex_const:Nn \c_datatool_dot_anchored_hhmmss_time_regex
 {
   \A \s*
   ( \ur{c_datatool_hour_regex} )
   \. ( \ur{c_datatool_minsec_regex} )
   (?: \. ( \ur{c_datatool_minsec_regex} ) ) ?
   (?: \s* ( am | pm ) ) ?
   \s* \Z
 }
\cs_new:Nn \datatool_ddmmyyyy_hhmmss_tz_parse_datetime:NNNnnnTF
 {
   \regex_extract_once:NnNTF #1 { #4 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_parse_regional_month:NeTF #3
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
       {
        \datatool_timestamp_set_day:Ne #3
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
        \datatool_timestamp_set_year:Ne #3
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
        \regex_extract_once:NnNTF #2 { #5 }
          \l_datatool_timestamp_match_seq
         {
           \exp_args:Ne \DTLCurrentLocaleIfpmTF
            { \seq_item:Nn \l_datatool_timestamp_match_seq { 5 } }
            {
             \datatool_timestamp_set_hour:Ne #3
               {
                 \int_eval:n
                  {
                    12 +
                    \seq_item:Nn \l_datatool_timestamp_match_seq { 2 }
                  }
               }
            }
            {
             \datatool_timestamp_set_hour:Ne #3
               { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
            }
           \datatool_timestamp_set_minute:Ne #3
             { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
           \datatool_timestamp_set_second:Ne #3
             { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
         }
         { #8 }
       \datatool_parse_regional_timezone:NnTF #3
        { #6 } { #7 } { #8 }
       }
       {
         #8
       }
    }
    { #8 }
 }
\cs_generate_variant:Nn
 \datatool_ddmmyyyy_hhmmss_tz_parse_datetime:NNNnnnTF
 { NNNeeeTF }
\cs_new:Nn \datatool_ddmmyy_hhmmss_tz_parse_datetime:NNNnnnTF
 {
   \regex_extract_once:NnNTF #1 { #4 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_parse_regional_month:NeTF #3
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
       {
        \datatool_timestamp_set_day:Ne #3
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
        \datatool_timestamp_set_year_add_century:Ne #3
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
        \regex_extract_once:NnNTF #2 { #5 }
          \l_datatool_timestamp_match_seq
         {
           \exp_args:Ne \DTLCurrentLocaleIfpmTF
            { \seq_item:Nn \l_datatool_timestamp_match_seq { 5 } }
            {
             \datatool_timestamp_set_hour:Ne #3
               {
                 \int_eval:n
                  {
                    12 +
                    \seq_item:Nn \l_datatool_timestamp_match_seq { 2 }
                  }
               }
            }
            {
             \datatool_timestamp_set_hour:Ne #3
               { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
            }
           \datatool_timestamp_set_minute:Ne #3
             { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
           \datatool_timestamp_set_second:Ne #3
             { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
         }
         { #8 }
       \datatool_parse_regional_timezone:NnTF #3
        { #6 } { #7 } { #8 }
       }
       {
         #8
       }
    }
    { #8 }
 }
\cs_generate_variant:Nn
 \datatool_ddmmyy_hhmmss_tz_parse_datetime:NNNnnnTF
 { NNNeeeTF }
\cs_new:Nn \datatool_mmddyyyy_hhmmss_tz_parse_datetime:NNNnnnTF
 {
   \regex_extract_once:NnNTF #1 { #4 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_parse_regional_month:NeTF #3
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
       {
        \datatool_timestamp_set_day:Ne #3
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
        \datatool_timestamp_set_year:Ne #3
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
        \regex_extract_once:NnNTF #2 { #5 }
          \l_datatool_timestamp_match_seq
         {
           \exp_args:Ne \DTLCurrentLocaleIfpmTF
            { \seq_item:Nn \l_datatool_timestamp_match_seq { 5 } }
            {
             \datatool_timestamp_set_hour:Ne #3
               {
                 \int_eval:n
                  {
                    12 +
                    \seq_item:Nn \l_datatool_timestamp_match_seq { 2 }
                  }
               }
            }
            {
             \datatool_timestamp_set_hour:Ne #3
               { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
            }
           \datatool_timestamp_set_minute:Ne #3
             { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
           \datatool_timestamp_set_second:Ne #3
             { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
         }
         { #8 }
       \datatool_parse_regional_timezone:NnTF #3
        { #6 } { #7 } { #8 }
       }
       {
         #8
       }
    }
    { #8 }
 }
\cs_generate_variant:Nn
 \datatool_mmddyyyy_hhmmss_tz_parse_datetime:NNNnnnTF
 { NNNeeeTF }
\cs_new:Nn \datatool_mmddyy_hhmmss_tz_parse_datetime:NNNnnnTF
 {
   \regex_extract_once:NnNTF #1 { #4 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_parse_regional_month:NeTF #3
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
       {
        \datatool_timestamp_set_day:Ne #3
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
        \datatool_timestamp_set_year_add_century:Ne #3
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
        \regex_extract_once:NnNTF #2 { #5 }
          \l_datatool_timestamp_match_seq
         {
           \exp_args:Ne \DTLCurrentLocaleIfpmTF
            { \seq_item:Nn \l_datatool_timestamp_match_seq { 5 } }
            {
             \datatool_timestamp_set_hour:Ne #3
               {
                 \int_eval:n
                  {
                    12 +
                    \seq_item:Nn \l_datatool_timestamp_match_seq { 2 }
                  }
               }
            }
            {
             \datatool_timestamp_set_hour:Ne #3
               { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
            }
           \datatool_timestamp_set_minute:Ne #3
             { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
           \datatool_timestamp_set_second:Ne #3
             { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
         }
         { #8 }
       \datatool_parse_regional_timezone:NnTF #3
        { #6 } { #7 } { #8 }
       }
       {
         #8
       }
    }
    { #8 }
 }
\cs_generate_variant:Nn
 \datatool_mmddyy_hhmmss_tz_parse_datetime:NNNnnnTF
 { NNNeeeTF }
\cs_new:Nn \datatool_yyyymmdd_hhmmss_tz_parse_datetime:NNNnnnTF
 {
   \regex_extract_once:NnNTF #1 { #4 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_parse_regional_month:NeTF #3
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
       {
        \datatool_timestamp_set_day:Ne #3
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
        \datatool_timestamp_set_year:Ne #3
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
        \regex_extract_once:NnNTF #2 { #5 }
          \l_datatool_timestamp_match_seq
         {
           \exp_args:Ne \DTLCurrentLocaleIfpmTF
            { \seq_item:Nn \l_datatool_timestamp_match_seq { 5 } }
            {
             \datatool_timestamp_set_hour:Ne #3
               {
                 \int_eval:n
                  {
                    12 +
                    \seq_item:Nn \l_datatool_timestamp_match_seq { 2 }
                  }
               }
            }
            {
             \datatool_timestamp_set_hour:Ne #3
               { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
            }
           \datatool_timestamp_set_minute:Ne #3
             { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
           \datatool_timestamp_set_second:Ne #3
             { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
         }
         { #8 }
       \datatool_parse_regional_timezone:NnTF #3
        { #6 } { #7 } { #8 }
       }
       {
         #8
       }
    }
    { #8 }
 }
\cs_generate_variant:Nn
 \datatool_yyyymmdd_hhmmss_tz_parse_datetime:NNNnnnTF
 { NNNeeeTF }
\cs_new:Nn \datatool_yymmdd_hhmmss_tz_parse_datetime:NNNnnnTF
 {
   \regex_extract_once:NnNTF #1 { #4 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_parse_regional_month:NeTF #3
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
       {
        \datatool_timestamp_set_day:Ne #3
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
        \datatool_timestamp_set_year_add_century:Ne #3
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
        \regex_extract_once:NnNTF #2 { #5 }
          \l_datatool_timestamp_match_seq
         {
           \exp_args:Ne \DTLCurrentLocaleIfpmTF
            { \seq_item:Nn \l_datatool_timestamp_match_seq { 5 } }
            {
             \datatool_timestamp_set_hour:Ne #3
               {
                 \int_eval:n
                  {
                    12 +
                    \seq_item:Nn \l_datatool_timestamp_match_seq { 2 }
                  }
               }
            }
            {
             \datatool_timestamp_set_hour:Ne #3
               { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
            }
           \datatool_timestamp_set_minute:Ne #3
             { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
           \datatool_timestamp_set_second:Ne #3
             { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
         }
         { #8 }
       \datatool_parse_regional_timezone:NnTF #3
        { #6 } { #7 } { #8 }
       }
       {
         #8
       }
    }
    { #8 }
 }
\cs_generate_variant:Nn
 \datatool_yymmdd_hhmmss_tz_parse_datetime:NNNnnnTF
 { NNNeeeTF }
\regex_new:N \l_datatool_regional_timestamp_sep_regex
\regex_set:Nn \l_datatool_regional_timestamp_sep_regex { \,? \s+ }
\cs_new:Nn \datatool_ddmmyyyy_hhmmss_tz_parse_timestamp:NNNnTF
 {
   \tl_set_eq:NN \l__datatool_tmpa_regex #1
   \tl_set_eq:NN \l__datatool_tmpb_regex #2
   \regex_extract_once:nnNTF
    {
      \A \s*
      ( \ur{l__datatool_tmpa_regex} )
      \ur{l_datatool_regional_timestamp_sep_regex}
      ( \ur{l__datatool_tmpb_regex} )
      \s*
      ( \ur{c_datatool_timezone_id_regex} ) ?
      \s*
      \Z
    }
    { #4 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_timestamp_zero:N #3
      \datatool_ddmmyyyy_hhmmss_tz_parse_datetime:NNNeeeTF
       #1 #2 #3
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
       { #5 } { #6 }
    }
    { #6 }
 }
\cs_generate_variant:Nn
 \datatool_ddmmyyyy_hhmmss_tz_parse_timestamp:NNNnTF
 { ccNnTF }
\cs_new:Nn \datatool_ddmmyy_hhmmss_tz_parse_timestamp:NNNnTF
 {
   \tl_set_eq:NN \l__datatool_tmpa_regex #1
   \tl_set_eq:NN \l__datatool_tmpb_regex #2
   \regex_extract_once:nnNTF
    {
      \A \s*
      ( \ur{l__datatool_tmpa_regex} )
      \ur{l_datatool_regional_timestamp_sep_regex}
      ( \ur{l__datatool_tmpb_regex} )
      \s*
      ( \ur{c_datatool_timezone_id_regex} ) ?
      \s*
      \Z
    }
    { #4 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_timestamp_zero:N #3
      \datatool_ddmmyy_hhmmss_tz_parse_datetime:NNNeeeTF
       #1 #2 #3
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
       { #5 } { #6 }
    }
    { #6 }
 }
\cs_generate_variant:Nn
 \datatool_ddmmyy_hhmmss_tz_parse_timestamp:NNNnTF
 { ccNnTF }
\cs_new:Nn \datatool_mmddyyyy_hhmmss_tz_parse_timestamp:NNNnTF
 {
   \tl_set_eq:NN \l__datatool_tmpa_regex #1
   \tl_set_eq:NN \l__datatool_tmpb_regex #2
   \regex_extract_once:nnNTF
    {
      \A \s*
      ( \ur{l__datatool_tmpa_regex} )
      \ur{l_datatool_regional_timestamp_sep_regex}
      ( \ur{l__datatool_tmpb_regex} )
      \s*
      ( \ur{c_datatool_timezone_id_regex} ) ?
      \s*
      \Z
    }
    { #4 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_timestamp_zero:N #3
      \datatool_mmddyyyy_hhmmss_tz_parse_datetime:NNNeeeTF
       #1 #2 #3
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
       { #5 } { #6 }
    }
    { #6 }
 }
\cs_generate_variant:Nn
 \datatool_mmddyyyy_hhmmss_tz_parse_timestamp:NNNnTF
 { ccNnTF }
\cs_new:Nn \datatool_mmddyy_hhmmss_tz_parse_timestamp:NNNnTF
 {
   \tl_set_eq:NN \l__datatool_tmpa_regex #1
   \tl_set_eq:NN \l__datatool_tmpb_regex #2
   \regex_extract_once:nnNTF
    {
      \A \s*
      ( \ur{l__datatool_tmpa_regex} )
      \ur{l_datatool_regional_timestamp_sep_regex}
      ( \ur{l__datatool_tmpb_regex} )
      \s*
      ( \ur{c_datatool_timezone_id_regex} ) ?
      \s*
      \Z
    }
    { #4 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_timestamp_zero:N #3
      \datatool_mmddyy_hhmmss_tz_parse_datetime:NNNeeeTF
       #1 #2 #3
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
       { #5 } { #6 }
    }
    { #6 }
 }
\cs_generate_variant:Nn
 \datatool_mmddyy_hhmmss_tz_parse_timestamp:NNNnTF
 { ccNnTF }
\cs_new:Nn \datatool_yyyymmdd_hhmmss_tz_parse_timestamp:NNNnTF
 {
   \tl_set_eq:NN \l__datatool_tmpa_regex #1
   \tl_set_eq:NN \l__datatool_tmpb_regex #2
   \regex_extract_once:nnNTF
    {
      \A \s*
      ( \ur{l__datatool_tmpa_regex} )
      \ur{l_datatool_regional_timestamp_sep_regex}
      ( \ur{l__datatool_tmpb_regex} )
      \s*
      ( \ur{c_datatool_timezone_id_regex} ) ?
      \s*
      \Z
    }
    { #4 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_timestamp_zero:N #3
      \datatool_yyyymmdd_hhmmss_tz_parse_datetime:NNNeeeTF
       #1 #2 #3
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
       { #5 } { #6 }
    }
    { #6 }
 }
\cs_generate_variant:Nn
 \datatool_yyyymmdd_hhmmss_tz_parse_timestamp:NNNnTF
 { ccNnTF }
\cs_new:Nn \datatool_yymmdd_hhmmss_tz_parse_timestamp:NNNnTF
 {
   \tl_set_eq:NN \l__datatool_tmpa_regex #1
   \tl_set_eq:NN \l__datatool_tmpb_regex #2
   \regex_extract_once:nnNTF
    {
      \A \s*
      ( \ur{l__datatool_tmpa_regex} )
      \ur{l_datatool_regional_timestamp_sep_regex}
      ( \ur{l__datatool_tmpb_regex} )
      \s*
      ( \ur{c_datatool_timezone_id_regex} ) ?
      \s*
      \Z
    }
    { #4 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_timestamp_zero:N #3
      \datatool_yymmdd_hhmmss_tz_parse_datetime:NNNeeeTF
       #1 #2 #3
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
       { #5 } { #6 }
    }
    { #6 }
 }
\cs_generate_variant:Nn
 \datatool_yymmdd_hhmmss_tz_parse_timestamp:NNNnTF
 { ccNnTF }
\cs_new:Nn \datatool_ddmmyyyy_hhmmss_tz_parse_timestamp:NNnTF
 {
   \regex_extract_once:NnNTF #1 { #3 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_timestamp_zero:N #2
      \datatool_parse_regional_month:NeTF #2
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
       {
        \datatool_timestamp_set_day:Ne #2
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
        \datatool_timestamp_set_year:Ne #2
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
        \exp_args:Ne \DTLCurrentLocaleIfpmTF
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 8 } }
         {
          \datatool_timestamp_set_hour:Ne #2
            {
              \int_eval:n
               {
                 12 +
                 \seq_item:Nn \l_datatool_timestamp_match_seq { 5 }
               }
            }
         }
         {
          \datatool_timestamp_set_hour:Ne #2
            { \seq_item:Nn \l_datatool_timestamp_match_seq { 5 } }
         }
        \datatool_timestamp_set_minute:Ne #2
          { \seq_item:Nn \l_datatool_timestamp_match_seq { 6 } }
        \datatool_timestamp_set_second:Ne #2
          { \seq_item:Nn \l_datatool_timestamp_match_seq { 7 } }
       \datatool_parse_regional_timezone:NeTF #2
        { \seq_item:Nn \l_datatool_timestamp_match_seq { 9 } }
        { #4 } { #5 }
      }
      {
        #5
      }
    }
    { #5 } % No match
 }
\cs_new:Nn \datatool_ddmmyy_hhmmss_tz_parse_timestamp:NNnTF
 {
   \regex_extract_once:NnNTF #1 { #3 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_timestamp_zero:N #2
      \datatool_parse_regional_month:NeTF #2
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
       {
        \datatool_timestamp_set_day:Ne #2
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
        \datatool_timestamp_set_year_add_century:Ne #2
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
        \exp_args:Ne \DTLCurrentLocaleIfpmTF
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 8 } }
         {
          \datatool_timestamp_set_hour:Ne #2
            {
              \int_eval:n
               {
                 12 +
                 \seq_item:Nn \l_datatool_timestamp_match_seq { 5 }
               }
            }
         }
         {
           \datatool_timestamp_set_hour:Ne #2
             { \seq_item:Nn \l_datatool_timestamp_match_seq { 5 } }
         }
        \datatool_timestamp_set_minute:Ne #2
          { \seq_item:Nn \l_datatool_timestamp_match_seq { 6 } }
        \datatool_timestamp_set_second:Ne #2
          { \seq_item:Nn \l_datatool_timestamp_match_seq { 7 } }
       \datatool_parse_regional_timezone:NeTF #2
        { \seq_item:Nn \l_datatool_timestamp_match_seq { 9 } }
        { #4 } { #5 }
      }
      {
        #5
      }
    }
    { #5 } % No match
 }
\cs_new:Nn \datatool_mmddyyyy_hhmmss_tz_parse_timestamp:NNnTF
 {
   \regex_extract_once:NnNTF #1 { #3 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_timestamp_zero:N #2
      \datatool_parse_regional_month:NeTF #2
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
       {
        \datatool_timestamp_set_day:Ne #2
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
        \datatool_timestamp_set_year:Ne #2
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
        \exp_args:Ne \DTLCurrentLocaleIfpmTF
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 8 } }
         {
          \datatool_timestamp_set_hour:Ne #2
            {
              \int_eval:n
               {
                 12 +
                 \seq_item:Nn \l_datatool_timestamp_match_seq { 5 }
               }
            }
         }
         {
           \datatool_timestamp_set_hour:Ne #2
             { \seq_item:Nn \l_datatool_timestamp_match_seq { 5 } }
         }
        \datatool_timestamp_set_minute:Ne #2
          { \seq_item:Nn \l_datatool_timestamp_match_seq { 6 } }
        \datatool_timestamp_set_second:Ne #2
          { \seq_item:Nn \l_datatool_timestamp_match_seq { 7 } }
       \datatool_parse_regional_timezone:NeTF #2
        { \seq_item:Nn \l_datatool_timestamp_match_seq { 9 } }
        { #4 } { #5 }
      }
      {
        #5
      }
    }
    { #5 } % No match
 }
\cs_new:Nn \datatool_mmddyy_hhmmss_tz_parse_timestamp:NNnTF
 {
   \regex_extract_once:NnNTF #1 { #3 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_timestamp_zero:N #2
      \datatool_parse_regional_month:NeTF #2
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
       {
        \datatool_timestamp_set_day:Ne #2
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
        \datatool_timestamp_set_year_add_century:Ne #2
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
        \exp_args:Ne \DTLCurrentLocaleIfpmTF
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 8 } }
         {
          \datatool_timestamp_set_hour:Ne #2
            {
              \int_eval:n
               {
                 12 +
                 \seq_item:Nn \l_datatool_timestamp_match_seq { 5 }
               }
            }
         }
         {
           \datatool_timestamp_set_hour:Ne #2
             { \seq_item:Nn \l_datatool_timestamp_match_seq { 5 } }
         }
        \datatool_timestamp_set_minute:Ne #2
          { \seq_item:Nn \l_datatool_timestamp_match_seq { 6 } }
        \datatool_timestamp_set_second:Ne #2
          { \seq_item:Nn \l_datatool_timestamp_match_seq { 7 } }
       \datatool_parse_regional_timezone:NeTF #2
        { \seq_item:Nn \l_datatool_timestamp_match_seq { 9 } }
        { #4 } { #5 }
      }
      {
        #5
      }
    }
    { #5 } % No match
 }
\cs_new:Nn \datatool_yyyymmdd_hhmmss_tz_parse_timestamp:NNnTF
 {
   \regex_extract_once:NnNTF #1 { #3 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_timestamp_zero:N #2
      \datatool_parse_regional_month:NeTF #2
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
       {
        \datatool_timestamp_set_year:Ne #2
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
        \datatool_timestamp_set_day:Ne #2
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
        \exp_args:Ne \DTLCurrentLocaleIfpmTF
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 8 } }
         {
          \datatool_timestamp_set_hour:Ne #2
            {
              \int_eval:n
               {
                 12 +
                 \seq_item:Nn \l_datatool_timestamp_match_seq { 5 }
               }
            }
         }
         {
           \datatool_timestamp_set_hour:Ne #2
             { \seq_item:Nn \l_datatool_timestamp_match_seq { 5 } }
         }
        \datatool_timestamp_set_minute:Ne #2
          { \seq_item:Nn \l_datatool_timestamp_match_seq { 6 } }
        \datatool_timestamp_set_second:Ne #2
          { \seq_item:Nn \l_datatool_timestamp_match_seq { 7 } }
       \datatool_parse_regional_timezone:NeTF #2
        { \seq_item:Nn \l_datatool_timestamp_match_seq { 9 } }
        { #4 } { #5 }
      }
      {
        #5
      }
    }
    { #5 } % No match
 }
\cs_new:Nn \datatool_yymmdd_hhmmss_tz_parse_timestamp:NNnTF
 {
   \regex_extract_once:NnNTF #1 { #3 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_timestamp_zero:N #2
      \datatool_parse_regional_month:NeTF #2
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
       {
        \datatool_timestamp_set_year_add_century:Ne #2
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
        \datatool_timestamp_set_day:Ne #2
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
        \exp_args:Ne \DTLCurrentLocaleIfpmTF
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 8 } }
         {
          \datatool_timestamp_set_hour:Ne #2
            {
              \int_eval:n
               {
                 12 +
                 \seq_item:Nn \l_datatool_timestamp_match_seq { 5 }
               }
            }
         }
         {
           \datatool_timestamp_set_hour:Ne #2
             { \seq_item:Nn \l_datatool_timestamp_match_seq { 5 } }
         }
        \datatool_timestamp_set_minute:Ne #2
          { \seq_item:Nn \l_datatool_timestamp_match_seq { 6 } }
        \datatool_timestamp_set_second:Ne #2
          { \seq_item:Nn \l_datatool_timestamp_match_seq { 7 } }
       \datatool_parse_regional_timezone:NeTF #2
        { \seq_item:Nn \l_datatool_timestamp_match_seq { 9 } }
        { #4 } { #5 }
      }
      {
        #5
      }
    }
    { #5 } % No match
 }
\cs_new:Nn \datatool_parse_regional_timezone:NnTF
 {
   \tl_if_empty:nTF { #2 }
    {
      #3
    }
    {
      \prop_get:NnNF \l_datatool_timezone_map_prop
        { #2 }
       \l_datatool_timezone_map_value_tl
       {
        \DTLCurrentLocaleGetTimeZoneMap { #2 }
        \quark_if_no_value:NT
          \l_datatool_timezone_map_value_tl
         {
           \tl_set:Nn \l_datatool_timezone_map_value_tl { #2 }
         }
       }
      \exp_args:NNV \regex_extract_once:NnNTF
         \c_datatool_timezone_regex
         \l_datatool_timezone_map_value_tl
         \l_datatool_regex_match_seq
        {
          \datatool_timestamp_set_tzhour:Ne #1
            { \seq_item:Nn \l_datatool_regex_match_seq { 2 } }
         \tl_if_empty:eF
            { \seq_item:Nn \l_datatool_regex_match_seq { 3 } }
           {
             \datatool_timestamp_set_tzminute:Ne #1
               { \seq_item:Nn \l_datatool_regex_match_seq { 3 } }
           }
          #3
        }
        { #4 }
    }
 }
\cs_generate_variant:Nn \datatool_parse_regional_timezone:NnTF
  { NeTF }
\cs_new:Nn \datatool_parse_regional_month:NnTF
 {
   \DTLCurrentLocaleGetMonthNameMap { #2 }
   \quark_if_no_value:NT
     \l_datatool_monthname_map_value_tl
    {
      \tl_set:Nn \l_datatool_monthname_map_value_tl { #2 }
    }
   \exp_args:NNV \regex_extract_once:NnNTF
      \c_datatool_month_number_regex
      \l_datatool_monthname_map_value_tl
      \l_datatool_regex_match_seq
     {
       \datatool_timestamp_set_month:Ne #1
         { \seq_item:Nn \l_datatool_regex_match_seq { 2 } }
       #3
     }
     { #4 }
 }
\cs_generate_variant:Nn \datatool_parse_regional_month:NnTF
 { NeTF }
\cs_new:Nn \datatool_ddmmyyyy_parse_date:NNnTF
 {
   \regex_extract_once:NnNTF #1 { #3 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_timestamp_zero:N #2
      \datatool_parse_regional_month:NeTF #2
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
       {
        \datatool_timestamp_set_day:Ne #2
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
        \datatool_timestamp_set_year:Ne #2
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
        #4
      }
      {
        #5
      }
    }
    { #5 } % No match
 }
\cs_new:Nn \datatool_mmddyyyy_parse_date:NNnTF
 {
   \regex_extract_once:NnNTF #1 { #3 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_timestamp_zero:N #2
      \datatool_parse_regional_month:NeTF #2
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
       {
        \datatool_timestamp_set_day:Ne #2
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
        \datatool_timestamp_set_year:Ne #2
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
        #4
      }
      {
        #5
      }
    }
    { #5 } % No match
 }
\cs_new:Nn \datatool_yyyymmdd_parse_date:NNnTF
 {
   \regex_extract_once:NnNTF #1 { #3 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_timestamp_zero:N #2
      \datatool_parse_regional_month:NeTF #2
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
       {
        \datatool_timestamp_set_year:Ne #2
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
        \datatool_timestamp_set_day:Ne #2
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
        #4
      }
      {
        #5
      }
    }
    { #5 } % No match
 }
\cs_new:Nn \datatool_ddmmyy_parse_date:NNnTF
 {
   \regex_extract_once:NnNTF #1 { #3 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_timestamp_zero:N #2
      \datatool_parse_regional_month:NeTF #2
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
       {
        \datatool_timestamp_set_day:Ne #2
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
        \datatool_timestamp_set_year_add_century:Ne #2
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
        #4
      }
      {
        #5
      }
    }
    { #5 } % No match
 }
\cs_new:Nn \datatool_mmddyy_parse_date:NNnTF
 {
   \regex_extract_once:NnNTF #1 { #3 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_timestamp_zero:N #2
      \datatool_parse_regional_month:NeTF #2
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
       {
        \datatool_timestamp_set_day:Ne #2
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
        \datatool_timestamp_set_year_add_century:Ne #2
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
        #4
      }
      {
        #5
      }
    }
    { #5 } % No match
 }
\cs_new:Nn \datatool_yymmdd_parse_date:NNnTF
 {
   \regex_extract_once:NnNTF #1 { #3 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_timestamp_zero:N #2
      \datatool_parse_regional_month:NeTF #2
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
       {
        \datatool_timestamp_set_year_add_century:Ne #2
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
        \datatool_timestamp_set_day:Ne #2
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
        #4
      }
      {
        #5
      }
    }
    { #5 } % No match
 }
\cs_new:Nn \datatool_ddmm_parse_date:NNnTF
 {
   \regex_extract_once:NnNTF #1 { #3 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_timestamp_zero:N #2
      \datatool_parse_regional_month:NeTF #2
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
       {
        \datatool_timestamp_set_day:Ne #2
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
        \datatool_timestamp_set_year:Nn #2 { }
        #4
      }
      {
        #5
      }
    }
    { #5 } % No match
 }
\cs_new:Nn \datatool_mmdd_parse_date:NNnTF
 {
   \regex_extract_once:NnNTF #1 { #3 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_timestamp_zero:N #2
      \datatool_parse_regional_month:NeTF #2
       { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
       {
        \datatool_timestamp_set_day:Ne #2
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
        \datatool_timestamp_set_year:Nn #2 { }
        #4
      }
      {
        #5
      }
    }
    { #5 } % No match
 }
\cs_new:Nn \datatool_hhmmss_parse_time:NnTF
 {
   \datatool_hhmmss_parse_time:NNnTF
     \c_datatool_colon_anchored_hhmmss_time_regex #1 { #2 } { #3 } { #4 }
 }
\cs_new:Nn \datatool_hhmmss_parse_time:NNnTF
 {
   \regex_extract_once:NnNTF
     #1 { #3 }
     \l_datatool_timestamp_match_seq
    {
      \datatool_timestamp_zero:N #2
        \exp_args:Ne \DTLCurrentLocaleIfpmTF
         { \seq_item:Nn \l_datatool_timestamp_match_seq { 5 } }
         {
          \datatool_timestamp_set_hour:Ne #2
            {
              \int_eval:n
               {
                 12 +
                 \seq_item:Nn \l_datatool_timestamp_match_seq { 2 }
               }
            }
         }
         {
           \datatool_timestamp_set_hour:Ne #2
             { \seq_item:Nn \l_datatool_timestamp_match_seq { 2 } }
         }
      \datatool_timestamp_set_minute:Ne #2
        { \seq_item:Nn \l_datatool_timestamp_match_seq { 3 } }
      \datatool_timestamp_set_second:Ne #2
        { \seq_item:Nn \l_datatool_timestamp_match_seq { 4 } }
      #4
    }
    { #5 } % No match
 }
\cs_generate_variant:Nn \datatool_hhmmss_parse_time:NNnTF
 { cNnTF }
\seq_put_right:Nn \l__datatool_known_currencies_seq { \$ }
\seq_put_right:Nn \l__datatool_known_currencies_seq {\pounds }
\seq_put_right:Nn \l__datatool_known_currencies_seq {\textdollar }
\seq_put_right:Nn \l__datatool_known_currencies_seq {\textstirling }
\seq_put_right:Nn \l__datatool_known_currencies_seq {\texteuro }
\seq_put_right:Nn \l__datatool_known_currencies_seq {\textyen }
\seq_put_right:Nn \l__datatool_known_currencies_seq {\textwon }
\seq_put_right:Nn \l__datatool_known_currencies_seq {\textcurrency }
\newcommand*{\@dtl@currency}{\$}
\newcommand*{\DTLCurrencySymbol}{\@dtl@currency}
\newcommand*{\DTLCurrencyCode}{XXX}
\NewDocumentCommand \DTLsetdefaultcurrency { m }
{
  \tl_if_exist:cTF { dtl@curr@ \tl_to_str:n { #1 } @sym }
  {
    \tl_set:Ne \@dtl@currency { \exp_not:c { DTLcurr #1 } }
    \tl_set:Ne \DTLCurrencyCode { #1 }
    \tl_set:Ne \DTLfmtcurrency
      { \exp_not:c { dtl@curr@ #1 @fmt } }
  }
  {
    \tl_set:Nn \DTLCurrencyCode { XXX }
    \tl_set:Nn \@dtl@currency { #1 }
  }
}
\cs_new:Nn \datatool_register_regional_currency_code:nn
 {
   \seq_put_right:Nn \l_datatool_regional_currencies_seq { #2 }
   \prop_put:Nnn \l_datatool_regional_currencies_prop { #1 } { #2 }
 }
\cs_new:Nn \datatool_currency_symbol_region_prefix:n
 {
   \DTLcurrCodeOrSymOrChar
    { }
    { \datatoolcurrencysymbolprefixfmt { #1 } }
    { \datatoolcurrencysymbolprefixfmt { #1 } }
 }
\newcommand{\DTLcurrSym}[1]{\csuse{dtl@curr@ #1 @sym}}
\newcommand{\DTLcurrChar}[1]{\csuse{dtl@curr@ #1 @tl}}
\newcommand{\DTLcurrStr}[1]{\csuse{dtl@curr@ #1 @str}}
\NewDocumentCommand{\DTLdefcurrency} { O{\dtlcurrdefaultfmt} m m }
{
  \group_begin:
  \char_set_catcode_other:N \$
  \__datatool_def_currency:nnnn { #1 } { #2 } { #3 }
}
\cs_new:Nn \__datatool_def_currency:nnnn
{
  \group_end:
  \datatool_def_currency:nnne { #1 } { #2 } { #3 } { #4 }
}
\cs_new:Nn \datatool_def_currency:nnn
 {
   \datatool_def_currency:nnnn
     { \dtlcurrdefaultfmt } { #1 } { #2 } { #3 }
 }
\cs_generate_variant:Nn \datatool_def_currency:nnn
  { nnV , nne , nVV }
\cs_new:Nn \datatool_def_currency:nnnn
 {
  \seq_put_right:Nn \l_datatool_currencies_seq { #2 }
  \str_set:cn { dtl@curr@ #2 @str } { #4 }
  \tl_set:cn { dtl@curr@ #2 @tl } { #4 }
  \tl_set:cn { dtl@curr@ #2 @sym } { #3 }
  \csedef { DTLcurr #2 }
   {
    \exp_not:N \dtltexorsort
     {
       \exp_not:N \DTLcurrCodeOrSymOrChar
        { #2 }
        { \exp_not:N \DTLcurrSym { #2 } }
        { \exp_not:N \DTLcurrChar { #2 } }
     }
     {
       \exp_not:N \DTLcurrStr { #2 }
     }
   }
  \DTLnewcurrencysymbol { #3 }
  \DTLnewcurrencysymbol { #4 }
  \exp_args:Nc \DTLnewcurrencysymbol { DTLcurr #2 }
  \csdef { dtl@curr@ #2 @fmt } { #1 }
 }
\cs_generate_variant:Nn \datatool_def_currency:nnnn
  { nnnV , nnne , nnVV }
\cs_new:Nn \datatool_get_currency_code:Nn
 {
   \__datatool_if_current_currency:nTF { #2 }
    {
      \tl_set_eq:NN #1 \DTLCurrencyCode
    }
    {
      \tl_clear:N #1
      \seq_map_inline:Nn \l_datatool_regional_currencies_seq
       {
         \tl_if_eq:nnTF { ##1 } { #2 }
          {
            \tl_set:Nn #1 { ##1 }
            \seq_map_break:
          }
          {
            \tl_if_eq:nnTF { \DTLcurr { ##1 } } { #2 }
             {
               \tl_set:Nn #1 { ##1 }
               \seq_map_break:
             }
             {
               \exp_args:Ne \tl_if_eq:nnTF { \exp_not:c { DTLcurr ##1 } } { #2 }
                {
                  \tl_set:Nn #1 { ##1 }
                  \seq_map_break:
                }
                {
                  \tl_if_eq:cnTF { dtl@curr@ ##1 @sym } { #2 }
                   {
                     \tl_set:Nn #1 { ##1 }
                     \seq_map_break:
                   }
                   {
                     \str_if_eq:vnT { dtl@curr@ ##1 @str } { #2 }
                      {
                        \tl_set:Nn #1 { ##1 }
                        \seq_map_break:
                      }
                   }
                }
             }
          }
       }
    }
 }
\cs_generate_variant:Nn  \datatool_get_currency_code:Nn { NV }
\prg_new_conditional:Npnn \__datatool_if_current_currency:n #1
   { T, F, TF }
 {
  \tl_if_eq:NnTF \@dtl@currency { #1 }
   {
     \prg_return_true:
   }
   {
     \tl_if_exist:cTF
      { DTLcurr \DTLCurrencyCode }
      {
        \tl_if_eq:cnTF
          { DTLcurr \DTLCurrencyCode }
          { #1 }
         {
           \prg_return_true:
         }
         {
           \exp_args:Nv \tl_if_eq:nnTF
             { dtl@curr@ \DTLCurrencyCode @sym } { #1 }
           {
             \prg_return_true:
           }
           {
             \str_if_eq:vnTF
               { dtl@curr@ \DTLCurrencyCode @str }
               { #1 }
             {
               \prg_return_true:
             }
             {
               \exp_args:Ne \tl_if_eq:nnTF
                { \exp_not:N \DTLcurr { \DTLCurrencyCode } }
                { #1 }
                {
                  \prg_return_true:
                }
                {
                  \prg_return_false:
                }
             }
           }
         }
      }
      {
       \prg_return_false:
      }
   }
 }
\cs_new:Nn \datatool_set_currency_symbol:nn
 {
   \tl_if_exist:cTF { dtl@curr@ #1 @sym }
    {
      \csdef { dtl@curr@ #1 @sym } { #2 }
      \DTLnewcurrencysymbol { #2 }
    }
    {
      \PackageError { datatool-base }
       {
         Can't ~ set ~ currency ~ symbol ~ to ~ \tl_to_str:n { #2 } ~ : ~
         Currency ~ ` #1 ' ~ not ~ defined
       }
       {
         Check ~ that ~ you ~ have ~ spelt ~ the ~
         currency ~ code ~ correctly
       }
    }
 }
\cs_generate_variant:Nn \datatool_set_currency_symbol:nn
 { nV , ne }
\newcommand{\DTLcurrency}[1]{\DTLfmtcurrency{\@dtl@currency}{#1}}
\newcommand{\DTLfmtcurr}[2]{%
  \cs_if_exist:cTF { dtl@curr@ #1 @fmt }
   {
     \use:c { dtl@curr@ #1 @fmt } { \DTLcurr { #1 } } { #2 }
   }
   { \DTLcurrency { #2 } }
}
\newcommand{\DTLfmtcurrency}{\dtlcurrdefaultfmt}
\newcommand{\dtlcurrdefaultfmt}{\dtlcurrprefixfmt}
\newcommand{\dtlcurrprefixfmt}[2]{
 \datatool_prefix_adjust_sign:nnn { #1 } { \dtlcurrfmtsep } { #2 }
}
\cs_new:Nn \datatool_prefix_adjust_sign:nnn
 {
   \bool_lazy_or:nnTF
      { \tl_if_head_eq_charcode_p:nN { #3 } + }
      { \tl_if_head_eq_charcode_p:nN { #3 } - }
    {
      \exp_args:Ne \datatool_adjust_sign_fmt:n { \tl_head:n { #3 } }
      #1 #2
      \tl_tail:n { #3 }
    }
    { #1 #2 #3 }
 }
\cs_new:Nn \datatool_adjust_sign_fmt:n
 {
   \ifmmode
     #1
   \else
    \tl_if_head_eq_charcode:nNTF { #1 } -
     {
       \textminus
     }
     { #1 }
  \fi
 }
\newcommand{\dtlcurrsuffixfmt}[2]{
 \datatool_suffix_adjust_sign:nnn { #1 } { \dtlcurrfmtsep } { #2 }
}
\cs_new:Nn \datatool_suffix_adjust_sign:nnn
 {
   \bool_lazy_or:nnTF
      { \tl_if_head_eq_charcode_p:nN { #3 } + }
      { \tl_if_head_eq_charcode_p:nN { #3 } - }
    {
      \exp_args:Ne \datatool_adjust_sign_fmt:n { \tl_head:n { #3 } }
      \tl_tail:n { #3 }
       #2 #1
    }
    { #3 #2 #1 }
 }
\newcommand{\dtlcurrfmtsymsep}{}
\ExplSyntaxOff
\newcommand{\dtlcurrfmtsep}{\DTLcurrCodeOrSymOrChar{~}{\dtlcurrfmtsymsep}{\dtlcurrfmtsymsep}}
\ExplSyntaxOn
\newcommand{\DTLcurr}[1]{\ifcsdef{DTLcurr#1}{\csuse{DTLcurr#1}}{#1}}
\newcommand{\DTLdefaultEURcurrencyfmt}{\dtlcurrdefaultfmt}
\datatool_def_currency:nnV
 { XXX }
 { \textcurrency }
 \l_datatool_currency_str
\cs_if_exist:NT \faBtc
 {
   \datatool_def_currency:nnV
     { XBT }
     { \faBtc }
     \l_datatool_bitcoin_str
 }
\tl_new:N \l__datatool_eurocs_tl
\cs_if_exist:NTF \euro
 {
   \tl_set:Nn \l__datatool_eurocs_tl { \euro }
 }
 {
  \cs_if_exist:NTF \Euro
   {
     \tl_set:Nn \l__datatool_eurocs_tl { \Euro }
   }
   {
    \cs_if_exist:NTF \EUR
    {
      \tl_set:Nn \l__datatool_eurocs_tl { \EUR }
    }
    {
      \cs_if_exist:NTF \faEur
      {
        \tl_set:Nn \l__datatool_eurocs_tl { \faEur }
      }
      {
        \cs_if_exist:NTF \wasyeuro
        {
          \tl_set:Nn \l__datatool_eurocs_tl { \wasyeuro }
        }
        {
          \cs_if_exist:NTF \texteuro
          {
            \tl_set:Nn \l__datatool_eurocs_tl { \texteuro }
          }
          {
            \tl_set:Nn \l__datatool_eurocs_tl { \l_datatool_euro_str }
          }
        }
      }
    }
   }
 }
\datatool_def_currency:nnVV
 { \DTLdefaultEURcurrencyfmt }
 { EUR }
 \l__datatool_eurocs_tl
 \l_datatool_euro_str
\newcommand \datatoolSetCurrencySort
 {
   \let \textdollar \c_dollar_str
   \let \textdollaroldstyle \c_dollar_str
   \let \textcentoldstyle \l_datatool_cent_str
   \let \textcent \l_datatool_cent_str
   \let \textsterling \l_datatool_pound_str
   \let \pounds \l_datatool_pound_str
   \let \textcurrency \l_datatool_currency_str
   \let \textyen \l_datatool_yen_str
   \let \textflorin \l_datatool_florin_str
   \let \texteuro \l_datatool_euro_str
   \let \textcolonmonetary \l_datatool_colonsign_str
   \let \textwon \l_datatool_won_str
   \let \textnaira \l_datatool_naira_str
   \let \textguarani \l_datatool_guarani_str
   \let \textpeso \l_datatool_peso_str
   \let \textlira \l_datatool_lira_str
   \let \textdong \l_datatool_dong_str
   \let \textbaht \l_datatool_baht_str
 }
\cs_new:Nn \__datatool_update_datatype:
 {
   \datatool_update_datatype:NNNN
     \@dtl@datatype
     \l__datatool_tmp_datatype_int
     \l__datatool_datum_currency_tl
     \l__datatool_tmp_currency_tl
 }
\cs_new:Nn \datatool_update_datatype:NNNN
 {
  \bool_lazy_or:nnF
     { \int_compare_p:nNn { #1 } = { #2 } }
     { \int_compare_p:nNn { #2 } = { \c_datatool_unknown_int } }
   {
    \int_compare:nNnTF { #1 } = { \c_datatool_unknown_int }
     {
       \int_set_eq:NN #1 #2
       \tl_set_eq:NN #3 #4
     }
     {
       \bool_lazy_or:nnTF
         { \datatool_if_temporal_datum_type_p:n { #1 } }
         { \datatool_if_temporal_datum_type_p:n { #2 } }
        {
          \bool_lazy_or:nnTF
           {
             \bool_lazy_and_p:nn
              { \int_compare_p:nNn { #1 } = { \c_datatool_date_int } }
              { \int_compare_p:nNn { #2 } = { \c_datatool_integer_int } }
           }
           {
             \bool_lazy_and_p:nn
              { \int_compare_p:nNn { #2 } = { \c_datatool_date_int } }
              { \int_compare_p:nNn { #1 } = { \c_datatool_integer_int } }
           }
           {
             \int_set_eq:NN #1 \c_datatool_date_int
           }
           {
             \int_set_eq:NN #1 \c_datatool_datetime_int
           }
          \tl_clear:N #3
        }
        {
         \int_compare:nNnT { #1 } < { #2 }
          {
           \int_set_eq:NN #1 #2
           \tl_set_eq:NN #3 #4
          }
        }
     }
   }
 }
\cs_new:Nn \__datatool_assign_result:N
{
  \datatool_assign_result:NNNN #1
   \@dtl@datatype
   \l__datatool_result_tl
   \l__datatool_datum_currency_tl
}
\cs_new:Nn \datatool_assign_result:NNNN
{
 \datatool_if_temporal_datum_type:nTF { #2 }
  {
    \datatool_decimal_to_temporal:Nnn
      #1 { #2 } { #3 }
  }
  {
    \tl_if_empty:NTF #4
     {
       \exp_args:NV \DTLdecimaltolocale #3 #1
     }
     {
       \exp_args:NVV \__datatool_decimal_to_currency:nnN
          #4 #3 #1
     }
  }
}
\cs_new:Nn \datatool_numeric_fn:NnnNN
 {
  \DTLconverttodecimal { #2 } \l__datatool_resulta_tl
  \int_set_eq:NN
    \l__datatool_tmp_datatype_int
    \@dtl@datatype
  \tl_set_eq:NN
    \l__datatool_tmp_currency_tl
    \l__datatool_datum_currency_tl
  \DTLconverttodecimal { #3 } \l__datatool_resultb_tl
  \__datatool_update_datatype:
  \datatool_if_any_int_datum_type:nTF { \@dtl@datatype }
   {
     \tl_set:Ne \l__datatool_result_tl
      { #5 { \l__datatool_resulta_tl } { \l__datatool_resultb_tl } }
   }
   {
     #4
       { \l__datatool_result_tl }
       { \l__datatool_resulta_tl }
       { \l__datatool_resultb_tl }
   }
  \__datatool_assign_result:N #1
 }
\cs_new:Nn \datatool_numeric_fn:NnNN
 {
  \DTLconverttodecimal { #2 } \l__datatool_resulta_tl
  \datatool_if_any_int_datum_type:nTF { \@dtl@datatype }
   {
     \tl_set:Ne \l__datatool_result_tl
      { #4 { \l__datatool_resulta_tl }  }
   }
   {
     #3
       { \l__datatool_result_tl }
       { \l__datatool_resulta_tl }
   }
  \__datatool_assign_result:N #1
 }
\cs_new:Nn \datatool_numeric_fn:NnN
 {
  \DTLconverttodecimal { #2 } \l__datatool_resulta_tl
   #3
     { \l__datatool_result_tl }
     { \l__datatool_resulta_tl }
  \datatool_if_any_int_datum_type:nTF { \@dtl@datatype }
   {
      \int_set_eq:NN \@dtl@datatype \c_datatool_decimal_int
   }
  \__datatool_assign_result:N #1
 }
\cs_new:Nn \datatool_numeric_list_fn:NnNN
 {
   \@dtl@assigntmpseq { #2 }
   \int_set:Nn \l__datatool_count_int
     { \seq_count:N \l__datatool_tmp_seq }
   \int_if_zero:nTF { \l__datatool_count_int }
    {
      \PackageWarning { datatool-base }
         { empty ~ list ~ ` #2 ' ~ found ~ in ~ aggregate ~ function }
      \tl_set_eq:NN #1 \DTLnumbernull
    }
    {
      \seq_pop_left:NN \l__datatool_tmp_seq \l__datatool_resulta_tl
      \exp_args:NV \DTLconverttodecimal
        \l__datatool_resulta_tl
        \l__datatool_result_tl
      \seq_map_inline:Nn \l__datatool_tmp_seq
       {
         \int_set_eq:NN
           \l__datatool_tmp_datatype_int
           \@dtl@datatype
         \tl_set_eq:NN
           \l__datatool_tmp_currency_tl
           \l__datatool_datum_currency_tl
         \tl_set_eq:NN
           \l__datatool_resulta_tl
           \l__datatool_result_tl
         \DTLconverttodecimal { ##1 } \l__datatool_resultb_tl
         \__datatool_update_datatype:
         \datatool_if_any_int_datum_type:nTF { \@dtl@datatype }
          {
            \tl_set:Ne \l__datatool_result_tl
             { #4 { \l__datatool_resulta_tl } { \l__datatool_resultb_tl } }
          }
          {
            #3
              { \l__datatool_result_tl }
              { \l__datatool_resulta_tl }
              { \l__datatool_resultb_tl }
          }
       }
      \__datatool_assign_result:N #1
    }
 }
\cs_new:Nn \datatool_decimal_list_fn:NnN
 {
   \@dtl@assigntmpseq { #2 }
   \int_set:Nn \l__datatool_count_int
     { \seq_count:N \l__datatool_tmp_seq }
   \int_if_zero:nTF { \l__datatool_count_int }
    {
      \PackageError { datatool-base }
        { empty ~ list ~ ` #2 ' ~ found ~ in ~ aggregate ~ function }
        { one ~ or ~ more ~ numeric ~ items ~ are ~ expected }
    }
    {
      \seq_pop_left:NN \l__datatool_tmp_seq \l__datatool_resulta_tl
      \datatool_set_fp:NV #1 \l__datatool_resulta_tl
      \seq_map_inline:Nn \l__datatool_tmp_seq
       {
         \int_set_eq:NN
           \l__datatool_tmp_datatype_int
           \@dtl@datatype
         \tl_set_eq:NN
           \l__datatool_tmp_currency_tl
           \l__datatool_datum_currency_tl
         \datatool_set_fp:Nn \l__datatool_tmpa_fp { ##1 }
         \__datatool_update_datatype:
            #3 #1 { \l__datatool_tmpa_fp }
       }
    }
 }
\NewDocumentCommand \DTLadd { m m m }
{
  \datatool_numeric_fn:NnnNN
    #1 { #2 } { #3 } \dtladd \datatool_int_add:nn
}
\cs_new:Nn \datatool_int_add:nn { \int_eval:n { #1 + #2 } }
\NewDocumentCommand \DTLgadd { m m m }
{
  \DTLadd { \l__datatool_resulta_tl } { #2 } { #3 }
  \tl_gset_eq:NN #1 \l__datatool_resulta_tl
}
\NewDocumentCommand \DTLaddall { m m }
{
  \datatool_numeric_list_fn:NnNN
    #1 { #2 } \dtladd \datatool_int_add:nn
}
\NewDocumentCommand \DTLgaddall { m m }
{
  \DTLaddall { \l__datatool_resultb_tl } { #2 }
  \tl_gset_eq:NN #1 \l__datatool_resultb_tl
}
\NewDocumentCommand \DTLsub { m m m }
{
  \datatool_numeric_fn:NnnNN
    #1 { #2 } { #3 } \dtlsub \datatool_int_sub:nn
}
\cs_new:Nn \datatool_int_sub:nn { \int_eval:n { #1 - ( #2 ) } }
\NewDocumentCommand \DTLgsub { m m m }
{
  \DTLsub { \l__datatool_resulta_tl } {#2} {#3}
  \tl_gset_eq:NN #1 \l__datatool_resulta_tl
}
\NewDocumentCommand \DTLmul { m m m }
{
  \datatool_numeric_fn:NnnNN
    #1 { #2 } { #3 } \dtlmul \datatool_int_mul:nn
}
\cs_new:Nn \datatool_int_mul:nn { \int_eval:n { ( #1 ) * ( #2 ) } }
\newcommand*{\DTLgmul}[3]{%
  \DTLmul{ \l__datatool_resulta_tl } {#2} {#3}
  \tl_gset_eq:NN #1 \l__datatool_resulta_tl
}
\NewDocumentCommand \DTLdiv { m m m }
{
  \datatool_numeric_fn:NnnNN
    #1 { #2 } { #3 } \dtldiv \int_div_round:nn
}
\NewDocumentCommand \DTLgdiv { m m m }
{
  \DTLdiv{ \l__datatool_resulta_tl } {#2} {#3}
  \tl_gset_eq:NN #1 \l__datatool_resulta_tl
}
\NewDocumentCommand \DTLabs { m m }
{
  \datatool_numeric_fn:NnNN
    #1 { #2 } \dtlabs \int_abs:n
}
\NewDocumentCommand \DTLgabs { m m }
{
  \DTLabs{ \l__datatool_resulta_tl } {#2}
  \tl_gset_eq:NN #1 \l__datatool_resulta_tl
}
\NewDocumentCommand \DTLneg { m m }
{
  \datatool_numeric_fn:NnNN
    #1 { #2 } \dtlneg \datatool_int_neg:n
}
\cs_new:Nn \datatool_int_neg:n
  { \int_eval:n { - ( #1 ) } }
\NewDocumentCommand \DTLgneg { m m }
{
  \DTLneg{ \l__datatool_resulta_tl } {#2}
  \tl_gset_eq:NN #1 \l__datatool_resulta_tl
}
\NewDocumentCommand \DTLsqrt { m m }
{
  \datatool_numeric_fn:NnN #1 { #2 } \dtlroot
}
\NewDocumentCommand \DTLgsqrt { m m }
{
  \DTLsqrt{ \l__datatool_resulta_tl } {#2}
  \tl_gset_eq:NN #1 \l__datatool_resulta_tl
}
\NewDocumentCommand \DTLmin { m m m }
{
  \datatool_numeric_fn:NnnNN
    #1 { #2 } { #3 } \dtlmin \int_min:nn
}
\NewDocumentCommand \DTLgmin { m m m }
{
  \DTLmin{ \l__datatool_resulta_tl } {#2} {#3}
  \tl_gset_eq:NN #1 \l__datatool_resulta_tl
}
\NewDocumentCommand \DTLminall { m m }
{
  \datatool_numeric_list_fn:NnNN
    #1 { #2 } \dtlmin \int_min:nn
}
\NewDocumentCommand \DTLgminall { m m }
{
  \DTLminall{ \l__datatool_resultb_tl } { #2 }
  \tl_gset_eq:NN #1 \l__datatool_resultb_tl
}
\NewDocumentCommand \DTLmax { m m m }
{
  \datatool_numeric_fn:NnnNN
    #1 { #2 } { #3 } \dtlmax \int_max:nn
}
\NewDocumentCommand \DTLgmax { m m m }
{
  \DTLmax { \l__datatool_resultb_tl } { #2 } { #3 }
  \tl_gset_eq:NN #1 \l__datatool_resultb_tl
}
\NewDocumentCommand \DTLmaxall { m m }
{
  \datatool_numeric_list_fn:NnNN
    #1 { #2 } \dtlmax \int_max:nn
}
\NewDocumentCommand \DTLgmaxall { m m }
{
  \DTLmaxall{ \l__datatool_resultb_tl } { #2 }
  \tl_gset_eq:NN #1 \l__datatool_resultb_tl
}
\NewDocumentCommand \DTLmeanforall { m m }
{
  \datatool_decimal_list_fn:NnN
    \l__datatool_total_fp { #2 } \fp_add:Nn
  \int_if_zero:nTF { \l__datatool_count_int }
   {
     \tl_set_eq:NN #1 \DTLnumbernull
   }
   {
     \fp_set:Nn
       \l__datatool_mean_fp
       { \l__datatool_total_fp / \l__datatool_count_int }
     \tl_set:Ne
       \l__datatool_result_tl
       { \fp_use:N \l__datatool_mean_fp }
     \__datatool_assign_result:N #1
   }
}
\NewDocumentCommand \DTLgmeanforall { m m }
{
  \DTLmeanforall{ \l__datatool_resultb_tl } { #2 }
  \tl_gset_eq:NN #1 \l__datatool_resultb_tl
}
\NewDocumentCommand \DTLvarianceforall { m m }
{
  \@dtl@assigntmpseq{#2}
  \int_zero:N \l__datatool_count_int
  \fp_zero:N \l__datatool_total_fp
  \int_set_eq:NN \@dtl@datatype \c_datatool_unknown_int
  \tl_clear:N \l__datatool_datum_currency_tl
  \seq_clear:N \l__datatool_tmpb_seq
  \seq_map_inline:Nn \l__datatool_tmp_seq
   {
     \int_incr:N \l__datatool_count_int
     \int_set_eq:NN
       \l__datatool_tmp_datatype_int
       \@dtl@datatype
     \tl_set_eq:NN
       \l__datatool_tmp_currency_tl
       \l__datatool_datum_currency_tl
     \DTLconverttodecimal { ##1 } \l__datatool_resulta_tl
     \__datatool_update_datatype:
     \seq_put_right:No \l__datatool_tmpb_seq { \l__datatool_resulta_tl }
     \fp_add:Nn
       \l__datatool_total_fp
       { \l__datatool_resulta_tl }
   }
  \int_if_zero:nTF { \l__datatool_count_int }
   {
     \PackageWarning { datatool-base }
        { empty ~ list ~ ` #2 ' ~ found ~ in ~ aggregate ~ function }
     \tl_set_eq:NN #1 \DTLnumbernull
   }
   {
    \fp_set:Nn
      \l__datatool_mean_fp
      {  \l__datatool_total_fp  /  \l__datatool_count_int  }
    \fp_zero:N \l__datatool_tmpa_fp
    \seq_map_inline:Nn \l__datatool_tmpb_seq
     {
       \fp_set:Nn \l__datatool_tmpb_fp
        {
          ##1 - \l__datatool_mean_fp
        }
       \fp_add:Nn \l__datatool_tmpa_fp
        {
           \l__datatool_tmpb_fp *  \l__datatool_tmpb_fp
        }
     }
    \fp_set:Nn \l__datatool_tmpa_fp { \l__datatool_tmpa_fp / \l__datatool_count_int }
    \tl_set:Ne
      \l__datatool_result_tl
      { \fp_use:N \l__datatool_tmpa_fp }
    \__datatool_assign_result:N #1
   }
}
\NewDocumentCommand \DTLgvarianceforall { m m }
{
  \DTLvarianceforall { \l__datatool_resultb_tl } { #2 }
  \tl_gset_eq:NN #1 \l__datatool_resultb_tl
}
\NewDocumentCommand \DTLsdforall { m m }
{
  \@dtl@assigntmpseq{#2}
  \int_zero:N \l__datatool_count_int
  \fp_zero:N \l__datatool_total_fp
  \int_set_eq:NN \@dtl@datatype \c_datatool_unknown_int
  \tl_clear:N \l__datatool_datum_currency_tl
  \seq_clear:N \l__datatool_tmpb_seq
  \seq_map_inline:Nn \l__datatool_tmp_seq
   {
     \int_incr:N \l__datatool_count_int
     \int_set_eq:NN
       \l__datatool_tmp_datatype_int
       \@dtl@datatype
     \tl_set_eq:NN
       \l__datatool_tmp_currency_tl
       \l__datatool_datum_currency_tl
     \DTLconverttodecimal { ##1 } \l__datatool_resulta_tl
     \__datatool_update_datatype:
     \seq_put_right:No \l__datatool_tmpb_seq { \l__datatool_resulta_tl }
     \fp_add:Nn
       \l__datatool_total_fp
       { \l__datatool_resulta_tl }
   }
  \int_if_zero:nTF { \l__datatool_count_int }
   {
     \PackageWarning { datatool-base }
        { empty ~ list ~ ` #2 ' ~ found ~ in ~ aggregate ~ function }
     \tl_set_eq:NN #1 \DTLnumbernull
   }
   {
     \fp_set:Nn
       \l__datatool_mean_fp
       {  \l__datatool_total_fp  /  \l__datatool_count_int  }
     \fp_zero:N \l__datatool_tmpa_fp
     \seq_map_inline:Nn \l__datatool_tmpb_seq
      {
        \fp_set:Nn \l__datatool_tmpb_fp
         {
           ##1 - \l__datatool_mean_fp
         }
        \fp_add:Nn \l__datatool_tmpa_fp
         {
            \l__datatool_tmpb_fp *  \l__datatool_tmpb_fp
         }
      }
     \fp_set:Nn \l__datatool_tmpa_fp
        { sqrt ( \l__datatool_tmpa_fp / \l__datatool_count_int ) }
     \tl_set:Ne
       \l__datatool_result_tl
       { \fp_use:N \l__datatool_tmpa_fp }
     \__datatool_assign_result:N #1
   }
}
\NewDocumentCommand \DTLgsdforall { m m }
{
  \DTLsdforall { \l__datatool_resultb_tl } { #2 }
  \tl_gset_eq:NN #1 \l__datatool_resultb_tl
}
\NewDocumentCommand \DTLround { m m m }
{
  \DTLconverttodecimal{#2} \l__datatool_result_tl
  \dtlround
    { \l__datatool_result_tl }
    { \l__datatool_result_tl }
    { #3 }
  \__datatool_assign_result:N #1
}
\NewDocumentCommand \DTLground { m m m }
{
  \DTLround { \l__datatool_resulta_tl } { #2 } { #3 }
  \tl_gset_eq:NN #1 \l__datatool_resulta_tl
}
\NewDocumentCommand \DTLtrunc { m m m }
{
  \DTLconverttodecimal { #2 } \l__datatool_result_tl
  \dtltrunc
    { \l__datatool_result_tl }
    { \l__datatool_result_tl }
    { #3 }
  \__datatool_assign_result:N #1
}
\NewDocumentCommand \DTLgtrunc { m m m }
{
  \DTLtrunc{ \l__datatool_resulta_tl } {#2} {#3}
  \tl_gset_eq:NN #1 \l__datatool_resulta_tl
}
\NewDocumentCommand \DTLclip { m m }
{
  \DTLconverttodecimal{#2} \l__datatool_result_tl
  \dtlclip
    { \l__datatool_result_tl }
    { \l__datatool_result_tl }
  \__datatool_assign_result:N #1
}
\NewDocumentCommand \DTLgclip { m m }
{
  \DTLclip{ \l__datatool_resulta_tl } {#2}
  \tl_gset_eq:NN #1 \l__datatool_resulta_tl
}
\newcommand{\DTLCurrentLocaleGetInitialLetter}[2]{%
  \datatool_get_first_letter:nN { #1 } #2
}
\regex_new:N \l__datatool_initial_cs_regex
\regex_set:Nn \l__datatool_initial_cs_regex { \A \c{.+} \cB(.) }
\NewDocumentCommand{\DTLGetInitialLetter} { m m }
 {
   \bool_if:NTF \l__datatool_initial_purify_early_bool
   {
     \tl_if_head_is_group:nTF { #1 }
      {
        \tl_set:Nx #2 { \text_purify:n { \tl_head:n { #1 } } }
      }
      {
        \exp_args:Nx \__datatool_get_initial_letter:nN
          { \text_purify:n { #1 } } #2
      }
   }
   {
     \__datatool_get_initial_letter:nN { #1 } #2
   }
 }
\cs_new:Nn \__datatool_get_initial_letter:nN
 {
   \tl_if_blank:nTF { #1 }
    {
      \tl_clear:N #2
    }
    {
      \tl_if_head_is_group:nTF { #1 }
       {
         \tl_set:Nx #2 { \tl_head:n { #1 } }
         \tl_set:Nx #2 { \text_purify:n { #2 } }
       }
       {
        \regex_match:NnTF \l__datatool_initial_cs_regex { #1 }
         {
           \tl_set:Nx #2 { \tl_tail:n { #1 } }
           \exp_args:NNx \tl_set:Nx #2 { \exp_args:No \tl_head:n { #2 } }
           \exp_args:No \DTLCurrentLocaleGetInitialLetter { #2 } { #2 }
           \tl_set:Nx #2 { \tl_head:n { #1 } { \exp_not:o { #2 } } }
         }
         {
           \DTLCurrentLocaleGetInitialLetter { #1 } { #2 }
         }
       }
    }
 }
\cs_new:Nn \datatool_get_first_grapheme:nN
 {
   \tl_clear:N #2
   \exp_args:Nx \text_map_inline:nn { \text_purify:n { #1 } }
   {
     \tl_set:Nn #2 { ##1 }
     \text_map_break:
   }
 }
\prg_new_conditional:Npnn \datatool_if_letter:n #1
  { T, F, TF }
 {
   \tl_if_head_eq_catcode:nNTF { #1 } \c_catcode_letter_token
    { \prg_return_true: }
    {
      \exp_args:Nee \tl_if_eq:nnTF
       { \text_uppercase:n { #1 } } { \text_lowercase:n { #1 } }
       { \prg_return_false: }
       { \prg_return_true: }
    }
 }
\cs_new:Nn \datatool_get_first_letter:nN
 {
   \tl_clear:N #2
   \exp_args:Nx \text_map_inline:nn { \text_purify:n { #1 } }
   {
     \datatool_if_letter:nT { ##1 }
      {
        \tl_set:Nn #2 { ##1 }
        \text_map_break:
      }
   }
 }
\regex_new:N \l_datatool_word_head_regex
\regex_set:Nn \l_datatool_word_head_regex
 {
    ([[:punct:][:digit:]]*)
    ([^[:punct:][:digit:][:space:]\~]+?)
    ([[:punct:][:digit:]]*)
    ((?:[[:space:]\~]|\c{protect}?\c{(?:nobreak)?space\ ?})+)
 }
\regex_set:Nn \l_datatool_word_hyphen_regex
 {
    ([[:punct:][:digit:]]*)
    ([^[:punct:][:digit:][:space:]\~]+?)
    ([[:punct:][:digit:]]*)
    -{1}
 }
\regex_set:Nn \l_datatool_word_apos_regex
 {
    ([[:punct:][:digit:]]*)
    ([^[:punct:][:digit:][:space:]\~]+)
    \ur{l_datatool_apos_regex}
    (
      [^[:punct:][:digit:][:space:]\~]+
      (?:\ur{l_datatool_apos_regex}[^[:punct:][:digit:][:space:]\~]+)*
    )
    ([[:punct:][:digit:]]*)
    ((?:[[:space:]\~]|\c{protect}?\c{(?:nobreak)?space\ ?})+)
 }
\regex_set:Nn \l_datatool_word_apos_hyphen_regex
 {
    ([[:punct:][:digit:]]*)
    ([^[:punct:][:digit:][:space:]\~]+)
    \ur{l_datatool_apos_regex}
    (
      [^[:punct:][:digit:][:space:]\~]+
      (?:\ur{l_datatool_apos_regex}[^[:punct:][:digit:][:space:]\~]+)*
    )
    ([[:punct:][:digit:]]*)
    -{1}
 }
\regex_set:Nn \l_datatool_word_apos_tail_regex
 {
    ([[:punct:][:digit:]]*)
    ([^[:punct:][:digit:][:space:]\~]+)
    \ur{l_datatool_apos_regex}
    (
      [^[:punct:][:digit:][:space:]\~]+
      (?:\ur{l_datatool_apos_regex}[^[:punct:][:digit:][:space:]\~]+)*
    )
    ([[:punct:][:digit:]]*)
    \Z
 }
\regex_set:Nn \l_datatool_word_tail_regex
 {
    ([[:punct:][:digit:]]*)
    ([^[:punct:][:digit:][:space:]\~]+)
    ([[:punct:][:digit:]]*)
    \Z
 }
\regex_set:Nn \l_datatool_symbols_regex
 {
    ((?:[!-@\[\]\^\_`\{\|\}]|\c{[[:alpha:][:punct:]]+})+?)
    ((?:[[:space:]\-\~]|\c{(?:nobreak)?space})+)
 }
\regex_set:Nn \l_datatool_other_regex
 {
    (.+?)
    ((?:[[:space:]\-\~]|\c{(?:nobreak)?space})+)
 }
\cs_new:Nn \__datatool_leading_punc:n { \exp_not:n { #1 } }
\cs_new:Nn \__datatool_trailing_punc:n { \exp_not:n { #1 } }
\cs_new:Nn \__datatool_word:n { \exp_not:n { #1 } }
\cs_new:Nn \__datatool_word_hyphen:n { \exp_not:n { #1 } }
\cs_new:Nn \__datatool_word_apos:nn { \exp_not:n { #1 } ' \exp_not:n { #2 } }
\cs_new:Nn \__datatool_word_apos_hyphen:nn { \exp_not:n { #1 } ' \exp_not:n { #2 } }
\cs_new:Nn \__datatool_last_word_apos:nn { \exp_not:n { #1 } ' \exp_not:n { #2 } }
\cs_new:Nn \__datatool_last_word:n { \exp_not:n { #1 } }
\cs_new:Nn \__datatool_word_sep:n { \exp_not:n { #1 } }
\cs_new:Nn \__datatool_hyphen_sep: { - }
\cs_new:Nn \__datatool_symbol:n { \exp_not:n { #1 } }
\cs_new:Nn \datatool_parse_words:N
 {
   \exp_args:NNo \datatool_parse_words:Nn #1 { #1 }
 }
\cs_new:Nn \datatool_parse_words:Nn
 {
   \tl_set:Nx #1 { \tl_trim_spaces:n { #2 } }
   \regex_replace_case_all:nN
    {
      \l_datatool_word_head_regex
        {
          \c{__datatool_leading_punc:n}{\1}
          \c{__datatool_word:n}{\2}
          \c{__datatool_trailing_punc:n}{\3}
          \c{__datatool_word_sep:n}{\4}
        }
      \l_datatool_word_apos_hyphen_regex
        {
          \c{__datatool_leading_punc:n}{\1}
          \c{__datatool_word_apos_hyphen:nn}{\2}{\3}
          \c{__datatool_trailing_punc:n}{\4}
          \c{__datatool_hyphen_sep:n}
        }
      \l_datatool_word_hyphen_regex
        {
          \c{__datatool_leading_punc:n}{\1}
          \c{__datatool_word_hyphen:n}{\2}
          \c{__datatool_trailing_punc:n}{\3}
          \c{__datatool_hyphen_sep:n}
        }
      \l_datatool_word_apos_regex
        {
          \c{__datatool_leading_punc:n}{\1}
          \c{__datatool_word_apos:nn}{\2}{\3}
          \c{__datatool_trailing_punc:n}{\4}
          \c{__datatool_word_sep:n}{\5}
        }
      \l_datatool_word_apos_tail_regex
        {
          \c{__datatool_leading_punc:n}{\1}
          \c{__datatool_last_word_apos:nn}{\2}{\3}
          \c{__datatool_trailing_punc:n}{\4}
        }
      \l_datatool_word_tail_regex
        {
          \c{__datatool_leading_punc:n}{\1}
          \c{__datatool_last_word:n}{\2}
          \c{__datatool_trailing_punc:n}{\3}
        }
      \l_datatool_symbols_regex
        {
          \c{__datatool_symbol:n}{\1}
          \c{__datatool_word_sep:n}{\4}
        }
      \l_datatool_other_regex
        {
          \c{__datatool_symbol:n}{\1}
          \c{__datatool_word_sep:n}{\4}
        }
    }
    #1
 }
\NewDocumentCommand \DTLinitials { m }
{
  \group_begin:
   \DTLstoreinitials { #1 } { \l__datatool_tmpb_tl }
   \l__datatool_tmpb_tl
  \group_end:
}
\NewDocumentCommand \xDTLinitials { m }
{
  \exp_args:No \DTLinitials { #1 }
}
\NewDocumentCommand \DTLstoreinitials { m m }
{
  \tl_clear:N #2
  \tl_if_empty:nF { #1 }
  {
    \datatool_parse_words:Nn \l__datatool_tmpa_tl { #1 }
    \tl_put_right:Nn \l__datatool_tmpa_tl { \q_recursion_tail }
    \__datatool_store_initials:N #2
    \q_recursion_stop
  }
}
\cs_new:Nn \__datatool_store_initials:N
 {
   \tl_set:Nx \l__datatool_tmp_initial_tl { \tl_head:N \l__datatool_tmpa_tl }
   \tl_set:Nx \l__datatool_tmpa_tl { \tl_tail:N \l__datatool_tmpa_tl }
   \tl_if_eq:NnTF
    \l__datatool_tmp_initial_tl { \__datatool_word:n }
    {
      \tl_set:Nx \l__datatool_tmp_initial_tl { \tl_head:N \l__datatool_tmpa_tl }
      \tl_set:Nx \l__datatool_tmpa_tl { \tl_tail:N \l__datatool_tmpa_tl }
      \exp_args:No \DTLStoreInitialGetLetter
         { \l__datatool_tmp_initial_tl } \l__datatool_tmp_initial_tl
      \tl_if_empty:NF \l__datatool_tmp_initial_tl
       {
         \tl_put_right:Nn #1 { \DTLinitialpunc }
         \tl_put_right:Nx #1 { { \l__datatool_tmp_initial_tl } }
         \tl_put_right:Nn #1 { { \DTLbetweeninitials } }
       }
    }
    {
      \tl_if_eq:NnTF
       \l__datatool_tmp_initial_tl { \__datatool_last_word:n }
       {
         \tl_set:Nx \l__datatool_tmp_initial_tl { \tl_head:N \l__datatool_tmpa_tl }
         \tl_set:Nx \l__datatool_tmpa_tl { \tl_tail:N \l__datatool_tmpa_tl }
         \exp_args:No \DTLStoreInitialGetLetter
            { \l__datatool_tmp_initial_tl } \l__datatool_tmp_initial_tl
         \tl_if_empty:NF \l__datatool_tmp_initial_tl
          {
            \tl_put_right:Nn #1 { \DTLinitialpunc }
            \tl_put_right:Nx #1 { { \l__datatool_tmp_initial_tl } }
            \tl_put_right:Nn #1 { { \DTLafterinitials } }
          }
       }
       {
         \tl_if_eq:NnTF
          \l__datatool_tmp_initial_tl { \__datatool_word_hyphen:n }
          {
            \tl_set:Nx \l__datatool_tmp_initial_tl { \tl_head:N \l__datatool_tmpa_tl }
            \tl_set:Nx \l__datatool_tmpa_tl { \tl_tail:N \l__datatool_tmpa_tl }
            \exp_args:No \DTLStoreInitialGetLetter
              { \l__datatool_tmp_initial_tl } \l__datatool_tmp_initial_tl
            \tl_if_empty:NF \l__datatool_tmp_initial_tl
             {
               \tl_put_right:Nn #1 { \DTLinitialpunc }
               \tl_put_right:Nx #1 { { \l__datatool_tmp_initial_tl } }
               \tl_put_right:Nn #1 { { \DTLafterinitialbeforehyphen } }
               \tl_put_right:Nn #1 { \DTLinitialhyphen }
             }
          }
          {
            \tl_if_eq:NnTF
             \l__datatool_tmp_initial_tl { \__datatool_word_apos:nn }
             {
               \tl_set:Nx \l__datatool_tmp_initial_tl { \tl_head:N \l__datatool_tmpa_tl }
               \tl_set:Nx \l__datatool_tmpa_tl { \tl_tail:N \l__datatool_tmpa_tl }
               \exp_args:No \DTLStoreInitialGetLetter
                 { \l__datatool_tmp_initial_tl } \l__datatool_tmp_initial_tl
               \tl_if_empty:NTF \l__datatool_tmp_initial_tl
                {
                  \tl_set:Nx \l__datatool_tmp_initial_tl { \tl_head:N \l__datatool_tmpa_tl }
                  \tl_set:Nx \l__datatool_tmpa_tl { \tl_tail:N \l__datatool_tmpa_tl }
                  \exp_args:No \DTLStoreInitialGetLetter
                    { \l__datatool_tmp_initial_tl } \l__datatool_tmp_initial_tl
                  \tl_if_empty:NF \l__datatool_tmp_initial_tl
                   {
                     \tl_put_right:Nn #1 { \DTLinitialpunc }
                     \tl_put_right:Nx #1 { { \l__datatool_tmp_initial_tl } }
                     \tl_put_right:Nn #1 { { \DTLbetweeninitials } }
                   }
                }
                {
                  \tl_put_right:Nn #1 { \DTLaposinitialpunc }
                  \tl_put_right:Nx #1 { { \l__datatool_tmp_initial_tl } }
                  \tl_set:Nx \l__datatool_tmp_initial_tl { \tl_head:N \l__datatool_tmpa_tl }
                  \tl_set:Nx \l__datatool_tmpa_tl { \tl_tail:N \l__datatool_tmpa_tl }
                  \exp_args:No \DTLStoreInitialGetLetter
                    { \l__datatool_tmp_initial_tl } \l__datatool_tmp_initial_tl
                  \tl_put_right:Nx #1 { { \l__datatool_tmp_initial_tl } }
                  \tl_put_right:Nn #1 { { \DTLbetweeninitials } }
                }
             }
             {
               \tl_if_eq:NnTF
                \l__datatool_tmp_initial_tl { \__datatool_word_apos_hyphen:nn }
                {
                  \tl_set:Nx \l__datatool_tmp_initial_tl { \tl_head:N \l__datatool_tmpa_tl }
                  \tl_set:Nx \l__datatool_tmpa_tl { \tl_tail:N \l__datatool_tmpa_tl }
                  \exp_args:No \DTLStoreInitialGetLetter
                    { \l__datatool_tmp_initial_tl } \l__datatool_tmp_initial_tl
                  \tl_if_empty:NTF \l__datatool_tmp_initial_tl
                   {
                     \tl_set:Nx \l__datatool_tmp_initial_tl
                       { \tl_head:N \l__datatool_tmpa_tl }
                     \tl_set:Nx \l__datatool_tmpa_tl
                       { \tl_tail:N \l__datatool_tmpa_tl }
                     \exp_args:No \DTLStoreInitialGetLetter
                       { \l__datatool_tmp_initial_tl } \l__datatool_tmp_initial_tl
                     \tl_if_empty:NF \l__datatool_tmp_initial_tl
                      {
                        \tl_put_right:Nn #1 { \DTLinitialpunc }
                        \tl_put_right:Nx #1 { { \l__datatool_tmp_initial_tl } }
                        \tl_put_right:Nn #1 { { \DTLafterinitialbeforehyphen } }
                        \tl_put_right:Nn #1 { \DTLinitialhyphen }
                      }
                   }
                   {
                     \tl_put_right:Nn #1 { \DTLaposinitialpunc }
                     \tl_put_right:Nx #1 { { \l__datatool_tmp_initial_tl } }
                     \tl_set:Nx \l__datatool_tmp_initial_tl
                       { \tl_head:N \l__datatool_tmpa_tl }
                     \tl_set:Nx \l__datatool_tmpa_tl
                       { \tl_tail:N \l__datatool_tmpa_tl }
                     \exp_args:No \DTLStoreInitialGetLetter
                       { \l__datatool_tmp_initial_tl } \l__datatool_tmp_initial_tl
                     \tl_put_right:Nx #1 { { \l__datatool_tmp_initial_tl } }
                     \tl_put_right:Nn #1 { { \DTLafterinitialbeforehyphen } }
                     \tl_put_right:Nn #1 { \DTLinitialhyphen }
                   }
                }
                {
                  \tl_if_eq:NnT
                   \l__datatool_tmp_initial_tl { \__datatool_last_word_apos:nn }
                   {
                     \tl_set:Nx \l__datatool_tmp_initial_tl
                        { \tl_head:N \l__datatool_tmpa_tl }
                     \tl_set:Nx \l__datatool_tmpa_tl
                        { \tl_tail:N \l__datatool_tmpa_tl }
                     \exp_args:No \DTLStoreInitialGetLetter
                       { \l__datatool_tmp_initial_tl } \l__datatool_tmp_initial_tl
                     \tl_if_empty:NTF \l__datatool_tmp_initial_tl
                      {
                        \tl_set:Nx \l__datatool_tmp_initial_tl
                          { \tl_head:N \l__datatool_tmpa_tl }
                        \tl_set:Nx \l__datatool_tmpa_tl
                          { \tl_tail:N \l__datatool_tmpa_tl }
                        \exp_args:No \DTLStoreInitialGetLetter
                          { \l__datatool_tmp_initial_tl } \l__datatool_tmp_initial_tl
                        \tl_if_empty:NF \l__datatool_tmp_initial_tl
                         {
                           \tl_put_right:Nn #1 { \DTLinitialpunc }
                           \tl_put_right:Nx #1 { { \l__datatool_tmp_initial_tl } }
                           \tl_put_right:Nn #1 { { \DTLafterinitials } }
                         }
                      }
                      {
                        \tl_put_right:Nn #1 { \DTLaposinitialpunc }
                        \tl_put_right:Nx #1 { { \l__datatool_tmp_initial_tl } }
                        \tl_set:Nx \l__datatool_tmp_initial_tl
                          { \tl_head:N \l__datatool_tmpa_tl }
                        \tl_set:Nx \l__datatool_tmpa_tl
                          { \tl_tail:N \l__datatool_tmpa_tl }
                        \exp_args:No \DTLStoreInitialGetLetter
                          { \l__datatool_tmp_initial_tl } \l__datatool_tmp_initial_tl
                        \tl_put_right:Nx #1 { { \l__datatool_tmp_initial_tl } }
                        \tl_put_right:Nn #1 { { \DTLafterinitials } }
                      }
                   }
                }
             }
          }
       }
    }
   \quark_if_recursion_tail_stop:N \l__datatool_tmpa_tl
   \__datatool_store_initials:N #1
 }
\newcommand{\DTLStoreInitialGetLetter}[2]{\DTLGetInitialLetter{#1}{#2}}
\newcommand*{\DTLafterinitials}{.}
\newcommand*{\DTLbetweeninitials}{.}
\newcommand*{\DTLafterinitialbeforehyphen}{.}
\newcommand*{\DTLinitialhyphen}{-}
\newcommand{\DTLinitialpunc}[2]{#1#2}
\newcommand{\DTLaposinitialpunc}[3]{#1#3}
\newrobustcmd*{\DTLifAllUpperCase}[3]{%
  \tl_set:Nx \l__datatool_tmpa_tl { \text_purify:n { #1 } }
  \tl_set:Nx \l__datatool_tmpb_tl
    { \text_uppercase:n { \l__datatool_tmpa_tl } }
  \tl_if_eq:NNTF
   \l__datatool_tmpa_tl  \l__datatool_tmpb_tl
  { #2 } { #3 }
}
\newrobustcmd*{\DTLifAllLowerCase}[3]{%
  \tl_set:Nx \l__datatool_tmpa_tl { \text_purify:n { #1 } }
  \tl_set:Nx \l__datatool_tmpb_tl
    { \text_lowercase:n { \l__datatool_tmpa_tl } }
  \tl_if_eq:NNTF
   \l__datatool_tmpa_tl \l__datatool_tmpb_tl
  { #2 } { #3 }
}
\newrobustcmd{\DTLsubstitute}[3]{%
 \tl_replace_once:Nnn #1 { #2 } { #3 }
}
\newrobustcmd*{\DTLsplitstring}[4]{%
  \def\dtl@splitstr##1#2##2\@nil{%
    \def#3{##1}%
    \def#4{##2}%
    \ifdefempty{#4}%
    {%
      \let\@dtl@replaced=\@empty
    }%
    {%
      \def\@dtl@replaced{#2}%
      \dtl@split@str##2\@nil
    }%
  }%
  \def\dtl@split@str##1#2\@nil{\def#4{##1}}%
  \dtl@splitstr#1#2\@nil
}
\newrobustcmd*{\DTLxsplitstring}[2]{%
  \exp_args:Noo \DTLsplitstring { #1 } { #2 }
}
\newrobustcmd{\DTLsubstituteall}[3]{%
  \tl_replace_all:Nnn #1 { #2 } { #3 }
}
\newif\if@dtl@condition
\tl_new:N \l__datatool_prefix_tl
\tl_new:N \l__datatool_suffix_tl
\int_new:N \l__datatool_prefix_int
\int_new:N \l__datatool_suffix_int
\prg_new_conditional:Npnn \__datatool_if_starts_or_ends_with:nn #1 #2
 { T, F, TF}
 {
   \tl_clear:N \l__datatool_prefix_tl
   \tl_clear:N \l__datatool_suffix_tl
   \tl_if_eq:nnTF { #1 } { #2 }
    {
      \tl_set:Nn \l__datatool_prefix_tl { #2 }
      \prg_return_true:
    }
    {
     \int_set:Nn \l__datatool_prefix_int { \tl_count:n { #2 } }
     \int_set:Nn \l__datatool_suffix_int { \tl_count:n { #1 } }
     \int_compare:nNnTF { \l__datatool_suffix_int } > { \l__datatool_prefix_int }
      {
        \tl_if_eq:enTF
          { \tl_range:nnn { #1 } { \c_one_int } { \l__datatool_prefix_int } }
          { #2 }
         {
           \tl_set:Nn \l__datatool_prefix_tl { #2 }
           \tl_set:Ne \l__datatool_suffix_tl
             {
               \tl_range:nnn { #1 }
                { \l__datatool_prefix_int + \c_one_int }
                { \l__datatool_suffix_int }
             }
           \prg_return_true:
         }
         {
           \int_sub:Nn \l__datatool_suffix_int { \l__datatool_prefix_int }
           \tl_if_eq:enTF
             {
               \tl_range:nnn { #1 }
                 { \l__datatool_suffix_int + \c_one_int }
                 { - \c_one_int }
             }
             { #2 }
            {
              \tl_set:Nn \l__datatool_prefix_tl { #2 }
              \tl_set:Ne \l__datatool_suffix_tl
                {
                  \tl_range:nnn { #1 }
                   { \c_one_int }
                   { \l__datatool_suffix_int }
                }
              \prg_return_true:
            }
            {
              \prg_return_false:
            }
         }
      }
      {
        \prg_return_false:
      }
    }
 }
\cs_generate_variant:Nn \__datatool_if_starts_or_ends_with:nnTF
 { VvTF , VeTF, VnTF }
\cs_new:Nn \__datatool_if_starts_with:NnTF
 {
   \exp_args:NV \__datatool_if_starts_with:nnTF #1 { #2 } { #3 } { #4 }
 }
\cs_new:Nn \__datatool_if_starts_with:nnTF
 {
   \tl_clear:N \l__datatool_prefix_tl
   \tl_set:Nn \l__datatool_suffix_tl { #1 }
   \tl_set:Nn \l__datatool_tmpa_tl { #1 \q_recursion_tail }
   \tl_set:Nn \l__datatool_tmpb_tl { #2 \q_recursion_tail }
   \__datatool_if_starts_with:
   \q_recursion_stop
   \__datatool_result:nn { #3 } { #4 }
 }
\cs_new:Nn \__datatool_if_starts_with:
{
   \exp_args:No \tl_if_head_is_space:nTF { \l__datatool_tmpa_tl }
   {
     \tl_set:Nn \l__datatool_tmpc_tl { ~ }
     \tl_set:Nx \l__datatool_tmpa_tl
       { \tl_head:N \l__datatool_tmpa_tl \tl_tail:N \l__datatool_tmpa_tl }
   }
   {
     \tl_set:Nx \l__datatool_tmpc_tl
       { \tl_head:N \l__datatool_tmpa_tl }
     \tl_set:Nx \l__datatool_tmpa_tl
       { \tl_tail:N \l__datatool_tmpa_tl }
   }
   \exp_args:No \tl_if_head_is_space:nTF { \l__datatool_tmpb_tl }
   {
     \tl_set:Nn \l__datatool_tmpd_tl { ~ }
     \tl_set:Nx \l__datatool_tmpb_tl
       { \tl_head:N \l__datatool_tmpb_tl \tl_tail:N \l__datatool_tmpb_tl }
   }
   {
     \tl_set:Nx \l__datatool_tmpd_tl
       { \tl_head:N \l__datatool_tmpb_tl }
     \tl_set:Nx \l__datatool_tmpb_tl
       { \tl_tail:N \l__datatool_tmpb_tl }
   }
   \cs_set:Nn \__datatool_next: { }
   \if_meaning:w \q_recursion_tail \l__datatool_tmpd_tl
     \cs_set_eq:NN \__datatool_next: \__datatool_starts_with_true:
   \else
     \if_meaning:w \q_recursion_tail \l__datatool_tmpc_tl
       \cs_set_eq:NN \__datatool_next: \__datatool_starts_with_false:
     \else
       \str_if_eq:NNTF \l__datatool_tmpc_tl \l__datatool_tmpd_tl
        {
         \tl_put_right:No \l__datatool_prefix_tl { \l__datatool_tmpd_tl }
        }
        {
         \cs_set_eq:NN \__datatool_next: \__datatool_starts_with_false:
        }
     \fi
   \fi
   \__datatool_next:
   \__datatool_if_starts_with:
}
\cs_new:Nn \__datatool_starts_with_false:
 {
   \cs_set:Nn \__datatool_result:nn { ##2 }
   \tl_clear:N \l__datatool_prefix_tl
   \use_none_delimit_by_q_recursion_stop:w
 }
\cs_new:Nn \__datatool_starts_with_true:
 {
   \cs_set:Nn \__datatool_result:nn { ##1 }
   \if_meaning:w \q_recursion_tail \l__datatool_tmpc_tl
     \tl_clear:N \l__datatool_suffix_tl
   \else
     \tl_set_eq:NN \l__datatool_suffix_tl \l__datatool_tmpc_tl
     \exp_after:wN \__datatool_suffix_tail:w \l__datatool_tmpa_tl
   \fi
   \use_none_delimit_by_q_recursion_stop:w
 }
\cs_new:Npn \__datatool_suffix_tail:w #1\q_recursion_tail
 {
   \tl_put_right:Nn \l__datatool_suffix_tl { #1 }
 }
\cs_new:Npn \__datatool_if_starts_with:NnT #1#2#3
 {
   \__datatool_if_starts_with:NnTF #1 { #2 } { #3 } { }
 }
\newcommand{\@dtl@checknumerical}[1]{%
 \tl_if_single_token:nTF { #1 }
 { \exp_args:No \__datatool_parse_datum:n { #1 } }
 { \__datatool_parse_datum:n { #1 }}
}
\newrobustcmd{\DTLifnumerical}[3]{%
 \@dtl@checknumerical { #1 }
 \datatool_if_numeric_datum_type:nTF { \@dtl@datatype }
   { #2 } { #3 }
}
\NewDocumentCommand \DTLiftemporal { m m m }
{
 \tl_if_single_token:nTF { #1 }
 { \exp_args:No \__datatool_parse_datum:n { #1 } }
 { \__datatool_parse_datum:n { #1 }}
 \datatool_if_temporal_datum_type:nTF { \@dtl@datatype }
   { #2 } { #3 }
}
\newcommand*{\dtl@testbothnumerical}[2]{%
  \DTLifnumerical { #1 }
  {
    \DTLifnumerical { #2 } { \@dtl@conditiontrue } { \@dtl@conditionfalse }
  }
  { \@dtl@conditionfalse }
}
\newrobustcmd{\DTLifreal}[3]{%
 \tl_if_single_token:nTF { #1 }
 { \exp_args:No \__datatool_parse_datum:n { #1 } }
 { \__datatool_parse_datum:n { #1 }}
 \int_compare:nNnTF { \@dtl@datatype } = { \c_datatool_decimal_int }
  { #2 } { #3 }
}
\newrobustcmd{\DTLifint}[3]{%
 \tl_if_single_token:nTF { #1 }
 { \exp_args:No \__datatool_parse_datum:n { #1 } }
 { \__datatool_parse_datum:n { #1 }}
 \int_compare:nNnTF { \@dtl@datatype } = { \c_datatool_integer_int }
  { #2 } { #3 }
}
\NewDocumentCommand \DTLiftimestamp { m m m }
{
 \tl_if_single_token:nTF { #1 }
 { \exp_args:No \__datatool_parse_datum:n { #1 } }
 { \__datatool_parse_datum:n { #1 }}
 \int_compare:nNnTF { \@dtl@datatype } = { \c_datatool_datetime_int }
  { #2 } { #3 }
}
\NewDocumentCommand \DTLifdate { m m m }
{
 \tl_if_single_token:nTF { #1 }
 { \exp_args:No \__datatool_parse_datum:n { #1 } }
 { \__datatool_parse_datum:n { #1 }}
 \int_compare:nNnTF { \@dtl@datatype } = { \c_datatool_date_int }
  { #2 } { #3 }
}
\NewDocumentCommand \DTLiftime { m m m }
{
 \tl_if_single_token:nTF { #1 }
  { \exp_args:No \__datatool_parse_datum:n { #1 } }
  { \__datatool_parse_datum:n { #1 }}
 \int_compare:nNnTF { \@dtl@datatype } = { \c_datatool_time_int }
  { #2 } { #3 }
}
\newrobustcmd{\DTLifstring}[3]{%
 \tl_if_single_token:nTF { #1 }
 { \exp_args:No \__datatool_parse_datum:n { #1 } }
 { \__datatool_parse_datum:n { #1 }}
 \int_compare:nNnTF { \@dtl@datatype } = { \c_datatool_string_int }
  { #2 } { #3 }
}
\newrobustcmd{\DTLifcurrency}[3]{%
 \tl_if_single_token:nTF { #1 }
 { \exp_args:No \__datatool_parse_datum:n { #1 } }
 { \__datatool_parse_datum:n { #1 }}
 \int_compare:nNnTF { \@dtl@datatype } = { \c_datatool_currency_int }
  { #2 } { #3 }
}
\newrobustcmd*{\DTLifcurrencyunit}[4]{%
 \tl_if_single_token:nTF { #1 }
 { \exp_args:No \__datatool_parse_datum:n { #1 } }
 { \__datatool_parse_datum:n { #1 }}
 \ifnum\@dtl@datatype=\c_datatool_currency_int
   \tl_if_eq:NnTF \l__datatool_datum_currency_tl { #2 }
   { #3 }
   {
     \tl_if_eq:NnTF \l__datatool_datum_currency_tl { \@dtl@currency }
     {
       \tl_if_eq:NnTF \@dtl@currency { #2 }
       { #3 }
       { #4 }
     }
     { #4 }
   }
 \else
  #4
 \fi
}
\newrobustcmd{\DTLifcasedatatype}[5]{%
  \tl_if_single_token:nTF { #1 }
  { \exp_args:No \__datatool_parse_datum:n { #1 } }
  { \__datatool_parse_datum:n { #1 }}
  \ifcase\@dtl@datatype
   #2% string
  \or
   #3% integer
  \or
   #4% number
  \or
   #5% currency
  \fi
}
\cs_new:Nn \__datatool_parse_numbers_ii:nnNN
{
  \tl_if_single_token:nTF { #1 }
  { \exp_args:No \__datatool_parse_datum:n { #1 } }
  { \__datatool_parse_datum:n { #1 }}
  \ifnum\@dtl@datatype > \c_datatool_string_int
    \tl_set_eq:NN #3 \l__datatool_datum_value_tl
  \else
    \tl_set:Nn #3 { 0 }
  \fi
  \int_set_eq:NN \l__datatool_tmp_datatype_int \@dtl@datatype
  \tl_if_single_token:nTF { #2 }
  { \exp_args:No \__datatool_parse_datum:n { #2 } }
  { \__datatool_parse_datum:n { #2 }}
  \ifnum\@dtl@datatype > \c_datatool_string_int
    \tl_set_eq:NN #4 \l__datatool_datum_value_tl
  \else
    \tl_set:Nn #4 { 0 }
  \fi
  \int_compare:nNnT
   { \l__datatool_tmp_datatype_int } > { \@dtl@datatype }
  {
    \int_set_eq:NN \@dtl@datatype \l__datatool_tmp_datatype_int
  }
}
\cs_new:Nn \__datatool_parse_numbers_iii:nnnNNN
{
  \__datatool_parse_numbers_ii:nnNN { #1 } { #2 } #4 #5
  \tl_if_single_token:nTF { #3 }
  { \exp_args:No \__datatool_parse_datum:n { #3 } }
  { \__datatool_parse_datum:n { #3 }}
  \ifnum\@dtl@datatype > \c_datatool_string_int
    \tl_set_eq:NN #6 \l__datatool_datum_value_tl
  \else
    \tl_set:Nn #6 { 0 }
  \fi
}
\newrobustcmd*{\DTLifnumlt}[4]{%
  \__datatool_parse_numbers_ii:nnNN { #1 } { #2 } \@dtl@numi \@dtl@numii
  \dtlifnumlt{\@dtl@numi}{\@dtl@numii} { #3 } { #4 }
}
\newrobustcmd*{\DTLifnumgt}[4]{%
  \__datatool_parse_numbers_ii:nnNN { #1 } { #2 } \@dtl@numi \@dtl@numii
  \dtlifnumgt{\@dtl@numi}{\@dtl@numii} { #3 } { #4 }
}
\newrobustcmd*{\DTLifnumeq}[4]{%
  \__datatool_parse_numbers_ii:nnNN { #1 } { #2 } \@dtl@numi \@dtl@numii
  \dtlifnumeq{\@dtl@numi}{\@dtl@numii} { #3 } { #4 }
}
\newrobustcmd*{\DTLifnumclosedbetween}[5]{%
 \__datatool_parse_numbers_iii:nnnNNN { #1 } { #2 } { #3 }
  \@dtl@numi \@dtl@numii \@dtl@numiii
 \DTLifFPclosedbetween{\@dtl@numi}{\@dtl@numii}{\@dtl@numiii}{#4}{#5}%
}
\newrobustcmd*{\DTLifnumopenbetween}[5]{%
 \__datatool_parse_numbers_iii:nnnNNN { #1 } { #2 } { #3 }
  \@dtl@numi \@dtl@numii \@dtl@numiii
 \DTLifFPopenbetween{\@dtl@numi}{\@dtl@numii}{\@dtl@numiii}{#4}{#5}%
}
\NewDocumentCommand \DTLnumcompare { m m m }
{
  \__datatool_parse_numbers_ii:nnNN { #2 } { #3 } \@dtl@numi \@dtl@numii
  \int_compare:nNnTF
    { \@dtl@datatype } < { \c_datatool_decimal_int }
  {
    \int_compare:nNnTF { \@dtl@numi } < { \@dtl@numii }
     { \int_set:Nn #1 { -1 } }
     {
       \int_compare:nNnTF { \@dtl@numi } > { \@dtl@numii }
       { \int_set_eq:NN #1 \c_one_int }
       { \int_zero:N #1 }
     }
  }
  {
    \fp_compare:nNnTF { \@dtl@numi } < { \@dtl@numii }
     { \int_set:Nn #1 { -1 } }
     {
       \fp_compare:nNnTF { \@dtl@numi } > { \@dtl@numii }
       { \int_set_eq:NN #1 \c_one_int }
       { \int_zero:N #1 }
     }
  }
}
\newcommand*{\dtlcompare}[3]{%
  \__datatool_get_compare_sort:Nn \l__datatool_tmpa_str { #2 }
  \__datatool_get_compare_sort:Nn \l__datatool_tmpb_str { #3 }
  \__datatool_strcmp:NNN #1 \l__datatool_tmpa_str \l__datatool_tmpb_str
}
\newcommand*{\dtlicompare}[3]{%
  \__datatool_get_icompare_sort:Nn \l__datatool_tmpa_str { #2 }
  \__datatool_get_icompare_sort:Nn \l__datatool_tmpb_str { #3 }
  \__datatool_strcmp:NNN #1 \l__datatool_tmpa_str \l__datatool_tmpb_str
}
\cs_new:Nn \__datatool_strcmp:NNN
{
  \exp_args:NNoo \__datatool_strcmp:Nnn #1 { #2 } { #3 }
}
\cs_if_exist:NTF \strcmp
{
  \cs_new:Nn \__datatool_strcmp:Nnn
   {
     \int_set:Nn #1 { \strcmp { #2 } { #3 } }
   }
  \cs_new:Nn  \datatool_strcmp:nn
   {
     \strcmp { #1 } { #2 }
   }
}
{
  \cs_if_exist:NTF \pdfstrcmp
   {
     \cs_new:Nn \__datatool_strcmp:Nnn
      {
        \int_set:Nn #1 { \pdfstrcmp{ #2 } { #3 } }
      }
     \cs_new:Nn  \datatool_strcmp:nn
      {
        \pdfstrcmp { #1 } { #2 }
      }
   }
   {
     \cs_new:Nn \__datatool_strcmp:Nnn
      {
        \str_if_eq:nnTF { #2 } { #3 }
        { \int_zero:N #1 }
        {
          \str_compare:nNnTF { #2 } < { #3 }
          { \int_set:Nn #1 { -1 } }
          { \int_set_eq:NN #1 \c_one_int }
        }
      }
     \cs_new:Nn  \datatool_strcmp:nn
      {
        \str_if_eq:nnTF { #1 } { #2 }
        { \c_zero_int }
        {
          \str_compare:nNnTF { #1 } < { #2 }
           { -1 }
           { \c_one_int }
        }
      }
  }
}
\cs_new:Nn \__datatool_numcmp:Nnn
{
 \dtlifnumlt { #2 } { #3 }
  { #1=-1\relax }
  {
    \dtlifnumgt { #2 } { #3} { #1=1\relax } { #1=0\relax }
  }
}
\tl_new:N \l__datatool_cmpa_tl
\tl_new:N \l__datatool_cmpb_tl
\tl_const:Nn \c__datatool_space_tl { ~ }
\cs_new:Nn \__datatool_get_compare_sort:Nn
 {
   \bool_if:NTF \l__datatool_compare_expand_cs_bool
   {
     \tl_set:Nx \l__datatool_cmpb_tl { \text_purify:n { #2 } }
   }
   {
     \tl_set:Nn \l__datatool_cmpb_tl { #2 }
   }
   \tl_replace_all:Nnn \l__datatool_cmpb_tl { ~ } { \c__datatool_space_tl }
   \tl_clear:N \l__datatool_cmpa_tl
   \exp_args:No \tl_map_function:nN
     { \l__datatool_cmpb_tl }
     \__datatool_get_compare_sort_fn:n
   \bool_if:NTF \l__datatool_compare_expand_cs_bool
   {
     \str_set:Nx #1 { \l__datatool_cmpa_tl }
   }
   {
     \str_set:Nx #1 { \text_purify:n { \l__datatool_cmpa_tl } }
   }
 }
\cs_new:Nn \__datatool_get_icompare_sort:Nn
 {
   \bool_if:NTF \l__datatool_compare_expand_cs_bool
   {
     \tl_set:Nx \l__datatool_cmpb_tl { \text_purify:n { #2 } }
   }
   {
     \tl_set:Nn \l__datatool_cmpb_tl { #2 }
   }
   \tl_replace_all:Nnn \l__datatool_cmpb_tl { ~ } { \c__datatool_space_tl }
   \tl_clear:N \l__datatool_cmpa_tl
   \exp_args:No \tl_map_function:nN
     { \l__datatool_cmpb_tl }
     \__datatool_get_compare_sort_fn:n
   \bool_if:NTF \l__datatool_compare_expand_cs_bool
   {
     \str_set:Nx #1 { \text_lowercase:n { \l__datatool_cmpa_tl } }
   }
   {
     \str_set:Nx #1
      { \text_purify:n { \text_lowercase:n { \l__datatool_cmpa_tl } } }
   }
 }
\cs_new:Nn \__datatool_get_compare_sort_fn:n
 {
   \tl_if_head_eq_catcode:nNTF { #1 } \relax
   {
     \tl_if_eq:nnTF { \c__datatool_space_tl } { #1 }
      {
        \tl_put_right:Nn \l__datatool_cmpa_tl { ~ }
      }
      {
        \ifdtlcompareskipcs
        \else
          \tl_put_right:Nn \l__datatool_cmpa_tl { ^^J }
        \fi
      }
   }
   { \tl_put_right:Nn \l__datatool_cmpa_tl { #1 } }
 }
\newcommand*{\dtlwordindexcompare}[3]{%
  \@dtldictcompare{#1}{#2}{#3}{\@dtl@wordbreak}%
}
\newcommand*{\dtlletterindexcompare}[3]{%
  \@dtldictcompare{#1}{#2}{#3}{}%
}
\newcommand*{\@dtldictcompare}[4]{%
  \group_begin:
  \dtl@SortWordCommands@hook
  \exp_args:Nxx \__datatool_set_tmp_dictcomp:nn { #2 } { #3 }
  \tl_if_empty:nT { #4 }
  {
    \tl_replace_all:Nnn \l__datatool_dictcompa_tl { ~ } {}
    \tl_replace_all:Nnn \l__datatool_dictcompb_tl { ~ } {}
  }
  \str_set:NV \l__datatool_tmpa_str \l__datatool_dictcompa_tl
  \str_set:NV \l__datatool_tmpb_str \l__datatool_dictcompb_tl
  \__datatool_strcmp:NNN #1 \l__datatool_tmpa_str \l__datatool_tmpb_str
}
\tl_new:N \l__datatool_dictcompa_tl
\tl_new:N \l__datatool_dictcompb_tl
\cs_new:Nn \__datatool_set_tmp_dictcomp:nn
{
  \group_end:
  \DTLsortwordhandler { #1 } { \l__datatool_dictcompa_tl }
  \DTLsortwordhandler { #2 } { \l__datatool_dictcompb_tl }
}
\newcommand*{\datatoolpersoncomma}{,\space}
\newcommand*{\datatoolplacecomma}{,\space}
\newcommand*{\datatoolsubjectcomma}{,\space}
\newcommand*{\datatoolparenstart}{\space}
\newcommand*{\datatoolparen}[1]{\space (#1)}
\newcommand{\dtlicomparewords}[3]{%
  \dtlicompare{#1}{#2}{#3}%
}
\newcommand{\dtlcomparewords}[3]{%
  \dtlcompare{#1}{#2}{#3}%
}
\newrobustcmd*{\dtlifcasechargroup}[4]{%
  \regex_match:nnTF { \A \d \Z} { #1 }
  { #3 }
  {
    \regex_match:nnTF { \A [[:alpha:]] \Z} { #1 }
    { #2 }
    { #3 }
  }
}
\newcommand*{\dtlparsewords}[2]{%
  \group_begin:
   \tl_set:Nx \l__datatool_tmpa_tl { \tl_trim_spaces:n { #1 } }
   \regex_replace_case_all:nN
    {
      \l_datatool_word_head_regex
        {
          \2 \cM\|
        }
      \l_datatool_word_hyphen_regex
        {
          \2 \cM\|
        }
      \l_datatool_word_tail_regex
        {
          \2
        }
      \l_datatool_symbols_regex
        { }
    }
    \l__datatool_tmpa_tl
    \forlistloop { #2 } { \l__datatool_tmpa_tl }
  \group_end:
}
\NewDocumentCommand \DTLifstringlt { s m m m m }
{
  \IfBooleanTF { #1 }
   {
     \@sDTLifstringlt { #2 } { #3 } { #4 } { #5 }
   }
   {
     \@DTLifstringlt { #2 } { #3 } { #4 } { #5 }
   }
}
\newcommand*{\@DTLifstringlt}[4]{
  \exp_args:NNo \__datatool_get_compare_sort:Nn
    \l__datatool_tmpa_str { #1 }
  \exp_args:NNo \__datatool_get_compare_sort:Nn
    \l__datatool_tmpb_str { #2 }
  \str_compare:eNeTF
    { \l__datatool_tmpa_str }
     <
    { \l__datatool_tmpb_str }
   { #3 } { #4 }
}
\newcommand*{\@sDTLifstringlt}[4]{
  \exp_args:NNo \__datatool_get_icompare_sort:Nn
    \l__datatool_tmpa_str { #1 }
  \exp_args:NNo \__datatool_get_icompare_sort:Nn
    \l__datatool_tmpb_str { #2 }
  \str_compare:eNeTF
    { \l__datatool_tmpa_str }
     <
    { \l__datatool_tmpb_str }
   { #3 } { #4 }
}
\NewDocumentCommand \DTLiflt { s m m m m }
{
  \IfBooleanTF { #1 }
   {
     \@sDTLiflt { #2 } { #3 } { #4 } { #5 }
   }
   {
     \@DTLiflt { #2 } { #3 } { #4 } { #5 }
   }
}
\newcommand*{\@DTLiflt}[4]{
  \dtl@testbothnumerical {#1} {#2}
  \if@dtl@condition
   \DTLifnumlt {#1} {#2} {#3} {#4}
  \else
   \@DTLifstringlt {#1} {#2} {#3} {#4}
  \fi
}
\newcommand*{\@sDTLiflt}[4]{
  \dtl@testbothnumerical {#1} {#2}
  \if@dtl@condition
   \DTLifnumlt {#1} {#2} {#3} {#4}
  \else
   \@sDTLifstringlt {#1} {#2} {#3} {#4}
  \fi
}
\NewDocumentCommand \DTLifstringgt { s m m m m }
{
  \IfBooleanTF { #1 }
   {
     \@sDTLifstringgt { #2 } { #3 } { #4 } { #5 }
   }
   {
     \@DTLifstringgt { #2 } { #3 } { #4 } { #5 }
   }
}
\newcommand*{\@DTLifstringgt}[4]{
  \exp_args:NNo \__datatool_get_compare_sort:Nn
    \l__datatool_tmpa_str { #1 }
  \exp_args:NNo \__datatool_get_compare_sort:Nn
    \l__datatool_tmpb_str { #2 }
  \str_compare:eNeTF
    { \l__datatool_tmpa_str }
     >
    { \l__datatool_tmpb_str }
   { #3 } { #4 }
}
\newcommand*{\@sDTLifstringgt}[4]{
  \exp_args:NNo \__datatool_get_icompare_sort:Nn
    \l__datatool_tmpa_str { #1 }
  \exp_args:NNo \__datatool_get_icompare_sort:Nn
    \l__datatool_tmpb_str { #2 }
  \str_compare:eNeTF
    { \l__datatool_tmpa_str }
     >
    { \l__datatool_tmpb_str }
   { #3 } { #4 }
}
\NewDocumentCommand \DTLifgt { s m m m m }
{
  \IfBooleanTF { #1 }
   {
     \@sDTLifgt { #2 } { #3 } { #4 } { #5 }
   }
   {
     \@DTLifgt { #2 } { #3 } { #4 } { #5 }
   }
}
\newcommand*{\@DTLifgt}[4]{
  \dtl@testbothnumerical {#1} {#2}
  \if@dtl@condition
   \DTLifnumgt {#1} {#2} {#3} {#4}
  \else
   \@DTLifstringgt {#1} {#2} {#3} {#4}
  \fi
}
\newcommand*{\@sDTLifgt}[4]{
  \dtl@testbothnumerical {#1} {#2}
  \if@dtl@condition
   \DTLifnumgt {#1} {#2} {#3} {#4}
  \else
   \@sDTLifstringgt {#1} {#2} {#3} {#4}
  \fi
}
\NewDocumentCommand \DTLifstringeq { s m m m m }
{
  \IfBooleanTF { #1 }
   {
     \@sDTLifstringeq { #2 } { #3 } { #4 } { #5 }
   }
   {
     \@DTLifstringeq { #2 } { #3 } { #4 } { #5 }
   }
}
\newcommand*{\@DTLifstringeq}[4]{
  \exp_args:NNo \__datatool_get_compare_sort:Nn
    \l__datatool_tmpa_str { #1 }
  \exp_args:NNo \__datatool_get_compare_sort:Nn
    \l__datatool_tmpb_str { #2 }
  \str_compare:eNeTF
    { \l__datatool_tmpa_str }
     =
    { \l__datatool_tmpb_str }
   { #3 } { #4 }
}
\newcommand*{\@sDTLifstringeq}[4]{
  \exp_args:NNo \__datatool_get_icompare_sort:Nn
    \l__datatool_tmpa_str { #1 }
  \exp_args:NNo \__datatool_get_icompare_sort:Nn
    \l__datatool_tmpb_str { #2 }
  \str_compare:eNeTF
    { \l__datatool_tmpa_str }
     =
    { \l__datatool_tmpb_str }
   { #3 } { #4 }
}
\NewDocumentCommand \DTLifeq { s m m m m }
{
  \IfBooleanTF { #1 }
   {
     \@sDTLifeq { #2 } { #3 } { #4 } { #5 }
   }
   {
     \@DTLifeq { #2 } { #3 } { #4 } { #5 }
   }
}
\newcommand*{\@DTLifeq}[4]{
  \dtl@testbothnumerical {#1} {#2}
  \if@dtl@condition
   \DTLifnumeq {#1} {#2} {#3} {#4}
  \else
   \@DTLifstringeq {#1} {#2} {#3} {#4}
  \fi
}
\newcommand*{\@sDTLifeq}[4]{
  \dtl@testbothnumerical {#1} {#2}
  \if@dtl@condition
   \DTLifnumeq {#1} {#2} {#3} {#4}
  \else
   \@sDTLifstringeq {#1} {#2} {#3} {#4}
  \fi
}
\regex_new:N \l_datatool_space_regex
\regex_set:Nn \l_datatool_space_regex
 {
    ((?:[[:space:]\~])|(?:\c{protect}?\c{(?:nobreak)?space\ ?}))
 }
\newrobustcmd*{\DTLifSubString}{\@ifstar\@sDTLifSubString\@DTLifSubString}
\newcommand*{\@DTLifSubString}[4]{%
  \tl_set:Nx \l__datatool_tmpa_tl { \text_purify:n { #1 } }
  \tl_set:Nx \l__datatool_tmpb_tl { \text_purify:n { #2 } }
  \regex_replace_all:NnN \l_datatool_space_regex { \~ } \l__datatool_tmpa_tl
  \regex_replace_all:NnN \l_datatool_space_regex { \~ } \l__datatool_tmpb_tl
  \exp_args:NVV \str_if_in:nnTF
   \l__datatool_tmpa_tl \l__datatool_tmpb_tl
   { #3 } { #4 }
}
\newcommand*{\@sDTLifSubString}[2]{%
  \@DTLifSubString{ \text_lowercase:n { #1 } }{ \text_lowercase:n { #2 } }%
}
\newrobustcmd*{\DTLifStartsWith}{\@ifstar\@sDTLifStartsWith\@DTLifStartsWith}
\newcommand*{\@DTLifStartsWith}[4]{%
  \tl_set:Nx \l__datatool_tmpa_tl { \text_purify:n { #1 } }
  \tl_set:Nx \l__datatool_tmpb_tl { \text_purify:n { #2 } }
  \regex_replace_all:NnN \l_datatool_space_regex { \~ } \l__datatool_tmpa_tl
  \regex_replace_all:NnN \l_datatool_space_regex { \~ } \l__datatool_tmpb_tl
  \exp_args:NVV \__datatool_if_starts_with:nnTF
    \l__datatool_tmpa_tl \l__datatool_tmpb_tl
   { #3 } { #4 }
}
\newcommand*{\@sDTLifStartsWith}[2]{%
  \@DTLifStartsWith{ \text_lowercase:n { #1 } }{ \text_lowercase:n { #2 } }%
}
\newrobustcmd*{\DTLifEndsWith}{\@ifstar\@sDTLifEndsWith\@DTLifEndsWith}
\newcommand*{\@DTLifEndsWith}[4]{%
  \tl_set:Nx \l__datatool_tmpa_tl { \text_purify:n { #1 } }
  \tl_set:Nx \l__datatool_tmpb_tl { \text_purify:n { #2 } }
  \regex_replace_all:NnN \l_datatool_space_regex { \~ } \l__datatool_tmpa_tl
  \regex_replace_all:NnN \l_datatool_space_regex { \~ } \l__datatool_tmpb_tl
  \tl_reverse:N \l__datatool_tmpa_tl
  \tl_reverse:N \l__datatool_tmpb_tl
  \exp_args:NVV \__datatool_if_starts_with:nnTF
   \l__datatool_tmpa_tl \l__datatool_tmpb_tl
   { #3 } { #4 }
}
\newcommand*{\@sDTLifEndsWith}[2]{%
  \@DTLifEndsWith{ \text_lowercase:n { #1 } }{ \text_lowercase:n { #2 } }%
}
\NewDocumentCommand \DTLifstringclosedbetween { s m m m m m m }
{
  \IfBooleanTF { #1 }
   {
     \@sDTLifstringclosedbetween { #2 } { #3 } { #4 } { #5 } { #6 }
   }
   {
     \@DTLifstringclosedbetween { #2 } { #3 } { #4 } { #5 } { #6 }
   }
}
\newcommand*{\@DTLifstringclosedbetween}[5]{%
  \exp_args:NNo \__datatool_get_compare_sort:Nn
    \l__datatool_tmpa_str { #1 }
  \exp_args:NNo \__datatool_get_compare_sort:Nn
    \l__datatool_tmpb_str { #2 }
  \exp_args:NNo \__datatool_get_compare_sort:Nn
    \l__datatool_tmpc_str { #3 }
  \str_compare:eNeTF
    { \l__datatool_tmpa_str }
     <
    { \l__datatool_tmpb_str }
   { #5 }
   {
    \str_compare:eNeTF
      { \l__datatool_tmpa_str }
       >
      { \l__datatool_tmpc_str }
     { #5 } { #4 }
   }
}
\newcommand*{\@sDTLifstringclosedbetween}[5]{%
  \exp_args:NNo \__datatool_get_icompare_sort:Nn
    \l__datatool_tmpa_str { #1 }
  \exp_args:NNo \__datatool_get_icompare_sort:Nn
    \l__datatool_tmpb_str { #2 }
  \exp_args:NNo \__datatool_get_icompare_sort:Nn
    \l__datatool_tmpc_str { #3 }
  \str_compare:eNeTF
    { \l__datatool_tmpa_str }
     <
    { \l__datatool_tmpb_str }
   { #5 }
   {
    \str_compare:eNeTF
      { \l__datatool_tmpa_str }
       >
      { \l__datatool_tmpc_str }
     { #5 } { #4 }
   }
}
\NewDocumentCommand \DTLifclosedbetween { s m m m m m }
{
  \IfBooleanTF { #1 }
   {
     \@sDTLifclosedbetween { #2 } { #3 } { #4 } { #5 } { #6 }
   }
   {
     \@DTLifclosedbetween { #2 } { #3 } { #4 } { #5 } { #6 }
   }
}
\newcommand*{\@DTLifclosedbetween}[5]{%
  \dtl@testbothnumerical{#2}{#3}%
  \if@dtl@condition
    \DTLifnumerical { #1 }
     {
      \DTLifnumclosedbetween {#1} {#2} {#3} {#4} {#5}
     }
     {
      \@DTLifstringclosedbetween {#1} {#2} {#3} {#4} {#5}
     }
  \else
    \@DTLifstringclosedbetween {#1} {#2} {#3} {#4} {#5}
  \fi
}
\newcommand*{\@sDTLifclosedbetween}[5]{%
  \dtl@testbothnumerical{#2}{#3}%
  \if@dtl@condition
    \DTLifnumerical { #1 }
     {
      \DTLifnumclosedbetween {#1} {#2} {#3} {#4} {#5}
     }
     {
      \@sDTLifstringclosedbetween {#1} {#2} {#3} {#4} {#5}
     }
  \else
    \@sDTLifstringclosedbetween {#1} {#2} {#3} {#4} {#5}
  \fi
}
\NewDocumentCommand \DTLifstringopenbetween { s m m m m m m }
{
  \IfBooleanTF { #1 }
   {
     \@sDTLifstringopenbetween { #2 } { #3 } { #4 } { #5 } { #6 }
   }
   {
     \@DTLifstringopenbetween { #2 } { #3 } { #4 } { #5 } { #6 }
   }
}
\newcommand*{\@DTLifstringopenbetween}[5]{%
  \exp_args:NNo \__datatool_get_compare_sort:Nn
    \l__datatool_tmpa_str { #1 }
  \exp_args:NNo \__datatool_get_compare_sort:Nn
    \l__datatool_tmpb_str { #2 }
  \exp_args:NNo \__datatool_get_compare_sort:Nn
    \l__datatool_tmpc_str { #3 }
  \str_compare:eNeTF
    { \l__datatool_tmpa_str }
     >
    { \l__datatool_tmpb_str }
   {
    \str_compare:eNeTF
      { \l__datatool_tmpa_str }
       <
      { \l__datatool_tmpc_str }
      { #4 } { #5 }
   }
   { #5 }
}
\newcommand*{\@sDTLifstringopenbetween}[5]{%
  \exp_args:NNo \__datatool_get_icompare_sort:Nn
    \l__datatool_tmpa_str { #1 }
  \exp_args:NNo \__datatool_get_icompare_sort:Nn
    \l__datatool_tmpb_str { #2 }
  \exp_args:NNo \__datatool_get_icompare_sort:Nn
    \l__datatool_tmpc_str { #3 }
  \str_compare:eNeTF
    { \l__datatool_tmpa_str }
     >
    { \l__datatool_tmpb_str }
   {
    \str_compare:eNeTF
      { \l__datatool_tmpa_str }
       <
      { \l__datatool_tmpc_str }
      { #4 } { #5 }
   }
   { #5 }
}
\NewDocumentCommand \DTLifopenbetween { s m m m m m }
{
  \IfBooleanTF { #1 }
   {
     \@sDTLifopenbetween { #2 } { #3 } { #4 } { #5 } { #6 }
   }
   {
     \@DTLifopenbetween { #2 } { #3 } { #4 } { #5 } { #6 }
   }
}
\newcommand*{\@DTLifopenbetween}[5]{
  \dtl@testbothnumerical {#2} {#3}
  \if@dtl@condition
    \DTLifnumerical { #1 }
     {
      \DTLifnumopenbetween {#1} {#2} {#3} {#4} {#5}
     }
     {
      \@DTLifstringopenbetween {#1} {#2} {#3} {#4} {#5}
     }
  \else
    \@DTLifstringopenbetween {#1} {#2} {#3} {#4} {#5}
  \fi
}
\newcommand*{\@sDTLifopenbetween}[5]{
  \dtl@testbothnumerical {#2} {#3}
  \if@dtl@condition
    \DTLifnumerical { #1 }
     {
      \DTLifnumopenbetween {#1} {#2} {#3} {#4} {#5}
     }
     {
      \@sDTLifstringopenbetween {#1} {#2} {#3} {#4} {#5}
     }
  \else
    \@sDTLifstringopenbetween {#1} {#2} {#3} {#4} {#5}
  \fi
}
\ExplSyntaxOff
\let\DTLifFPopenbetween\dtlifnumopenbetween
\let\DTLifFPclosedbetween\dtlifnumclosedbetween
\newcommand*{\dtl@testlt}[2]{%
  \@DTLiflt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}%
}
\newcommand*{\DTLislt}[2]{%
  \TE@throw\noexpand\dtl@testlt{#1}{#2}\noexpand\if@dtl@condition
}
\newcommand*{\dtl@testiclt}[2]{%
  \@sDTLiflt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}%
}
\newcommand*{\DTLisilt}[2]{%
  \TE@throw\noexpand\dtl@testiclt{#1}{#2}\noexpand\if@dtl@condition
}
\newcommand*{\dtl@testgt}[2]{%
  \@DTLifgt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}%
}
\newcommand*{\DTLisgt}[2]{%
  \TE@throw\noexpand\dtl@testgt{#1}{#2}\noexpand\if@dtl@condition
}
\newcommand*{\dtl@testicgt}[2]{%
  \@sDTLifgt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}%
}
\newcommand*{\DTLisigt}[2]{%
  \TE@throw\noexpand\dtl@testicgt{#1}{#2}\noexpand\if@dtl@condition
}
\newcommand*{\dtl@testeq}[2]{%
  \@DTLifeq{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}%
}
\newcommand*{\DTLiseq}[2]{%
  \TE@throw\noexpand\dtl@testeq{#1}{#2}\noexpand\if@dtl@condition
}
\newcommand*{\dtl@testiceq}[2]{%
  \@sDTLifeq{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}%
}
\newcommand*{\DTLisieq}[2]{%
  \TE@throw\noexpand\dtl@testiceq{#1}{#2}\noexpand\if@dtl@condition
}
\newcommand*{\dtl@testifsubstring}[2]{%
  \@DTLifSubString{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}%
}
\newcommand*{\DTLisSubString}[2]{%
  \TE@throw\noexpand\dtl@testifsubstring{#1}{#2}%
  \noexpand\if@dtl@condition
}
\newcommand*{\dtl@testifisubstring}[2]{%
  \@sDTLifSubString{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}%
}
\newcommand*{\DTLisiSubString}[2]{%
  \TE@throw\noexpand\dtl@testifisubstring{#1}{#2}%
  \noexpand\if@dtl@condition
}
\newcommand*{\dtl@teststartswith}[2]{%
  \@DTLifStartsWith{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}%
}
\newcommand*{\DTLisPrefix}[2]{%
  \TE@throw\noexpand\dtl@teststartswith{#1}{#2}%
  \noexpand\if@dtl@condition
}
\newcommand*{\dtl@testistartswith}[2]{%
  \@sDTLifStartsWith{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}%
}
\newcommand*{\DTLisiPrefix}[2]{%
  \TE@throw\noexpand\dtl@testistartswith{#1}{#2}%
  \noexpand\if@dtl@condition
}
\newcommand*{\dtl@testendswith}[2]{%
  \@DTLifEndsWith{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}%
}
\newcommand*{\DTLisSuffix}[2]{%
  \TE@throw\noexpand\dtl@testendswith{#1}{#2}%
  \noexpand\if@dtl@condition
}
\newcommand*{\dtl@testiendswith}[2]{%
  \@sDTLifEndsWith{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}%
}
\newcommand*{\DTLisiSuffix}[2]{%
  \TE@throw\noexpand\dtl@testiendswith{#1}{#2}%
  \noexpand\if@dtl@condition
}
\newcommand*{\DTLisinlist}[2]{%
  \TE@throw\noexpand\dtl@testinlist{#1}{#2}%
  \noexpand\if@dtl@condition
}
\newcommand*{\dtl@testinlist}[2]{%
  \DTLifinlist{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}%
}
\newcommand*{\dtl@testnumclosedbetween}[3]{%
  \DTLifnumclosedbetween{#1}{#2}{#3}%
    {\@dtl@conditiontrue}{\@dtl@conditionfalse}%
}
\newcommand*{\DTLisnumclosedbetween}[3]{%
  \TE@throw\noexpand\dtl@testnumclosedbetween{#1}{#2}{#3}%
  \noexpand\if@dtl@condition
}
\let\DTLisFPclosedbetween\DTLisnumclosedbetween
\newcommand*{\dtl@testnumopenbetween}[3]{%
  \DTLifnumopenbetween{#1}{#2}{#3}%
    {\@dtl@conditiontrue}{\@dtl@conditionfalse}%
}
\newcommand*{\DTLisnumopenbetween}[3]{%
  \TE@throw\noexpand\dtl@testnumopenbetween{#1}{#2}{#3}%
  \noexpand\if@dtl@condition
}
\let\DTLisFPopenbetween\DTLisnumopenbetween
\newcommand*{\dtl@testclosedbetween}[3]{%
  \@DTLifclosedbetween{#1}{#2}{#3}%
    {\@dtl@conditiontrue}{\@dtl@conditionfalse}%
}
\newcommand*{\DTLisclosedbetween}[3]{%
  \TE@throw\noexpand\dtl@testclosedbetween{#1}{#2}{#3}%
  \noexpand\if@dtl@condition
}
\newcommand*{\dtl@testiclosedbetween}[3]{%
  \@sDTLifclosedbetween{#1}{#2}{#3}%
    {\@dtl@conditiontrue}{\@dtl@conditionfalse}%
}
\newcommand*{\DTLisiclosedbetween}[3]{%
  \TE@throw\noexpand\dtl@testiclosedbetween{#1}{#2}{#3}%
  \noexpand\if@dtl@condition
}
\newcommand*{\dtl@testopenbetween}[3]{%
  \@DTLifopenbetween{#1}{#2}{#3}%
    {\@dtl@conditiontrue}{\@dtl@conditionfalse}%
}
\newcommand*{\DTLisopenbetween}[3]{%
  \TE@throw\noexpand\dtl@testopenbetween{#1}{#2}{#3}%
  \noexpand\if@dtl@condition
}
\newcommand*{\dtl@testiopenbetween}[3]{%
  \@sDTLifopenbetween{#1}{#2}{#3}%
    {\@dtl@conditiontrue}{\@dtl@conditionfalse}%
}
\newcommand*{\DTLisiopenbetween}[3]{%
  \TE@throw\noexpand\dtl@testiopenbetween{#1}{#2}{#3}%
  \noexpand\if@dtl@condition
}
\newcommand*{\dtl@testFPislt}[2]{%
  \dtlifnumlt{#1}{#2}%
  {%
    \@dtl@conditiontrue
  }%
  {%
    \@dtl@conditionfalse
  }%
}
\newcommand*{\DTLisnumlt}[2]{%
  \TE@throw\noexpand\dtl@testFPislt{#1}{#2}%
  \noexpand\if@dtl@condition
}
\let\DTLisFPlt\DTLisnumlt
\newcommand*{\dtl@testFPisgt}[2]{%
  \dtlifnumgt{#1}{#2}%
  {%
    \@dtl@conditiontrue
  }%
  {%
   \@dtl@conditionfalse
  }%
}
\newcommand*{\DTLisnumgt}[2]{%
  \TE@throw\noexpand\dtl@testFPisgt{#1}{#2}%
  \noexpand\if@dtl@condition
}
\let\DTLisFPgt\DTLisnumgt
\newcommand*{\dtl@testFPiseq}[2]{%
 \dtlifnumeq{#1}{#2}%
 {%
   \@dtl@conditiontrue
 }%
 {%
  \@dtl@conditionfalse
 }%
}
\newcommand*{\DTLisnumeq}[2]{%
  \TE@throw\noexpand\dtl@testFPiseq{#1}{#2}%
  \noexpand\if@dtl@condition
}
\let\DTLisFPeq\DTLisnumeq
\newcommand*{\dtl@testFPislteq}[2]{%
 \dtlifnumlt{#1}{#2}%
 {%
   \@dtl@conditiontrue
 }%
 {%
   \@dtl@conditionfalse
 }%
 \if@dtl@condition
 \else
  \dtl@testFPiseq{#1}{#2}%
 \fi
}
\newcommand*{\DTLisnumlteq}[2]{%
 \TE@throw\noexpand\dtl@testFPislteq{#1}{#2}%
 \noexpand\if@dtl@condition
}
\let\DTLisFPlteq\DTLisnumlteq
\newcommand*{\dtl@testFPisgteq}[2]{%
 \dtlifnumgt{#1}{#2}%
 {%
   \@dtl@conditiontrue
 }%
 {%
   \@dtl@conditionfalse
 }%
 \if@dtl@condition
 \else
  \dtl@testFPiseq{#1}{#2}%
 \fi
}
\newcommand*{\DTLisnumgteq}[2]{%
  \TE@throw\noexpand\dtl@testFPisgteq{#1}{#2}%
  \noexpand\if@dtl@condition}
\let\DTLisFPgteq\DTLisnumgteq
\newcommand*{\dtl@teststring}[1]{%
  \DTLifstring{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
\newcommand*{\DTLisstring}[1]{%
  \TE@throw\noexpand\dtl@teststring{#1}\noexpand\if@dtl@condition}
\newcommand*{\dtl@testnumerical}[1]{%
  \DTLifnumerical{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}%
}
\newcommand*{\DTLisnumerical}[1]{%
  \TE@throw\noexpand\dtl@testnumerical{#1}\noexpand\if@dtl@condition}
\newcommand*{\dtl@testint}[1]{%
  \DTLifint{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
\newcommand*{\DTLisint}[1]{%
  \TE@throw\noexpand\dtl@testint{#1}\noexpand\if@dtl@condition}
\newcommand*{\dtl@testreal}[1]{%
  \DTLifreal{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
\newcommand*{\DTLisreal}[1]{%
  \TE@throw\noexpand\dtl@testreal{#1}\noexpand\if@dtl@condition}
\newcommand*{\dtl@testcurrency}[1]{%
  \DTLifcurrency{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
\newcommand*{\DTLiscurrency}[1]{%
  \TE@throw\noexpand\dtl@testcurrency{#1}\noexpand\if@dtl@condition}
\newcommand*{\dtl@testcurrencyunit}[2]{%
  \DTLifcurrencyunit{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
\newcommand*{\DTLiscurrencyunit}[2]{%
  \TE@throw\noexpand\dtl@testcurrencyunit{#1}{#2}%
  \noexpand\if@dtl@condition
}
\newcommand*{\dtlbreak}{%
  \PackageError{datatool}{Can't break out of anything}{}%
}
\long\def\dtlforint#1=#2\to#3\step#4\do#5{%
  \let\@dtl@orgbreak\dtlbreak
  \def\@dtl@endloophook{}%
  \def\dtlbreak{\def\@dtl@endloophook{#1=#3}}%
  #1=#2\relax
  \ifnum#4<0\relax
    \whiledo{\(#1>#3\)\TE@or\(#1=#3\)}%
    {%
      #5%
      \@dtl@endloophook
      \advance#1 by #4\relax
    }%
  \else
    \whiledo{\(#1<#3\)\TE@or\(#1=#3\)}%
    {%
      #5%
      \@dtl@endloophook
      \advance#1 by #4\relax
    }%
  \fi
  \let\dtlbreak\@dtl@orgbreak
}
\newcount\@dtl@foreach@level
\long\def\dtlgforint#1=#2\to#3\step#4\do#5{%
  \global#1=#2\relax
  \global\advance\@dtl@foreach@level by 1\relax
  \expandafter\global\expandafter
    \let\csname @dtl@endhook@\the\@dtl@foreach@level\endcsname
    \relax
  \expandafter\global\expandafter
    \let\csname @dtl@break@\the\@dtl@foreach@level\endcsname
    \dtlbreak
  \gdef\dtlbreak{\expandafter
     \gdef\csname @dtl@endhook@\the\@dtl@foreach@level\endcsname{%
       #1=#3}}%
  \ifnum#4<0\relax
    \whiledo{\(#1>#3\)\TE@or\(#1=#3\)}%
    {%
      #5%
      \csname @dtl@endhook@\the\@dtl@foreach@level\endcsname
      \global\advance#1 by #4\relax
    }%
  \else
    \whiledo{\(#1<#3\)\TE@or\(#1=#3\)}%
    {%
      #5%
      \csname @dtl@endhook@\the\@dtl@foreach@level\endcsname
      \global\advance#1 by #4\relax
    }%
  \fi
  \expandafter\global\expandafter\let\expandafter\dtlbreak
    \csname @dtl@break@\the\@dtl@foreach@level\endcsname
  \global\advance\@dtl@foreach@level by -1\relax
}
\NewDocumentEnvironment{dtlenvgforint}
 { m +b }
 {\dtlgforint#1\do{#2}}
 {}
\NewDocumentEnvironment{dtlenvgforint*}
 { m +!b }
 {\dtlgforint#1\do{#2}}
 {}
\ExplSyntaxOn
\newcommand\DTLresetLanguage
{
  \tl_clear:N \l_datatool_current_language_tl
  \renewcommand \DTLandname { \& }
  \renewcommand \DTLdatatypeunsetname { unset }
  \renewcommand \DTLdatatypestringname { string }
  \renewcommand \DTLdatatypeintegername { integer }
  \renewcommand \DTLdatatypedecimalname { decimal }
  \renewcommand \DTLdatatypecurrencyname { currency }
  \renewcommand \DTLdatatypedatetimename { date-time }
  \renewcommand \DTLdatatypedatename { date }
  \renewcommand \DTLdatatypetimename { time }
  \renewcommand \DTLdatatypeinvalidname { invalid }
  \renewcommand \DTLCurrentLocaleWordHandler [1] { }
  \renewcommand \DTLCurrentLocaleGetInitialLetter [2]
   {
    \datatool_get_first_letter:nN { ##1 } ##2
   }
  \renewcommand \DTLCurrentLocaleGetGroupString [3]
   {
     \tl_set:Nn ##3 { ##1 }
   }
  \renewcommand \DTLCurrentLocaleGetMonthNameMap [1]
   {
    \tl_set_eq:NN \l_datatool_monthname_map_value_tl \q_no_value
   }
  \renewcommand \DTLCurrentLocaleIfpmTF [ 3 ]
   {
     \tl_if_eq:nnTF { ##1 } { pm } { ##2 } { ##3 }
   }
  \renewcommand \dtllettergroup [1]
   {
     \text_titlecase_first:n { ##1 }
   }
  \renewcommand \dtlnonlettergroup [1]
   {
     \detokenize { ##1 }
   }
  \renewcommand \dtlnumbergroup [1] { ##1 }
  \renewcommand \dtlcurrencygroup [2] { ##1 }
  \renewcommand \dtldatetimegroup [1] { ##1 }
  \renewcommand \dtldategroup [1] { ##1 }
  \renewcommand \dtltimegroup [1] { ##1 }
}
\newcommand\DTLresetRegion
{
  \tl_clear:N \l_datatool_current_region_tl
  \DTLsetnumberchars { , } { . }
  \DTLsetdefaultcurrency { XXX }
  \renewcommand \DTLCurrentLocaleCurrencyDP { 2 }
  \renewcommand \dtlcurrfmtsymsep { }
  \renewcommand \DTLCurrentLocaleParseTimeStamp [ 4 ] { ##4 }
  \renewcommand \DTLCurrentLocaleParseDate [ 4 ] { ##4 }
  \renewcommand \DTLCurrentLocaleParseTime [ 4 ] { ##4 }
  \renewcommand \DTLCurrentLocaleGetTimeZoneMap [ 1 ]
   {
     \tl_set_eq:NN \l_datatool_timezone_map_value_tl \q_no_value
   }
  \renewcommand \DTLCurrentLocaleFormatDate [ 4 ]
   {
     \datatool_default_date_fmt:nnnn { ##1 } { ##2 } { ##3 } { ##4 }
   }
  \renewcommand \DTLCurrentLocaleFormatTime [ 3 ]
   {
     \datatool_default_time_fmt:nnn { ##1 } { ##2 } { ##3 }
   }
  \renewcommand \DTLCurrentLocaleFormatTimeZone [ 2 ]
   {
     \datatool_default_timezone_fmt:nn { ##1 } { ##2 }
   }
  \renewcommand \DTLCurrentLocaleFormatTimeStampNoZone [7]
   {
     \datatool_default_timestamp_fmt:nnnnnnn
       { ##1 } { ##2 } { ##3 } { ##4 } { ##5 } { ##6 } { ##7 }
   }
  \renewcommand \DTLCurrentLocaleFormatTimeStampWithZone [9]
   {
    \datatool_default_timestamp_fmt:nnnnnnnnn
      { ##1 } { ##2 } { ##3 } { ##4 } { ##5 } { ##6 } { ##7 } { ##8 } { ##9 }
   }
  \renewcommand \DTLCurrentLocaleTimeStampFmtSep { ~ }
}
\newcommand \RequireDatatoolDialect [1]
{
 \tl_clear:N \l_datatool_current_language_tl
 \__datatool_require_ldf:
  [
   \tl_if_empty:NF \CurrentTrackedRegion
    {
      \TrackLangRequireResource { \CurrentTrackedRegion }
      \tl_if_exist:cTF { DTL \CurrentTrackedRegion LocaleHook }
       {
         \exp_args:Nc \TrackLangAddToCaptions
           { DTL \CurrentTrackedRegion LocaleHook }
       }
       {
         \tl_new:c { DTL \CurrentTrackedRegion LocaleHook }
         \datatool_locale_warn:nn
          { datatool-base }
          {
            No ~ locale ~ hook ~ available ~ for ~ region ~ ` \CurrentTrackedRegion '
          }
       }
    }
   \TrackLangRequireResource { \CurrentTrackedTag }
  ]
  { datatool } { #1 }
 \tl_if_empty:NT \l_datatool_current_language_tl
  {
    \@TrackLangAddToHook
     {
       \tl_clear:N \l_datatool_current_language_tl
     }
     { captions }
  }
 \tl_if_empty:NF \CurrentTrackedRegion
  {
    \tl_if_exist:cF { DTL \CurrentTrackedRegion LocaleHook }
     {
       \cs_if_exist:NT \TrackLangRequireDialectOmitDialectLabel
        {
          \TrackLangRequireDialectOmitDialectLabel { datatool} { #1 }
          \csuse { DTL \CurrentTrackedRegion LocaleHook }
        }
     }
  }
}
\cs_new:Nn \__datatool_require_ldf:
 {
  \TrackLangRequireDialectOmitDialectLabelOmitOnlyRegion
 }
\cs_new:Nn \datatool_locale_define_keys:nn
{
  \keys_define:nn { datatool / locale / #1 } { #2 }
}
\NewDocumentCommand \DTLsetLocaleOptions { s O{} m m }
 {
   \IfBlankTF { #2 }
    {
      \IfBooleanTF { #1 }
       {
         \datatool_set_known_locale_options:nn { #3 } { #4 }
       }
       {
         \datatool_set_locale_options:nn { #3 } { #4 }
       }
    }
    {
      \clist_map_inline:nn { #2 }
       {
         \IfBooleanTF { #1 }
          {
            \datatool_set_known_locale_options:nn { ##1 / #3 } { #4 }
          }
          {
            \datatool_set_locale_options:nn { ##1 / #3 } { #4 }
          }
       }
    }
 }
\cs_new:Nn \datatool_set_locale_options:nn
 {
   \clist_map_inline:nn { #1 }
    {
      \keys_set:nn { datatool / locale / ##1 } { #2 }
    }
 }
\cs_new:Nn \datatool_set_known_locale_options:nn
 {
   \clist_map_inline:nn { #1 }
    {
      \keys_set_known:nn { datatool / locale / ##1 } { #2 }
    }
 }
\tl_new:N \l_datatool_current_language_tl
\tl_new:N \l_datatool_current_region_tl
\prg_new_conditional:Npnn \datatool_if_current_lang_region:nn #1 #2
   { T, F, TF }
 {
  \tl_if_eq:NnTF \l_datatool_current_language_tl { #1 }
   {
    \tl_if_eq:NnTF \l_datatool_current_region_tl { #2 }
     { \prg_return_true: }
     { \prg_return_false: }
   }
   { \prg_return_false: }
 }
\cs_new:Nn \datatool_warn_check_language_empty:nnn
 {
   \tl_if_empty:NTF \l_datatool_current_language_tl
    {
      \cs_if_exist:NTF \TrackLangRequireDialectOmitDialectLabelOmitOnlyRegion
       {
         \datatool_locale_warn:nn
          { #1 }
          {
            #3 ~
            (check ~ your ~ localisation ~ setting ~ includes ~
             language ~ and ~ region)
          }
       }
       {
         \datatool_locale_warn:nn
          { #1 }
          {
            #2 ~
            (try ~ updating ~ tracklang ~ to ~ at ~ least ~ version ~ 1.6.3)
          }
       }
    }
    { \datatool_locale_warn:nn { #1 } { #3 } }
 }
\cs_new:Nn \datatool_warn_check_head_language_empty:nnnn
 {
   \tl_if_head_eq_meaning:nNTF { #1 } \l_datatool_current_language_tl
    {
      \datatool_warn_check_language_empty:nnn { #2 } { #3 } { #4 }
    }
    {
      \datatool_locale_warn:nn { #2 } { #4 }
    }
 }
\cs_generate_variant:Nn  \datatool_warn_check_head_language_empty:nnnn
 { Vnnn }
\clist_map_inline:Nn \l__datatool_extra_locales_clist
 {
   \regex_match:nnTF { \A [A-Z]{2} \Z } { #1 }
    {
      \tl_set:Nn \l__datatool_tmpa_tl
       {
         \dtl@message { Adding ~ tracked ~ locale ~ ` und-#1 ' }
         \TrackLanguageTag { und-#1 }
       }
      \ForEachTrackedDialect{\l__datatool_dialect_tl}
       {
         \IfTrackedIsoCode
           { \TwoLetterIsoCountryCode }
           { \l__datatool_dialect_tl }
           {
             \dtl@message
              {
                Dialect ~ ` \l__datatool_dialect_tl' ~ already ~ has ~ region
              }
           }
           {
             \dtl@message
              { Adding ~ region ~ `#1' ~ to ~ locale ~ ` \l__datatool_dialect_tl ' }
             \AddTrackedRegion { #1 } { \l__datatool_dialect_tl }
             \tl_clear:N \l__datatool_tmpa_tl
           }
       }
      \l__datatool_tmpa_tl
    }
    {
      \TrackIfKnownLanguage { #1 }
       {
         \dtl@message { Adding ~ tracked ~ locale ~ ` #1 ' }
       }
       {
         \datatool_locale_warn:nn
          { datatool-base }
         { Unrecognised ~ language ~ in ~ locale ~ tag ~ ` #1 '}
       }
    }
 }
\newcommand{\datatool@do@load@locales}{}
\datatool@load@locales
{
  \renewcommand\datatool@do@load@locales
   {
    \AnyTrackedLanguages
     {
       \cs_if_exist:NF
         \TrackLangRequireDialectOmitDialectLabelOmitOnlyRegion
        {
          \datatool_locale_warn:nn
           {
            old ~ version ~ of ~ tracklang: ~ localisation ~ files ~
            may ~ not ~ all ~ load. ~ Upgrade ~ to ~ at ~ least ~
            tracklang ~ v1.6.3 ~ for ~ better ~ support
           }
          \cs_set:Nn \__datatool_require_ldf:
           { \TrackLangRequireDialect }
        }
       \ForEachTrackedDialect { \l__datatool_dialect_tl }
        {
         \RequireDatatoolDialect { \l__datatool_dialect_tl }
        }
     }
     { }
   }
}
\ExplSyntaxOff
\datatool@do@load@locales
\def\@dtl@gobbletonil#1\@nil{}
\def\@dtl@countdigits#1#2\relax{%
  \advance\@dtl@tmpcount by 1\relax
  \ifx.#2\relax
    \let\@dtl@countnext=\@gobble
  \else
    \let\@dtl@countnext=\@dtl@countdigits
  \fi
  \@dtl@countnext#2\relax
}
\newcommand*{\dtlenableUTFviii}{\booltrue{@dtl@utf8}}
\newcommand*{\dtldisableUTFviii}{\boolfalse{@dtl@utf8}}
\long\def\long@collect@body#1{%
  \@envbody{\@xp#1\@xp{\the\@envbody}}%
  \edef\process@envbody{\the\@envbody\@nx\end{\@currenvir}}%
  \@envbody\@emptytoks \def\begin@stack{b}%
  \begingroup
  \@xp\let\csname\@currenvir\endcsname\long@collect@@body
  \edef\process@envbody{\@xp\@nx\csname\@currenvir\endcsname}%
  \process@envbody
}
\long\def\long@addto@envbody#1{%
  \toks@{#1}%
  \edef\@dtl@tmp{\the\@envbody\the\toks@}%
  \global\@envbody\@xp{\@dtl@tmp}%
}
\long\def\long@collect@@body#1\end#2{%
  \protected@edef\begin@stack{%
    \long@push@begins#1\begin\end \@xp\@gobble\begin@stack
  }%
  \ifx\@empty\begin@stack
    \endgroup
    \@checkend{#2}%
    \long@addto@envbody{#1}%
  \else
    \long@addto@envbody{#1\end{#2}}%
  \fi
  \process@envbody
}
\long\def\long@push@begins#1\begin#2{%
  \ifx\end#2\else b\@xp\long@push@begins\fi
}
\ExplSyntaxOn
\newcommand \dtl@ifsingle [ 3 ]
 {
  \tl_if_single_token:nTF { #1 } { #2 } { #3 }
 }
\ExplSyntaxOff
\newcount\dtl@codeA
\newcount\dtl@codeB
\newcommand{\@dtl@listelement@outofrange}[1]{%
  \PackageWarning{datatool-base}{List index `\number#1' out of range}%
}
\newcommand{\dtl@sortlist}[2]{%
\def\@dtl@sortedlist{}%
\@for\@dtl@currentrow:=#1\do{%
\expandafter\dtl@insertinto\expandafter
  {\@dtl@currentrow}{\@dtl@sortedlist}{#2}%
\@endforfalse}%
\let#1=\@dtl@sortedlist
}
\newcommand{\dtl@insertinto}[3]{%
  \def\@dtl@newsortedlist{}%
  \@dtl@insertdonefalse
  \@for\dtl@srtelement:=#2\do{%
    \if@dtl@insertdone
      \expandafter\toks@\expandafter{\dtl@srtelement}%
      \edef\@dtl@newstuff{{\the\toks@}}%
    \else
      \expandafter#3\expandafter{\dtl@srtelement}{#1}%
      \ifnum\dtl@sortresult<0\relax
        \expandafter\toks@\expandafter{\dtl@srtelement}%
        \@dtl@toks{#1}%
        \edef\@dtl@newstuff{{\the\@dtl@toks},{\the\toks@}}%
        \@dtl@insertdonetrue
      \else
        \expandafter\toks@\expandafter{\dtl@srtelement}%
        \edef\@dtl@newstuff{{\the\toks@}}%
      \fi
    \fi
    \ifdefempty{\@dtl@newsortedlist}%
    {%
      \expandafter\toks@\expandafter{\@dtl@newstuff}%
      \edef\@dtl@newsortedlist{\the\toks@}%
    }%
    {%
      \expandafter\toks@\expandafter{\@dtl@newsortedlist}%
      \expandafter\@dtl@toks\expandafter{\@dtl@newstuff}%
      \edef\@dtl@newsortedlist{\the\toks@,\the\@dtl@toks}%
    }%
    \@endforfalse
  }%
  \ifdefempty{\@dtl@newsortedlist}%
  {%
    \@dtl@toks{#1}%
    \edef\@dtl@newsortedlist{{\the\@dtl@toks}}%
  }%
  {%
    \if@dtl@insertdone
    \else
      \expandafter\toks@\expandafter{\@dtl@newsortedlist}%
      \@dtl@toks{#1}%
      \edef\@dtl@newsortedlist{\the\toks@,{\the\@dtl@toks}}%
    \fi
  }%
  \global\let#2=\@dtl@newsortedlist
}
\ExplSyntaxOn
\newcommand \dtl@ifsingleorUTFviii [ 3 ]
{
 \tl_if_single_token:nTF { #1 }
 { #2 }
 {
   \ifbool{@dtl@utf8}
   {
     \tl_if_head_is_N_type:nTF { #1 }
     {
       \__datatool_isheadactivechar:w#1\q_stop
       {
         \ifnum\tl_count_tokens:n { #1 } = 2
           \expandafter \__datatool_isheadUTFviiitwooctets \expandafter
           { \__datatool_xpactiveheadchar }
           { #2 }
           { #3 }
         \else
           #3
         \fi
       }
       { #3 }
     }
     { #3 }
   }
   { #3 }
 }
}
\catcode`\@13\relax
\cs_new:Npn \__datatool_isheadactivechar:w #1 #2 \q_stop #3 #4
{
  \tl_if_head_eq_catcode:nNTF { #1 } @
  { \tl_set:No \__datatool_xpactiveheadchar { #1 } #3 }
  { #4 }
}
\catcode`\@11\relax
\cs_new:Npn \__datatool_isheadUTFviiitwooctets #1 #2 #3
{
 \tl_if_head_eq_meaning:nNTF { #1 } \UTFviii@two@octets
 { #2 } { #3 }
}
\ExplSyntaxOff
\def\dtl@if@two@octets#1#2\dtl@end@if@two@octets#3#4{%
  \ifbool{@dtl@utf8}
  {%
    \ifx\UTFviii@two@octets#1\relax
     #3%
    \else
     #4%
    \fi
  }%
  {%
    #4%
  }%
}
\def\dtl@getfirst@UTFviii#1#2#3\end@dtl@getfirst@UTFviii{%
  \def\dtl@first{#1#2}%
  \ifx\@nil#3\relax
    \def\dtl@rest{}%
  \else
    \expandafter\def\expandafter\dtl@rest\expandafter{\@dtl@firsttonil#3}%
  \fi
}
\def\@dtl@firsttonil#1\@nil{#1}
\ExplSyntaxOn
\newcommand{\@dtlgetfirstchar}[3]{
   \tl_if_empty:nTF { #1 }
   { \cs_set:Nn #2 {} \cs_set:Nn #3 {} }
   {
     \tl_if_single_token:nTF { #1 }
     { \cs_set:Nn #2 { #1 } \cs_set:Nn #3 {} }
     {
       \edef #2 { \tl_head:n { #1 } }
       \edef #3 { \tl_tail:n { #1 } }
       \ifbool{@dtl@utf8}
       {
         \tl_if_head_is_N_type:nTF { #1 }
         {
           \__datatool_isheadactivechar:w#1\q_stop
           {
             \expandafter \__datatool_isheadUTFviiitwooctets \expandafter
             { \__datatool_xpactiveheadchar }
             {
               \tl_put_right:Nx #2 { \tl_head:N #3 }
               \edef #3 { \tl_tail:N #3 }
             }
             { }
           }
           { }
         }
         { }
       }
       { }
     }
   }
 }
\ExplSyntaxOff
\def\dtl@getfirst#1#2\end@dtl@getfirst{%
  \dtlgetfirstchar{#1#2}{\dtl@first}{\dtl@rest}%
}%
\ExplSyntaxOn
\newcommand*{\dtl@setcharcode}[2]{%
 \exp_args:Nx \__datatool_setcharcode:nN { \text_purify:n { #1 } } #2
}
\cs_new:Npn \__datatool_setcharcode:nN #1#2
{
  \tl_if_empty:nTF { #1 }
  { #2=-1\relax }
  {
    \tl_if_head_is_space:nTF { #1 }
    { #2=32\relax }
    {
      \tl_if_head_eq_catcode:nNTF { #1 } \relax
      { #2=0\relax }
      {
        \tl_if_single_token:nTF { #1 }
        { \dtlsetcharcode{#1}{#2} }
        {
          \exp_args:Nx \dtlsetcharcode { \tl_head:n { #1 } } {#2}
          \ifbool{@dtl@utf8}
          {
            \ifnum#2>127
              \dtlsetUTFviiicharcode { #1 }{ #2 }
            \fi
          }
          { }
        }
      }
    }
  }
}
\ExplSyntaxOff
\newcommand*{\dtlsetcharcode}[2]{#2=`#1\relax}
\newcommand*{\dtlsetlccharcode}[2]{#2=\lccode`#1\relax}
\newcommand*\dtlsetUTFviiicharcode[2]{\dtlsetdefaultUTFviiicharcode{#1}{#2}}
\newcommand*\dtlsetUTFviiilccharcode[2]{\dtlsetdefaultUTFviiilccharcode{#1}{#2}}
\newcommand*\dtlsetdefaultUTFviiicharcode[2]{%
 \ifboolexpr
 {
      test {\ifstrequal{#1}{À}}
   or test {\ifstrequal{#1}{Á}}
   or test {\ifstrequal{#1}{Á}}
   or test {\ifstrequal{#1}{Ã}}
   or test {\ifstrequal{#1}{Ä}}
 }%
 {%
   #2=`A\relax
 }%
 {%
   \ifstrequal{#1}{Ç}%
   {%
     #2=`C\relax
   }%
   {%
     \ifboolexpr
     {
          test {\ifstrequal{#1}{È}}
       or test {\ifstrequal{#1}{É}}
       or test {\ifstrequal{#1}{Ê}}
       or test {\ifstrequal{#1}{Ë}}
     }%
     {%
       #2=`E\relax
     }%
     {%
       \ifboolexpr
       {
            test {\ifstrequal{#1}{Ì}}
         or test {\ifstrequal{#1}{Í}}
         or test {\ifstrequal{#1}{Î}}
         or test {\ifstrequal{#1}{Ï}}
       }%
       {%
         #2=`I\relax
       }%
       {%
         \ifstrequal{#1}{Ñ}%
         {%
           #2=`N\relax
         }%
         {%
           \ifboolexpr
           {
                test {\ifstrequal{#1}{Ò}}
             or test {\ifstrequal{#1}{Ó}}
             or test {\ifstrequal{#1}{Ô}}
             or test {\ifstrequal{#1}{Õ}}
             or test {\ifstrequal{#1}{Ö}}
           }%
           {%
             #2=`O\relax
           }%
           {%
             \ifboolexpr
             {
                  test {\ifstrequal{#1}{Ù}}
               or test {\ifstrequal{#1}{Ú}}
               or test {\ifstrequal{#1}{Û}}
               or test {\ifstrequal{#1}{Ü}}
             }%
             {%
               #2=`U\relax
             }%
             {%
               \ifstrequal{#1}{Ý}%
               {%
                 #2=`Y\relax
               }%
               {%
                 \ifboolexpr
                 {
                      test {\ifstrequal{#1}{à}}
                   or test {\ifstrequal{#1}{á}}
                   or test {\ifstrequal{#1}{á}}
                   or test {\ifstrequal{#1}{ã}}
                   or test {\ifstrequal{#1}{ä}}
                 }%
                 {%
                   #2=`a\relax
                 }%
                 {%
                   \ifstrequal{#1}{ç}%
                   {%
                     #2=`c\relax
                   }%
                   {%
                     \ifboolexpr
                     {
                          test {\ifstrequal{#1}{è}}
                       or test {\ifstrequal{#1}{é}}
                       or test {\ifstrequal{#1}{ê}}
                       or test {\ifstrequal{#1}{ë}}
                     }%
                     {%
                       #2=`e\relax
                     }%
                     {%
                       \ifboolexpr
                       {
                            test {\ifstrequal{#1}{ì}}
                         or test {\ifstrequal{#1}{í}}
                         or test {\ifstrequal{#1}{î}}
                         or test {\ifstrequal{#1}{ï}}
                       }%
                       {%
                         #2=`i\relax
                       }%
                       {%
                         \ifstrequal{#1}{ñ}%
                         {%
                           #2=`n\relax
                         }%
                         {%
                           \ifboolexpr
                           {
                                test {\ifstrequal{#1}{ò}}
                             or test {\ifstrequal{#1}{ó}}
                             or test {\ifstrequal{#1}{ô}}
                             or test {\ifstrequal{#1}{õ}}
                             or test {\ifstrequal{#1}{ö}}
                           }%
                           {%
                             #2=`o\relax
                           }%
                           {%
                             \ifboolexpr
                             {
                                  test {\ifstrequal{#1}{ù}}
                               or test {\ifstrequal{#1}{ú}}
                               or test {\ifstrequal{#1}{û}}
                               or test {\ifstrequal{#1}{ü}}
                             }%
                             {%
                               #2=`u\relax
                             }%
                             {%
                               \ifstrequal{#1}{ý}%
                               {%
                                 #2=`y\relax
                               }%
                               {%
                                 #2=64\relax
                               }%
                             }%
                           }%
                         }%
                       }%
                     }%
                   }%
                 }%
               }%
             }%
           }%
         }%
       }%
     }%
   }%
 }%
}
\newcommand*\dtlsetdefaultUTFviiilccharcode[2]{%
 \ifboolexpr
 {
      test {\ifstrequal{#1}{à}}
   or test {\ifstrequal{#1}{á}}
   or test {\ifstrequal{#1}{á}}
   or test {\ifstrequal{#1}{ã}}
   or test {\ifstrequal{#1}{ä}}
   or test {\ifstrequal{#1}{À}}
   or test {\ifstrequal{#1}{Á}}
   or test {\ifstrequal{#1}{Á}}
   or test {\ifstrequal{#1}{Ã}}
   or test {\ifstrequal{#1}{Ä}}
 }%
 {%
   #2=`a\relax
 }%
 {%
   \ifboolexpr
   {
        test {\ifstrequal{#1}{ç}}
     or test {\ifstrequal{#1}{Ç}}
   }
   {%
     #2=`c\relax
   }%
   {%
     \ifboolexpr
     {
          test {\ifstrequal{#1}{è}}
       or test {\ifstrequal{#1}{é}}
       or test {\ifstrequal{#1}{ê}}
       or test {\ifstrequal{#1}{ë}}
       or test {\ifstrequal{#1}{È}}
       or test {\ifstrequal{#1}{É}}
       or test {\ifstrequal{#1}{Ê}}
       or test {\ifstrequal{#1}{Ë}}
     }%
     {%
       #2=`e\relax
     }%
     {%
       \ifboolexpr
       {
            test {\ifstrequal{#1}{ì}}
         or test {\ifstrequal{#1}{í}}
         or test {\ifstrequal{#1}{î}}
         or test {\ifstrequal{#1}{ï}}
         or test {\ifstrequal{#1}{Ì}}
         or test {\ifstrequal{#1}{Í}}
         or test {\ifstrequal{#1}{Î}}
         or test {\ifstrequal{#1}{Ï}}
       }%
       {%
         #2=`i\relax
       }%
       {%
         \ifboolexpr
         {
              test {\ifstrequal{#1}{ñ}}
           or test {\ifstrequal{#1}{Ñ}}
         }
         {%
           #2=`n\relax
         }%
         {%
           \ifboolexpr
           {
                test {\ifstrequal{#1}{ò}}
             or test {\ifstrequal{#1}{ó}}
             or test {\ifstrequal{#1}{ô}}
             or test {\ifstrequal{#1}{õ}}
             or test {\ifstrequal{#1}{ö}}
             or test {\ifstrequal{#1}{Ò}}
             or test {\ifstrequal{#1}{Ó}}
             or test {\ifstrequal{#1}{Ô}}
             or test {\ifstrequal{#1}{Õ}}
             or test {\ifstrequal{#1}{Ö}}
           }%
           {%
             #2=`o\relax
           }%
           {%
             \ifboolexpr
             {
                  test {\ifstrequal{#1}{ù}}
               or test {\ifstrequal{#1}{ú}}
               or test {\ifstrequal{#1}{û}}
               or test {\ifstrequal{#1}{ü}}
               or test {\ifstrequal{#1}{Ù}}
               or test {\ifstrequal{#1}{Ú}}
               or test {\ifstrequal{#1}{Û}}
               or test {\ifstrequal{#1}{Ü}}
             }%
             {%
               #2=`u\relax
             }%
             {%
               \ifboolexpr
               {
                    test {\ifstrequal{#1}{ý}}
                 or test {\ifstrequal{#1}{Ý}}
               }%
               {%
                 #2=`y\relax
               }%
               {%
                 #2=96\relax
               }%
             }%
           }%
         }%
       }%
     }%
   }%
 }%
}
\endinput
%%
%% End of file `datatool-base.sty'.
