| 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 |
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)":
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 |