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'- Spec: POSIX
strftime - Family:
directive— every token is introduced by% - Literals: any non-directive text is literal verbatim; a literal
%is%%— see Literals & Adjacency
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.
| Meaning | Token |
|---|---|
| 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:
| Composite | Expands to |
|---|---|
%T | %H:%M:%S |
%R | %H:%M |
%F | %Y-%m-%d |
%D | %m/%d/%y |
%r | %I:%M:%S %p |
%n | newline (\n) |
%t | tab (\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:
| Flag | Meaning | Maps to |
|---|---|---|
%-X | unpadded | the field’s numeric style (%-d is a day with no leading zero) |
%0X | explicit zero-padding | the default 2-digit / 3-digit style |
%_X | blank-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/%lare 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%Cout 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.