NSDate начало и конец дня
-(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]]; Я получаю первое число месяца ... Почему так? Я использую эти два метода, потому что мне нужен интервал от первой секунды первой даты (beginningOfDay:date1) до последней секунды второй даты (endOfDay:Date2) ...
16 ответов
вам не хватает NSDayCalendarUnit
на
NSDateComponents *components = [cal components:( NSMonthCalendarUnit | NSYearCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit ) fromDate:date];
Начало Дня / Конец Дня - Swift 4
// 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
в 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))
Яблоко iOS NSCalendar документации. (См. Раздел:Календарным Расчетам)
мои расширения Swift для NSDate:
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
}
}
Swift 4 Простой и более точный ответ.
время начала: 00:00:00
время окончания: 23:59:59.5
var date = Date() // current date or replace with a specific date
var calendar = Calendar.current
let dateAtMidnight = calendar.startOfDay(for: date)
let dateAtEnd = calendar.date(bySettingHour: 23, minute: 59, second: 59, of: date)
Swift 4-XCode 9 С 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
вам не нужно настраивать компоненты на ноль, просто игнорируйте их:
-(NSDate *)beginningOfDay:(NSDate *)date
{
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:date];
return [calendar dateFromComponents:components];
}
Swift 3
class func today() -> NSDate {
return NSDate()
}
class func dayStart() -> NSDate {
return NSCalendar.current.startOfDay(for: NSDate() as Date) as NSDate
}
class func dayEnd() -> NSDate {
let components = NSDateComponents()
components.day = 1
components.second = -1
return NSCalendar.current.date(byAdding: components as DateComponents, to: self.dayStart() as Date)
}
для меня ни один из ответов здесь, и еще где на сайте 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. Поэтому нам нужно установить часовой пояс перед извлечением компонентов и позже при извлечении даты из этих компонентов.
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())!
}
}
еще один способ получить результат:
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];
С 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())
стоит помнить, что это принимает во внимание часовой пояс устройства. Вы можете установить .timeZone
on calendar
если вы хотите иметь, например, зону UTC.
ссылка на справочные страницы Apple: https://developer.apple.com/reference/foundation/nscalendar/1417161-startofday.
просто другой способ использования dateInterval(of:start:interval:for:)
of 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)
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)!
}
}
С
NSCalendar * calendar = [NSCalendar currentCalendar];
NSDate * startDate = [calendar startOfDayForDate:[NSDate date]];
NSLog(@"start date is %@", startDate);