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 date]]; Я получаю первый месяц... Почему? Я использую эти два метода, потому что мне нужен интервал, начиная с первой секунды первой даты (beginOfDay: date1) до последней секунды второй даты (endOfDay: Date2)...

Ответ 1

Вам не хватает NSDayCalendarUnit в

NSDateComponents *components = [cal components:( NSMonthCalendarUnit | NSYearCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit ) fromDate:date];

Ответ 2

Начало дня/конец дня - 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

Ответ 3

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

В 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. (См. Раздел " Календарные расчеты")

Методы NSCalendar обсуждаются NSHipster.

Ответ 5

Мои быстрые расширения для 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
    }
}

Ответ 6

Swift 5.1 - XCode 11 с классом 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

Ответ 7

Вам не нужно устанавливать компоненты в ноль, просто игнорируйте их:

-(NSDate *)beginningOfDay:(NSDate *)date
{
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *components = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:date];
    return [calendar dateFromComponents:components];
}

Ответ 8

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)
    }

Ответ 9

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

Для меня ни один из ответов здесь, а также где работает 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

В 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

Ответ 12

Вам не хватает NSDayCalendarUnit в компонентах.

Ответ 13

Еще один способ получить результат:

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];

Ответ 14

Objective-C

NSCalendar * calendar = [NSCalendar currentCalendar];
NSDate * startDate = [calendar startOfDayForDate:[NSDate date]];
NSLog(@"start date is %@", startDate);

Ответ 15

Просто еще один способ, используя 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)

Ответ 16

Так как iOS 8.0+ / macOS 10.12+ / tvOS 10.0+ / watchOS 3.0+ есть встроенная функция в Foundation, которую вы можете использовать из коробки. Нет необходимости реализовывать собственные функции.

public func startOfDay(for date: Date) -> Date

Итак, вы можете использовать его следующим образом:

let midnightDate = Calendar(identifier: .gregorian).startOfDay(for: Date())

Стоит помнить, что это учитывает часовой пояс устройства. Вы можете установить .timeZone на calendar, если хотите иметь, например, зону UTC.

Ссылка на справочные страницы Apple: https://developer.apple.com/reference/foundation/nscalendar/1417161-startofday.

Ответ 17

Для быстрой 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!)")

Ответ 18

Вот что я использую для 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, однако имейте в виду, что добавление расширения увеличивается время компиляции (если не в том же файле, класса), так что если вам это нужно только в одном месте или в одном классе... не используйте расширение.

Ответ 19

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)!
    }
}

Ответ 20

Просто для справки, простой способ установить начало и конец дня в 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)")

Ответ 21

Календарные единицы следует рассматривать как интервалы. В iOS 10 Calendar есть несколько хороших методов для этого.

let day = Calendar.autoupdatingCurrent.dateInterval(of: .day, for: Date())
day?.end
day?.start

Вы можете использовать тот же метод, чтобы получить начало/конец любого календарного компонента (неделя/месяц/год и т.д.)