NSDate gün başlangıcı ve gün sonu


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

}

Aradığımda: [self endOfDay: [NSDate tarihi]]; Ayın ilkini alıyorum ... Neden böyle? Bu iki yöntemi kullanıyorum çünkü ilk tarihin ilk saniyesinden (beginOfDay: date1) ikinci tarihin son saniyesine (endOfDay: Date2) kadar bir aralığa ihtiyacım var ...


2
Saatleri UTC saatine sıfır olarak ayarlamak istiyorsanız, timeIntervalSince ... değerini almanın daha kolay bir yolu, saatleri kısaltın ve ardından NSDate'e geri dönüştürün. Ve bu, zaman aralığını önce zaman diliminin saniyedenGMT'sine göre ayarlarsanız, ardından kısaltmadan sonra tersi şekilde ayarlarsanız, bu başka bir zaman dilimi için çalışacaktır. (Günün sonu, belli ki 23: 59: 59.999 sonradır ve bu, zaman aralığına sahipken basit bir ekleme ile elde edilebilir.)
Hot Licks

"Gün sonu" nun gerçek sonundan (bu durumda bir saniye) önce gelişigüzel bir zaman olarak belirlenmesi, hatalı yazılım için bir reçete gibi görünür. 1 ms kullanırsanız, aksaklıklar daha az sıklıkta olacaktır. Veya herhangi bir hatanın yakalanma olasılığının daha yüksek olması için 23 saati kullanabilirsiniz. :-)
Edward Brey

Yanıtlar:


33

Sen eksik NSDayCalendarUnityılında

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

1
Gün bileşenini eklersem önceki günün 23: 00'ını aldığım garip bir davranışım var.
Mike M

3
@Mike saat dilimini kullanın: components.timeZone = [NSTimeZone timeZoneWithName: @ "GMT"];
dimaxyu

@dimaxyu haklı. Hızlı bir şekilde: components.timeZone = NSTimeZone (ad: "GMT")
Tom Bevelander

221

Gün Başlangıcı / Gün Sonu - 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, NSMonthCalendarUnitVe NSDayCalendarUnitiOS 8. Kullanım olarak kaldırıldıktan NSCalendarUnitYear, NSCalendarUnitMonthve, NSCalendarUnitDayyerine!
T Boş

6
Günün başlangıcı için iOS8 + için [[NSCalendar currentCalendar] startOfDayForDate: ...] kullanın
GingerBreadMane

5
Bu, geçerli saat dilimindeki startOfDay'i döndürür! NSDate'in UTC cinsinden olması beklenir, ancak bu dönüştürücü, varsayılan saat dilimi için düzeltilmiş bir zamanı döndürür.
Tom Bevelander

3
EndOfDay neden isteğe bağlıdır? StartOfDay'in nil olmadığı, endOfDay'in ise nil olabileceği durumlar var mı?
Mansurov Ruslan

1
Bu nedenle, bunu nasıl kullandığınıza bağlı olarak, günlerin bitişleri ve başlangıçları arasındaki bir saniyelik boşluklara dikkat edin developer.apple.com/documentation/foundation/nsdate/…
atlex2

29

Swift 5 Basit ve daha kesin cevap.

Başlangıç ​​saati: 00:00:00

Bitiş saati: 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)

Ekstra

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
Bu nasıl farklıdır let dateAtEnd = Calendar.current.date(bySettingHour: 23, minute: 59, second: 59, of: Date())?
Andres Canella

1
Fark yok .
Ağustos Lin

21

İOS 8+ için bu gerçekten kullanışlıdır; yapabilirsin:

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

Günün sonuna ulaşmak için, gün sonunu nasıl tanımladığınıza bağlı olarak NSCalendar yöntemlerini 23 saat, 59 dakika, 59 saniye kullanın.

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

Tarih Matematik

Apple iOS NSCalendar Belgeleri . (Bakınız Bölüm: Takvimsel Hesaplamalar )

NSCalendar yöntemleri NSHipster tarafından tartışıldı .


17

NSDate için Swift uzantılarım:

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

Sadece saniyeyi -1 olarak ayarlayabilir ve dateByAddingTimeInterval kullanmadan aynısını elde edebilirsiniz
Ben Sinclair

saat dilimi sorunlarını önlemek için şunu ekleyin: components.timeZone = NSTimeZone (ad: "GMT")
Tom Bevelander

12

Swift 5.1 - XCode 11 ile Dateyerine sınıfı NSDateve CalenderyerineNSCalender

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

Kullanım:

    let myDate = Date()
    let startOfDate = myDate.startOfDay
    let endOfDate = myDate.endOfDay

DateOyun alanında denediğimde bildirilmemiş tür hatası alıyorum
John Doe

1
Burada benim için çalışıyor. UIKit'i ile import UIKitmi ithal ettiniz ?
Ben

2
@Ben Tarih ve Takvim UIKit'te değil, Kuruluşta, ancak UIKit Vakfı ithal ediyor
Arbitur

4

Bileşenleri sıfırlamak zorunda değilsiniz, onları yok sayın:

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

2
"Yeni" mevcut:, [calendar startOfDayForDate:date]ancak -endOfDayForDate:maalesef yok ...
Julian F. Weinert

4

Benim için cevapların hiçbiri burada ve başka yerlerde stackoverflow üzerinde çalıştı. Bugün başlamak için bunu yaptım.

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

Bunu not edin [gregorian setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];ve [components setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];.

Bir takvim oluşturulduğunda, güncel saat dilimiyle başlatılır ve tarih, bileşenlerinden çıkarıldığında, NSDate saat dilimi olmadığından, geçerli saat dilimindeki tarih UTC saat dilimi olarak kabul edilir. Bu nedenle, bileşenleri ayıklamadan önce ve daha sonra bu bileşenlerden tarihi çıkarırken zaman dilimini ayarlamamız gerekir.


4

Hızlı 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 Kullanımı
Apple, NSsınıf adından kaldırıyor, böylece NSDatetakas edilebilir Date. Onları her zaman başarısız olacaklarını söylemeye çalışırsanız bir derleyici uyarısı alabilirsiniz, ancak onları oyun alanında çalıştırdığınızda iyi çalışırlar.

Oluşturulan NSDateçekirdek veri modelimi ile değiştirdim Dateve hala çalışıyorlar.

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 ve üzerinde

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

Kullanım:

var currentDayStart = Date().startOfDayDate
var currentDayEnd = Date().endOfDayDate

2

Sonuç almanın bir yolu daha:

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

Amaç-C

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

2

Swift 4 için

    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

Bence bunu Swift'de yapmanın en kısa ve öz yolu şu:

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

Mükemmel! Teşekkürler!
Baran Emre

1

Yana iOS 8.0+ / macOS 10.12+ / tvOS 10.0+ / watchOS 3.0+bir kutunun dışında kullanabilirsiniz Vakfı, içinde işlevinde orada inşa edilmiştir. Kendi işlevlerini uygulamaya gerek yok.

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

Yani şu şekilde kullanabilirsiniz:

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

Bunun cihazın saat dilimini dikkate aldığını hatırlamakta fayda var. Sen ayarlayabilirsiniz .timeZoneüzerinde calendarsize örn UTC bölgesini sahip olmak istiyorsanız.

Apple referans sayfalarına bağlantı: https://developer.apple.com/reference/foundation/nscalendar/1417161-startofday .


1

Sadece başka bir yolu kullanarak dateInterval(of:start:interval:for:)birCalendar

Dönüşte startDate, günün başlangıcı ve gün intervaliçindeki saniye sayısını içerir.

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 için kullandığım şey bu:

    let calendar = Calendar.current
    let fromDate = calendar.startOfDay(for: Date())
    let endDate = calendar.date(bySettingHour: 23, minute: 59, second: 59, of: Date())

Benim için bir cazibe gibi çalışıyor. Bunu başlangıç ​​ve bitiş tarihleri ​​için bir uzantıya ekleyebilirsiniz Date, ancak bir uzantı eklemenin derleme süresini artıracağını unutmayın (sınıfla aynı dosyada olmadıkça), yani yalnızca bir yerde veya bir sınıfta ihtiyacınız varsa. .. bir uzantı kullanmayın.


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

Sadece referans için, Swift 4'te günün Başlangıcını ve Sonunu ayarlamanın basit yolu ,

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

Takvim birimleri aralıklar olarak düşünülmelidir. İOS 10 itibariyle Calendarbunun için bazı güzel yöntemler var

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

Herhangi bir takvim bileşeninin başlangıcını / sonunu almak için aynı yöntemi kullanabilirsiniz (hafta / ay / yıl vb.)


Bu yanlış. day?.endbu gece 23:59 değil, yarın 12:00 AM olarak değerlendirilir.
Casey Wagner
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.