-(NSDate *)beginningOfDay:(NSDate *)date
{
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *components = [cal components:( NSMonthCalendarUnit | NSYearCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit ) fromDate:date];
[components setHour:0];
[components setMinute:0];
[components setSecond:0];
return [cal dateFromComponents:components];
}
-(NSDate *)endOfDay:(NSDate *)date
{
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *components = [cal components:( NSMonthCalendarUnit | NSYearCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit ) fromDate:date];
[components setHour:23];
[components setMinute:59];
[components setSecond:59];
return [cal dateFromComponents:components];
}
当我打电话:[self endOfDay:[NSDate date]]; 我得到了本月的第一天......为什么?我使用这两种方法,因为我需要一个从第一个日期的第一秒开始的间隔(beginningOfDay:date1)到第二个日期的最后一秒(endOfDay:Date2)......
答案 0 :(得分:182)
// Extension
extension Date {
var startOfDay: Date {
return Calendar.current.startOfDay(for: self)
}
var endOfDay: Date {
var components = DateComponents()
components.day = 1
components.second = -1
return Calendar.current.date(byAdding: components, to: startOfDay)!
}
var startOfMonth: Date {
let components = Calendar.current.dateComponents([.year, .month], from: startOfDay)
return Calendar.current.date(from: components)!
}
var endOfMonth: Date {
var components = DateComponents()
components.month = 1
components.second = -1
return Calendar.current.date(byAdding: components, to: startOfMonth)!
}
}
// End of day = Start of tomorrow minus 1 second
// End of month = Start of next month minus 1 second
答案 1 :(得分:31)
您在
中缺少NSDayCalendarUnit
NSDateComponents *components = [cal components:( NSMonthCalendarUnit | NSYearCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit ) fromDate:date];
答案 2 :(得分:21)
在iOS 8+中,这非常方便;你可以这样做:
let startOfDay = NSCalendar.currentCalendar().startOfDayForDate(date)
要结束一天的结束,那么只需使用NSCalendar方法23小时59分59秒,具体取决于您如何定义结束日期。
// Swift 2.0
let components = NSDateComponents()
components.hour = 23
components.minute = 59
components.second = 59
let endOfDay = NSCalendar.currentCalendar().dateByAddingComponents(components, toDate: startOfDay, options: NSCalendarOptions(rawValue: 0))
Apple iOS NSCalendar Documentation。 (参见章节:日历计算)
答案 3 :(得分:20)
Swift 4 简单而精确的答案。
开始时间:00:00:00
结束时间:23:59:59.5
let date = Date() // current date or replace with a specific date
let calendar = Calendar.current
let startTime = calendar.startOfDay(for: date)
let endTime = calendar.date(bySettingHour: 23, minute: 59, second: 59, of: date)
答案 4 :(得分:16)
我对NSDate的Swift扩展:
Swift 1.2
extension NSDate {
func beginningOfDay() -> NSDate {
var calendar = NSCalendar.currentCalendar()
var components = calendar.components(.CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay, fromDate: self)
return calendar.dateFromComponents(components)!
}
func endOfDay() -> NSDate {
var components = NSDateComponents()
components.day = 1
var date = NSCalendar.currentCalendar().dateByAddingComponents(components, toDate: self.beginningOfDay(), options: .allZeros)!
date = date.dateByAddingTimeInterval(-1)!
return date
}
}
Swift 2.0
extension NSDate {
func beginningOfDay() -> NSDate {
let calendar = NSCalendar.currentCalendar()
let components = calendar.components([.Year, .Month, .Day], fromDate: self)
return calendar.dateFromComponents(components)!
}
func endOfDay() -> NSDate {
let components = NSDateComponents()
components.day = 1
var date = NSCalendar.currentCalendar().dateByAddingComponents(components, toDate: self.beginningOfDay(), options: [])!
date = date.dateByAddingTimeInterval(-1)
return date
}
}
答案 5 :(得分:11)
Swift 4.2 - XCode 10 Date
级而不是NSDate
和Calender
而不是NSCalender
extension Date {
var startOfDay : Date {
let calendar = Calendar.current
let unitFlags = Set<Calendar.Component>([.year, .month, .day])
let components = calendar.dateComponents(unitFlags, from: self)
return calendar.date(from: components)!
}
var endOfDay : Date {
var components = DateComponents()
components.day = 1
let date = Calendar.current.date(byAdding: components, to: self.startOfDay)
return (date?.addingTimeInterval(-1))!
}
}
用法:
let myDate = Date()
let startOfDate = myDate.startOfDay
let endOfDate = myDate.endOfDay
答案 6 :(得分:5)
我认为在Swift中最简洁的方法如下:
extension Date {
func startOfDay() -> Date {
return Calendar.current.startOfDay(for: self)
}
func endOfDay() -> Date {
return Calendar.current.date(bySettingHour: 23, minute: 59, second: 59, of: self) ?? self
}
}
答案 7 :(得分:4)
您不必将组件设置为零,只需忽略它们:
-(NSDate *)beginningOfDay:(NSDate *)date
{
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:date];
return [calendar dateFromComponents:components];
}
答案 8 :(得分:4)
Swift 3
main.js
答案 9 :(得分:4)
Swift3 使用 * XCode8
Apple正在从类名中删除NS
,以便NSDate
可以换出Date
。如果你试图让他们说他们总是会失败,你可能会得到一个编译器警告,但是当你在操场上运行时它们可以正常工作。
我将核心数据模型中生成的NSDate
替换为Date
,但它们仍可用。
extension Date {
func startTime() -> Date {
return Calendar.current.startOfDay(for: self)
}
func endTime() -> Date {
var components = DateComponents()
components.day = 1
components.second = -1
return Calendar.current.date(byAdding: components, to: startTime())!
}
}
答案 10 :(得分:3)
对我来说,这里没有任何答案,否则stackoverflow工作的地方。为了开始今天,我做到了这一点。
NSCalendar * gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
[gregorian setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSDateComponents *components = [gregorian components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay fromDate:[NSDate date]];
[components setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSDate *beginningOfToday = [gregorian dateFromComponents:components];
请注意[gregorian setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
和[components setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
。
创建日历时,它会使用当前时区进行初始化,并且从其组件中提取日期时,由于NSDate没有时区,因此将当前时区的日期视为UTC时区。因此,我们需要在提取组件之前设置时区,然后在从这些组件中提取日期时设置时区。
答案 11 :(得分:2)
您在组件中缺少NSDayCalendarUnit
。
答案 12 :(得分:2)
获得结果的另一种方法:
NSDate *date = [NSDate date];
NSDateComponents *components = [[NSDateComponents alloc] init];
components.day = [[NSCalendar currentCalendar] ordinalityOfUnit:(NSCalendarUnitDay) inUnit:(NSCalendarUnitEra) forDate:date];
NSDate *dayBegin = [[NSCalendar currentCalendar] dateFromComponents:components];
components.day += 1;
NSDate *dayEnd = [[NSCalendar currentCalendar] dateFromComponents:components];
答案 13 :(得分:1)
由于iOS 8.0+ / macOS 10.12+ / tvOS 10.0+ / watchOS 3.0+
基金会内置了一个内置功能,您可以直接使用它。无需实现自己的功能。
public func startOfDay(for date: Date) -> Date
所以你可以这样使用它:
let midnightDate = Calendar(identifier: .gregorian).startOfDay(for: Date())
值得记住的是,这需要考虑设备时区。如果您想拥有例如UTC区域,可以在.timeZone
上设置calendar
。
链接到Apple参考页面:https://developer.apple.com/reference/foundation/nscalendar/1417161-startofday。
答案 14 :(得分:1)
使用dateInterval(of:start:interval:for:)
Calendar
的另一种方式
返回时startDate
包含当天的开始时间,interval
包含当天的秒数。
func startAndEnd(of date : Date) -> (start : Date, end : Date) {
var startDate = Date()
var interval : TimeInterval = 0.0
Calendar.current.dateInterval(of: .day, start: &startDate, interval: &interval, for: date)
var endDate = startDate.addingTimeInterval(interval-1)
return (start : startDate, end : endDate)
}
let (start, end) = startAndEnd(of: Date())
print(start, end)
答案 15 :(得分:1)
快速4
var calendar = Calendar.current
calendar.timeZone = NSTimeZone(abbreviation: "UTC")! as TimeZone
let dateAtMidnight = calendar.startOfDay(for: Date())
//For End Date
var components = DateComponents()
components.day = 1
components.second = -1
let dateAtEnd = calendar.date(byAdding: components, to: dateAtMidnight)
print("dateAtMidnight :: \(dateAtMidnight)")
print("dateAtEnd :: \(dateAtEnd!)")
答案 16 :(得分:1)
这是我在Swift 4.2中使用的:
let calendar = Calendar.current
let fromDate = calendar.startOfDay(for: Date())
let endDate = calendar.date(bySettingHour: 23, minute: 59, second: 59, of: Date())
对我来说就像是一种魅力。
您可以将此扩展名添加到Date
的开始日期和结束日期的扩展名中,但是请记住,添加扩展名会增加编译时间(除非与该类位于同一文件中),因此,如果仅在一个位置需要它或在一堂课中...不要使用扩展名。
答案 17 :(得分:0)
extension Date {
func stringFrom(dateFormat: String) -> String {
let formatter = DateFormatter()
formatter.dateFormat = dateFormat
return formatter.string(from: self)
}
func firstSecondInDay() -> Date {
let dayStr = self.stringFrom(dateFormat: "yyyy-MM-dd")
let firstSecondStr = "\(dayStr) 00:00:00"
let format = DateFormatter()
format.dateFormat = "yyyy-MM-dd HH:mm:ss"
return format.date(from: firstSecondStr)!
}
func lastSecondInDay() -> Date {
let dayStr = self.stringFrom(dateFormat: "yyyy-MM-dd")
let laseSecondStr = "\(dayStr) 23:59:59"
let format = DateFormatter()
format.dateFormat = "yyyy-MM-dd HH:mm:ss"
return format.date(from: laseSecondStr)!
}
}
答案 18 :(得分:0)
仅供参考,在Swift 4中设置一天的开始和结束的简单方法,
var comp: DateComponents = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute, .second], from: Date())
comp.hour = 0
comp.minute = 0
comp.second = 0
comp.timeZone = TimeZone(abbreviation: "UTC")!
//Set Start of Day
let startDate : Date = Calendar.current.date(from: comp)!
print(“Day of Start : \(startDate)")
//Set End of Day
comp.hour = 23
comp.minute = 59
comp.second = 59
let endDate : Date = Calendar.current.date(from:comp)!
print("Day of End : \(endDate)")
答案 19 :(得分:0)
日历单位应视为间隔。从iOS 10开始,Calendar
为此提供了一些不错的方法
let day = Calendar.autoupdatingCurrent.dateInterval(of: .day, for: Date())
day?.end
day?.start
您可以使用相同的方法来获取任何日历组件的开始/结束(周/月/年等)
答案 20 :(得分:0)
在Swift 3及更高版本中
extension Date {
var startOfDayDate: Date {
return Calendar.current.startOfDay(for: self)
}
var endOfDayDate: Date {
let nextDayDate = Calendar.current.date(byAdding: .day, value: 1, to: self.startOfDayDate)!
return nextDayDate.addingTimeInterval(-1)
}
}
用法:
var currentDayStart = Date().startOfDayDate
var currentDayEnd = Date().endOfDayDate
答案 21 :(得分:0)
在Swift 5.3中,Calendar.current.startOfDay()和Calendar.current.date(bySettingHour :, minutes :, second :, of :)都是时区特定的。如果您希望将日期归一化为相同的时间(而不考虑时区),则应使用这样的GMT时间。
// Normalize time of aDate to 12:00 GMT
let aDate = Date()
let twelveGMT = 12 + TimeZone.current.secondsFromGMT() / 3600
let normalizedDate = Calendar.current.date(bySettingHour: twelveGMT, minute: 0, second: 0, of: aDate)
答案 22 :(得分:0)
由于 Calendar
结构包含 startOfDay(for:)
,我发现最好将 endOfDay(for:)
方法封装在 Calendar
上的扩展中,而不是在 Date
中。< /p>
以下代码可以放在 Playground 文件中以便快速执行。
import Foundation
extension Calendar {
func endOfDay(for date: Date) -> Date {
// Get the start of the date argument.
let dayStart = self.startOfDay(for: date)
// Add one day to the start of the day
// in order to get the start of the following day.
guard let nextDayStart = self.date(byAdding: .day, value: 1, to: dayStart) else {
preconditionFailure("Expected start of next day")
}
// Create date components that will subtract a single
// second from the start of the next day. This will
// allow you to get the last hour, last minute, and last
// second of the previous day, which is the day for the
// date argument that was passed to this method.
var components = DateComponents()
components.second = -1
// Add the date components to the date for the next
// day, which will perform the subtraction of the single
// second. This will return the end of the day for the date
// that was passed into this method.
guard let dayEnd = self.date(byAdding: components, to: nextDayStart) else {
preconditionFailure("Expected end of day")
}
// Simply return the date value.
return dayEnd
}
}
要查看格式化的日期,请创建一个 DateFormatter
并打印输出。
let formatter = DateFormatter()
formatter.dateStyle = .long
formatter.timeStyle = .long
Calendar.current.endOfDay(for: Date()) // "Dec 31, 2020 at 11:59 PM"