Saya mencoba untuk mencari tahu apakah tanggal saat ini termasuk dalam rentang tanggal menggunakan NSDate atau tidak.
Misalnya, Anda bisa mendapatkan tanggal / waktu saat ini menggunakan NSDate:
NSDate rightNow = [NSDate date];
Saya kemudian ingin menggunakan tanggal tersebut untuk memeriksa apakah berada dalam kisaran 9AM - 5PM .
objective-c
cocoa
cocoa-touch
datetime
nsdate
Brock Woolf
sumber
sumber
Jawaban:
Saya datang dengan solusi. Jika Anda memiliki solusi yang lebih baik, silakan tinggalkan dan saya akan menandainya sebagai benar.
+ (BOOL)date:(NSDate*)date isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate { if ([date compare:beginDate] == NSOrderedAscending) return NO; if ([date compare:endDate] == NSOrderedDescending) return NO; return YES; }
sumber
- (BOOL)isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate;
return !([date compare:startDate] == NSOrderedAscending || [date compare:endDate] == NSOrderedDescending);
Untuk bagian pertama, gunakan jawaban dari @kperryua untuk membuat objek NSDate yang ingin Anda bandingkan. Dari jawaban Anda atas pertanyaan Anda sendiri, sepertinya Anda sudah mengetahuinya.
Untuk benar-benar membandingkan tanggal, saya setuju dengan komentar @Tim atas jawaban Anda. Ini lebih ringkas namun sebenarnya sama persis dengan kode Anda, dan saya akan menjelaskan alasannya.
+ (BOOL) date:(NSDate*)date isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate { return (([date compare:beginDate] != NSOrderedAscending) && ([date compare:endDate] != NSOrderedDescending)); }
Meskipun pernyataan return tampaknya harus mengevaluasi kedua operan operator &&, sebenarnya tidak demikian. Kuncinya adalah " evaluasi sirkuit pendek ", yang diimplementasikan dalam berbagai macam bahasa pemrograman, dan tentunya di C. Pada dasarnya, operator
&
dan&&
"sirkuit pendek" jika argumen pertama adalah 0 (atau NO, nil, dll.) , sementara|
dan||
melakukan hal yang sama jika argumen pertama bukan 0. Jikadate
muncul sebelumnyabeginDate
, tes kembaliNO
tanpa perlu membandingkanendDate
. Pada dasarnya, ini melakukan hal yang sama dengan kode Anda, tetapi dalam satu pernyataan pada satu baris, bukan 5 (atau 7, dengan spasi).Ini dimaksudkan sebagai masukan yang konstruktif, karena ketika pemrogram memahami cara bahasa pemrograman khusus mereka mengevaluasi ekspresi logis, mereka dapat membangunnya secara lebih efektif tanpa terlalu memperhatikan efisiensi. Namun, ada tes serupa yang akan menjadi kurang efisien, karena tidak semua operator hubungan arus pendek. (Memang, sebagian besar tidak dapat mengalami hubungan arus pendek, seperti operator perbandingan numerik.) Jika ragu, selalu aman untuk menyatakan secara eksplisit dalam memecah logika Anda, tetapi kode dapat jauh lebih mudah dibaca ketika Anda membiarkan bahasa / kompilator menangani hal-hal kecil untukmu.
sumber
Versi Brock Woolf di Swift:
extension NSDate { func isBetweenDates(beginDate: NSDate, endDate: NSDate) -> Bool { if self.compare(beginDate) == .OrderedAscending { return false } if self.compare(endDate) == .OrderedDescending { return false } return true } }
sumber
Jika Anda ingin mengetahui apakah tanggal saat ini berada di antara dua titik waktu tertentu (09.00 - 17.00 pada 7/1/09), gunakan NSCalendar dan NSDateComponents untuk membuat instans NSDate untuk waktu yang diinginkan dan bandingkan dengan tanggal saat ini.
Jika Anda ingin tahu apakah tanggal saat ini berada di antara dua jam ini setiap hari, maka Anda mungkin bisa pergi ke arah lain. Buat objek NSDateComponents dengan dan NSCalendar dan NSDate Anda dan bandingkan komponen jam.
sumber
Jika Anda dapat menargetkan iOS 10.0 + / macOS 10.12+, gunakan
DateInterval
kelas tersebut.Pertama, buat interval tanggal dengan tanggal mulai dan akhir:
let start: Date = Date() let middle: Date = Date() let end: Date = Date() let dateInterval: DateInterval = DateInterval(start: start, end: end)
Kemudian, periksa apakah tanggal tersebut dalam interval dengan menggunakan
contains
metodeDateInterval
:let dateIsInInterval: Bool = dateInterval.contains(middle) // true
sumber
Ini dapat dilakukan dengan mudah menggunakan interval waktu tanggal, seperti:
const NSTimeInterval i = [date timeIntervalSinceReferenceDate]; return ([startDate timeIntervalSinceReferenceDate] <= i && [endDate timeIntervalSinceReferenceDate] >= i);
sumber
Melanjutkan solusi Quinn dan Brock, sangat bagus untuk implementasi subclass NSDate, sehingga dapat digunakan di mana saja seperti ini:
-(BOOL) isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate { return (([self compare:beginDate] != NSOrderedAscending) && ([self compare:endDate] != NSOrderedDescending)); }
Dan di bagian mana pun dari kode Anda, Anda dapat menggunakannya sebagai:
[myNSDate isBetweenDate:thisNSDate andDate:thatNSDate];
(myNSDate, thisNSDate dan thatNSDate tentu saja NSDates :)
sumber
Ada solusi yang lebih baik dan lebih cepat untuk masalah ini.
extention Date { func isBetween(from startDate: Date,to endDate: Date) -> Bool { let result = (min(startDate, endDate) ... max(startDate, endDate)).contains(self) return result } }
Kemudian Anda bisa menyebutnya seperti ini.
todayDate.isBetween(from: startDate, to: endDate)
Bahkan Anda dapat melewatkan tanggal secara acak karena ekstensi ini memeriksa mana yang minimum dan mana yang tidak.
Anda bisa menggunakannya di swift 3 ke atas.
sumber
Dengan Swift 5, Anda dapat menggunakan salah satu dari dua solusi di bawah ini untuk memeriksa apakah tanggal terjadi di antara dua tanggal lainnya.
# 1. Menggunakan
DateInterval
'scontains(_:)
metodeDateInterval
memiliki metode yang disebutcontains(_:)
.contains(_:)
memiliki deklarasi berikut:func contains(_ date: Date) -> Bool
Kode Playground berikut menunjukkan cara menggunakan
contains(_:)
untuk memeriksa apakah tanggal terjadi di antara dua tanggal lain:import Foundation let calendar = Calendar.current let startDate = calendar.date(from: DateComponents(year: 2010, month: 11, day: 22))! let endDate = calendar.date(from: DateComponents(year: 2015, month: 5, day: 1))! let myDate = calendar.date(from: DateComponents(year: 2012, month: 8, day: 15))! let dateInterval = DateInterval(start: startDate, end: endDate) let result = dateInterval.contains(myDate) print(result) // prints: true
# 2. Menggunakan
ClosedRange
'scontains(_:)
metodeClosedRange
memiliki metode yang disebutcontains(_:)
.contains(_:)
memiliki deklarasi berikut:func contains(_ element: Bound) -> Bool
Kode Playground berikut menunjukkan cara menggunakan
contains(_:)
untuk memeriksa apakah tanggal terjadi di antara dua tanggal lain:import Foundation let calendar = Calendar.current let startDate = calendar.date(from: DateComponents(year: 2010, month: 11, day: 22))! let endDate = calendar.date(from: DateComponents(year: 2015, month: 5, day: 1))! let myDate = calendar.date(from: DateComponents(year: 2012, month: 8, day: 15))! let range = startDate ... endDate let result = range.contains(myDate) //let result = range ~= myDate // also works print(result) // prints: true
sumber
Versi yang lebih baik di Swift:
@objc public class DateRange: NSObject { let startDate: Date let endDate: Date init(startDate: Date, endDate: Date) { self.startDate = startDate self.endDate = endDate } @objc(containsDate:) func contains(_ date: Date) -> Bool { let startDateOrder = date.compare(startDate) let endDateOrder = date.compare(endDate) let validStartDate = startDateOrder == .orderedAscending || startDateOrder == .orderedSame let validEndDate = endDateOrder == .orderedDescending || endDateOrder == .orderedSame return validStartDate && validEndDate } }
sumber