3

I have to determine H and H+3 where H is >= to nearest Hour.

Let me show you some examples :

if today's hour is 0h00 -> H = 0h and H+3 = 3h

if today's hour is 0h01 -> H = 1h and H+3 = 3h

if today's hour is 21h00 -> H = 21h and H+3 = 0h

if today's hour is 22h34 -> H = 23h and H+3 = 2h (day + 1)

I am new to Swift, I know how to get the nearest hour in Obj C, but with Swift I'm not sure.

Is there a fast way to determine those 2 variables H and H+3 in order to set the text of two labels at any given time.

I tried this method but it gives me the nearest hour but the closest one, not >=.

func nextHourDate() -> NSDate? {
    let calendar = NSCalendar.currentCalendar()
    let date = NSDate()
    let minuteComponent = calendar.components(NSCalendarUnit.Minute, fromDate: date)
    let components = NSDateComponents()
    components.minute = 60 - minuteComponent.minute
    return calendar.dateByAddingComponents(components, toDate: date, options: [])
}

I'm developing in Swift 2.3

EDIT :

After reading the answers/comments, here is what I developed.

func determineH() -> NSDate? {
        let gregorian = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
        let now = NSDate()
        let components = gregorian.components([.Year, .Month, .Day, .Hour, .Minute, .Second], fromDate: now)

        if components.minute != 0 {
            components.hour = components.hour + 1
            components.minute = 0
        }

        let date = gregorian.dateFromComponents(components)!
        return date
    }
  • "I'm developing in Swift 2.3" Why? You are "new to Swift" so why learn a language that will be dead any day now? Learn Swift 3, not Swift 2. – matt Jan 20 '17 at 16:10
  • Because I am maintaining an application developed in Swift 2.3. I need to make a release soon. I will be translating the application when I won't be under pressure. –  Jan 20 '17 at 16:17
  • Good answer. :) – matt Jan 20 '17 at 16:22
  • But thank you for the advice, you are not the only one telling me this. I can't wait to be learning Swift 3, you can't imagine. –  Jan 20 '17 at 16:26
  • 1
    I didn't mean to yank your chain. Apologies. – matt Jan 20 '17 at 16:29
  • Nsdate knows no timezone. Seems ok to me in that regard – Daij-Djan Jan 21 '17 at 23:21

3 Answers3

2

To get next hour, you add 1 hour and then drop the minutes. If you want nextHour(12:00PM) to be 12:00PM instead of 1:00PM then add 59 minutes 59 seconds instead of 1 hour. Note this doesn't deal with the milliseconds; if you care about that, zero it out also:

    extension Date {
        func advancedToNextHour() -> Date? {
            var date = self
            date += TimeInterval(59*60+59)
            let calendar = Calendar.current
            let components = calendar.dateComponents([.second, .minute], from: date)
            guard let minutes = components.minute,
                  let seconds = components.second else {
                return nil
            }
            return date - TimeInterval(minutes)*60 - TimeInterval(seconds)
        }
        func advancedToNearest(hours: Int) -> Date? {
            guard let next = advancedToNextHour(), hours > 0 else {
                return nil
            }
            return next + TimeInterval(hours-1)*60*60
        }
    }

    print(Date().advancedToNextHour())
    print(Date().advancedToNearest(hours: 3))
Josh Homann
  • 15,933
  • 3
  • 30
  • 33
2

based on your code:

check minutes of the current hour and go back to the last full hour and only then add!?

Ill not provide the code for that arithmetic masterpiece since you already almost there

best: work with dateComponents more

only increase the hours property and reset minutes to 0!?

comps.hours += 1
comps.minutes = 0
Community
  • 1
  • 1
Daij-Djan
  • 49,552
  • 17
  • 113
  • 135
0

You can also create a Calendar extension like this:

extension Calendar {
    func nextFullHour(after date: Date) -> Date {
        let components = dateComponents([.hour, .minute], from: date)
        
        if components.minute != 0 {
            let fullHour = self.date(byAdding: .minute, value: -components.minute!, to: date)!
            let nextFullHour = self.date(byAdding: .hour, value: 1, to: fullHour)!
            return nextFullHour
        }
        
        return date
    }
}

And then it would just be Calendar.current.nextFullHour(after: Date())

potmo
  • 131
  • 1
  • 4