ฉันกำลังพยายามหาว่าวันที่ปัจจุบันอยู่ในช่วงวันที่โดยใช้ NSDate หรือไม่
ตัวอย่างเช่นคุณสามารถรับวันที่ / เวลาปัจจุบันโดยใช้ NSDate:
NSDate rightNow = [NSDate date];
จากนั้นฉันต้องการใช้วันที่ดังกล่าวเพื่อตรวจสอบว่าอยู่ในช่วง9.00-17.00 น . หรือไม่
ฉันกำลังพยายามหาว่าวันที่ปัจจุบันอยู่ในช่วงวันที่โดยใช้ NSDate หรือไม่
ตัวอย่างเช่นคุณสามารถรับวันที่ / เวลาปัจจุบันโดยใช้ NSDate:
NSDate rightNow = [NSDate date];
จากนั้นฉันต้องการใช้วันที่ดังกล่าวเพื่อตรวจสอบว่าอยู่ในช่วง9.00-17.00 น . หรือไม่
คำตอบ:
ฉันคิดวิธีแก้ปัญหาขึ้นมา หากคุณมีวิธีแก้ไขที่ดีกว่าอย่าลังเลที่จะทิ้งไว้และฉันจะทำเครื่องหมายว่าถูกต้อง
+ (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;
}
- (BOOL)isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate;
return !([date compare:startDate] == NSOrderedAscending || [date compare:endDate] == NSOrderedDescending);
สำหรับส่วนแรกให้ใช้คำตอบจาก@kperryuaเพื่อสร้างออบเจ็กต์ NSDate ที่คุณต้องการเปรียบเทียบ จากคำตอบของคุณสำหรับคำถามของคุณเองดูเหมือนว่าคุณคิดออกแล้ว
สำหรับการเปรียบเทียบวันที่จริงฉันเห็นด้วยกับความคิดเห็นของ@Timในคำตอบของคุณ มันกระชับมากขึ้น แต่ก็เทียบเท่ากับรหัสของคุณจริงๆและฉันจะอธิบายว่าทำไม
+ (BOOL) date:(NSDate*)date isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate {
return (([date compare:beginDate] != NSOrderedAscending) && ([date compare:endDate] != NSOrderedDescending));
}
แม้ว่าอาจดูเหมือนว่าคำสั่งส่งคืนต้องประเมินตัวถูกดำเนินการทั้งสองตัวของตัวดำเนินการ && แต่ก็ไม่ได้เป็นเช่นนั้นจริง กุญแจสำคัญคือ " การประเมินการลัดวงจร " ซึ่งนำไปใช้ในภาษาการเขียนโปรแกรมที่หลากหลายและแน่นอนในภาษา C โดยทั่วไปตัวดำเนินการ&และ&&"ลัดวงจร" หากอาร์กิวเมนต์แรกเป็น 0 (หรือ NO, ศูนย์ ฯลฯ ) ในขณะที่|และ||ทำเช่นเดียวกันถ้าอาร์กิวเมนต์แรกคือไม่ 0 ถ้าdateมาก่อนbeginDateผลตอบแทนการทดสอบโดยไม่ต้องไปเปรียบเทียบกับNO endDateโดยทั่วไปจะทำสิ่งเดียวกันกับรหัสของคุณ แต่เป็นคำสั่งเดียวในบรรทัดเดียวไม่ใช่ 5 (หรือ 7 ที่มีช่องว่าง)
สิ่งนี้มีจุดมุ่งหมายเพื่อเป็นอินพุตที่สร้างสรรค์เนื่องจากเมื่อโปรแกรมเมอร์เข้าใจวิธีที่ภาษาโปรแกรมเฉพาะของตนประเมินนิพจน์เชิงตรรกะพวกเขาสามารถสร้างได้อย่างมีประสิทธิภาพมากขึ้นโดยไม่ต้องมีประสิทธิภาพมากนัก อย่างไรก็ตามมีการทดสอบที่คล้ายกันซึ่งจะมีประสิทธิภาพน้อยกว่าเนื่องจากตัวดำเนินการบางรายไม่ลัดวงจร (อันที่จริงแล้วส่วนใหญ่ไม่สามารถลัดวงจรได้เช่นตัวดำเนินการเปรียบเทียบเชิงตัวเลข) เมื่อมีข้อสงสัยการแยกตรรกะของคุณออกจากกันอย่างชัดเจนจะปลอดภัยเสมอ แต่โค้ดจะอ่านได้ง่ายขึ้นมากเมื่อคุณปล่อยให้ภาษา / คอมไพเลอร์จัดการกับสิ่งเล็กน้อย สำหรับคุณ.
เวอร์ชัน Brock Woolf ใน 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
}
}
หากคุณต้องการทราบว่าวันที่ปัจจุบันอยู่ระหว่างจุดที่กำหนดสองจุดในเวลา (9.00-17.00 น. ของวันที่ 7/1/52) ให้ใช้ NSCalendar และ NSDateComponents เพื่อสร้างอินสแตนซ์ NSDate สำหรับเวลาที่ต้องการและเปรียบเทียบกับวันที่ปัจจุบัน
หากคุณต้องการทราบว่าวันที่ปัจจุบันอยู่ระหว่างสองชั่วโมงนี้ทุกวันหรือไม่คุณอาจไปทางอื่น สร้างออบเจ็กต์ NSDateComponents ด้วยและ NSCalendar และ NSDate ของคุณและเปรียบเทียบส่วนประกอบชั่วโมง
หากคุณสามารถกำหนดเป้าหมายเป็น iOS 10.0 + / macOS 10.12+ ได้ให้ใช้DateIntervalคลาส
ขั้นแรกสร้างช่วงวันที่โดยมีวันที่เริ่มต้นและวันที่สิ้นสุด:
let start: Date = Date()
let middle: Date = Date()
let end: Date = Date()
let dateInterval: DateInterval = DateInterval(start: start, end: end)
จากนั้นตรวจสอบว่าวันที่อยู่ในช่วงเวลาหรือไม่โดยใช้containsวิธีการDateInterval:
let dateIsInInterval: Bool = dateInterval.contains(middle) // true
สามารถทำได้อย่างง่ายดายโดยใช้ช่วงเวลาของวันที่ดังนี้:
const NSTimeInterval i = [date timeIntervalSinceReferenceDate];
return ([startDate timeIntervalSinceReferenceDate] <= i &&
[endDate timeIntervalSinceReferenceDate] >= i);
การดำเนินการต่อด้วยโซลูชันของ Quinn และ Brock เป็นสิ่งที่ดีมากในการใช้งาน NSDate ย่อยดังนั้นจึงสามารถใช้งานได้ทุกที่ดังนี้:
-(BOOL) isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate {
return (([self compare:beginDate] != NSOrderedAscending) && ([self compare:endDate] != NSOrderedDescending));
}
และที่ส่วนใดส่วนหนึ่งของรหัสคุณสามารถใช้เป็น:
[myNSDate isBetweenDate:thisNSDate andDate:thatNSDate];
(myNSDate, thisNSDate และ thatNSDate แน่นอนว่า NSDates :)
มีวิธีแก้ปัญหาที่ดีกว่าและรวดเร็วกว่าสำหรับปัญหานี้
extention Date {
func isBetween(from startDate: Date,to endDate: Date) -> Bool {
let result = (min(startDate, endDate) ... max(startDate, endDate)).contains(self)
return result
}
}
แล้วจะเรียกแบบนี้ก็ได้
todayDate.isBetween(from: startDate, to: endDate)
แม้ว่าคุณจะผ่านการสุ่มวันที่ได้เนื่องจากส่วนขยายนี้จะตรวจสอบว่าส่วนขยายใดต่ำสุดและส่วนขยายใดไม่ได้
คุณสามารถใช้ใน swift 3 ขึ้นไป
ด้วย Swift 5 คุณสามารถใช้หนึ่งในสองวิธีด้านล่างเพื่อตรวจสอบว่าวันที่เกิดขึ้นระหว่างวันที่สองวันอื่น ๆ หรือไม่
DateInterval's contains(_:)วิธีDateIntervalcontains(_:)มีวิธีการที่เรียกว่า contains(_:)มีประกาศดังต่อไปนี้:
func contains(_ date: Date) -> Bool
ระบุว่าช่วงเวลานี้มีวันที่ที่กำหนดหรือไม่
รหัส Playground ต่อไปนี้แสดงวิธีใช้contains(_:)เพื่อตรวจสอบว่าวันที่เกิดขึ้นระหว่างวันที่สองวันอื่น ๆ หรือไม่:
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
ClosedRange's contains(_:)วิธีClosedRangecontains(_:)มีวิธีการที่เรียกว่า contains(_:)มีประกาศดังต่อไปนี้:
func contains(_ element: Bound) -> Bool
ส่งคืนค่าบูลีนที่ระบุว่าองค์ประกอบที่ระบุมีอยู่ในช่วงหรือไม่
รหัส Playground ต่อไปนี้แสดงวิธีใช้contains(_:)เพื่อตรวจสอบว่าวันที่เกิดขึ้นระหว่างวันที่สองวันอื่น ๆ หรือไม่:
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
เวอร์ชันที่ดีกว่าใน 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
}
}