How to Check If Time Is Within a Specific Range in Swift

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

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

Check if current time is between range of times considering after midnight - Swift

Here is my solution that takes a little different approach by using a struct with minute and hour as Int's

struct Time: Comparable {
var hour = 0
var minute = 0

init(hour: Int, minute: Int) {
self.hour = hour
self.minute = minute
}
init(_ date: Date) {
let calendar = Calendar.current
hour = calendar.component(.hour, from: date)
minute = calendar.component(.minute, from: date)
}

static func == (lhs: Time, rhs: Time) -> Bool {
return lhs.hour == rhs.hour && lhs.minute == rhs.minute
}

static func < (lhs: Time, rhs: Time) -> Bool {
return (lhs.hour < rhs.hour) || (lhs.hour == rhs.hour && lhs.minute < rhs.minute)
}

static func create(time: String) -> Time? {
let parts = time.split(separator: ":")
if let hour = Int(parts[0]), let minute = Int(parts[1]) {
return Time(hour: hour, minute: minute)
}
return nil
}

static func isOpen(open: Time, close: Time) -> Bool {
let isClosingAfterMidnight = close.hour < open.hour ? true : false
let currentTime = Time(Date())

if isClosingAfterMidnight {
return currentTime > close && currentTime < open ? false : true
}
return currentTime >= open && currentTime < close
}
}

And it can be used like

if let open = Time.create(time: todayWh.openingAt), let close = Time.create(time: todayWh.closingAt) {
return Time.isOpen(open: open, close: close))
} else {
//error handling
}

It should work also after midnight :) Of course the Time struct could be used directly in the wh array.

Find if current time is between a range

Yes you can using NSDateComponents which will return the hour in the 24 hour format.

NSDateComponents *components = [[NSCalendar currentCalendar] components:NSHourCalendarUnit fromDate:[NSDate date]];
NSInteger hour = [components hour];

if(hour >= 0 && hour < 12)
NSLog(@"Good morning, foo");
else if(hour >= 12 && hour < 17)
NSLog(@"Good afternoon, foo");
else if(hour >= 17)
NSLog(@"Good evening, foo");

Swift 3

let hour = Calendar.current.component(.hour, from: Date())

if hour >= 0 && hour < 12 {
print("Good Morning")
} else if hour >= 12 && hour < 17 {
print("Good Afternoon")
} else if hour >= 17 {
print("Good Evening")
}

Check if date falls between 2 dates

Swift 2

For a better answer see Swift ≧ 3.

You already have the code for conversion of your date string in KeysData to NSDate. Assuming you have the two dates in startdate and enddate, all you have to do is check if the current date is in between:

let startDate = ...
let endDate = ...

NSDate().isBetween(date: startDate, andDate: endDate)

extension NSDate {
func isBetweeen(date date1: NSDate, andDate date2: NSDate) -> Bool {
return date1.compare(self) == self.compare(date2)
}
}

Edit: If you want to perform an inclusive range check, use this condition:

 extension NSDate {
func isBetween(date date1: NSDate, andDate date2: NSDate) -> Bool {
return date1.compare(self).rawValue * self.compare(date2).rawValue >= 0
}
}

ios- Check whether current time is between two times or not

Try this

NSDateComponents *components = [[NSCalendar currentCalendar] components:NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit fromDate:[NSDate date]];
NSInteger currentHour = [components hour];
NSInteger currentMinute = [components minute];
NSInteger currentSecond = [components second];

if (currentHour < 7 || (currentHour > 21 || currentHour == 21 && (currentMinute > 0 || currentSecond > 0))) {
// Do Something
}

Replace 7, 21 with your time

I get this from How to compare time

Swfit- Check whether current time is between two time string

You can set the date formatter defaultDate for today, parse the date strings, create a DateInterval with the start and end date and check if it contains now Date():

extension Formatter {
static let today: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.locale = .init(identifier: "en_US_POSIX")
dateFormatter.defaultDate = Calendar.current.startOfDay(for: Date())
dateFormatter.dateFormat = "hh:mm a"
return dateFormatter

}()
}


func checkIfCurrentTimeIsBetween(startTime: String, endTime: String) -> Bool {
guard let start = Formatter.today.date(from: startTime),
let end = Formatter.today.date(from: endTime) else {
return false
}
return DateInterval(start: start, end: end).contains(Date())
}


let startTime = "10:30 AM"
let endTime = "06:30 PM"
checkIfCurrentTimeIsBetween(startTime: startTime, endTime: endTime) // true

How to determine date falls in between two dates swift

If you have Date objects, they are Comparable and Equatable. You can write code like:

if breakDate >= startDate && breakDate <= endDate then {
// breakDate is between startDate and endDate
}

Edit:

As pointed out by LeoDabus in the comments, you could also use the pattern match operator (although I personally don't like it)

if startDate ... endDate ~= breakDate then {
// breakDate is between startDate and endDate
}

or contains:

if (startDate...endDate).contains(breakDate) then {
// breakDate is between startDate and endDate
}

If you have date strings, create a date formatter that converts your date strings to Date objects, then use code like the above.

If the date strings are always in "Internet" date format (ISO 8601), and you are certain they will always be in the same time zone, you can also use string comparison and compare the date strings directly (using any of the above forms of comparison, except maybe contains?)

Check if a given date is the closest to the current date and time compared to an array of dates

I think you may be going about this the hard way. It seems what you really want is the earliest event from all events. If so, that can be accomplished like this:

First, make your Event struct conform to Comparable by date:

struct Event: Identifiable, Comparable {

var id = UUID().uuidString
var eventTitle: String
var eventDescription: String
var eventDate: Date

static func < (lhs: Event, rhs: Event) -> Bool {
lhs.eventDate < rhs.eventDate
}
}

Then you can return the minimum element in the array. The following will return the earliest event in time, but remember that there is no check in it to make sure that it is the earliest future event, if that is what you need.

private func earliestEvent(events: [Event]) -> Event? {
return events.min()
}

This returns an optional Event as it could fail, such as in the case where the array is empty.

Edit:

private func earliestEvent(event: Event, events: [Event]) -> Bool {
guard let earliestEvent = events.min() else { return false }
return event == earliestEvent
}


Related Topics



Leave a reply



Submit