Ich frage mich, ob es eine neue und großartige Möglichkeit gibt, die Anzahl der Tage zwischen zwei NSDates in Swift / dem "neuen" Kakao zu ermitteln.
ZB wie in Ruby würde ich tun:
(end_date - start_date).to_i
Ich frage mich, ob es eine neue und großartige Möglichkeit gibt, die Anzahl der Tage zwischen zwei NSDates in Swift / dem "neuen" Kakao zu ermitteln.
ZB wie in Ruby würde ich tun:
(end_date - start_date).to_i
Antworten:
Sie müssen auch den Zeitunterschied berücksichtigen. Wenn Sie beispielsweise die Daten 2015-01-01 10:00
und vergleichen 2015-01-02 09:00
, werden Tage zwischen diesen Daten als 0 (Null) zurückgegeben, da die Differenz zwischen diesen Daten weniger als 24 Stunden (23 Stunden) beträgt.
Wenn Sie die genaue Tageszahl zwischen zwei Daten ermitteln möchten, können Sie dieses Problem folgendermaßen umgehen:
// Assuming that firstDate and secondDate are defined
// ...
let calendar = NSCalendar.currentCalendar()
// Replace the hour (time) of both dates with 00:00
let date1 = calendar.startOfDayForDate(firstDate)
let date2 = calendar.startOfDayForDate(secondDate)
let flags = NSCalendarUnit.Day
let components = calendar.components(flags, fromDate: date1, toDate: date2, options: [])
components.day // This will return the number of day(s) between dates
let calendar = Calendar.current
// Replace the hour (time) of both dates with 00:00
let date1 = calendar.startOfDay(for: firstDate)
let date2 = calendar.startOfDay(for: secondDate)
let components = calendar.dateComponents([.day], from: date1, to: date2)
calendar.date(bySettingHour: 12, minute: 00, second: 00, of: calendar.startOfDay(for: firstDate))
startOfDay()
scheint unnötig zu sein) : calendar.date(bySettingHour: 12, minute: 0, second: 0, of: firstDate)
.
Hier ist meine Antwort für Swift 2:
func daysBetweenDates(startDate: NSDate, endDate: NSDate) -> Int
{
let calendar = NSCalendar.currentCalendar()
let components = calendar.components([.Day], fromDate: startDate, toDate: endDate, options: [])
return components.day
}
today
undtomorrow
Ich sehe ein paar Swift3-Antworten, also füge ich meine eigenen hinzu:
public static func daysBetween(start: Date, end: Date) -> Int {
Calendar.current.dateComponents([.day], from: start, to: end).day!
}
Die Benennung fühlt sich schneller an, es ist eine Zeile und mit der neuesten dateComponents()
Methode.
Ich habe meine Objective-C-Antwort übersetzt
let start = "2010-09-01"
let end = "2010-09-05"
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let startDate:NSDate = dateFormatter.dateFromString(start)
let endDate:NSDate = dateFormatter.dateFromString(end)
let cal = NSCalendar.currentCalendar()
let unit:NSCalendarUnit = .Day
let components = cal.components(unit, fromDate: startDate, toDate: endDate, options: nil)
println(components)
Ergebnis
<NSDateComponents: 0x10280a8a0>
Day: 4
Das Schwierigste war, dass die automatische Vervollständigung darauf besteht, dass Datum und Datum vorliegen NSDate?
, aber tatsächlich müssen sie NSDate!
den Angaben in der Referenz entsprechen.
Ich sehe nicht ein, wie eine gute Lösung mit einem Operator aussehen würde, da Sie die Einheit jeweils anders spezifizieren möchten. Sie könnten das Zeitintervall zurückgeben, aber dann werden Sie nicht viel gewinnen.
.DayCalendarUnit
veraltet. Ich glaube jetzt solltest du .CalendarUnitDay
stattdessen verwenden.
let components = cal.components(.Day, fromDate: startDate, toDate: endDate, options: [])
.Day
jetzt
Hier ist eine sehr schöne Date
Erweiterung, um Unterschiede zwischen Daten in Jahren, Monaten, Tagen, Stunden, Minuten, Sekunden zu erhalten
extension Date {
func years(sinceDate: Date) -> Int? {
return Calendar.current.dateComponents([.year], from: sinceDate, to: self).year
}
func months(sinceDate: Date) -> Int? {
return Calendar.current.dateComponents([.month], from: sinceDate, to: self).month
}
func days(sinceDate: Date) -> Int? {
return Calendar.current.dateComponents([.day], from: sinceDate, to: self).day
}
func hours(sinceDate: Date) -> Int? {
return Calendar.current.dateComponents([.hour], from: sinceDate, to: self).hour
}
func minutes(sinceDate: Date) -> Int? {
return Calendar.current.dateComponents([.minute], from: sinceDate, to: self).minute
}
func seconds(sinceDate: Date) -> Int? {
return Calendar.current.dateComponents([.second], from: sinceDate, to: self).second
}
}
date
sollte sinceDate
in Funktionsparametern sein.
days
und es funktioniert gut.
func years(since date: Date) -> Int? { return Calendar.current.dateComponents[.year], from: date, to: self).years }
, und Sie könnten es so nennen let y = date1.years(since: date2)
. Dies könnte mit modernen Namenskonventionen vereinbar sein.
Update für Swift 3 iOS 10 Beta 4
func daysBetweenDates(startDate: Date, endDate: Date) -> Int {
let calendar = Calendar.current
let components = calendar.dateComponents([Calendar.Component.day], from: startDate, to: endDate)
return components.day!
}
Hier ist die Antwort für Swift 3 (getestet für IOS 10 Beta)
func daysBetweenDates(startDate: Date, endDate: Date) -> Int
{
let calendar = Calendar.current
let components = calendar.components([.day], from: startDate, to: endDate, options: [])
return components.day!
}
Dann können Sie es so nennen
let pickedDate: Date = sender.date
let NumOfDays: Int = daysBetweenDates(startDate: pickedDate, endDate: Date())
print("Num of Days: \(NumOfDays)")
Swift 3. Vielen Dank an Emin Buğra Saral für den startOfDay
Vorschlag.
extension Date {
func daysBetween(date: Date) -> Int {
return Date.daysBetween(start: self, end: date)
}
static func daysBetween(start: Date, end: Date) -> Int {
let calendar = Calendar.current
// Replace the hour (time) of both dates with 00:00
let date1 = calendar.startOfDay(for: start)
let date2 = calendar.startOfDay(for: end)
let a = calendar.dateComponents([.day], from: date1, to: date2)
return a.value(for: .day)!
}
}
Verwendung:
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let start = dateFormatter.date(from: "2017-01-01")!
let end = dateFormatter.date(from: "2018-01-01")!
let diff = Date.daysBetween(start: start, end: end) // 365
Die Dinge, die in Swift eingebaut sind, sind immer noch sehr einfach. Wie sie in diesem frühen Stadium sein sollten. Sie können jedoch Ihre eigenen Inhalte hinzufügen, wobei das Risiko besteht, dass Operatoren und globale Domänenfunktionen überlastet werden. Sie sind jedoch lokal für Ihr Modul.
let now = NSDate()
let seventies = NSDate(timeIntervalSince1970: 0)
// Standard solution still works
let days = NSCalendar.currentCalendar().components(.CalendarUnitDay,
fromDate: seventies, toDate: now, options: nil).day
// Flashy swift... maybe...
func -(lhs:NSDate, rhs:NSDate) -> DateRange {
return DateRange(startDate: rhs, endDate: lhs)
}
class DateRange {
let startDate:NSDate
let endDate:NSDate
var calendar = NSCalendar.currentCalendar()
var days: Int {
return calendar.components(.CalendarUnitDay,
fromDate: startDate, toDate: endDate, options: nil).day
}
var months: Int {
return calendar.components(.CalendarUnitMonth,
fromDate: startDate, toDate: endDate, options: nil).month
}
init(startDate:NSDate, endDate:NSDate) {
self.startDate = startDate
self.endDate = endDate
}
}
// Now you can do this...
(now - seventies).months
(now - seventies).days
Hier ist meine Antwort für Swift 3:
func daysBetweenDates(startDate: NSDate, endDate: NSDate, inTimeZone timeZone: TimeZone? = nil) -> Int {
var calendar = Calendar.current
if let timeZone = timeZone {
calendar.timeZone = timeZone
}
let dateComponents = calendar.dateComponents([.day], from: startDate.startOfDay, to: endDate.startOfDay)
return dateComponents.day!
}
Es gibt noch kaum eine Swift-spezifische Standardbibliothek. nur die schlanken grundlegenden numerischen, Zeichenfolgen- und Sammlungstypen.
Es ist durchaus möglich, solche Abkürzungen mithilfe von Erweiterungen zu definieren, aber was die eigentlichen Out-of-the-Box-APIs betrifft, gibt es keinen "neuen" Kakao. Swift wird nur direkt denselben alten ausführlichen Cocoa-APIs zugeordnet, die bereits vorhanden sind.
Ich werde meine Version hinzufügen, obwohl dieser Thread ein Jahr alt ist. Mein Code sieht folgendermaßen aus:
var name = txtName.stringValue // Get the users name
// Get the date components from the window controls
var dateComponents = NSDateComponents()
dateComponents.day = txtDOBDay.integerValue
dateComponents.month = txtDOBMonth.integerValue
dateComponents.year = txtDOBYear.integerValue
// Make a Gregorian calendar
let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)
// Get the two dates we need
var birthdate = calendar?.dateFromComponents(dateComponents)
let currentDate = NSDate()
var durationDateComponents = calendar?.components(NSCalendarUnit.CalendarUnitDay, fromDate: birthdate!, toDate: currentDate, options: nil)
let numberOfDaysAlive = durationDateComponents?.day
println("\(numberOfDaysAlive!)")
txtGreeting.stringValue = "Hello \(name), You have been alive for \(numberOfDaysAlive!) days."
Ich hoffe es hilft jemandem.
Prost,
Erins Methode wurde auf Swift 3 aktualisiert. Dies zeigt Tage ab heute (ohne Berücksichtigung der Tageszeit).
func daysBetweenDates( endDate: Date) -> Int
let calendar: Calendar = Calendar.current
let date1 = calendar.startOfDay(for: Date())
let date2 = calendar.startOfDay(for: secondDate)
return calendar.dateComponents([.day], from: date1, to: date2).day!
}
Dies ergibt einen absoluten Unterschied in Tagen zwischen einigen Date
und heute:
extension Date {
func daysFromToday() -> Int {
return abs(Calendar.current.dateComponents([.day], from: self, to: Date()).day!)
}
}
und dann benutze es:
if someDate.daysFromToday() >= 7 {
// at least a week from today
}
Sie können die folgende Erweiterung verwenden:
public extension Date {
func daysTo(_ date: Date) -> Int? {
let calendar = Calendar.current
// Replace the hour (time) of both dates with 00:00
let date1 = calendar.startOfDay(for: self)
let date2 = calendar.startOfDay(for: date)
let components = calendar.dateComponents([.day], from: date1, to: date2)
return components.day // This will return the number of day(s) between dates
}
}
Dann können Sie es so nennen:
startDate.daysTo(endDate)
Swift 3.2
extension DateComponentsFormatter {
func difference(from fromDate: Date, to toDate: Date) -> String? {
self.allowedUnits = [.year,.month,.weekOfMonth,.day]
self.maximumUnitCount = 1
self.unitsStyle = .full
return self.string(from: fromDate, to: toDate)
}
}
Alle Antworten sind gut. Für Lokalisierungen müssen wir jedoch eine Anzahl von Dezimaltagen zwischen zwei Daten berechnen. So können wir das nachhaltige Dezimalformat bereitstellen.
// This method returns the fractional number of days between to dates
func getFractionalDaysBetweenDates(date1: Date, date2: Date) -> Double {
let components = Calendar.current.dateComponents([.day, .hour], from: date1, to: date2)
var decimalDays = Double(components.day!)
decimalDays += Double(components.hour!) / 24.0
return decimalDays
}
extension Date {
func daysFromToday() -> Int {
return Calendar.current.dateComponents([.day], from: self, to: Date()).day!
}
}
Dann benutze es gerne
func dayCount(dateString: String) -> String{
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM dd,yyyy hh:mm a"
let fetchedDate = dateFormatter.date(from: dateString)
let day = fetchedDate?.daysFromToday()
if day! > -1{
return "\(day!) days passed."
}else{
return "\(day! * -1) days left."
}
}
Schnelle 3 - Tage von heute bis heute
func daysUntilDate(endDateComponents: DateComponents) -> Int
{
let cal = Calendar.current
var components = cal.dateComponents([.era, .year, .month, .day], from: NSDate() as Date)
let today = cal.date(from: components)
let otherDate = cal.date(from: endDateComponents)
components = cal.dateComponents([Calendar.Component.day], from: (today! as Date), to: otherDate!)
return components.day!
}
Rufen Sie die Funktion so auf
// Days from today until date
var examnDate = DateComponents()
examnDate.year = 2016
examnDate.month = 12
examnDate.day = 15
let daysCount = daysUntilDate(endDateComponents: examnDate)
Eine einfachere Möglichkeit wäre, am Datum eine Erweiterung zu erstellen
public extension Date {
public var currentCalendar: Calendar {
return Calendar.autoupdatingCurrent
}
public func daysBetween(_ date: Date) -> Int {
let components = currentCalendar.dateComponents([.day], from: self, to: date)
return components.day!
}
}
func completeOffset(from date:Date) -> String? {
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .brief
return formatter.string(from: Calendar.current.dateComponents([.year,.month,.day,.hour,.minute,.second], from: date, to: self))
}
Wenn Sie Jahr, Monat, Tage und Stunden als Zeichenfolge benötigen, verwenden Sie diese Option
var morgen = Calendar.current.date (byAdding: .day, Wert: 1, bis: Date ())!
let dc = morgen.completeOffset (von: Date ())
Swift 4
func getDateHeader(indexPath: Int) -> String {
let formatter2 = DateFormatter()
formatter2.dateFormat = "MM-dd-yyyy"
var dateDeadline : Date?
dateDeadline = formatter2.date(from: arrCompletedDate[indexPath] as! String)
let currentTime = dateDeadline?.unixTimestamp
let calendar = NSCalendar.current
let date = NSDate(timeIntervalSince1970: Double(currentTime!))
if calendar.isDateInYesterday(date as Date) { return "Yesterday" }
else if calendar.isDateInToday(date as Date) { return "Today" }
else if calendar.isDateInTomorrow(date as Date) { return "Tomorrow" }
else {
let startOfNow = calendar.startOfDay(for: NSDate() as Date)
let startOfTimeStamp = calendar.startOfDay(for: date as Date)
let components = calendar.dateComponents([.day], from: startOfNow, to: startOfTimeStamp)
let day = components.day!
if day < 1 { return "\(abs(day)) days ago" }
else { return "In \(day) days" }
}
}
Dies ist eine aktualisierte Version von Emins Antwort für Swift 5, die den Vorschlag enthält, Mittag anstelle von Mitternacht als endgültige Zeit für den Vergleich von Tagen zu verwenden. Es behandelt auch den möglichen Ausfall verschiedener Datumsfunktionen, indem ein optionales zurückgegeben wird.
///
/// This is an approximation; it does not account for time differences. It will set the time to 1200 (noon) and provide the absolute number
/// of days between now and the given date. If the result is negative, it should be read as "days ago" instead of "days from today."
/// Returns nil if something goes wrong initializing or adjusting dates.
///
func daysFromToday() -> Int?
{
let calendar = NSCalendar.current
// Replace the hour (time) of both dates with noon. (Noon is less likely to be affected by DST changes, timezones, etc. than midnight.)
guard let date1 = calendar.date(bySettingHour: 12, minute: 00, second: 00, of: calendar.startOfDay(for: Date())),
let date2 = calendar.date(bySettingHour: 12, minute: 00, second: 00, of: calendar.startOfDay(for: self)) else
{
return nil
}
return calendar.dateComponents([.day], from: date1, to: date2).day
}
Schnelle 5.2.4-Lösung:
import UIKit
let calendar = Calendar.current
let start = "2010-09-01"
let end = "2010-09-05"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let firstDate = dateFormatter.date(from: start)!
let secondDate = dateFormatter.date(from: end)!
// Replace the hour (time) of both dates with 00:00
let date1 = calendar.startOfDay(for: firstDate)
let date2 = calendar.startOfDay(for: secondDate)
let components = calendar.dateComponents([Calendar.Component.day], from: date1, to: date2)
components.day // This will return the number of day(s) between dates
func simpleIndex(ofDate: Date) -> Int {
// index here just means today 0, yesterday -1, tomorrow 1 etc.
let c = Calendar.current
let todayRightNow = Date()
let d = c.date(bySetting: .hour, value: 13, of: ofDate)
let t = c.date(bySetting: .hour, value: 13, of: todayRightNow)
if d == nil || today == nil {
print("weird problem simpleIndex#ofDate")
return 0
}
let r = c.dateComponents([.day], from: today!, to: d!)
// yesterday is negative one, tomorrow is one
if let o = r.value(for: .day) {
return o
}
else {
print("another weird problem simpleIndex#ofDate")
return 0
}
}
let calendar = NSCalendar.currentCalendar();
let component1 = calendar.component(.Day, fromDate: fromDate)
let component2 = calendar.component(.Day, fromDate: toDate)
let difference = component1 - component2