Swift Xcodeの日付から日付オブジェクトをどのように作成しますか?
たとえば、JavaScriptでは次のようにします。
var day = new Date('2014-05-20');
Swift Xcodeの日付から日付オブジェクトをどのように作成しますか?
たとえば、JavaScriptでは次のようにします。
var day = new Date('2014-05-20');
回答:
Swiftには独自のDate
タイプがあります。使用する必要はありませんNSDate
。
Swiftでは、日付と時刻は、2001年1月1日の基準日00:00:00 UTCからの秒数を測定する64ビット浮動小数点数に格納されます。これはDate
構造で表されます。次のようにすると、現在の日付と時刻がわかります。
let currentDateTime = Date()
他の日時を作成するには、次のいずれかの方法を使用できます。
方法1
2001年の基準日の前後の秒数がわかっている場合は、それを使用できます。
let someDateTime = Date(timeIntervalSinceReferenceDate: -123456789.0) // Feb 2, 1997, 10:26 AM
方法2
もちろん、(相対的な秒数ではなく)年、月、日、時間などを使用してを作成する方が簡単Date
です。これを使用DateComponents
して、コンポーネントを指定しCalendar
、日付を作成できます。Calendar
与えDate
コンテキストを。それ以外の場合、どのタイムゾーンまたはカレンダーでそれを表現するかをどのようにして知るのでしょうか?
// Specify date components
var dateComponents = DateComponents()
dateComponents.year = 1980
dateComponents.month = 7
dateComponents.day = 11
dateComponents.timeZone = TimeZone(abbreviation: "JST") // Japan Standard Time
dateComponents.hour = 8
dateComponents.minute = 34
// Create date from components
let userCalendar = Calendar.current // user calendar
let someDateTime = userCalendar.date(from: dateComponents)
他のタイムゾーンの省略形はここにあります。空白のままにすると、デフォルトではユーザーのタイムゾーンが使用されます。
方法3
最も簡潔な方法(ただし、必ずしも最良とは限りません)は、を使用することDateFormatter
です。
let formatter = DateFormatter()
formatter.dateFormat = "yyyy/MM/dd HH:mm"
let someDateTime = formatter.date(from: "2016/10/08 22:31")
Unicodeの技術基準は、他のフォーマットを示しているDateFormatter
サポートします。
日付と時刻を読みやすい形式で表示する方法については、私の完全な回答を参照してください。これらの優れた記事も読んでください:
これは、既存の拡張機能を使用して行うのが最適です。 NSDate
クラスのです。
次の拡張機能は、指定した形式の日付文字列を使用して現在のロケールで日付を作成する新しい初期化子を追加します。
extension NSDate
{
convenience
init(dateString:String) {
let dateStringFormatter = NSDateFormatter()
dateStringFormatter.dateFormat = "yyyy-MM-dd"
dateStringFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
let d = dateStringFormatter.dateFromString(dateString)!
self.init(timeInterval:0, sinceDate:d)
}
}
これで、次のようにするだけでSwiftからNSDateを作成できます。
NSDate(dateString:"2014-06-06")
この実装はNSDateFormatterをキャッシュしないことに注意してください。これは、パフォーマンス上の理由から、 NSDate
。この方法でのを。
また、NSDate
正しく解析できない文字列を渡して初期化しようとすると、この実装は単にクラッシュすることにも注意してください。これは、によって返されるオプションの値が強制的にアンラップされるためですdateFromString
。nil
不正な解析でを返したい場合は、理想的には失敗する初期化子を使用します。しかし、Swift 1.2の制限により、今はそれを行うことはできません(2015年6月)。そのため、クラスファクトリーメソッドを使用するのが次善の策です。
両方の問題に対処するより複雑な例は、https://gist.github.com/algal/09b08515460b7bd229faです。
extension Date {
init(_ dateString:String) {
let dateStringFormatter = DateFormatter()
dateStringFormatter.dateFormat = "yyyy-MM-dd"
dateStringFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX") as Locale
let date = dateStringFormatter.date(from: dateString)!
self.init(timeInterval:0, since:date)
}
}
NSDateFormatter
、関数がアクセスされるたびに再作成されることです。日付の書式ガイドは述べて安く操作ではありませんフォーマッタ日付を作成します。また、このクラスはiOS7以降スレッドセーフなので、すべてのNSDate
拡張機能で安全に使用できます。
Swiftには独自の日付型はありませんが、既存のCocoa NSDate
型を使用する必要があります。例:
class Date {
class func from(year: Int, month: Int, day: Int) -> Date {
let gregorianCalendar = NSCalendar(calendarIdentifier: .gregorian)!
var dateComponents = DateComponents()
dateComponents.year = year
dateComponents.month = month
dateComponents.day = day
let date = gregorianCalendar.date(from: dateComponents)!
return date
}
class func parse(_ string: String, format: String = "yyyy-MM-dd") -> Date {
let dateFormatter = DateFormatter()
dateFormatter.timeZone = NSTimeZone.default
dateFormatter.dateFormat = format
let date = dateFormatter.date(from: string)!
return date
}
}
次のように使用できます:
var date = Date.parse("2014-05-20")
var date = Date.from(year: 2014, month: 05, day: 20)
NSDateFormatter
の方法date(from:)
。戻りますnil
。この問題は、fabric.ioクラッシュログで見つかりました。
これがSwift 4.2での方法です。
extension Date {
/// Create a date from specified parameters
///
/// - Parameters:
/// - year: The desired year
/// - month: The desired month
/// - day: The desired day
/// - Returns: A `Date` object
static func from(year: Int, month: Int, day: Int) -> Date? {
let calendar = Calendar(identifier: .gregorian)
var dateComponents = DateComponents()
dateComponents.year = year
dateComponents.month = month
dateComponents.day = day
return calendar.date(from: dateComponents) ?? nil
}
}
使用法:
let marsOpportunityLaunchDate = Date.from(year: 2003, month: 07, day: 07)
dateComponents
例:
var myObject = NSDate()
let futureDate = myObject.dateByAddingTimeInterval(10)
let timeSinceNow = myObject.timeIntervalSinceNow
Swift 3.0では、この方法で日付オブジェクトを設定しています。
extension Date
{
init(dateString:String) {
let dateStringFormatter = DateFormatter()
dateStringFormatter.dateFormat = "yyyy-MM-dd"
dateStringFormatter.locale = Locale(identifier: "en_US_POSIX")
let d = dateStringFormatter.date(from: dateString)!
self(timeInterval:0, since:d)
}
}
個人的には、失敗する可能性のあるイニシャライザであるべきだと思います。
extension Date {
init?(dateString: String) {
let dateStringFormatter = DateFormatter()
dateStringFormatter.dateFormat = "yyyy-MM-dd"
if let d = dateStringFormatter.date(from: dateString) {
self.init(timeInterval: 0, since: d)
} else {
return nil
}
}
}
それ以外の場合、無効な形式の文字列は例外を発生させます。
@mythzの回答によると、私はswift3
構文を使用して彼の拡張機能の更新版を投稿することにしました。
extension Date {
static func from(_ year: Int, _ month: Int, _ day: Int) -> Date?
{
let gregorianCalendar = Calendar(identifier: .gregorian)
let dateComponents = DateComponents(calendar: gregorianCalendar, year: year, month: month, day: day)
return gregorianCalendar.date(from: dateComponents)
}
}
私はparse
メソッドを使用しませんが、必要に応じてこの投稿を更新します。
ある場所の日付値を別の場所の時間値と組み合わせる必要があることがよくあります。これを実現するためのヘルパー関数を書きました。
let startDateTimeComponents = NSDateComponents()
startDateTimeComponents.year = NSCalendar.currentCalendar().components(NSCalendarUnit.Year, fromDate: date).year
startDateTimeComponents.month = NSCalendar.currentCalendar().components(NSCalendarUnit.Month, fromDate: date).month
startDateTimeComponents.day = NSCalendar.currentCalendar().components(NSCalendarUnit.Day, fromDate: date).day
startDateTimeComponents.hour = NSCalendar.currentCalendar().components(NSCalendarUnit.Hour, fromDate: time).hour
startDateTimeComponents.minute = NSCalendar.currentCalendar().components(NSCalendarUnit.Minute, fromDate: time).minute
let startDateCalendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)
combinedDateTime = startDateCalendar!.dateFromComponents(startDateTimeComponents)!
Appleのデータフォーマットガイドによると
日付フォーマッターの作成は、安価な操作ではありません。フォーマッターを頻繁に使用する可能性がある場合、通常、複数のインスタンスを作成して破棄するよりも、単一のインスタンスをキャッシュする方が効率的です。1つのアプローチは、静的変数を使用することです
そして、これが失敗可能なイニシャライザであることに@Leonに同意しますが、シードデータを入力すると、失敗しないものがある可能性があります(のようにUIImage(imageLiteralResourceName:)
)。
だからここに私のアプローチがあります:
extension DateFormatter {
static let yyyyMMdd: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
formatter.calendar = Calendar(identifier: .iso8601)
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.locale = Locale(identifier: "en_US_POSIX")
return formatter
}()
}
extension Date {
init?(yyyyMMdd: String) {
guard let date = DateFormatter.yyyyMMdd.date(from: yyyyMMdd) else { return nil }
self.init(timeInterval: 0, since: date)
}
init(dateLiteralString yyyyMMdd: String) {
let date = DateFormatter.yyyyMMdd.date(from: yyyyMMdd)!
self.init(timeInterval: 0, since: date)
}
}
そして今単に呼び出すことを楽しんでください:
// For seed data
Date(dateLiteralString: "2020-03-30")
// When parsing data
guard let date = Date(yyyyMMdd: "2020-03-30") else { return nil }
NSDate
Objective-Cと同じように使用しますか?