I wish this were generally possible, but POSIX locale categories have only so many formats, most of which correspond to more historic formats/scenarios, but if you get d_fmt
and t_fmt
right, things seem to improve generally. Some time ago, I’ve created one that comes as suitably close to a full ISO 8601 locale as possible on a Debian GNU/Linux (glibc) system.
The way to do this correctly is not entirely trivial. You’ve got to create a full locale of your own, even if you only use it for LC_CTIME
. You’ve got to edit some values manually, but only for date/time; you can, thankfully, just include the defaults for the others.
I’ve done this for de_DE
(or rather de_DE.UTF-8
) as base locale. The resulting locale definition file looks as follows (but read on below):
comment_char %
escape_char /
% $MirOS: contrib/hosted/tg/deb/de_DE@iso8601,v 1.1 2021/04/05 21:13:47 tg Exp $
%-
% This is an alternative locale definition file, GNU libc compatible,
% which provides an LC_TIME category that is mostly conformant to DIN
% 5008 and ISO 8601. It uses %-d as an extension (use the alternative
% date_fmt if not supported); the timezone offset is rendered without
% colon due to https://bugs.debian.org/799476 which is not proper but
% the best we can currently do; date +'%Y-%m-%dT%H:%M:%S%:z' works.
%
% Install with:
% $ sudo localedef -i de_DE@iso8601 -f UTF-8 -c de_DE.UTF-8@iso8601
% glibc
LC_IDENTIFICATION
title "German locale for Germany with DIN ISO 8601 date/time format"
source "BOSng"
contact "mirabilos"
language "German"
territory "Germany"
revision "1.0"
date "2021-04-04"
category "i18n:2012";LC_IDENTIFICATION
category "i18n:2012";LC_CTYPE
category "i18n:2012";LC_COLLATE
category "i18n:2012";LC_TIME
category "i18n:2012";LC_NUMERIC
category "i18n:2012";LC_MONETARY
category "i18n:2012";LC_MESSAGES
category "i18n:2012";LC_PAPER
category "i18n:2012";LC_NAME
category "i18n:2012";LC_ADDRESS
category "i18n:2012";LC_TELEPHONE
category "i18n:2012";LC_MEASUREMENT
END LC_IDENTIFICATION
% POSIX
LC_CTYPE
copy "de_DE"
END LC_CTYPE
% POSIX
LC_COLLATE
copy "de_DE"
END LC_COLLATE
% POSIX
LC_TIME
abday "So";"Mo";"Di";"Mi";"Do";"Fr";"Sa"
day "Sonntag";/
"Montag";/
"Dienstag";/
"Mittwoch";/
"Donnerstag";/
"Freitag";/
"Samstag"
abmon "Jan.";/
"Feb.";/
"M<U00E4>rz";/
"Apr.";/
"Mai";/
"Juni";/
"Juli";/
"Aug.";/
"Sep.";/
"Okt.";/
"Nov.";/
"Dez."
mon "Januar";/
"Februar";/
"M<U00E4>rz";/
"April";/
"Mai";/
"Juni";/
"Juli";/
"August";/
"September";/
"Oktober";/
"November";/
"Dezember"
% this *should* be the first line; GNU cannot even do its own extensions right
%d_t_fmt "%Y-%m-%dT%H:%M:%S%:z (%Z), %G-W%V-%u (%a)"
d_t_fmt "%Y-%m-%dT%H:%M:%S%z (%Z), %G-W%V-%u (%a)"
d_fmt "%Y-%m-%d"
t_fmt "%H:%M:%S"
am_pm "";""
t_fmt_ampm ""
week 7;19971130;4
first_weekday 2
first_workday 2
cal_direction 1
% use the second line if %-d does not work for you
date_fmt "%A, %-d. %B %Y, %H:%M:%S %Z"
%date_fmt "%a %Y-%m-%d, %H:%M:%S %Z"
END LC_TIME
% POSIX
LC_NUMERIC
copy "de_DE"
END LC_NUMERIC
% POSIX
LC_MONETARY
copy "de_DE"
END LC_MONETARY
% POSIX
LC_MESSAGES
copy "de_DE"
END LC_MESSAGES
% glibc
LC_PAPER
copy "de_DE"
END LC_PAPER
% glibc
LC_NAME
copy "de_DE"
END LC_NAME
% glibc
LC_ADDRESS
copy "de_DE"
END LC_ADDRESS
% glibc
LC_TELEPHONE
copy "de_DE"
END LC_TELEPHONE
% glibc
LC_MEASUREMENT
copy "de_DE"
END LC_MEASUREMENT
If you wish to do this for some other locale, such as es_ES
, you’ll need to make the following modifications to it (in my example, I’m unashamedly copying from glibc localedata/locales/es_ES
):
- change
title
, language
and territory
in the head (and the others, source
, contact
, revision
and date
as well while there) to suitable values (e.g. language Spanish, territory Spain)
- if not using glibc, you might need to remove a few entries commented with
% glibc
(such as LC_NAME
), but don’t if your system does support them (the -c
flag to localedef
should also make it accept that, but YMMV)
- change all the
copy "de_DE"
lines (there’s a lot of them!) to copy "es_ES"
- change
abday
to a list of weekday name abbreviations (starting with Sunday), e.g. "dom";"lun";"mar";"mi<U00E9>";"jue";"vie";"s<U00E1>b"
(here you have also the chance to use 2‑letter or 3‑letter abbreviations to suit your taste)
- change
day
to a list of full weekday names, e.g. "domingo";"lunes";"martes";"mi<U00E9>rcoles";"jueves";"viernes";"s<U00E1>bado"
- change
abmon
and mon
to abbreviated and full month names ("ene";"feb";…
and "enero";"febrero";…
)
- save as
es_ES@iso8601
- change the comment near the beginning appropriately, the compile command is now
sudo localedef -i es_ES@iso8601 -f UTF-8 -c es_ES.UTF-8@iso8601
Then, you can export LC_TIME=es_ES.UTF-8@iso8601
to use this. Alternatively, if you do not have superuser priviliegues, you can use LOCPATH
(or MUSL_LOCPATH
) to install the locale data locally; for glibc, this looks as follows:
mkdir -p ~/.local/locpath
localedef -i es_ES@iso8601 -f UTF-8 -c ~/.local/locpath/es_ES.UTF-8@iso8601
Thereafter, export LOCPATH=$HOME/.local/locpath
and LC_TIME=es_ES.UTF-8@iso8601
to use.
For other languages, countries, encodings, etc. proceed correspondingly.
In theory, you can also set LC_ALL
to it, since it copies the remaining locale category definitions from the corresponding master file for the chosen locale.