Skip to Content

strftime

The C / POSIX strftime token grammar — the %-directives shared by C, Python, Ruby, and PHP. Imported from rosetta-date/dialects:

import { convert } from 'rosetta-date' import { moment, strftime } from 'rosetta-date/dialects' convert('%Y-%m-%d', { from: strftime, to: moment }) // 'YYYY-MM-DD' convert('DD/MM/YYYY', { from: moment, to: strftime }) // '%d/%m/%Y'

A directive grammar

strftime belongs to the directive family — the mirror image of the delimited family: every token is introduced by the % marker, and all other text — letters included — is literal. So Y on its own is the literal letter Y; only %Y is the year. Because each directive is self-delimiting, adjacent directives never need a separator (%H%M is unambiguous).

Tokens

Each directive and the canonical field it maps to. For how these compare across dialects, see Token Mapping.

MeaningToken
Calendar year%Y
Calendar year, 2-digit%y
Century, 2-digit%C
ISO week-numbering year%G
ISO week-numbering year, 2-digit%g
Month, 2-digit%m
Month, abbreviated%b
Month, wide%B
Day of month, 2-digit%d
Day of month, space-padded%e
Day of year, 3-digit%j
ISO week of year, 2-digit%V
Weekday, number (locale)%w
Weekday, number (ISO)%u
Weekday, abbreviated%a
Weekday, wide%A
AM/PM%p
AM/PM, lowercase%P
Hour 0–23, 2-digit%H
Hour 0–23, space-padded%k
Hour 1–12, 2-digit%I
Hour 1–12, space-padded%l
Minute%M
Second%S
Time-zone name%Z
Offset, ±hhmm%z
Unix timestamp, seconds%s
Localized date (short)%x
Localized time (with seconds)%X
Localized date + time (full)%c

Composite directives

A handful of directives are composites — a single spelling that stands for a whole sub-pattern. They expand on parse, so converting one out yields the expanded fields:

CompositeExpands to
%T%H:%M:%S
%R%H:%M
%F%Y-%m-%d
%D%m/%d/%y
%r%I:%M:%S %p
%nnewline (\n)
%ttab (\t)

A composite is a parse-time macro, so rendering produces its expansion, never the composite: %T round-trips to %H:%M:%S (identical output, normalized spelling), the same way an alias normalizes — just across several tokens. %n and %t are the same mechanism applied to literal whitespace: they expand to a literal newline/tab, so they normalize to that raw character (the output is identical, only the %n/%t spelling is not preserved).

Padding flags

A directive may carry a glibc padding flag between the % and the field letter, overriding that field’s default padding:

FlagMeaningMaps to
%-Xunpaddedthe field’s numeric style (%-d is a day with no leading zero)
%0Xexplicit zero-paddingthe default 2-digit / 3-digit style
%_Xblank-padding (space)the space-padded qualifier (%_m is a space-padded month)

%-X fills the numeric forms the bare directives lack. %d is always zero-padded, so %-d is how strftime writes a plain numeric day, matching moment’s D and ldml’s d. It is recognized for %-d %-m %-H %-I %-M %-S %-j %-V. %0X is redundant with the bare directive, so it parses but normalizes to %X on render.

%_X is recognized for the same fields (%_d %_m %_H %_I %_M %_S %_j %_V). %_d, %_H, and %_I are the flag form of the %e/%k/%l presets and normalize to them. The rest extend blank-padding to fields with no preset letter. No other built-in dialect renders a blank-padded field, so converting one out falls to the unsupported-token policy.

Aliases

%h is parsed as an abbreviated month, the same as %b; it normalizes to %b when rendered.

Caveats

  • %e / %k / %l are blank-padded. No other built-in dialect has a blank-padded form, so converting one to a dialect that lacks it has no clean target — it falls to the unsupported-token policy. A dialect that does define the blank-padded form round-trips cleanly.
  • %C (century) has no built-in counterpart. No other built-in dialect renders a century, so converting %C out has no clean target — it falls to the unsupported-token policy. A dialect that defines the century round-trips cleanly.
  • The locale presets (%c / %x / %X) map at a fixed width. POSIX leaves their exact form to the locale, so the date/time-style mapping is a reasonable approximation, not an exact one.
Last updated on