Сравнение NSDates без компонента времени

В быстрой игровой площадке я использовал

NSDate.date() 

Но это всегда появляется с добавленным элементом времени. Для моего приложения мне нужно игнорировать элемент времени. Возможно ли это в Свифт? Как это можно сделать? Даже если бы я мог установить элемент времени в одно и то же время на каждой дате, которая тоже будет работать.

Кроме того, я пытаюсь сравнить две даты, и в настоящий момент я использую следующий код:

var earlierDate:NSDate = firstDate.earlierDate(secondDate)

Это единственный способ или я могу сделать это таким образом, чтобы игнорировать элемент времени? Например, я не хочу, чтобы результат был в тот же день, но в разное время.

Ответ 1

Используйте эту функцию Calendar для сравнения дат в iOS 8. 0+

func compare(_ date1: Date, to date2: Date, toGranularity component: Calendar.Component) -> ComparisonResult


прохождение .day как единица

Используйте эту функцию следующим образом:

let now = Date()
// "Sep 23, 2015, 10:26 AM"
let olderDate = Date(timeIntervalSinceNow: -10000)
// "Sep 23, 2015, 7:40 AM"

var order = Calendar.current.compare(now, to: olderDate, toGranularity: .hour)

switch order {
case .orderedDescending:
    print("DESCENDING")
case .orderedAscending:
    print("ASCENDING")
case .orderedSame:
    print("SAME")
}

// Compare to hour: DESCENDING

var order = Calendar.current.compare(now, to: olderDate, toGranularity: .day)


switch order {
case .orderedDescending:
    print("DESCENDING")
case .orderedAscending:
    print("ASCENDING")
case .orderedSame:
    print("SAME")
}

// Compare to day: SAME

Ответ 2

В NSCalendar есть несколько полезных методов в iOS 8. 0+:

startOfDayForDate, isDateInToday, isDateInYesterday, isDateInTomorrow

И даже сравнить дни:

func isDate(date1: NSDate!, inSameDayAsDate date2: NSDate!) -> Bool

Чтобы игнорировать элемент времени, вы можете использовать это:

var toDay = Calendar.current.startOfDay(for: Date())

Но, если вам нужно поддерживать также iOS 7, вы всегда можете написать расширение

extension NSCalendar {
    func myStartOfDayForDate(date: NSDate!) -> NSDate!
    {
        let systemVersion:NSString = UIDevice.currentDevice().systemVersion
        if systemVersion.floatValue >= 8.0 {
            return self.startOfDayForDate(date)
        } else {
            return self.dateFromComponents(self.components(.CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay, fromDate: date))
        }
    }
}

Ответ 3

Я написал следующий метод для сравнения двух дат путем заимствования из решения Ashley Mills. Он сравнивает две даты и возвращает true, если две даты одинаковы (лишены времени).

func compareDate(date1:NSDate, date2:NSDate) -> Bool {
    let order = NSCalendar.currentCalendar().compareDate(date1, toDate: date2,
        toUnitGranularity: .Day)
    switch order {
    case .OrderedSame:
        return true
    default:
        return false
    }
}

И он называется так:

if compareDate(today, date2: anotherDate) {
    // The two dates are on the same day.
}

Ответ 4

Сравнение двух дат в быстром.

    // Date comparision to compare current date and end date.
    var dateComparisionResult:NSComparisonResult = currentDate.compare(endDate)

    if dateComparisionResult == NSComparisonResult.OrderedAscending
    {
        // Current date is smaller than end date.
    }
    else if dateComparisionResult == NSComparisonResult.OrderedDescending
    {
        // Current date is greater than end date.
    }
    else if dateComparisionResult == NSComparisonResult.OrderedSame
    {
        // Current date and end date are same.
    }

Ответ 5

В Swift 4:

func compareDate(date1:Date, date2:Date) -> Bool {
    let order = NSCalendar.current.compare(date1, to: date2, toGranularity: .day)
    switch order {
    case .orderedSame:
        return true
    default:
        return false
    }
}

Ответ 6

Поддержка iOS7

let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let date1String = dateFormatter.stringFromDate(date1)
let date2String = dateFormatter.stringFromDate(date2)
if date1String == date2String {
    println("Equal date")
}

Ответ 7

Вы можете сравнить две даты, используя это описание.

let date1 = NSDate()
let date2 = NSDate(timeIntervalSinceNow: 120)
if date1.description == date2.description {
    print(true)
} else {
    print(false)   // false (I have added 2 seconds between them)
}

Если вы хотите установить элемент времени ваших дат в другое время, вы можете сделать следующее:

extension NSDate {
    struct Calendar {
        static let gregorian = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
    }
    var day:    Int { return Calendar.gregorian.component(.Day,    fromDate: self)   }
    var month:  Int { return Calendar.gregorian.component(.Month,  fromDate: self)  }
    var year:   Int { return Calendar.gregorian.component(.Year,   fromDate: self)  }

    var noon: NSDate {
        return Calendar.gregorian.dateWithEra(1, year: year, month: month, day: day, hour: 12, minute: 0, second: 0, nanosecond: 0)!
    }
}

let date1 = NSDate()
let date2 = NSDate(timeIntervalSinceNow: 120)
print(date1.noon == date2.noon)   // true

, или вы также можете сделать это, используя NSDateFormatter:

extension NSDate {
    struct Date {
        static let formatterYYYYMMDD: NSDateFormatter = {
            let formatter = NSDateFormatter()
            formatter.dateFormat = "yyyyMMdd"
            return formatter
        }()
    }
    var yearMonthDay: String {
        return Date.formatterYYYYMMDD.stringFromDate(self)
    }
    func isSameDayAs(date:NSDate) -> Bool {
        return yearMonthDay == date.yearMonthDay
    }
}

let date1 = NSDate()
let date2 = NSDate(timeIntervalSinceNow: 120)
print(date1.yearMonthDay == date2.yearMonthDay)   // true

print(date1.isSameDayAs(date2))    // true

Другой вариант (iOS8 +) - использовать метод calendar isDate (inSameDayAsDate:):

extension NSDate {
    struct Calendar {
        static let gregorian = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
    }
    func isInSameDayAs(date date: NSDate) -> Bool {
        return Calendar.gregorian.isDate(self, inSameDayAsDate: date)
    }
}
let date1 = NSDate()
let date2 = NSDate(timeIntervalSinceNow: 120)
if date1.isInSameDayAs(date: date2 ){
    print(true)   // true
} else {
    print(false)
}

Ответ 8

Для Swift3

var order = NSCalendar.current.compare(firstDate, to: secondDate, toGranularity: .hour)

if order == .orderedSame {
    //Both the dates are same. 
    //Your Logic.
}

Ответ 9

Я написал расширение Swift 4 для сравнения двух дат:

import Foundation

extension Date {      
  func isSameDate(_ comparisonDate: Date) -> Bool {
    let order = Calendar.current.compare(self, to: comparisonDate, toGranularity: .day)
    return order == .orderedSame
  }

  func isBeforeDate(_ comparisonDate: Date) -> Bool {
    let order = Calendar.current.compare(self, to: comparisonDate, toGranularity: .day)
    return order == .orderedAscending
  }

  func isAfterDate(_ comparisonDate: Date) -> Bool {
    let order = Calendar.current.compare(self, to: comparisonDate, toGranularity: .day)
    return order == .orderedDescending
  }
}

Использование:

startDate.isSameDateAs(endDate) // returns a true or false

Ответ 10

Swift:

extension NSDate {

    /**
    Compares current date with the given one down to the seconds.
    If date==nil, then always return false

    :param: date date to compare or nil

    :returns: true if the dates has equal years, months, days, hours, minutes and seconds.
    */
    func sameDate(date: NSDate?) -> Bool {
        if let d = date {
            let calendar = NSCalendar.currentCalendar()
            if NSComparisonResult.OrderedSame == calendar.compareDate(self, toDate: d, toUnitGranularity: NSCalendarUnit.SecondCalendarUnit) {
                return true
            }

        }
        return false
    }
}

Ответ 11

Swift 3

        let order = NSCalendar.current.compare(date1, to: date2, toGranularity: .day)

        if order == .orderedAscending { 
          // date 1 is older
        }
        else if order == .orderedDescending { 
          // date 1 is newer
        }
        else if order == .orderedSame { 
          // same day/hour depending on granularity parameter
        }

Ответ 12

Когда вы NSDate.date() на игровой площадке, вы увидите напечатанное описание по умолчанию. Используйте NSDateFormatter для печати локализованного описания объекта даты, возможно, только с частью даты.

Чтобы обнулить определенные части даты (для сравнения), используйте NSDateComponents в сочетании с NSCalendar.

Ответ 13

По моему опыту, большинство проблем с использованием NSDate исходят из неправильного предположения, что NSDate может использоваться для представления даты в "нормальном" смысле (т.е. 24 периода, начинающихся в полночь в локальном часовом поясе). В обычном (повседневном/не-программировании) использовании, 1 января 2014 года в Лондоне такая же дата, как и 1 января в Пекине или Нью-Йорке , хотя они охватывают разные периоды в реальном времени. Чтобы довести это до крайности, время на острове Рождества - это UTC + 14, а время на острове Мидуэй - UTC-11. Таким образом, 1 января 2014 года на этих двух островах установлена ​​одна и та же дата, даже если никто не запускается, пока другой не будет завершен в течение часа.

Если это тип даты, которую вы записываете (и если вы не записываете компонент времени, это, вероятно, есть), то не используйте NSDate (который хранит только секунды, прошедшие с 2001-01-01 00:00 UTC, ничего больше), но хранить год и день как целые числа - возможно, создав свой собственный класс CivilDate, который обертывает эти значения, и вместо этого используйте это.

Только окунитесь в NSDate, чтобы сравнить даты, а затем убедитесь, что явное объявление часового пояса как "UTC" для обоих NSDates для целей сравнения.

Ответ 14

Swift 4

func compareDate(date1:Date, date2:Date) -> Bool {
    let order = Calendar.current.compare(date1, to: date2,toGranularity: .day)
    switch order {
    case .orderedSame:
        return true
    default:
        return false
    }
}

Ответ 15

Swift iOS 8 и. Если вам нужно больше, чем просто большие или меньшие сопоставления даты. Например, это тот же день или предыдущий день,...

extension Date {
    func compareTo(date: Date, toGranularity: Calendar.Component ) -> ComparisonResult  {
        var cal = Calendar.current
        cal.timeZone = TimeZone(identifier: "Europe/Paris")!
        return cal.compare(self, to: date, toGranularity: toGranularity)
        }
    }

Примеры использования этого в фильтре см. в этом ответе:

fooobar.com/questions/44168/...

Ответ 16

Чтобы ответить на ваш вопрос:

Возможно ли это в Swift?

Да, это возможно


Ааа, ты тоже хочешь сейчас КАК

let cal = NSCalendar.currentCalendar()
cal.rangeOfUnit(.DayCalendarUnit, startDate: &d1, interval: nil, forDate: d1) // d1 NSDate?
cal.rangeOfUnit(.DayCalendarUnit, startDate: &d2, interval: nil, forDate: d2) // d2 NSDate?

Теперь d1 и d2 будут содержать даты в начале их дней.

сравнить с d1!.compare(d2!)

Чтобы отобразить их без временной части, используйте NSDateFormatter.