Как вы создаете объект даты из даты в Swift Xcode.
Например, в JavaScript вы бы сделали:
var day = new Date('2014-05-20');
Как вы создаете объект даты из даты в Swift Xcode.
Например, в JavaScript вы бы сделали:
var day = new Date('2014-05-20');
Ответы:
Swift имеет свой Date
тип. Не нужно использовать NSDate
.
В Swift даты и время хранятся в 64-битном числе с плавающей запятой, которое измеряет количество секунд с базовой даты 1 января 2001 года в 00:00:00 UTC . Это выражено в 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)
}
}
Теперь вы можете создать NSDate из Swift, просто выполнив:
NSDate(dateString:"2014-06-06")
Обратите внимание, что эта реализация не кэширует NSDateFormatter, что может потребоваться из соображений производительности, если вы собираетесь создавать множество NSDate
s таким способом.
Также обратите внимание, что эта реализация просто потерпит крах, если вы попытаетесь инициализировать NSDate
, передав строку, которая не может быть проанализирована правильно. Это связано с принудительной разверткой необязательного значения, возвращаемого функцией dateFromString
. Если вы хотите вернуть a nil
при плохом разборе, в идеале вы должны использовать неисправный инициализатор; но вы не можете сделать это сейчас (июнь 2015 г.) из-за ограничений в Swift 1.2, поэтому следующий ваш лучший выбор - использовать метод фабрики классов.
Более сложный пример, который решает обе проблемы, находится здесь: 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 нет собственного типа Date, но вы должны использовать существующий NSDate
тип Cocoa , например:
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
Согласно документации Apple
Пример :
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
Создание средства форматирования даты - не дешевая операция. Если вы, вероятно, будете часто использовать средство форматирования, обычно более эффективно кэшировать один экземпляр, чем создавать и распоряжаться несколькими экземплярами. Одним из подходов является использование статической переменной
И хотя я согласен с @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?