How to determine if an NSDate is today?
Solution 1
In macOS 10.9+ & iOS 8+, there's a method on NSCalendar/Calendar that does exactly this!
- (BOOL)isDateInToday:(NSDate *)date
So you'd simply do
Objective-C:
BOOL today = [[NSCalendar currentCalendar] isDateInToday:date];
Swift 3:
let today = Calendar.current.isDateInToday(date)
Solution 2
You can compare date components:
NSDateComponents *otherDay = [[NSCalendar currentCalendar] components:NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:aDate];
NSDateComponents *today = [[NSCalendar currentCalendar] components:NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:[NSDate date]];
if([today day] == [otherDay day] &&
[today month] == [otherDay month] &&
[today year] == [otherDay year] &&
[today era] == [otherDay era]) {
//do stuff
}
Edit:
I like stefan's method more, I think it makes for a cleaner and more understandable if statement:
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *components = [cal components:(NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:[NSDate date]];
NSDate *today = [cal dateFromComponents:components];
components = [cal components:(NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:aDate];
NSDate *otherDate = [cal dateFromComponents:components];
if([today isEqualToDate:otherDate]) {
//do stuff
}
Chris, I've incorporated your suggestion. I had to look up what era was, so for anyone else who doesn't know, it distinguishes between BC and AD. This is probably unnecessary for most people, but it's easy to check and adds some certainty, so I've included it. If you're going for speed, this probably isn't a good method anyway.
NOTE as with many answers on SO, after 7 years this is totally out of date. In Swift now just use .isDateInToday
Solution 3
This is an offshoot to your question, but if you want to print an NSDate with "Today" or "Yesterday", use the function
- (void)setDoesRelativeDateFormatting:(BOOL)b
for NSDateFormatter
Solution 4
I would try to get today's date normalized to midnight and the second date, normalize to midnight then compare if it is the same NSDate.
From an Apple example here's how you normalize to midnight today's date, do the same for the second date and compare:
NSCalendar * gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents * components =
[gregorian components:
(NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit)
fromDate:[NSDate date]];
NSDate * today = [gregorian dateFromComponents:components];
Solution 5
Working Swift 3 & 4 extension of the suggestion by Catfish_Man:
extension Date {
func isToday() -> Bool {
return Calendar.current.isDateInToday(self)
}
}
Related videos on Youtube
Seunghoon
http://twitter.com/yeonsh Work experiences on Go, Python, C++, Objective-C, Java, Swift and Dart(Flutter) Learning: Haskell, Rust, Swift
Updated on July 25, 2020Comments
-
Seunghoon almost 4 years
How to check if an
NSDate
belongs to today?I used to check it using first 10 characters from
[aDate description]
.[[aDate description] substringToIndex:10]
returns string like"YYYY-MM-DD"
so I compared the string with the string returned by[[[NSDate date] description] substringToIndex:10]
.Is there more fast and/or neat way to check?
Thanks.
-
ArtOfWarfare almost 11 yearsI believe my method is the only one (as of my writing this) that actually refers to Apple's documentation and does what they suggest within it to determine if two days are the same. Although other methods may work, I believe my method is most future proof. stackoverflow.com/a/17641925/901641
-
vikingosegundo almost 11 years@ArtOfWarfare: I disagree. Your code still needs to deal with time intervals, but apple provides methods that already factor this away — see: stackoverflow.com/a/17642033/106435
-
gnasher729 about 10 yearsThe NSDate "description" method displays the date in UTC format, that is Greenwich Mean Time, with no correction for daylight savings time. If you're late in the evening in the USA, or early in the morning in India, it will not display what is "today" according to your calendar. You need an NSCalendar object to translate the NSDate into a day, and to convert the current date into a day, then compare them.
-
-
Jaanus about 14 yearsWhat you say is correct, but the interval doesn't really help to check if date is today.
-
Kirill about 14 yearsJust keep in mind that this is it tells you if you are within 24 hours since now, but not if the dates are the same. A one second difference can be different dates and a 86399 second difference can be the same date.
-
alesplin about 14 years@David: True. Didn't think about that as I was doing 3 other things while answering the question, and your answer wasn't posted when I loaded the page.
-
Seunghoon about 14 yearsThanks. I think it is more neat and future-safe solution to my question.
-
Kirill about 13 yearsThis doesn't tell you if both NSDates are the same date, just which one is earlier, even if they're the same day.
-
Chris Page over 12 yearsWhy include hours, minutes and seconds when creating
comps
when you're immediately setting them to zero? Also, I think you need to include the era. -
Chris Page over 12 yearsI think you need to include the era component, too. I think it's a coin toss between the two approaches; isEqualToDate seems nicer, but it seems a little wasteful and takes about the same number of lines to reconstruct a date from the components.
-
Chris Page over 12 yearsI think you need to include the era, too.
-
Kirill over 12 yearsPlease note that while this will work in almost every case, there are such things as leap seconds. I don't know if or how Apple's NSDate class handles them, but there is some chance this won't work. This is more a "did you know" rather than a criticism of your method as they're exceedingly rare (24 in history).
-
Accatyyc almost 12 yearsThanks for this. The accepted way was way too CPU intensive for our app so we needed to optimize this.
-
Glenn Maynard over 11 yearsSince both "otherDay" and "today" only have those four fields filled anyway (that's all you requested), you can just use [today equalTo:otherDay], without jumping the hoops in the second one.
-
Kirill over 11 years@Glenn Are you suggesting I compare NSDateComponents in the first one? I hadn't really thought about that, but it also seems like a good idea.
-
Basil Bourque over 11 yearsClever idea. But I assume that looking for the string "Today" would break if you localize.
-
Sean Kladek about 11 years@DavidKanarek Digging up old posts...I wouldn't recommend comparing date components directly, if you get into a situation where you need to offset one of the components, you may get something like month == 3, day == 34. Converting to dates will correctly interpret this as April 3, comparing date components will not see this as the same as month == 4, day == 3.
-
devios1 almost 11 yearsThat's actually not a bad solution. Not sure why it was so downvoted. Using integer division will cut off the remainder and compare just the "days" value of the unix long time, after correcting for GMT. I think this is the cleanest solution of them all to be quite frank.
-
Andreas Ley almost 11 yearsBear in mind that an Era does start at 00:00 GMT! This method might not work correctly if one of the dates (or both) are not in the GMT timezone.
-
vikingosegundo over 10 yearswhat about dates that are not 24 hours long, but 23 or 25 due to Daylight Saving Times?
-
vikingosegundo over 10 years@chaiguy: this is a bad solution as it assumes, that each day is 24 hours long — what is not the case. Due to Daylight Saving Times days can be 23, 24 or 25 hours long.
-
devios1 over 10 yearsHmm that's true. However the average per year is exactly 24 hours, so it will only potentially be off by one hour worst case, as I see it. Perhaps that could be checked for explicitly.
-
vikingosegundo over 10 years@chaiguy: no. just never use a code that contains 60*60*24. or live with your headache.
-
vikingosegundo over 10 yearsThis does not answer the question at all. You should delete it.
-
vikingosegundo over 10 yearsThis code will fail for daylight saving times. Everybody using code with the infamous number 86,400 deserve the headache it may cause.
-
alesplin over 10 yearsI'm not inclined to do so, given that at the very least it doesn't contain anything that is going to cause harm (unlike some of the other 'magic number' answers below). It's obviously not correct or complete, but it could be an approach that may prove useful to someone doing something similar that happens across it.
-
gnasher729 about 10 yearsActually, two NSDates that are 86399 + 3600 seconds apart can be on the same day, but only once a year.
-
gnasher729 about 10 years"secondsFromGMT" changes abruptly twice a year in most places in the world. Much safer to use the NSCalendar methods.
-
artooras almost 10 yearsShouldn't a date be normalised by setting time to 12, i.e. midday, not midnight? Since date is in GMT, setting it to midday ensures that time zone variations both ways (and they go up to 12h only both ways) does not 'jump' into the day before or after.
-
vikingosegundo almost 10 yearsThis answer is nothing but noise. It does neither attempt to answer the question nor is it necessary to refer to
timeIntervalSinceNow
as it is covered in many other posts. Also handling day comparison with checking for seconds encourage error-prone division by 86400. -
Catfish_Man almost 10 yearsCheck using the iOS 8 SDK
-
Nurbol over 9 yearsI'm confused by the above comment, this is definitely iOS 8: - (BOOL)isDateInToday:(NSDate *)date NS_AVAILABLE(10_9, 8_0);
-
Catfish_Man over 9 yearsYes, that's what I said. The previous commenter was confused by looking at the iOS 7 SDK, presumably. It had a different declaration.
-
Daij-Djan almost 8 yearsfor 'today' this is the perfect answer :)
-
Thanh Pham over 7 yearsSame as Catfish_Man's answer!
-
Supertecnoboff over 5 yearsExcellent answer!