[英]How can I set an NSDate object to midnight?
我有一個NSDate
對象,我想將其設置為任意時間(例如午夜),以便我可以使用timeIntervalSince1970
函數一致地檢索數據,而不必擔心創建對象的時間。
我嘗試使用NSCalendar
並使用一些 Objective-C 方法修改其組件,如下所示:
let date: NSDate = NSDate()
let cal: NSCalendar = NSCalendar(calendarIdentifier: NSGregorianCalendar)!
let components: NSDateComponents = cal.components(NSCalendarUnit./* a unit of time */CalendarUnit, fromDate: date)
let newDate: NSDate = cal.dateFromComponents(components)
上述方法的問題是你只能設置一個時間單位( /* a unit of time */
),所以你只能有以下之一是准確的:
有沒有辦法同時設置小時、分鍾和秒並保留日期(日/月/年)?
你的陳述
上述方法的問題是只能設置一個單位時間...
是不正確的。 NSCalendarUnit
符合從BitwiseOperationsType
繼承的RawOptionSetType
協議。 這意味着選項可以按位與&
和|
組合。 .
在Swift 2 (Xcode 7)中,它再次被更改為提供類似集合的接口的OptionSetType
,例如,參見Error combine NSCalendarUnit with OR (pipe) in Swift 2.0 。
因此,以下在 iOS 7 和 iOS 8 中編譯和工作:
let date = NSDate()
let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
// Swift 1.2:
let components = cal.components(.CalendarUnitDay | .CalendarUnitMonth | .CalendarUnitYear, fromDate: date)
// Swift 2:
let components = cal.components([.Day , .Month, .Year ], fromDate: date)
let newDate = cal.dateFromComponents(components)
(請注意,我省略了變量的類型注釋,Swift 編譯器會自動從賦值右側的表達式中推斷出類型。)
還可以使用rangeOfUnit()
方法(iOS 7 和 iOS 8)確定給定一天(午夜)的開始:
let date = NSDate()
let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
var newDate : NSDate?
// Swift 1.2:
cal.rangeOfUnit(.CalendarUnitDay, startDate: &newDate, interval: nil, forDate: date)
// Swift 2:
cal.rangeOfUnit(.Day, startDate: &newDate, interval: nil, forDate: date)
如果您的部署目標是 iOS 8,那么它就更簡單了:
let date = NSDate()
let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let newDate = cal.startOfDayForDate(date)
Swift 3 (Xcode 8) 的更新:
let date = Date()
let cal = Calendar(identifier: .gregorian)
let newDate = cal.startOfDay(for: date)
是的。
您根本不需要擺弄NSCalendar
的組件; 您可以簡單地調用dateBySettingHour
方法並將ofDate
參數與您現有的日期一起使用。
let date: NSDate = NSDate()
let cal: NSCalendar = NSCalendar(calendarIdentifier: NSGregorianCalendar)!
let newDate: NSDate = cal.dateBySettingHour(0, minute: 0, second: 0, ofDate: date, options: NSCalendarOptions())!
對於斯威夫特 3:
let date: Date = Date()
let cal: Calendar = Calendar(identifier: .gregorian)
let newDate: Date = cal.date(bySettingHour: 0, minute: 0, second: 0, of: date)!
然后,為了讓你的時間從 1970 年開始,你可以做
let time: NSTimeInterval = newDate.timeIntervalSince1970
dateBySettingHour
在 OS X Mavericks (10.9) 中引入,並在 iOS 8 中獲得了 iOS 支持。
NSCalendar.h
中的聲明:
/*
This API returns a new NSDate object representing the date calculated by setting hour, minute, and second to a given time.
If no such time exists, the next available time is returned (which could, for example, be in a different day than the nominal target date).
The intent is to return a date on the same day as the original date argument. This may result in a date which is earlier than the given date, of course.
*/
- (NSDate *)dateBySettingHour:(NSInteger)h minute:(NSInteger)m second:(NSInteger)s ofDate:(NSDate *)date options:(NSCalendarOptions)opts NS_AVAILABLE(10_9, 8_0);
這是一個不使用dateBySettingHour
函數的示例(以確保您的代碼仍然與 iOS 7 設備兼容):
NSDate* now = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *dateComponents = [gregorian components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:now];
NSDate* midnightLastNight = [gregorian dateFromComponents:dateComponents];
呸。
我喜歡用 C# 編碼是有原因的...
任何人都喜歡一些可讀的代碼..?
DateTime midnightLastNight = DateTime.Today;
;-)
Swift iOS 8 及更高版本:人們往往會忘記 Calendar 和 DateFormatter 對象有一個 TimeZone。 如果您沒有設置所需的時區,並且默認時區值不適合您,則生成的小時和分鍾可能會關閉。
注意:在實際應用中,您可以進一步優化此代碼。
注意:當不關心時區時,結果在一台設備上可能是好的,而在另一台設備上的結果可能會因為時區設置不同而變差。
注意:一定要添加一個現有的時區標識符! 此代碼不處理丟失或拼寫錯誤的時區名稱。
func dateTodayZeroHour() -> Date {
var cal = Calendar.current
cal.timeZone = TimeZone(identifier: "Europe/Paris")!
return cal.startOfDay(for: Date())
}
你甚至可以擴展語言。 如果默認時區適合您,請不要設置它。
extension Date {
var midnight: Date {
var cal = Calendar.current
cal.timeZone = TimeZone(identifier: "Europe/Paris")!
return cal.startOfDay(for: self)
}
var midday: Date {
var cal = Calendar.current
cal.timeZone = TimeZone(identifier: "Europe/Paris")!
return cal.date(byAdding: .hour, value: 12, to: self.midnight)!
}
}
並像這樣使用它:
let formatter = DateFormatter()
formatter.timeZone = TimeZone(identifier: "Europe/Paris")
formatter.dateFormat = "yyyy/MM/dd HH:mm:ss"
let midnight = Date().midnight
let midnightString = formatter.string(from: midnight)
let midday = Date().midday
let middayString = formatter.string(from: midday)
let wheneverMidnight = formatter.date(from: "2018/12/05 08:08:08")!.midnight
let wheneverMidnightString = formatter.string(from: wheneverMidnight)
print("dates: \(midnightString) \(middayString) \(wheneverMidnightString)")
在我們的例子中,字符串轉換和 DateFormatter 需要用於某些格式化和移動時區,因為日期對象本身並不保留或關心時區值。
小心! 結果值可能會因計算鏈中某處的時區偏移而有所不同!
斯威夫特 5+
let date = Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: Date())
在我看來,最容易驗證但可能不是最快的解決方案是使用字符串。
func set( hours: Int, minutes: Int, seconds: Int, ofDate date: Date ) -> Date {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let newDateString = "\(dateFormatter.string(from: date)) \(hours):\(minutes):\(seconds)"
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
return dateFormatter.date(from: newDateString)
}
func resetHourMinuteSecond(date: NSDate, hour: Int, minute: Int, second: Int) -> NSDate{
let nsdate = NSCalendar.currentCalendar().dateBySettingHour(hour, minute: minute, second: second, ofDate: date, options: NSCalendarOptions(rawValue: 0))
return nsdate!
}
使用當前日歷獲取當前時間的一天開始。
let today = Calendar.current.startOfDay(for: Date())
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.