-
-
Notifications
You must be signed in to change notification settings - Fork 899
DateTime
Print the current date and time
| Module type | datetime |
| Default order | 53 — only used by --gen-config
|
| Module source | src/modules/datetime/datetime.c |
| Detection source | — (src/common/time.h for the clock) |
The registry name is DateTime — that is what --list-modules and this page's file name use, and what
a config's type has to say. The key it prints is the localised display name, Date & Time in
English.
Prints the local date and time at the moment the module runs:
Date & Time: 2026-01-01 09:00:00
That is ISO 8601 with a space instead of T, produced by strftime("%F %T"). The module reads the
wall clock directly — there is no caching layer involved, so with --dynamic-interval each round
prints a fresh timestamp.
With a format you can build any shape you like from 24 variables:
Date & Time: 2026-01-01 09:00:00 +0800
| Platform | Implementation | Notes |
|---|---|---|
| Everywhere | src/modules/datetime/datetime.c |
Platform independent — no detection layer |
The clock comes from ffTimeGetNow(). Only the implementation of that helper varies:
clock_gettime(CLOCK_REALTIME) on POSIX, the shared user-data KSYSTEM_TIME on Windows,
real_time_clock_usecs() on Haiku. Everything downstream is standard C localtime() + strftime(),
so the output is identical on every platform.
| Option | Type | Default | Description |
|---|---|---|---|
format |
string | – | The output format; empty means the default YYYY-MM-DD HH:MM:SS
|
key |
string | – | Replaces Date & Time; a single space hides the key and the separator |
keyColor |
color | – | Overrides display.color.keys
|
keyIcon |
string | – | Used when display.key.type includes the icon bit |
keyWidth |
integer | – | Overrides display.key.width
|
outputColor |
color | – | Overrides display.color.output
|
condition |
object | – | See Global |
There is no timezone, no locale and no clock-source option: the module uses the process's local time
and the process's LC_TIME. An empty format string ("" or null) falls back to the default
output rather than printing an empty line, because the module only takes the format path when the
string is non-empty.
fastfetch -h datetime-format prints the list, and the module is one of the few whose -h output is
architecture-independent. The example column below is the timestamp the source file itself uses as
its reference — 2022-02-21, a Monday, local time 15:18:37:
| Variable | Description | For 2022-02-21 15:18:37 |
|---|---|---|
{year} |
Year | 2022 |
{year-short} |
Last two digits of year | 22 |
{month} |
Month | 2 |
{month-pretty} |
Month with leading zero | 02 |
{month-name} |
Month name | February |
{month-name-short} |
Month name short | Feb |
{week} |
Week number on year | 8 |
{weekday} |
Weekday | Monday |
{weekday-short} |
Weekday short | Mon |
{day-in-year} |
Day in year | 52 |
{day-in-month} |
Day in month | 21 |
{day-in-week} |
Day in week | 1 |
{day-pretty} |
Day in month with leading zero | 21 |
{hour} |
Hour | 15 |
{hour-pretty} |
Hour with leading zero | 15 |
{hour-12} |
Hour 12h format | 3 |
{hour-12-pretty} |
Hour 12h format with leading zero | 03 |
{minute} |
Minute | 18 |
{minute-pretty} |
Minute with leading zero | 18 |
{second} |
Second | 37 |
{second-pretty} |
Second with leading zero | 37 |
{am-pm} |
AM or PM | PM |
{offset-from-utc} |
Offset from UTC in the ISO 8601 format | depends on the timezone, e.g. +0800
|
{timezone-name} |
Locale-dependent timezone name or abbreviation | depends on the timezone, e.g. CST
|
All 24 are output-format only; none of them is available in the key. The * markers that -h prints
for some modules do not appear here.
{ "type": "DateTime", "result": "2026-01-01T09:00:00.123+0800" }The result is a full ISO 8601 timestamp with milliseconds and a numeric UTC offset, produced by
ffTimeToFullStr() — not the module's text output and not affected by format. The value is
sampled when the JSON document is written, which is a separate ffTimeGetNow() call from the one the
text output used, so the two can differ by a few milliseconds (or, in --format json runs, be the
same instant only by luck).
European day-first format:
{ "type": "datetime", "format": "{day-pretty}.{month-pretty}.{year}" }A 12-hour clock with an explicit zone:
{ "type": "datetime", "format": "{hour-12}:{minute-pretty}:{second-pretty} {am-pm} ({timezone-name})" }Week and day-of-year, for a log header:
{ "type": "datetime", "format": "week {week}, day {day-in-year} of {year}" }A timestamp that is part of a sentence, with a renamed key:
{ "type": "datetime", "key": "Now", "format": "{weekday}, {month-name} {day-in-month}" }Now: Monday, February 21
Dropping the key entirely:
{ "type": "datetime", "key": " " }-
{week}is not an ISO 8601 week number. It istm_yday / 7 + 1, i.e. a week counter that starts on 1 January and ignores both the weekday and the year boundary. On 2026-09-22 it prints38wheredate +%V(and every ISO calendar) says39. -
{day-in-week}numbers Monday as 1 and Sunday as 7, which differs from C'stm_wday(Sunday 0) and from the%u/%wdistinction that trips people up elsewhere. -
Month and weekday names follow
LC_TIME. The module never callssetlocale(LC_ALL, ""), butsrc/common/impl/init.cdoes callsetlocale(LC_TIME, ""), so{month-name},{month-name-short},{weekday},{weekday-short}and{am-pm}are localised — withLC_TIME=de_DE.UTF-8the same run printsDienstagwhere the C locale printsTuesday. Note that onlyLC_TIMEis consulted;LANGalone has no effect unless it selects the time category. -
An unknown variable is printed literally and silently.
format: "{nope}"outputs{nope}with no warning, even withdisplay.showErrorsenabled, so a typo in a long format string is easy to miss. -
Only
{{is an escape.{{renders a literal{;}and}}are passed through as-is, soformat: "{{year}}"prints{year}}rather than{year}. There is no way to write{…}around a variable without the stray closing brace. -
An unknown key is reported before the timestamp. The parse pass runs first, so
{ "type": "datetime", "nope": 1 }printsDate & Time: Unknown JSON key nope Date & Time: 2022-02-21 15:18:37The warning only shows up when
display.showErrorsis true. -
formatdoes not change the JSON output.--format jsonalways reports the full ISO timestamp inresult, so a config that formats the text output will disagree with the JSON. If a consumer needs the formatted string, read the text output or use acommandmodule. -
The module has no fixed granularity option.
{second}is as fine as it gets; there is no sub-second variable, andresultin JSON is the only field that carries milliseconds.
ffPrintDateTime() (src/modules/datetime/datetime.c) takes the clock in milliseconds, converts it
to time_t and runs localtime(). From there it takes one of two paths:
-
No
format: a singlestrftime(buffer, sizeof buffer, "%F %T", tm)— the ISO date, a space, the 24-hour time — written after the key withputs(). Astrftime()failure (buffer too small, which cannot happen for this pattern) reportsstrftime() failedand returnsfalse. -
With
format:printDateTimeFormat()fills anFFDateTimeResulton the stack field by field and hands all 24 values toFF_PRINT_FORMAT_CHECKED.
The provenance of the fields is mixed, which is worth knowing when one of them looks off: {year},
{month}, {hour}, {minute}, {second} and the derived {year-short}, {week},
{day-in-year}, {day-in-week} are arithmetic on struct tm, while {month-pretty},
{month-name}, {month-name-short}, {weekday}, {weekday-short}, {day-pretty},
{hour-pretty}, {hour-12-pretty}, {minute-pretty}, {second-pretty}, {offset-from-utc},
{timezone-name} and {am-pm} are strftime() output. The one place where the two families could
have disagreed — the 12-hour clock, where strftime("%I") maps midnight and noon to 12 while
tm_hour % 12 maps them to 0 — is reconciled with result.hour12 = result.hour % 12 ?: 12: the
GNU ?: extension, used throughout the codebase, yields the right-hand side when the remainder is
zero.
ffGenerateDateTimeJsonResult() does not touch the options at all: it writes ffTimeToFullStr( ffTimeGetNow()) into result, using yyjson_mut_obj_add_strcpy() so the static buffer the helper
returns is copied rather than aliased.
{ "type": "datetime", "format": "{year}-{month-pretty}-{day-pretty} {hour-pretty}:{minute-pretty}:{second-pretty} {offset-from-utc}" }