Skip to content

Instantly share code, notes, and snippets.

@hmhmsh
Last active January 29, 2021 07:50
Show Gist options
  • Save hmhmsh/9dda2381be2cab92828fe8b65fa86942 to your computer and use it in GitHub Desktop.
Save hmhmsh/9dda2381be2cab92828fe8b65fa86942 to your computer and use it in GitHub Desktop.
Template enum for DateFormatter
extension DateFormatter {
/**
SeeAlso:
[Date Field Symbol Table](http://www.unicode.org/reports/tr35/tr35-25.html#Date_Field_Symbol_Table)
*/
enum Template: String, CaseIterable {
/**
Era - Replaced with the Era string for the current date. One to three letters for the abbreviated form, four letters for the long form, five for the narrow form.
*/
case G
/**
Year. Normally the length specifies the padding, but for two letters it also specifies the maximum length.
*/
case y
/**
Year (in "Week of Year" based calendars). Normally the length specifies the padding, but for two letters it also specifies the maximum length. This year designation is used in ISO year-week calendar as defined by ISO 8601, but can be used in non-Gregorian based calendar systems where week date processing is desired. May not always be the same value as calendar year.
*/
case Y
/**
Extended year. This is a single number designating the year of this calendar system, encompassing all supra-year fields. For example, for the Julian calendar system, year numbers are positive, with an era of BCE or CE. An extended year value for the Julian calendar system assigns positive values to CE years and negative values to BCE years, with 1 BCE being year 0.
*/
case u
/**
Cyclic year name. Calendars such as the Chinese lunar calendar (and related calendars) and the Hindu calendars use 60-year cycles of year names. Use one through three letters for the abbreviated name, four for the full name, or five for the narrow name (currently the data only provides abbreviated names, which will be used for all requested name widths). If the calendar does not provide cyclic year name data, or if the year value to be formatted is out of the range of years for which cyclic name data is provided, then numeric formatting is used (behaves like 'y').
*/
case U
/**
Quarter - Use one or two for the numerical quarter, three for the abbreviation, or four for the full name.
*/
case Q
/**
Stand-Alone Quarter - Use one or two for the numerical quarter, three for the abbreviation, or four for the full name.
*/
case q
/**
Month - Use one or two for the numerical month, three for the abbreviation, or four for the full name, or five for the narrow name.
*/
case M
/**
Stand-Alone Month - Use one or two for the numerical month, three for the abbreviation, or four for the full name, or 5 for the narrow name.
*/
case L
/**
This pattern character is deprecated, and should be ignored in patterns. It was originally intended to be used in combination with M to indicate placement of the symbol for leap month in the Chinese calendar. Placement of that marker is now specified using locale-specific <monthPatterns> data, and formatting and parsing of that marker should be handled as part of supporting the regular M and L pattern characters.
*/
case l
/**
Week of Year.
*/
case w
/**
Week of Month
*/
case W
/**
Date - Day of the month
*/
case d
/**
Day of year
*/
case D
/**
Day of Week in Month. The example is for the 2nd Wed in July
*/
case F
/**
Modified Julian day. This is different from the conventional Julian day number in two regards. First, it demarcates days at local zone midnight, rather than noon GMT. Second, it is a local number; that is, it depends on the local time zone. It can be thought of as a single number that encompasses all the date-related fields.
*/
case g
/**
Day of week - Use one through three letters for the short day, or four for the full name, or five for the narrow name.
*/
case E
/**
Local day of week. Same as E except adds a numeric value that will depend on the local starting day of the week, using one or two letters. For this example, Monday is the first day of the week.
*/
case e
/**
Stand-Alone local day of week - Use one letter for the local numeric value (same as 'e'), three for the short day, or four for the full name, or five for the narrow name.
*/
case c
/**
AM or PM
*/
case a
/**
Hour [1-12]. When used in skeleton data or in a skeleton passed in an API for flexible data pattern generation, it should match the 12-hour-cycle format preferred by the locale (h or K); it should not match a 24-hour-cycle format (H or k). Use hh for zero padding.
*/
case h
/**
Hour [0-23]. When used in skeleton data or in a skeleton passed in an API for flexible data pattern generation, it should match the 24-hour-cycle format preferred by the locale (H or k); it should not match a 12-hour-cycle format (h or K). Use HH for zero padding.
*/
case H
/**
Hour [0-11]. When used in a skeleton, only matches K or h, see above. Use KK for zero padding.
*/
case K
/**
Hour [1-24]. When used in a skeleton, only matches k or H, see above. Use kk for zero padding.
*/
case k
/**
This is a special-purpose symbol. It must not occur in pattern or skeleton data. Instead, it is reserved for use in skeletons passed to APIs doing flexible date pattern generation. In such a context, it requests the preferred hour format for the locale (h, H, K, or k), as determined by whether h, H, K, or k is used in the standard short time format for the locale. In the implementation of such an API, 'j' must be replaced by h, H, K, or k before beginning a match against availableFormats data. Note that use of 'j' in a skeleton passed to an API is the only way to have a skeleton request a locale's preferred time cycle type (12-hour or 24-hour).
*/
case j
/**
Minute. Use one or two for zero padding.
*/
case m
/**
Second. Use one or two for zero padding.
*/
case s
/**
Fractional Second - truncates (like other time fields) to the count of letters. (example shows display using pattern SSSS for seconds value 12.34567)
*/
case S
/**
Milliseconds in day. This field behaves exactly like a composite of all time-related fields, not including the zone fields. As such, it also reflects discontinuities of those fields on DST transition days. On a day of DST onset, it will jump forward. On a day of DST cessation, it will jump backward. This reflects the fact that is must be combined with the offset field to obtain a unique local time value.
*/
case A
/**
Time Zone - with the specific non-location format. Where that is unavailable, falls back to localized GMT format. Use one to three letters for the short format or four for the full format.
For more information about timezone formats, see [Appendix J: Time Zone Display Names](http://www.unicode.org/reports/tr35/tr35-25.html#Time_Zone_Fallback).
*/
case z
/**
Time Zone - RFC 822 GMT format.
For more information about timezone formats, see [Appendix J: Time Zone Display Names](http://www.unicode.org/reports/tr35/tr35-25.html#Time_Zone_Fallback).
*/
case Z
/**
Time Zone - The localized GMT format.
For more information about timezone formats, see [Appendix J: Time Zone Display Names](http://www.unicode.org/reports/tr35/tr35-25.html#Time_Zone_Fallback).
*/
case ZZZZ
/**
Time Zone - ISO8601 time zone format.
For more information about timezone formats, see [Appendix J: Time Zone Display Names](http://www.unicode.org/reports/tr35/tr35-25.html#Time_Zone_Fallback).
*/
case ZZZZZ
/**
Time Zone - with the generic non-location format. Where that is unavailable, uses special fallback rules given in [Appendix J](http://www.unicode.org/reports/tr35/tr35-25.html#Time_Zone_Fallback). Use one letter for short format, four for long format.
For more information about timezone formats, see [Appendix J: Time Zone Display Names](http://www.unicode.org/reports/tr35/tr35-25.html#Time_Zone_Fallback).
*/
case v
/**
Time Zone - Identical to the format for z. This specifier formerly had slightly different behavior than the z specifier before the deprecation of the commonlyUsed element. Use z instead of V whenever possible in date formats.
For more information about timezone formats, see [Appendix J: Time Zone Display Names](http://www.unicode.org/reports/tr35/tr35-25.html#Time_Zone_Fallback).
*/
case V
/**
Time Zone - with the generic location format. Where that is unavailable, falls back to the localized GMT format. (Fallback is only necessary with a GMT-style Time Zone ID, like Etc/GMT-830.)
This is especially useful when presenting possible timezone choices for user selection, since the naming is more uniform than the v format.
For more information about timezone formats, see [Appendix J: Time Zone Display Names](http://www.unicode.org/reports/tr35/tr35-25.html#Time_Zone_Fallback).
*/
case VVVV
}
static func dateFormat(template: Template..., options: Int = 0, locale: Locale? = nil) -> String? {
self.dateFormat(template: template, options: options, locale: locale)
}
static func dateFormat(template: [Template], options: Int = 0, locale: Locale? = nil) -> String? {
let template = template.reduce("") { $0 + $1.rawValue }
return DateFormatter.dateFormat(fromTemplate: template, options: options, locale: locale)
}
}
let formatter = DateFormatter()
formatter.dateFormat = DateFormatter.dateFormat(template: .y, .M, .d, locale: .current)
print(formatter.string(from: Date())) // 1/29/2021
enum MyTemplate {
case ymca
case full
var templates: [DateFormatter.Template] {
switch self {
case .ymca:
return [.Y, .M, .c, .A]
case .full:
return [.y, .M, .d, .k, .H, .m, .s]
}
}
}
let formatter = DateFormatter()
formatter.dateFormat = DateFormatter.dateFormat(template: MyTemplate.full.templates, locale: .current)
print(formatter.string(from: Date())) // 1/29/2021, 16:47:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment