NSDate 시작일과 종료일


104
    -(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)까지의 간격이 필요하기 때문에이 두 가지 방법을 사용합니다.


2
시간을 0 UTC 시간으로 설정하려면 timeIntervalSince ...를 얻는 더 쉬운 방법이고 시간을 자른 다음 다시 NSDate로 변환합니다. 그리고 이것은 먼저 시간대의 secondsFromGMT로 시간 간격을 조정 한 다음 잘린 후 반대 방식으로 조정하면 다른 시간대에서 작동합니다. (하루의 끝은 분명히 나중에 23 : 59 : 59.999이며 시간 간격이있는 동안 간단한 추가로 얻을 수 있습니다.)
Hot Licks

실제 종료 (이 경우 1 초) 전 임의의 시간으로 "종료일"을 지정하는 것은 결함이있는 소프트웨어의 레시피처럼 보입니다. 1ms를 사용하면 글리치가 덜 자주 발생합니다. 또는 23 시간을 사용하여 버그가 잡힐 가능성을 높일 수 있습니다. :-)
Edward Brey

답변:


33

당신은 누락 NSDayCalendarUnit

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

1
요일 구성 요소를 추가하면 전날 23:00이되는 이상한 동작이 있습니다.
Mike M

3
@Mike 사용 시간대 : components.timeZone = [NSTimeZone timeZoneWithName : @ "GMT"];
dimaxyu

@dimaxyu가 맞습니다. 신속하게 its : components.timeZone = NSTimeZone (name : "GMT")
Tom Bevelander

220

하루의 시작 / 하루의 끝 — 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

1
NSYearCalendarUnit, NSMonthCalendarUnit,와 NSDayCalendarUnit아이폰 OS 8. 기준으로 사용되지 않습니다 NSCalendarUnitYear, NSCalendarUnitMonth그리고 NSCalendarUnitDay대신!
T Blank

6
하루의 시작을 위해 사용 [[NSCalendar currentCalendar] startOfDayForDate : ...] iOS8의에 대한 +
GingerBreadMane

5
이것은 현재 시간대의 startOfDay를 반환합니다! NSDate는 UTC로 예상되지만이 변환기는 기본 시간대에 대해 수정 된 시간을 반환합니다.
Tom Bevelander 2016 년

3
endOfDay가 선택 사항 인 이유는 무엇입니까? startOfDay가 nil이 아니라 endOfDay가 nil이 될 수있는 상황이 있습니까?
Mansurov Ruslan

1
따라서 이것을 사용하는 방법에 따라 일의 끝과 시작 사이에 1 초의 간격을 염두에 두어야합니다. developer.apple.com/documentation/foundation/nsdate/…
atlex2 dec

29

Swift 5 간단하고 정확한 답변.

시작 시간 : 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)

특별한

let yesterday = Calendar.current.date(byAdding: .day, value: -1, to: noon)!
let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: noon)!
let specificDate = Date("2020-01-01")

extension Date {
    init(_ dateString:String) {
        let dateStringFormatter = DateFormatter()
        dateStringFormatter.dateFormat = "yyyy-MM-dd"
        dateStringFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX") as Locale
        let date = dateStringFormatter.date(from: dateString)!
        self.init(timeInterval:0, since:date)
    }
}

2
이게 어떻게 let dateAtEnd = Calendar.current.date(bySettingHour: 23, minute: 59, second: 59, of: Date())다릅니 까?
Andres Canella 18.06.28

1
차이 없음 .
August Lin

21

iOS 8+에서는 정말 편리합니다. 넌 할 수있어:

let startOfDay = NSCalendar.currentCalendar().startOfDayForDate(date)

하루의 끝을 확인하려면 하루의 끝을 정의하는 방법에 따라 23 시간 59 분 59 초 동안 NSCalendar 메서드를 사용하면됩니다.

// 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 문서 . (섹션 : 달력 계산 참조 )

NSHipster에서 논의한 NSCalendar 메서드 .


17

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

스위프트 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
    }
}

당신은 -1 초 설정하고 dateByAddingTimeInterval 사용하지 않고 같은를 얻을 수 있습니다
벤 싱클레어

시간대 문제를 방지하려면 다음을 추가하십시오. components.timeZone = NSTimeZone (name : "GMT")
Tom Bevelander

12

스위프트 5.1 - 엑스 코드 (11)Date대신의 클래스 NSDateCalender대신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

나는 오류 유형 선언되지 않은 얻고 Date난 놀이터에서 그것을 시도
홍길동

1
여기서 저에게 효과가 있습니다. UIKit을 가져 import UIKit왔습니까?
Ben

2
@Ben Date and Calendar는 UIKit이 아니라 Foundation에 있지만 UIKit이 Foundation을 가져옵니다
Arbitur

4

구성 요소를 0으로 설정할 필요없이 무시하면됩니다.

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

2
"새로"사용 가능 : [calendar startOfDayForDate:date],하지만 -endOfDayForDate:안타깝게도 는 없습니다 ...
Julian F. Weinert 2016

4

나에게는 여기에 대한 답변이 없으며 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 시간대로 간주됩니다. 따라서 구성 요소를 추출하기 전과 나중에 이러한 구성 요소에서 날짜를 추출 할 때 시간대를 설정해야합니다.


4

스위프트 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)
    }

4

Swift3는 사용 * XCode8
애플을 제거하고 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())!
  }
}

4

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

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

2

NSDayCalendarUnit구성 요소 가 누락되었습니다 .


2

목표 -C

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

2

신속한 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!)")

2

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

저건 완벽 해! 고마워!
Baran Emre

1

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

이것은 장치 시간대를 고려한다는 점을 기억할 가치가 있습니다. 당신은 설정할 수 있습니다 .timeZonecalendar당신이 예를 들어, UTC 시간대를 갖고 싶어합니다.

Apple 참조 페이지 링크 : https://developer.apple.com/reference/foundation/nscalendar/1417161-startofday .


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)

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있지만 확장을 추가하면 컴파일 시간이 증가하므로 (클래스와 동일한 파일에 있지 않는 한) 한 위치 또는 한 클래스에서만 필요합니다. .. 확장자를 사용하지 마십시오.


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

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

-1

달력 단위는 간격으로 생각해야합니다. iOS 10 Calendar에는 이에 대한 몇 가지 좋은 방법이 있습니다.

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

동일한 방법을 사용하여 달력 구성 요소 (주 / 월 / 년 등)의 시작 / 종료를 가져올 수 있습니다.


이것은 올바르지 않습니다. day?.end오늘 밤 11:59 PM이 아니라 내일 12:00 AM으로 평가됩니다.
Casey Wagner
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.