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 Date
typ. 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 Date
strukturze . 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ć, DateComponents
aby określić składniki, a następnie Calendar
utworzyć datę. To Calendar
daje Date
kontekst. 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 DateFormatter
obsł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 NSDate
klasy.
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 NSDate
w ten sposób.
Należy również pamiętać, że ta implementacja po prostu ulegnie awarii, jeśli spróbujesz zainicjować an NSDate
przez 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 nil
przy 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)
}
}
NSDateFormatter
każ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 NSDate
rozszerzeń.
Swift nie ma własnego typu Date, ale możesz użyć istniejącego NSDate
typu 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)
NSDateFormatter
metody 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 swift3
skł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 parse
metody, 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 }
NSDate
tak jak w Objective-C?