Last active
November 4, 2024 08:46
-
-
Save Koshimizu-Takehito/39d59eaaac6794d726ef0739b099cd8a to your computer and use it in GitHub Desktop.
Date.FormatStyle の出力サンプル
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import SwiftUI | |
struct ContentView: View { | |
@State private var date = ISO8601DateFormatter().date(from: "2025-01-01T00:00:00+09:00")! | |
@State private var code: LanguageCode = .japanese | |
@State private var timeZoneID: TimeZoneID = .jst | |
@State private var calendarName: CalendarName = .gregorian | |
var body: some View { | |
NavigationStack { | |
List { | |
Section("出力") { | |
DateCell($date, style: style1) | |
DateCell($date, style: style2) | |
} | |
Section("暦法") { | |
ForEach(CalendarName.allCases, id: \.self) { | |
SelectionCell($calendarName, value: $0) | |
} | |
} | |
Section("ロケール") { | |
ForEach(LanguageCode.allCases, id: \.self) { | |
SelectionCell($code, value: $0) | |
} | |
} | |
Section("タイムゾーン") { | |
ForEach(TimeZoneID.allCases, id: \.self) { | |
SelectionCell($timeZoneID, value: $0) | |
} | |
} | |
} | |
.contentTransition(.numericText(countsDown: false)) | |
.animation(.default, value: date) | |
.animation(.default, value: code) | |
.animation(.default, value: timeZoneID) | |
.animation(.default, value: calendarName) | |
.environment(\.locale, Locale(identifier: code.rawValue)) | |
.environment(\.timeZone, TimeZone(timeZoneID)) | |
.environment(\.calendar, Calendar(identifier: calendarName.identifier)) | |
} | |
} | |
private var style1: Date.FormatStyle { | |
.dateTime.year().month().day().hour().minute().second() | |
} | |
private var style2: Date.FormatStyle { | |
.dateTime.year().month(.twoDigits).day(.twoDigits) | |
} | |
} | |
/// 言語コード | |
enum LanguageCode: String, Hashable, CaseIterable, CustomStringConvertible { | |
case japanese = "ja_JP" | |
case english = "en_US" | |
case th_TH = "th_TH" | |
case hi_IN = "hi_IN" | |
var description: String { rawValue } | |
} | |
/// タイムゾーン | |
enum TimeZoneID: String, Hashable, CaseIterable, CustomStringConvertible { | |
case jst = "JST" | |
case utc = "UTC" | |
var description: String { rawValue } | |
} | |
/// 暦法 | |
enum CalendarName: String, Hashable, CaseIterable, CustomStringConvertible { | |
case gregorian = "グレゴリオ暦" | |
case japanese = "和暦" | |
case chinese = "中国暦" | |
case buddhist = "仏暦" | |
case indian = "インド暦" | |
var identifier: Calendar.Identifier { | |
switch self { | |
case .gregorian: | |
return .gregorian | |
case .japanese: | |
return .japanese | |
case .chinese: | |
return .chinese | |
case .buddhist: | |
return .buddhist | |
case .indian: | |
return .indian | |
} | |
} | |
var description: String { rawValue } | |
} | |
extension TimeZone { | |
init(_ id: TimeZoneID) { | |
self.init(identifier: id.rawValue)! | |
} | |
} | |
struct DateCell: View { | |
@Binding private var date: Date | |
@EnvironmentFormat private var style: Date.FormatStyle | |
init(_ date: Binding<Date>, style: Date.FormatStyle) { | |
self._date = date | |
self._style = .init(wrappedValue: style) | |
} | |
var body: some View { | |
Text(date.formatted(style)) | |
.font(.body.monospacedDigit().bold()) | |
} | |
} | |
@propertyWrapper | |
struct EnvironmentFormat: DynamicProperty { | |
@Environment(\.locale) private var locale | |
@Environment(\.timeZone) private var timeZone | |
@Environment(\.calendar) private var calendar | |
private var value: Date.FormatStyle | |
init(wrappedValue value: Date.FormatStyle) { | |
self.value = value | |
} | |
var wrappedValue: Date.FormatStyle { | |
var value = value | |
value.timeZone = timeZone | |
value.locale = locale | |
value.calendar = calendar | |
return value | |
} | |
} | |
struct SelectionCell<T: Equatable>: View { | |
@Binding private var selection: T | |
private let value: T | |
init(_ selection: Binding<T>, value: T) { | |
_selection = selection | |
self.value = value | |
} | |
var body: some View { | |
Button { | |
selection = value | |
} label: { | |
HStack { | |
Text("\(value)") | |
Spacer() | |
Image(systemName: "checkmark") | |
.opacity(selection == value ? 1 : 0) | |
} | |
} | |
} | |
} | |
#Preview { | |
ContentView() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
ja_JP
en_US