Checking When a Date Has Passed - Swift

Check if date is before current date (Swift)

I find the earlierDate method.

if date1.earlierDate(date2).isEqualToDate(date1)  {
print("date1 is earlier than date2")
}

You also have the laterDate method.

Swift 3 to swift 5:

if date1 < date2  {
print("date1 is earlier than date2")
}

Check if specific date isToday (or passed) Swift

You can do:

if Date() >= Calendar.current.dateWith(year: 2020, month: 3, day: 28) ?? Date.distantFuture {
return true
} else {
return false
}

where dateWith(year:month:day:) is defined as:

extension Calendar {
func dateWith(year: Int, month: Int, day: Int) -> Date? {
var dateComponents = DateComponents()
dateComponents.year = year
dateComponents.month = month
dateComponents.day = day
return date(from: dateComponents)
}
}

This method basically returns the Date with the specified year, month, and day, with the hour, minute, and second components all being 0, that is, start of the specified day. In other words, I am checking whether the instant now is after the start of the day 2020-03-28.

How to check if 24 hours have passed in Swift

You can use UserDefault to save the date upon creation of the record. The syntax will be

UserDefaults.standard.set(Date(), forKey:"creationTime")

Whenever you want to check the saved date, retrieve it in this way

if let date = UserDefaults.standard.object(forKey: "creationTime") as? Date {
if let diff = Calendar.current.dateComponents([.hour], from: date, to: Date()).hour, diff > 24 {
//do something
}
}

Checking when a date has passed - Swift

Implement to observe

NSCalendarDayChangedNotification

Posted whenever the calendar day of the system changes, as determined
by the system calendar, locale, and time zone. This notification does
not provide an object.

If the the device is asleep when the day changes, this notification
will be posted on wakeup. Only one notification will be posted on
wakeup if the device has been asleep for multiple days.

There are no guarantees about the timeliness of when this notification
will be received by observers. As such, you should not rely on this
notification being posted or received at any precise time.

The notification is posted through [NSNotificationCenter defaultCenter].

Example:

In applicationDidFinishLaunching add

NSNotificationCenter.defaultCenter().addObserver(self, selector:"calendarDayDidChange:", name:NSCalendarDayChangedNotification, object:nil)

and implement the method

func calendarDayDidChange(notification : NSNotification)
{
doSomethingWhenDayHasChanged()
}

or use the block API.

If the class including the observer is not the application delegate class you might remove the observer at some time.

Swift - check if a timestamp is yesterday, today, tomorrow, or X days ago

Calendar has methods for all three cases

func isDateInYesterday(_ date: Date) -> Bool
func isDateInToday(_ date: Date) -> Bool
func isDateInTomorrow(_ date: Date) -> Bool

To calculate the days earlier than yesterday use

func dateComponents(_ components: Set<Calendar.Component>, 
from start: Date,
to end: Date) -> DateComponents

pass [.day] to components and get the day property from the result.


This is a function which considers also is in for earlier and later dates by stripping the time part (Swift 3+).

func dayDifference(from interval : TimeInterval) -> String
{
let calendar = Calendar.current
let date = Date(timeIntervalSince1970: interval)
if calendar.isDateInYesterday(date) { return "Yesterday" }
else if calendar.isDateInToday(date) { return "Today" }
else if calendar.isDateInTomorrow(date) { return "Tomorrow" }
else {
let startOfNow = calendar.startOfDay(for: Date())
let startOfTimeStamp = calendar.startOfDay(for: date)
let components = calendar.dateComponents([.day], from: startOfNow, to: startOfTimeStamp)
let day = components.day!
if day < 1 { return "\(-day) days ago" }
else { return "In \(day) days" }
}
}

Alternatively you could use DateFormatter for Yesterday, Today and Tomorrow to get localized strings for free

func dayDifference(from interval : TimeInterval) -> String
{
let calendar = Calendar.current
let date = Date(timeIntervalSince1970: interval)
let startOfNow = calendar.startOfDay(for: Date())
let startOfTimeStamp = calendar.startOfDay(for: date)
let components = calendar.dateComponents([.day], from: startOfNow, to: startOfTimeStamp)
let day = components.day!
if abs(day) < 2 {
let formatter = DateFormatter()
formatter.dateStyle = .short
formatter.timeStyle = .none
formatter.doesRelativeDateFormatting = true
return formatter.string(from: date)
} else if day > 1 {
return "In \(day) days"
} else {
return "\(-day) days ago"
}
}

Update:

In macOS 10.15 / iOS 13 RelativeDateTimeFormatter was introduced to return (localized) strings relative to a specific date.

How to check if 3 days have passed

Here's how I would do it. Every time your app launches or comes back to the foreground, do the following:

  • Read a saved NSDate from NSUserDefaults.

  • Figure out the number of midnights that have passed from the saved
    date until now. (Do a search in the Xcode docs on "Midnights" to find
    NSCalendar code for calculating the number of days between 2 dates.)

  • Save today's date to NSUserDefaults as the new saved date

I wrote this method as an extension to NSDate:

  /**
This function calcuates an ordinal day number for the receiver
using the Gregorian calendar.

:returns: an integer day number
*/

func dayNumber() -> Int
{
let calendar = DateUtils.gregorianCalendar
return calendar.ordinalityOfUnit(NSCalendarUnit.CalendarUnitDay,
inUnit: NSCalendarUnit.CalendarUnitEra, forDate: self)
}

It uses a class DateUtils to manage a single instance of the Gregorian NSCalendar. That lets me avoid creating a new instance of the Gregorian calendar for each date operation I need to do.

class DateUtils
{
static let gregorianCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
}

Swift 4: Checking if week, month, 2 months, etc. has passed since initial launch using Calendar

From what I understand of your question, you want a button to display if they have had the app for more than a certain amount of time. If that is the case, I've written some code that will be helpful to you:

let timeSinceInstalled = -(installedDate ?? Date()).timeIntervalSinceNow

Button1.isHidden = timeSinceInstalled < 604800
Button2.isHidden = timeSinceInstalled < 2592000
Button3.isHidden = timeSinceInstalled < 5184000

You can actually replace most of the code inside of your viewDidLoad() function, even the part where you check if installedDate == nil. Here is your updated code:

override func viewDidLoad() {
super.viewDidLoad()
let timeSinceInstalled = -(installedDate ?? Date()).timeIntervalSinceNow
Button1.isHidden = timeSinceInstalled < 604800
Button2.isHidden = timeSinceInstalled < 2592000
Button3.isHidden = timeSinceInstalled < 5184000
}

var installedDate: Date? {
get {
return UserDefaults.standard.object(forKey: "installedDateKey") as? Date
}
set {
UserDefaults.standard.set(newValue, forKey: "installedDateKey")
}
}

If you want to set the title to "You have none available" when the button should not be clickable, here is the code for that:

override func viewDidLoad() {
super.viewDidLoad()
let timeSinceInstalled = -(installedDate ?? Date()).timeIntervalSinceNow
setTitle(Button1, timeSinceInstalled < 604800)
setTitle(Button2, timeSinceInstalled < 2592000)
setTitle(Button3, timeSinceInstalled < 5184000)
}

func setTitle(_ button: UIButton, _ statement: Bool) {
button.setTitle(statement ? "You have none available" : "Click me", for: .normal)
button.isEnabled = !statement
}

var installedDate: Date? {
get {
return UserDefaults.standard.object(forKey: "installedDateKey") as? Date
}
set {
UserDefaults.standard.set(newValue, forKey: "installedDateKey")
}
}

Comparing two dates in swift in order to check if a day has gone by

Your code cannot work.

The logic is supposed to be:

  • Get the day from UserDefaults,
  • Compare it to the current day.
  • If the values are not equal save the new day to UserDefaults

class UserInfoViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()

let dateToday = Calendar.current.component(.day, from: Date())
let dateToCompare = UserDefaults.standard.integer(forKey: "userDefaultDate")
if dateToCompare != dateToCompare {
UserDefaults.standard.set(dateToday, forKey: "userDefaultDate")
resetLabel.isHidden = false
} else {
resetLabel.isHidden = true
}
}
}

Note:

Never use value(forKey: with UserDefaults.

There are many convenience methods and for objects use object(forKey:

Edit

It's more reliable to save the Date object and compare using isDateInToday of Calendar

class UserInfoViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()

let dateToday = Date()
let calendar = Calendar.current
let dateToCompare = UserDefaults.standard.object(forKey: "userDefaultDate") as? Date ?? Date.distantPast
if calendar.isDateInToday(dateToCompare) {
resetLabel.isHidden = true
} else {
UserDefaults.standard.set(dateToday, forKey: "userDefaultDate")
resetLabel.isHidden = false
}
}
}

How to check if date is at least previous day?

timeIntervalSinceNow is a FloatingPoint value with a very high precision, that represents seconds passed since the Date.


To check if current date is at least on a previous day, you could do something like this:

extension Date {
var isAtLeastPreviousDay: Bool {
return isPast && !isToday
}

private var isPast: Bool {
return self < Date()
}

private var isToday: Bool {
return Calendar.current.isDateInToday(self)
}
}


Related Topics



Leave a reply



Submit