Jak utworzyć obiekt daty z daty w swift xcode.
np. w javascript zrobiłbyś:
var day = new Date('2014-05-20');
Jak utworzyć obiekt daty z daty w swift xcode.
np. w javascript zrobiłbyś:
var day = new Date('2014-05-20');
Odpowiedzi:
Swift ma swój własny Datetyp. Nie ma potrzeby używania NSDate.
W języku Swift daty i godziny są przechowywane w 64-bitowej liczbie zmiennoprzecinkowej mierzącej liczbę sekund od daty odniesienia 1 stycznia 2001 r. O godzinie 00:00:00 czasu UTC . Wyraża się to w Datestrukturze . Poniższe informacje podają aktualną datę i godzinę:
let currentDateTime = Date()
Aby utworzyć inne daty i godziny, możesz użyć jednej z następujących metod.
Metoda 1
Jeśli znasz liczbę sekund przed lub po dacie odniesienia 2001, możesz z tego skorzystać.
let someDateTime = Date(timeIntervalSinceReferenceDate: -123456789.0) // Feb 2, 1997, 10:26 AM
Metoda 2
Oczywiście łatwiej byłoby użyć takich rzeczy jak lata, miesiące, dni i godziny (zamiast względnych sekund), aby utworzyć plik Date. W tym celu możesz użyć, DateComponentsaby określić składniki, a następnie Calendarutworzyć datę. To Calendardaje Datekontekst. W przeciwnym razie skąd miałoby wiedzieć, w jakiej strefie czasowej lub kalendarzu ma to wyrazić?
// 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)
Inne skróty stref czasowych można znaleźć tutaj . Jeśli pozostawisz to pole puste, domyślnie używana jest strefa czasowa użytkownika.
Metoda 3
Najbardziej zwięzłym (ale niekoniecznie najlepszym) sposobem może być użycie DateFormatter.
let formatter = DateFormatter()
formatter.dateFormat = "yyyy/MM/dd HH:mm"
let someDateTime = formatter.date(from: "2016/10/08 22:31")
Te normy techniczne Unicode pokazać inne formaty , że DateFormatterobsługuje.
Zobacz moją pełną odpowiedź, jak wyświetlić datę i godzinę w czytelnym formacie. Przeczytaj także te doskonałe artykuły:
Najlepiej jest to zrobić, używając rozszerzenia istniejącej NSDateklasy.
Poniższe rozszerzenie dodaje nowy inicjator, który utworzy datę w bieżących ustawieniach regionalnych przy użyciu ciągu daty w określonym formacie.
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)
}
}
Teraz możesz utworzyć NSDate w Swift, wykonując:
NSDate(dateString:"2014-06-06")
Zauważ, że ta implementacja nie buforuje NSDateFormatter, co możesz chcieć zrobić ze względu na wydajność, jeśli spodziewasz się tworzenia wielu plików NSDatew ten sposób.
Należy również pamiętać, że ta implementacja po prostu ulegnie awarii, jeśli spróbujesz zainicjować an NSDateprzez przekazanie ciągu, którego nie można poprawnie przeanalizować. Dzieje się tak z powodu wymuszonego rozpakowania wartości opcjonalnej zwróconej przez dateFromString. Jeśli chciałbyś zwrócić a nilprzy złej analizie, najlepiej byłoby użyć nieudanego inicjatora; ale nie możesz tego zrobić teraz (czerwiec 2015) z powodu ograniczeń w Swift 1.2, więc następnym najlepszym wyborem jest użycie metody fabryki klas.
Bardziej rozbudowany przykład, który dotyczy obu problemów, znajduje się tutaj: 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)
}
}
NSDateFormatterkażdym razem, gdy uzyskuje się dostęp do funkcji. Jak podaje przewodnik po formatowaniu daty , utworzenie programu formatującego datę nie jest tanią operacją . Ponadto klasa jest bezpieczna dla wątków od iOS7, więc można ją bezpiecznie używać dla wszystkich NSDaterozszerzeń.
Swift nie ma własnego typu Date, ale możesz użyć istniejącego NSDatetypu Cocoa , np .:
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
}
}
Które możesz użyć na przykład:
var date = Date.parse("2014-05-20")
var date = Date.from(year: 2014, month: 05, day: 20)
NSDateFormattermetody date(from:). Wraca nil. Znalazłem ten problem w dzienniku awarii fabric.io.
Oto, jak zrobiłem to w 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
}
}
Stosowanie:
let marsOpportunityLaunchDate = Date.from(year: 2003, month: 07, day: 07)
dateComponents
Zgodnie z dokumentacją Apple
Przykład:
var myObject = NSDate()
let futureDate = myObject.dateByAddingTimeInterval(10)
let timeSinceNow = myObject.timeIntervalSinceNow
W Swift 3.0 ustawiłeś w ten sposób obiekt daty.
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)
}
}
Osobiście uważam, że powinien to być dostępny inicjalizator:
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
}
}
}
W przeciwnym razie ciąg o nieprawidłowym formacie zgłosi wyjątek.
Zgodnie z odpowiedzią @mythz zdecydowałem się opublikować zaktualizowaną wersję jego rozszerzenia przy użyciu swift3składni.
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)
}
}
Nie używam parsemetody, ale jak ktoś będzie potrzebował, zaktualizuję ten post.
Często mam potrzebę łączenia wartości dat z jednego miejsca z wartościami czasu w innym. Napisałem funkcję pomocniczą, aby to osiągnąć.
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)!
Zgodnie z instrukcją formatowania danych firmy Apple
Tworzenie programu formatującego datę nie jest tanią operacją. Jeśli często używasz programu formatującego, zwykle bardziej wydajne jest buforowanie pojedynczego wystąpienia niż tworzenie i usuwanie wielu wystąpień. Jednym podejściem jest użycie zmiennej statycznej
I chociaż zgadzam się z @Leon, że powinien to być dostępny inicjator, kiedy wprowadzasz dane początkowe, możemy mieć taki, który nie jest dostępny (tak jak jest UIImage(imageLiteralResourceName:)).
Oto moje podejście:
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)
}
}
A teraz ciesz się po prostu dzwoniąc:
// For seed data
Date(dateLiteralString: "2020-03-30")
// When parsing data
guard let date = Date(yyyyMMdd: "2020-03-30") else { return nil }
NSDatetak jak w Objective-C?