Swift 3 - найти количество календарных дней между двумя датами
То, как я это делал в Swift 2.3, было:
let currentDate = NSDate()
let currentCalendar = NSCalendar.currentCalendar()
var startDate : NSDate?
var endDate : NSDate?
// The following two lines set the `startDate` and `endDate` to the start of the day
currentCalendar.rangeOfUnit(.Day, startDate: &startDate, interval: nil, forDate: currentDate)
currentCalendar.rangeOfUnit(.Day, startDate: &endDate, interval: nil, forDate: self)
let intervalComps = currentCalendar.components([.Day], fromDate: startDate!, toDate: endDate!, options: [])
print(intervalComps.day)
Теперь все изменилось с помощью Swift 3. Мне нужно либо использовать NSCalendar
, либо NSDate
, постоянно набирать casting с помощью as
или находить способ Swift 3 сделать это.
Какой правильный способ сделать это в Swift 3?
Ответы
Ответ 1
Оказывается, это намного проще сделать в Swift 3:
extension Date {
func interval(ofComponent comp: Calendar.Component, fromDate date: Date) -> Int {
let currentCalendar = Calendar.current
guard let start = currentCalendar.ordinality(of: comp, in: .era, for: date) else { return 0 }
guard let end = currentCalendar.ordinality(of: comp, in: .era, for: self) else { return 0 }
return end - start
}
}
Edit
Сравнение обыденности двух дат должно быть в пределах того же era
вместо того же year
, так как, естественно, две даты могут падать в разные годы.
Использование
let yesterday = Date(timeInterval: -86400, since: Date())
let tomorrow = Date(timeInterval: 86400, since: Date())
let diff = tomorrow.interval(ofComponent: .day, fromDate: yesterday)
// return 2
Ответ 2
В Swift 4 имеется простая однострочная линия для получения количества дней (или любого другого DateComponent) между двумя датами:
let diffInDays = Calendar.current.dateComponents([.day], from: dateA, to: dateB).day
Ответ 3
Версия Swift 4
let startDate = "2000-11-22"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let formatedStartDate = dateFormatter.date(from: startDate)
let currentDate = Date()
let components = Set<Calendar.Component>([.second, .minute, .hour, .day, .month, .year])
let differenceOfDate = Calendar.current.dateComponents(components, from: formatedStartDate!, to: currentDate)
print (differenceOfDate)
Отпечатано -
год: 16 месяцев: 10 дней: 19 часов: 12 минут: 16 секунд: 42 isLeapMonth: false
swift4 calendar date
Ответ 4
Если кто-то хочет сделать это более конкретно, следуйте инструкциям ниже.
1.Добавить это продление даты
extension Date {
/// Returns the amount of years from another date
func years(from date: Date) -> Int {
return Calendar.current.dateComponents([.year], from: date, to: self).year ?? 0
}
/// Returns the amount of months from another date
func months(from date: Date) -> Int {
return Calendar.current.dateComponents([.month], from: date, to: self).month ?? 0
}
/// Returns the amount of weeks from another date
func weeks(from date: Date) -> Int {
return Calendar.current.dateComponents([.weekOfMonth], from: date, to: self).weekOfMonth ?? 0
}
/// Returns the amount of days from another date
func days(from date: Date) -> Int {
return Calendar.current.dateComponents([.day], from: date, to: self).day ?? 0
}
/// Returns the amount of hours from another date
func hours(from date: Date) -> Int {
return Calendar.current.dateComponents([.hour], from: date, to: self).hour ?? 0
}
/// Returns the amount of minutes from another date
func minutes(from date: Date) -> Int {
return Calendar.current.dateComponents([.minute], from: date, to: self).minute ?? 0
}
/// Returns the amount of seconds from another date
func seconds(from date: Date) -> Int {
return Calendar.current.dateComponents([.second], from: date, to: self).second ?? 0
}
/// Returns the amount of nanoseconds from another date
func nanoseconds(from date: Date) -> Int {
return Calendar.current.dateComponents([.nanosecond], from: date, to: self).nanosecond ?? 0
}
/// Returns the a custom time interval description from another date
func offset(from date: Date) -> String {
var result: String = ""
if years(from: date) > 0 { return "\(years(from: date))y" }
if months(from: date) > 0 { return "\(months(from: date))M" }
if weeks(from: date) > 0 { return "\(weeks(from: date))w" }
if seconds(from: date) > 0 { return "\(seconds(from: date))" }
if days(from: date) > 0 { result = result + " " + "\(days(from: date)) D" }
if hours(from: date) > 0 { result = result + " " + "\(hours(from: date)) H" }
if minutes(from: date) > 0 { result = result + " " + "\(minutes(from: date)) M" }
if seconds(from: date) > 0 { return "\(seconds(from: date))" }
return ""
}
}
2. Определите это глобально
fileprivate var timer: Timer?
3. Вызовите этот метод в viewDidLoad или куда угодно
override func viewDidLoad() {
super.viewDidLoad()
self.getRemainingTime()
}
4.Usage
fileprivate func getRemainingTime() {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let startDate = "2018-06-02 10:11:12"
let currentDate = dateFormatter.string(from: Date())
if currentDate != startDate {
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(calculateTime)), userInfo: nil, repeats: true)
RunLoop.current.add(timer!, forMode: RunLoopMode.commonModes)
timer?.fire()
}
else {
self.timer?.invalidate()
self.timer = nil
}
}
func calculateTime() {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let stdate : String = "2018-06-02 10:11:12"
let startDate = dateFormatter.date(from: stdate)!
let currentDate = Date()
let strTimer : String = startDate.offset(from: currentDate)
if !strTimer.isEmpty {
let stDay: String = "\((Int(strTimer)! % 31536000) / 86400)"
let stHour: String = "\((Int(strTimer)! % 86400) / 3600)"
let stMin: String = "\((Int(strTimer)! % 3600) / 60)"
let stSec: String = "\(Int(strTimer)! % 60)"
yourLabelOutlet.text = "Start In :\(stDay) Days \(stHour) Hours \(stMin) Minutes \(stSec) Seconds"
}
}
Работает как очарование. Вы можете использовать каждую отдельную строку на стороне вашего интерфейса, наслаждайтесь
Ответ 5
В Swift4 мы можем легко получить дни между двумя разными датами календаря, используя приведенные ниже коды.
Во-первых, разница в днях с текущей датой.
let previousDate = "2017-03-01"
let currentDate = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let previousDateFormated : Date? = dateFormatter.date(from: previousDate)
let difference = currentDate.timeIntervalSince(previousDateFormated!)
var differenceInDays = Int(difference/(60 * 60 * 24 ))
print(differenceInDays)
Продолжая приведенный выше код... Ниже приведен список дней для двух разных дат. содержимое предыдущей даты берется с даты выше.
let futureDate = "2017-12-30"
let futureDateFormatted : Date? = dateFormatter.date(from: futureDate)
differenceInDays = (futureDateFormatted?.timeIntervalSince(previousDateFormated!))! / (60 * 60 * 24)
print(differenceInDays)
Ответ 6
private func calculateDaysBetweenTwoDates(start: Date, end: Date) -> Int {
let currentCalendar = Calendar.current
guard let start = currentCalendar.ordinality(of: .day, in: .era, for: start) else {
return 0
}
guard let end = currentCalendar.ordinality(of: .day, in: .era, for: end) else {
return 0
}
return end - start
}
Ответ 7
private func days(actual day1:[Int],expect day2:[Int]) -> Int {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let first = "\(day1[2])-\(day1[1])-\(day1[0])"
let firstDate = dateFormatter.date(from:first)!
let last = "\(day2[2])-\(day2[1])-\(day2[0])"
let lastDate = dateFormatter.date(from:last)!
let currentCalendar = NSCalendar.current
let components = currentCalendar.dateComponents([.day], from: firstDate, to: lastDate)
return components.day!
}
Другой подход к сопоставлению с компонентами дневного месяца года
Использование:
Введите даты в следующем формате
[dd, mm, yyyy]
[9, 6, 2017]
[6, 6, 2017]
Ответ 8
Обновлен для Swift 3:
если вы хотите напечатать количество дней, а также список дней между двумя датами календаря, которые используются ниже простого кода;
//Объявление переменной:
var daysListArray = [String]()
//функция Defination:
func printCountBtnTwoDates(mStartDate: Date, mEndDate: Date) -> Int {
let calendar = Calendar.current
let formatter = DateFormatter()
var newDate = mStartDate
daysListArray.removeAll()
while newDate <= mEndDate {
formatter.dateFormat = "yyyy-MM-dd"
daysListArray.append(formatter.string(from: newDate))
newDate = calendar.date(byAdding: .day, value: 1, to: newDate)!
}
// print("daysListArray: \(daysListArray)") // if you want to print list between start date and end date
return daysListArray.count
}
//Чтобы вызвать функцию выше:
let count = self.printCountBtnTwoDates(mStartDate: your_start_date, mEndDate: your_end_date)
print("count: \(count)") // date count
//Наслаждайтесь кодированием...!
Ответ 9
Нашел это в другой ветке, но это было, наконец, самое простое решение для меня, использующее Swift 4:
let previousDate = ENTER DATE HERE
let now = Date()
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .brief // May delete the word brief to let Xcode show you the other options
formatter.allowedUnits = [.month, .day, .hour]
formatter.maximumUnitCount = 1 // Show just one unit (i.e. 1d vs. 1d 6hrs)
let stringDate = formatter.string(from: previousDate, to: now)
Ответ 10
Если кому-то потребуется отобразить все единицы времени, например, "часы, минуты, секунды", а не только "часы". Допустим, разница во времени между двумя датами составляет 1 час 59 минут 20 секунд. Эта функция будет отображать "1 ч 59 м 20 с".
Вот мой код:
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'hh:mm:ss"
let start = dateFormatter.date(from: "2019-01-31T07:45:00")!
let end = dateFormatter.date(from: "2019-03-01T06:30:00")!
print("Date Difference : ", end.offsetFrom(date: start))
Определение функции:
extension Date {
func offsetFrom(date : Date) -> String {
let dayHourMinuteSecond: Set = [.day, .hour, .minute, .second]
let difference = NSCalendar.current.dateComponents(dayHourMinuteSecond, from: date, to: self);
let seconds = "\(difference.second ?? 0)s"
let minutes = "\(difference.minute ?? 0)m" + " " + seconds
let hours = "\(difference.hour ?? 0)h" + " " + minutes
let days = "\(difference.day ?? 0)d" + " " + hours
if let day = difference.day, day > 0 { return days }
if let hour = difference.hour, hour > 0 { return hours }
if let minute = difference.minute, minute > 0 { return minutes }
if let second = difference.second, second > 0 { return seconds }
return ""
}
}