how to check if time is within a specific range in swift

swift, time

Solution

There are lots of ways to do this. Personally, I don't like working with strings if I can avoid it. I'd rather deal with date components.

Below is code that creates dates for 8:00 and 16:30, and then compares the dates to see if the current date/time falls in that range.

It's longer than other people's code, but I think it's worth learning how to do calculations with dates using a Calendar:

EDIT #3:

This answer is from a long time ago. I'll leave the old answer below, but here is the current solution:

@CodenameDuchess' answer uses a system function, `date(bySettingHour:minute:second:of:matchingPolicy:repeatedTimePolicy:direction:)`

Using that function, the code can be simplified to this:

import UIKit

// The function `Calendar.date(bySettingHour:minute:second)` lets you 
// create date objects for a given time in the same day of given date
// For example, 8:00 today

let calendar = Calendar.current
let now = Date()
let eight_today = calendar.date(
  bySettingHour: 8,
  minute: 0,
  second: 0,
  of: now)!

let four_thirty_today = calendar.date(
  bySettingHour: 16,
  minute: 30,
  second: 0,
  of: now)!

// In recent versions of Swift Date objectst are comparable, so you can 
// do greater than, less than, or equal to comparisons on dates without
// needing a date extension

if now >= eight_today &&
  now <= four_thirty_today
{
  print("The time is between 8:00 and 16:30")
}

The old (Swift 2) answer follows, for historical completeness:

This code uses a Calendar object to get the day/month/year of the current date, and adds the desired hour/minute components, and then generates a date for those components.

import UIKit
//-------------------------------------------------------------
//NSDate extensions.
extension NSDate
{
  /**
  This adds a new method dateAt to NSDate.

  It returns a new date at the specified hours and minutes of the receiver

  :param: hours: The hours value
  :param: minutes: The new minutes

  :returns: a new NSDate with the same year/month/day as the receiver, but with the specified hours/minutes values
  */
  func dateAt(#hours: Int, minutes: Int) -> NSDate
  {
    let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!

    //get the month/day/year componentsfor today's date.

    println("Now = \(self)")

    let date_components = calendar.components(
      NSCalendarUnit.CalendarUnitYear |
        NSCalendarUnit.CalendarUnitMonth |
        NSCalendarUnit.CalendarUnitDay,
      fromDate: self)

    //Create an NSDate for 8:00 AM today.
    date_components.hour = hours
    date_components.minute = minutes
    date_components.second = 0

    let newDate = calendar.dateFromComponents(date_components)!
        return newDate
  }
}
//-------------------------------------------------------------
//Tell the system that NSDates can be compared with ==, >, >=, <, and <= operators
extension NSDate: Equatable {}
extension NSDate: Comparable {}

//-------------------------------------------------------------
//Define the global operators for the 
//Equatable and Comparable protocols for comparing NSDates

public func ==(lhs: NSDate, rhs: NSDate) -> Bool
{
  return lhs.timeIntervalSince1970 == rhs.timeIntervalSince1970
}

public func <(lhs: NSDate, rhs: NSDate) -> Bool
{
  return lhs.timeIntervalSince1970 < rhs.timeIntervalSince1970
}
public func >(lhs: NSDate, rhs: NSDate) -> Bool
{
  return lhs.timeIntervalSince1970 > rhs.timeIntervalSince1970
}
public func <=(lhs: NSDate, rhs: NSDate) -> Bool
{
  return lhs.timeIntervalSince1970 <= rhs.timeIntervalSince1970
}
public func >=(lhs: NSDate, rhs: NSDate) -> Bool
{
  return lhs.timeIntervalSince1970 >= rhs.timeIntervalSince1970
}
//-------------------------------------------------------------

let now = NSDate()
let eight_today = now.dateAt(hours: 8, minutes: 0)
let four_thirty_today = now.dateAt(hours:16, minutes: 30)

if now >= eight_today &&
  now <= four_thirty_today
{
  println("The time is between 8:00 and 16:30")
}

EDIT:

The code in this answer has changed a LOT for Swift 3.

Instead of using `NSDate`, it makes more sense to us the native `Date` object, and `Date` objects are `Equatable` and `Comparable` "out of the box".

Thus we can get rid of the `Equatable` and `Comparable` extensions and the definitions for the `<`, `>` and `=` operators.

Then we need to do a fair amount of tweaking of the syntax in the `dateAt` function to follow Swift 3 syntax. The new extension looks like this in Swift 3:

Swift 3 version:

import Foundation

extension Date
{

  func dateAt(hours: Int, minutes: Int) -> Date
  {
    let calendar = NSCalendar(calendarIdentifier: NSCalendar.Identifier.gregorian)!

    //get the month/day/year componentsfor today's date.


    var date_components = calendar.components(
      [NSCalendar.Unit.year,
       NSCalendar.Unit.month,
       NSCalendar.Unit.day],
      from: self)

    //Create an NSDate for the specified time today.
    date_components.hour = hours
    date_components.minute = minutes
    date_components.second = 0

    let newDate = calendar.date(from: date_components)!
    return newDate
  }
}


let now = Date()
let eight_today = now.dateAt(hours: 8, minutes: 0)
let four_thirty_today = now.dateAt(hours: 16, minutes: 30)

if now >= eight_today &&
  now <= four_thirty_today
{
  print("The time is between 8:00 and 16:30")
}

Problem

Hi I am trying to check if the current time is within a time range, say 8:00 - 16:30. My code below shows that I can obtain the current time as a string, but I am unsure how I can use this value to check if it is inside the time range specified above. Any help would be greatly appreciated! ``` var todaysDate:NSDate = NSDate() var dateFormatter:NSDateFormatter = NSDateFormatter() dateFormatter.dateFormat = "HH:mm" var dateInFormat:String = dateFormatter.stringFromDate(todaysDate) println(dateInFormat) // 23:54 ```

Original source