Appendix B — Datetime formatting patterns

The fmt_datetime() function supports two powerful systems for custom datetime formatting: CLDR datetime patterns and strptime format codes. This appendix provides a comprehensive reference for both.

B.1 CLDR datetime patterns

The CLDR (Common Locale Data Repository) datetime pattern system allows you to create highly customized, locale-aware datetime output. A pattern string consists of two types of elements:

Pattern fields: one or more repetitions of a specific pattern character (from the reserved sets A–Z and a–z). These fields are replaced with date and time data when formatting.

Literal text: any characters outside the reserved sets, including spaces and punctuation. Text between single vertical quotes (e.g., 'at') is output verbatim. Use two adjacent single quotes ('') to represent a literal single quote.

B.1.1 Pattern examples

The following examples use the datetime "2018-07-04T22:05:09.2358(America/Vancouver)":

Pattern Output
“mm/dd/y” 05/04/2018
“EEEE, MMMM d, y” Wednesday, July 4, 2018
“MMM d E” Jul 4 Wed
“HH:mm” 22:05
“h:mm a” 10:05 PM
“EEEE, MMMM d, y ‘at’ h:mm a” Wednesday, July 4, 2018 at 10:05 PM

B.2 Year patterns

B.2.1 Calendar year (y)

The calendar year is always numeric. The field length specifies the minimum number of digits, zero-padded as necessary. The exception is "yy", which yields only the two low-order digits.

Pattern Output Notes
“y” 2018 Full year
“yy” 18 Two-digit year
“yyy” to “yyyyyyyyy” 2018 to 000002018 Zero-padded to width

The two-digit year "yy" persists on receipts, expiration dates, and informal documents where the century is obvious from context. The Y2K episode demonstrated the hazards of truncating years in systems that store or compare dates, but for display purposes the two-digit form remains acceptable when ambiguity is impossible. For table formatting, the full year "y" is nearly always the better default: it costs only two extra characters and eliminates any chance of misinterpretation.

B.2.2 Week-based year (Y)

The year in week-based calendars, where year transitions occur on week boundaries. This may differ from calendar year "y" near year transitions. Used with pattern "w" for ISO 8601 week dates.

Pattern Output Notes
“Y” 2018 Full year
“YY” 18 Two-digit year
“YYY” to “YYYYYYYYY” 2018 to 000002018 Zero-padded to width

The week-based year becomes important at the seams between calendar years. A date like December 31, 2018 might belong to ISO week 1 of 2019, meaning "Y" would return 2019 while "y" returns 2018. This discrepancy surprises people who have never encountered ISO week numbering, and it has caused real bugs in reporting systems that mixed the two year types. Unless you are specifically constructing ISO week dates (common in European business reporting and manufacturing logistics), use "y" for the calendar year and leave "Y" alone.

B.3 Quarter patterns

B.3.1 Quarter of year (Q and q)

Quarter names vary by width and context. The formatting form (Q) is used within complete date strings; the standalone form (q) is for independent use (e.g., calendar headers).

Pattern Output Notes
“Q” / “q” 3 Numeric, one digit
“QQ” / “qq” 03 Numeric, two digits (zero-padded)
“QQQ” / “qqq” Q3 Abbreviated
“QQQQ” / “qqqq” 3rd quarter Wide
“QQQQQ” / “qqqqq” 3 Narrow

Quarters appear throughout financial reporting, where earnings releases, regulatory filings, and fiscal planning all organize time into three-month blocks. A table of quarterly revenue figures will likely reach for "QQQ" (yielding “Q3”) or "QQQQ" (yielding “3rd quarter”) depending on the desired formality. The distinction between formatting and standalone forms matters primarily in languages where grammatical case changes with context. In Russian or Czech, the standalone form of “3rd quarter” takes a different grammatical ending than the same expression embedded within a complete date. English speakers will never notice the difference, but international applications should use the appropriate form.

B.4 Month patterns

B.4.1 Month (M and L)

Month names vary by width and context. The formatting form (M) is used within complete date strings; the standalone form (L) is for independent use.

Pattern Output Notes
“M” / “L” 7 Numeric, minimum digits
“MM” / “LL” 07 Numeric, two digits (zero-padded)
“MMM” / “LLL” Jul Abbreviated
“MMMM” / “LLLL” July Wide
“MMMMM” / “LLLLL” J Narrow

The formatting ("M") and standalone ("L") distinction carries the same linguistic motivation as quarters, and the same practical advice applies: use "M" when the month appears within a date expression and "L" when it appears as an isolated label (a calendar column header, a dropdown menu, a table grouping row). In English the two produce identical output. In Finnish, Ukrainian, and several other languages, the standalone form uses the nominative case while the formatting form uses the genitive or partitive case, producing visibly different text.

The narrow form ("MMMMM" or "LLLLL") reduces each month to a single letter. This creates obvious ambiguity (“J” could mean January, June, or July) so narrow months are suitable only when space is extremely constrained and the surrounding context resolves the ambiguity, such as tiny calendar grid headers where the column position implies the month.

B.5 Week patterns

B.5.1 Week of year (w)

Values range from 1 to 53. Week 1 is the first week containing the minimum number of days specified for that locale.

Pattern Output Notes
“w” 27 Minimum digits
“ww” 27 Two digits (zero-padded)

B.5.2 Week of month (W)

Values range from 1 to 5. The first day of each month is always in week 1.

Pattern Output
“W” 1

Week numbering varies across locales more than most people realize. ISO 8601 defines week 1 as the week containing the first Thursday of the year, with weeks starting on Monday. The United States traditionally starts weeks on Sunday and defines week 1 as the week containing January 1. These differences mean the same date can fall in different numbered weeks depending on locale settings. The "w" pattern respects the locale configuration, which is usually the right behavior for audience-facing output. For data interchange where consistency matters regardless of locale, pair "Y" (week-based year) with "w" (week number) to produce unambiguous ISO 8601 week dates.

B.6 Day patterns

B.6.1 Day of month (d)

The day of the month, from 1 to 31.

Pattern Output Notes
“d” 4 Minimum digits
“dd” 04 Two digits (zero-padded)

B.6.2 Day of year (D)

Values range from 1 to 365 (or 366 in leap years). The field length specifies minimum digits with zero-padding.

Pattern Output Notes
“D” 185 Minimum digits
“DD” 185 Zero-padded to 2
“DDD” 185 Zero-padded to 3

B.6.3 Day of week in month (F)

Returns the occurrence number of the weekday within the month (e.g., “2nd Monday in March”). Days 1–7 yield 1, days 8–14 yield 2, and so on.

Pattern Output
“F” 1

B.6.4 Modified Julian date (g)

The number of days since midnight November 17, 1858. Width specifies minimum digits with zero-padding.

Pattern Output
“g” to “ggggggggg” 58303 to 000058303

These day-counting patterns serve specialized communities. Day of year ("D") appears in agriculture (growing degree day calculations reference the ordinal date), military communications (the Julian date format YYDDD remains standard in some branches), and satellite operations (orbital computations often index by day of year). Day of week in month ("F") powers expressions like “the second Tuesday in November”, the pattern behind recurring event scheduling and holiday calculations (U.S. Thanksgiving is the fourth Thursday in November). The modified Julian date ("g") serves astronomy, geodesy, and satellite tracking, where a continuous day count avoids the headaches of leap years, month boundaries, and historical calendar reforms. Most table formatting will never need these patterns, but when the domain calls for them, nothing else substitutes.

B.7 Weekday patterns

B.7.1 Day of week name (E)

The name of the day of the week, available in four different widths.

Pattern Output Notes
“E”, “EE”, or “EEE” Wed Abbreviated
“EEEE” Wednesday Wide
“EEEEE” W Narrow
“EEEEEE” We Short

Choosing the right weekday width depends on available space and surrounding context. The abbreviated form ("E" through "EEE", yielding “Wed”) suits column headers in weekly schedules and compact table layouts. The wide form ("EEEE", yielding “Wednesday”) reads naturally in full sentences and spacious table cells. The narrow form ("EEEEE", yielding “W”) works only in highly constrained spaces like small calendar grids, and even then it creates ambiguity: Tuesday and Thursday both reduce to “T” in English. The short form ("EEEEEE", yielding “We”) offers a useful middle ground: two letters provide enough distinction to eliminate ambiguity while fitting tighter layouts than the three-letter abbreviation.

B.8 Period patterns

B.8.1 AM/PM (a)

Provides AM/PM and the narrow "a" and "p" forms.

Pattern Output Notes
“a”, “aa”, or “aaa” PM Abbreviated
“aaaa” PM Wide
“aaaaa” p Narrow

B.8.2 AM/PM with noon and midnight (b)

Provides AM/PM plus special forms for exactly noon (12:00) and midnight (00:00).

Pattern At Midnight At Noon Notes
“b”, “bb”, or “bbb” midnight noon Abbreviated
“bbbb” midnight noon Wide
“bbbbb” mi n Narrow

B.8.3 Flexible day periods (B)

Locale-specific phrases like “in the afternoon” or “in the evening”.

Pattern Morning (08:30) Afternoon (14:00) Notes
“B”, “BB”, or “BBB” in the morning in the afternoon Abbreviated
“BBBB” in the morning in the afternoon Wide
“BBBBB” in the morning in the afternoon Narrow

The progression from "a" through "b" to "B" reflects increasing sophistication in describing the human experience of time. The simple AM/PM distinction ("a") suffices for most English-language contexts but perpetuates the confusion of whether 12:00 AM means noon or midnight (a question that has generated an astonishing amount of debate for something with a definitive answer: midnight). The noon-and-midnight-aware pattern ("b") resolves this by substituting the actual words “noon” and “midnight” at those exact moments, which is unambiguous. The flexible day periods ("B") go further still, replacing the binary AM/PM split with locale-specific phrases that describe parts of the day as people actually experience them. Japanese distinguishes early morning, morning, afternoon, evening, and night with specific terms. Chinese uses different divisions than English. Using "B" produces output that sounds natural to speakers of each language, rather than imposing the English-centric AM/PM convention on everyone.

B.9 Hour, minute, and second patterns

B.9.1 Hour 0–23 (H)

Standard 24-hour clock where midnight is 00:00.

Pattern Output Notes
“H” 8 Minimum digits
“HH” 08 Two digits (zero-padded)

B.9.2 Hour 1–12 (h)

Standard 12-hour clock where midnight is 12:00.

Pattern Output Notes
“h” 8 Minimum digits
“hh” 08 Two digits (zero-padded)

B.9.3 Hour 1–24 (k)

Less common 24-hour clock where midnight is 24:00.

Pattern Output Notes
“k” 9 Minimum digits
“kk” 09 Two digits (zero-padded)

B.9.4 Hour 0–11 (K)

Less common 12-hour clock where midnight is 00:00.

Pattern Output Notes
“K” 7 Minimum digits
“KK” 07 Two digits (zero-padded)

These four hour systems exist because different cultures and technical domains have historically told time in different ways. The 24-hour clock ("H", ranging from 0 to 23) dominates in continental Europe, military and aviation contexts, and ISO 8601 timestamps; it is unambiguous and needs no AM/PM qualifier. The 12-hour clock ("h", ranging from 1 to 12) pairs with AM/PM and prevails in everyday usage across the United States, the United Kingdom, India, and several other countries. The 1–24 clock ("k", where midnight is 24:00 rather than 0:00) appears in some Japanese broadcasting schedules, where a program airing at “25:00” means 1:00 AM, a convention that avoids splitting a single evening’s programming across two calendar dates. The 0–11 clock ("K") is largely an implementation artifact that rarely appears in user-facing output. For most table work, "HH:mm" (24-hour) or "h:mm a" (12-hour with AM/PM) covers what you need; choose based on your audience’s conventions.

B.9.5 Minute (m)

This is just the time part for the minute of the hour.

Pattern Output Notes
“m” 5 Minimum digits
“mm” 05 Two digits (zero-padded)

B.9.6 Second (s)

Provides solely the time part for the second of the minute.

Pattern Output Notes
“s” 9 Minimum digits
“ss” 09 Two digits (zero-padded)

B.9.7 Fractional second (S)

Truncates to the specified width. Add a decimal point manually to the pattern if needed.

Pattern Output
“S” to “SSSSSSSSS” 2 to 235000000

B.9.8 Milliseconds in day (A)

The number of milliseconds since midnight (max 86,400,000).

Pattern Output
“A” to “AAAAAAAAA” 439722 to 000439722

B.10 Era patterns

B.10.1 Era designator (G)

The Gregorian calendar has two eras: AD (Anno Domini) and BC (Before Christ).

Pattern Output Notes
“G”, “GG”, or “GGG” AD Abbreviated
“GGGG” Anno Domini Wide
“GGGGG” A Narrow

Era designators are unnecessary for the vast majority of modern dates but become essential in two situations. First, historical datasets extending before the Common Era need some way to distinguish 44 BC from AD 44. Second, certain locales use non-Gregorian calendar eras. The Japanese calendar counts years from the accession of each emperor: 2024 is Reiwa 6 (令和6年). When formatting dates for Japanese users, the era designator conveys information that the Gregorian year alone cannot. The CLDR system handles this transparently: the same "G" pattern produces “AD” in English and the appropriate era name in Japanese, adapting automatically to the configured locale.

B.11 Time zone patterns

B.11.1 Specific non-location format (z)

User-friendly time zone names. Falls back to localized GMT format if unavailable.

Pattern Output Notes
“z”, “zz”, or “zzz” PDT Short specific
“zzzz” Pacific Daylight Time Long specific

B.11.2 Common UTC offset formats (Z)

ISO 8601 and localized GMT offset formats for time zones.

Pattern Output Notes
“Z”, “ZZ”, or “ZZZ” -0700 ISO 8601 basic format
“ZZZZ” GMT-7:00 Long localized GMT format
“ZZZZZ” -07:00 ISO 8601 extended format

B.11.3 Localized GMT formats (O)

GMT-based offset formats that adapt to the user’s locale.

Pattern Output Notes
“O” GMT-7 Short (omits zero minutes)
“OOOO” GMT-07:00 Long (always includes minutes)

B.11.4 Generic non-location format (v)

Useful for recurring events where specific daylight/standard distinction isn’t needed.

Pattern Output Notes
“v” PT Short generic
“vvvv” Pacific Time Long generic

B.11.5 Time zone ID and exemplar city (V)

Formats that display time zone identifiers and representative cities.

Pattern Output Notes
“V” cavan Short time zone ID
“VV” America/Vancouver Long time zone ID
“VVV” Vancouver Exemplar city
“VVVV” Vancouver Time Generic location format

B.11.6 ISO 8601 formats with Z for UTC (X)

Uses Z when the local time offset is 0.

Pattern Output Notes
“X” -07 Basic (h, optional m)
“XX” -0700 Basic (h & m)
“XXX” -07:00 Extended (h & m)
“XXXX” -0700 Basic (h, m, optional s)
“XXXXX” -07:00 Extended (h, m, optional s)

B.11.7 ISO 8601 formats without Z (x)

Same as X patterns but never uses Z for UTC.

Pattern Output Notes
“x” -07 Basic (h, optional m)
“xx” -0700 Basic (h & m)
“xxx” -07:00 Extended (h & m)
“xxxx” -0700 Basic (h, m, optional s)
“xxxxx” -07:00 Extended (h, m, optional s)

Choosing the right time zone format depends on who will read the output and what they need to do with it. For human readers needing to know the local time, the specific non-location format ("z", producing “PDT” or “Pacific Daylight Time”) communicates clearly. For recurring events like weekly meetings, the generic format ("v", producing “Pacific Time”) avoids the distraction of specifying daylight or standard time, since the meeting happens regardless of which is in effect. For machine-readable logs, API timestamps, and data interchange, the ISO 8601 formats ("X" or "x") provide unambiguous numeric offsets that any parser can interpret. The location format ("V", producing “America/Vancouver”) is the most robust for storage and computation because it encodes the complete time zone rules including historical changes, but it may confuse non-technical readers. In tables, the short specific format ("z") usually strikes the best balance between precision and readability.

B.12 strptime format codes

As an alternative to CLDR patterns, you can use strptime-style format codes. Each code starts with % and represents a specific date or time element.

B.12.1 strptime examples

The following examples use the datetime "2015-06-08 23:05:37.48":

Pattern Output
“%m/%d/%Y” 06/08/2015
“%A, %B %e, %Y” Monday, June 8, 2015
“%b %e %a” Jun 8 Mon
“%H:%M” 23:05
“%I:%M %p” 11:05 pm
“%A, %B %e, %Y at %I:%M %p” Monday, June 8, 2015 at 11:05 pm

The strptime system predates CLDR by decades, originating in the C programming language’s standard library and inherited by POSIX, Perl, Python, Ruby, and R. If you have written strftime() or strptime() calls in any of these languages, the %-prefixed codes will feel immediately familiar. The CLDR pattern system is more expressive (it supports locale-aware output, standalone versus formatting forms, and flexible day periods that strptime cannot represent) but strptime is simpler and sufficient for many common formatting tasks.

When choosing between the two systems in gt, consider your requirements. If you need locale-sensitive output (month names in French, day periods in Japanese, grammatically correct quarter labels in Czech), use CLDR patterns. If you are formatting dates for a primarily English-speaking audience and want the comfort of "%Y-%m-%d" syntax, strptime works perfectly. The two systems produce identical results for straightforward formats like ISO 8601 dates; they diverge only when locale-specific behavior enters the picture.

B.12.2 Date codes

Format codes for year, month, day, and week components.

Code Output Description
“%a” Mon Abbreviated day of week
“%A” Monday Full day of week
“%w” 1 Day of week (0–6; Sunday = 0)
“%u” 1 Day of week (1–7; Monday = 1)
“%y” 15 Two-digit year
“%Y” 2015 Full year
“%b” Jun Abbreviated month
“%B” June Full month
“%m” 06 Month number (zero-padded)
“%d” 08 Day number (zero-padded)
“%e” 8 Day number (no padding)
“%j” 159 Day of year (zero-padded)
“%W” 23 Week number
“%V” 24 ISO 8601 week number
“%C” 20 Century number

B.12.3 Time codes

Format codes for hour, minute, second, and AM/PM components.

Code Output Description
“%H” 23 Hour (24-hour clock)
“%I” 11 Hour (12-hour clock)
“%M” 05 Minute
“%S” 37 Second
“%OS3” 37.480 Seconds with decimals (3 places shown)
“%p” pm AM/PM indicator

B.12.4 Other codes

Additional format codes for time zones and special characters.

Code Output Description
“%z” +0000 Signed time zone offset
“%F” 2015-06-08 ISO 8601 date format
“%%” % Literal percent sign