Як створити об’єкт дати з дати у швидкому xcode.
наприклад, у JavaScript ви зробите:
var day = new Date('2014-05-20');
Як створити об’єкт дати з дати у швидкому xcode.
наприклад, у JavaScript ви зробите:
var day = new Date('2014-05-20');
Відповіді:
Свіфт має свій 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
. Якщо ви хочете повернути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 немає власного типу дати, але ви можете використовувати існуючий 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
Згідно з документацією 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?