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
Why Does an @Objc Enum Have a Different Description Than a Pure Swift Enum
How to Enumerate a Slice Using the Original Indices
Render a 3D Model (Hair) with Semi-Transparent Texture in Scenekit
Custom Bullets from Images on Uitextview or Uilabel Swift
Swift: Unable to Decompose Tuple in Certain Closures (E.G., Reduce with Enumerate)
Animate the Fractioncomplete of Uiviewpropertyanimator for Blurring the Background
How to Cast an _Nsmallocblock_ to Its Underlying Type in Swift 3
Subclass of Gkgraphnode Costtonode Method Never Getting Called
Getting Data from Findobjectsinbackgroundwithblock in Swift
Can't Use Concrete Subclass to Implement a Property in Protocol in Swift
Generic Swift Dictionary Extension for Nil Filtering
Using Swift Library in Xamarin
Detail View Is Not Updated When the Model Is Updated (Using List) Swiftui
Iterating with for .. in on a Changing Collection
Convert Bar Chart to a Grouped Bar Chart with Danielgindi/Ios-Charts and Swift