Saya bertanya-tanya apakah ada kemungkinan baru dan mengagumkan untuk mendapatkan jumlah hari antara dua NSDates di Swift / Cocoa "baru"?
Misalnya seperti di Ruby saya akan melakukan:
(end_date - start_date).to_i
Saya bertanya-tanya apakah ada kemungkinan baru dan mengagumkan untuk mendapatkan jumlah hari antara dua NSDates di Swift / Cocoa "baru"?
Misalnya seperti di Ruby saya akan melakukan:
(end_date - start_date).to_i
Jawaban:
Anda juga harus mempertimbangkan perbedaan waktu. Misalnya jika Anda membandingkan tanggal 2015-01-01 10:00
dan 2015-01-02 09:00
, hari-hari di antara tanggal tersebut akan kembali sebagai 0 (nol) karena perbedaan antara tanggal tersebut kurang dari 24 jam (itu 23 jam).
Jika tujuan Anda adalah mendapatkan nomor hari yang tepat di antara dua tanggal, Anda dapat mengatasi masalah ini seperti ini:
// 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()
tampaknya tidak perlu): calendar.date(bySettingHour: 12, minute: 0, second: 0, of: firstDate)
.
Inilah jawaban saya untuk 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
dantomorrow
Saya melihat beberapa jawaban Swift3 jadi saya akan menambahkan jawaban saya sendiri:
public static func daysBetween(start: Date, end: Date) -> Int {
Calendar.current.dateComponents([.day], from: start, to: end).day!
}
Penamaannya terasa lebih Swifty, satu baris, dan menggunakan dateComponents()
metode terbaru .
Saya menerjemahkan jawaban Objective-C saya
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)
hasil
<NSDateComponents: 0x10280a8a0>
Day: 4
Bagian tersulit adalah bahwa pelengkapan otomatis menegaskan fromDate dan toDate akan NSDate?
, tetapi memang harus NSDate!
seperti yang ditunjukkan dalam referensi.
Saya tidak melihat bagaimana solusi yang baik dengan operator akan terlihat, karena Anda ingin menentukan unit secara berbeda di setiap kasus. Anda dapat mengembalikan interval waktu, tetapi Anda tidak mendapatkan banyak keuntungan.
.DayCalendarUnit
sudah usang. Saya percaya sekarang Anda harus menggunakan .CalendarUnitDay
sebagai gantinya.
let components = cal.components(.Day, fromDate: startDate, toDate: endDate, options: [])
.Day
sekarang
Ini sangat bagus, Date
perpanjangan untuk mendapatkan perbedaan antara tanggal dalam tahun, bulan, hari, jam, menit, detik
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
harus sinceDate
dalam parameter fungsi.
days
dan berfungsi dengan baik.
func years(since date: Date) -> Int? { return Calendar.current.dateComponents[.year], from: date, to: self).years }
, dan Anda bisa menyebutnya sebagai let y = date1.years(since: date2)
. Itu mungkin lebih konsisten dengan konvensi penamaan modern.
Pembaruan untuk 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!
}
Inilah jawaban untuk Swift 3 (diuji untuk 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!
}
Kemudian Anda bisa menyebutnya seperti ini
let pickedDate: Date = sender.date
let NumOfDays: Int = daysBetweenDates(startDate: pickedDate, endDate: Date())
print("Num of Days: \(NumOfDays)")
Swift 3. Terima kasih kepada Emin Buğra Saral di atas atas startOfDay
sarannya.
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)!
}
}
Pemakaian:
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
Hal-hal yang dibangun dengan cepat masih sangat mendasar. Seperti seharusnya pada tahap awal ini. Tetapi Anda dapat menambahkan barang Anda sendiri dengan risiko yang datang dengan operator yang membebani dan fungsi domain global. Mereka akan menjadi lokal untuk modul Anda.
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
Inilah jawaban saya untuk 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!
}
Hampir tidak ada pustaka standar khusus Swift; hanya jenis numerik dasar, string, dan koleksi.
Sangat mungkin untuk mendefinisikan singkatan seperti itu menggunakan ekstensi, tetapi sejauh API out-of-the-box yang sebenarnya berjalan, tidak ada Cocoa "baru"; Swift hanya memetakan langsung ke API Kakao verbose lama yang sama seperti yang sudah ada.
Saya akan menambahkan versi saya meskipun utas ini berumur satu tahun. Kode saya terlihat seperti ini:
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."
Saya harap ini membantu seseorang.
Bersulang,
Metode Erin diperbarui ke Swift 3, Ini menunjukkan hari dari hari ini (dengan mengabaikan waktu)
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!
}
Ini mengembalikan perbedaan mutlak dalam hari antara beberapa Date
dan hari ini:
extension Date {
func daysFromToday() -> Int {
return abs(Calendar.current.dateComponents([.day], from: self, to: Date()).day!)
}
}
dan kemudian gunakan:
if someDate.daysFromToday() >= 7 {
// at least a week from today
}
Anda dapat menggunakan ekstensi berikut:
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
}
}
Kemudian, Anda bisa menyebutnya seperti ini:
startDate.daysTo(endDate)
Swift 3.2.0
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)
}
}
Semua jawaban bagus. Tetapi untuk Pelokalan kita perlu menghitung jumlah hari desimal di antara dua tanggal. sehingga kami dapat menyediakan format desimal berkelanjutan.
// 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!
}
}
Lalu gunakan seperti itu
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."
}
}
Ini adalah versi terbaru dari jawaban Emin untuk Swift 5 yang menggabungkan saran untuk menggunakan siang hari, bukan tengah malam sebagai waktu yang pasti untuk membandingkan hari. Ini juga menangani potensi kegagalan berbagai fungsi tanggal dengan mengembalikan opsional.
///
/// 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
}
Swift 3 - Hari dari hari ini sampai saat ini
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!
}
Fungsi panggilan seperti ini
// Days from today until date
var examnDate = DateComponents()
examnDate.year = 2016
examnDate.month = 12
examnDate.day = 15
let daysCount = daysUntilDate(endDateComponents: examnDate)
pilihan yang lebih mudah adalah membuat ekstensi pada Tanggal
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))
}
jika Anda membutuhkan hari bulan tahun dan jam sebagai string gunakan ini
var besok = Calendar.current.date (byAdding: .day, value: 1, to: Date ())!
biarkan dc = besok.completeOffset (dari: Tanggal ())
Cepat 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" }
}
}
Solusi Swift 5.2.4:
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