Related
What is the most efficient way to obtain an NSDate object that represents midnight of the current day?
New API in iOS 8
iOS 8 includes a new method on NSCalendar called startOfDayForDate, which is really easy to use:
let startOfToday = NSCalendar.currentCalendar().startOfDayForDate(NSDate())
Apple's description:
This API returns the first moment date of a given date.
Pass in [NSDate date], for example, if you want the start of "today".
If there were two midnights, it returns the first. If there was none, it returns the first moment that did exist.
Update, regarding time zones:
Since startOfDayForDate is a method on NSCalendar, it uses the NSCalendar's time zone. So if I wanted to see what time it was in New York, when today began in Los Angeles, I could do this:
let losAngelesCalendar = NSCalendar.currentCalendar().copy() as! NSCalendar
losAngelesCalendar.timeZone = NSTimeZone(name: "America/Los_Angeles")!
let dateTodayBeganInLosAngeles = losAngelesCalendar.startOfDayForDate(NSDate())
dateTodayBeganInLosAngeles.timeIntervalSince1970
let dateFormatter = NSDateFormatter()
dateFormatter.dateStyle = .MediumStyle
dateFormatter.timeStyle = .ShortStyle
dateFormatter.timeZone = NSTimeZone(name: "America/New_York")!
let timeInNewYorkWhenTodayBeganInLosAngeles = dateFormatter.stringFromDate(dateTodayBeganInLosAngeles)
print(timeInNewYorkWhenTodayBeganInLosAngeles) // prints "Jul 29, 2015, 3:00 AM"
Try this:
NSDate *const date = NSDate.date;
NSCalendar *const calendar = NSCalendar.currentCalendar;
NSCalendarUnit const preservedComponents = (NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay);
NSDateComponents *const components = [calendar components:preservedComponents fromDate:date];
NSDate *const normalizedDate = [calendar dateFromComponents:components];
NSCalendar *cal = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
[cal setTimeZone:[NSTimeZone systemTimeZone]];
NSDateComponents * comp = [cal components:( NSYearCalendarUnit| NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit) fromDate:[NSDate date]];
[comp setMinute:0];
[comp setHour:0];
[comp setSecond:0];
NSDate *startOfToday = [cal dateFromComponents:comp];
If you mean midnight as 23:59 then set component's hour as 23 and minutes as 59.
Swift:
let cal = NSCalendar.currentCalendar()
//tip:NSCalendarUnit can be omitted, but with the presence of it, you can take advantage of Xcode's auto-completion
var comps = cal.components(NSCalendarUnit.YearCalendarUnit | .MonthCalendarUnit | .DayCalendarUnit | .HourCalendarUnit | .MinuteCalendarUnit | .SecondCalendarUnit, fromDate: NSDate())
comps.hour = 0
comps.minute = 0
comps.second = 0
let midnightOfToday = cal.dateFromComponents(comps)!
Swift 2.2:
let cal = NSCalendar.currentCalendar()
let comps = cal.components([.Year, .Month, .Day, .Hour, .Minute, .Second], fromDate: NSDate())
comps.hour = 0
comps.minute = 0
comps.second = 0
let midnightOfToday = cal.dateFromComponents(comps)!
Objective-C:
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *comps = [cal components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute) fromDate:[NSDate date]];
[comps setHour:0];
[comps setMinute:0];
[comps setSecond:0];
NSDate *midnightOfToday = [cal dateFromComponents:comps];
You could use the following method to get the midnight value for an NSDate.
- (NSDate *)dateAtBeginningOfDayForDate:(NSDate *)inputDate
{
// Use the user's current calendar and time zone
NSCalendar *calendar = [NSCalendar currentCalendar];
NSTimeZone *timeZone = [NSTimeZone systemTimeZone];
[calendar setTimeZone:timeZone];
// Selectively convert the date components (year, month, day) of the input date
NSDateComponents *dateComps = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:inputDate];
// Set the time components manually
[dateComps setHour:0];
[dateComps setMinute:0];
[dateComps setSecond:0];
// Convert back
NSDate *beginningOfDay = [calendar dateFromComponents:dateComps];
return beginningOfDay;
}
Thkis is taken from here website.
From iOS8, you can use startDayForDate.
So, in order to get the start of today (Objective -C):
NSDate * midnight;
midnight = [[NSCalendar currentCalendar] startOfDayForDate: [NSDate date]];
try this:
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *now = [NSDate date];
NSDateComponents *components = [gregorian components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit fromDate:now];
NSDateFormatter* df = [[NSDateFormatter alloc]init];
[df setDateFormat:#"MM/dd/yyyy HH:mm:ss.SSS"];
NSLog(#"%#",[df stringFromDate:[gregorian dateFromComponents:components]]);
NSDate *now = [NSDate date];
NSDate *beginningOfToday = nil;
[[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit startDate:&beginningOfToday interval:NULL forDate:now];
You could use NSCalendar's dateBySettingHour:minute:second:ofDate:options:
So it would be as easy as doing:
NSCalendar *calendar = [NSCalendar currentCalendar];
calendar.timeZone = [NSTimeZone timeZoneWithName:#"UTC"];
NSDate *midnight = [calendar dateBySettingHour:0 minute:0 second:0 ofDate:[NSDate date] options:0];
let calendar = NSCalendar.currentCalendar()
let unitFlags: NSCalendarUnit = [.Year, .Month, .Day, .Minute, .Second]
let components = calendar.components(unitFlags , fromDate: NSDate())
components.hour = 0
components.minute = 0
components.second = 0
//Gives Midnight time of today
let midnightOfToday = calendar.dateFromComponents(components)!
I am setting up an NSPredicate for a fetch to Core Data which is set up like so:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(date >= %#) AND (date <= %#)", todaysDate, tomorrowsDate];
I need todaysDate to be today at 00:00:00, and I need tomorrowsDate to be today at 23:59:59.
I can't set todaysDate equal to [NSDate date] and then manipulate the hours, minutes, and seconds with NSDateComponents because [NSDate date] gives me a date which is 5 hours ahead of my local actual time (so if it's 11:00 pm here on May 6th, then [NSDate date] would give me "2014-05-07 04:00:00 +0000", but I still need it to think that it is May 6th, not 7th!).
How can I manipulate the tools I have in Xcode to consistently get my variable todaysDate to be today at midnight, and tomorrowsDate to be a second before midnight strikes tomorrow?
The rangeOfUnit:... method of NSCalendar is a convenient method to
compute the start of the current day and the start of tomorrow
in your local time zone:
NSDate *now = [NSDate date];
NSCalendar *cal = [NSCalendar currentCalendar];
NSDate *todaysDate;
NSDate *tomorrowsDate;
NSTimeInterval interval;
[cal rangeOfUnit:NSDayCalendarUnit startDate:&todaysDate interval:&interval forDate:now];
tomorrowsDate = [todaysDate dateByAddingTimeInterval:interval];
so that you can use it in the predicate with >= and <:
[NSPredicate predicateWithFormat:#"(date >= %#) AND (date < %#)", todaysDate, tomorrowsDate]
to fetch all objects of the current day.
Remark: Don't let the NSLog() output of NSDate objects confuse you.
NSDate represents an absolute point in time and knows nothing about time zones.
NSLog(#"%#", todaysDate) prints the date according to the GMT time zone and not in your local time zone.
To print the dates according to your time zone, use p todaysDate in the debugger console (instead of po),
or print
[todaysDate descriptionWithLocale:[NSLocale currentLocale]]
The following works for me:
- (NSDate *)dateWithDate:(NSDate *)date Hour:(NSInteger)hour Minute:(NSInteger)minute Second:(NSInteger)second {
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:date];
components.hour = hour;
components.minute = minute;
components.second = second;
return [calendar dateFromComponents:components];
}
Example:
NSDate *beginningOfDay = [self dateWithDate:[NSDate date] Hour:0 Minute:0 Second:0];
NSDate *endOfDay = [self dateWithDate:[NSDate date] Hour:23 Minute:59 Second:59];
Swift:
let cal = NSCalendar.currentCalendar()
//tip:NSCalendarUnit can be omitted, but with the presence of it, you can take advantage of Xcode's auto-completion
var comps = cal.components(NSCalendarUnit.YearCalendarUnit | .MonthCalendarUnit | .DayCalendarUnit | .HourCalendarUnit | .MinuteCalendarUnit | .SecondCalendarUnit, fromDate: NSDate())
comps.hour = 0
comps.minute = 0
comps.second = 0
let todaysDate = cal.dateFromComponents(comps)!
let tomorrowsDate = NSDate(timeInterval: 86399, sinceDate: todaysDate)
Objective-C:
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *comps = [cal components: (NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit) fromDate: [NSDate date]];
[comps setHour:0];
[comps setMinute:0];
[comps setSecond:0];
NSDate *todaysDate = [cal dateFromComponents:comps];
NSDate *tomorrowsDate = [NSDate dateWithTimeInterval: 86399 sinceDate:todaysDate];
I want to get the day, month and year components of NSDate in integer form i.e. if the date is 1/2/1988 then I should get 1, 2 and 1988 separately as an integer. How can I do this in iOS? I found the similar question but the method descriptionWithCalendarFormat: gives a warning and seems to be deprecated by now.
Here you are,
NSDate *currentDate = [NSDate date];
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDateComponents* components = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay fromDate:currentDate]; // Get necessary date components
[components month]; //gives you month
[components day]; //gives you day
[components year]; // gives you year
You can use NSDateComponents for that as above.
Please visit this page for details.
Yes by the use of NSCalendar, though, i think this will make your work.
NSDateComponents *components = [[NSCalendar currentCalendar] components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit fromDate:[NSDate date]];
NSInteger day = [components day];
NSInteger month = [components month];
NSInteger year = [components year];
Swift
let components = NSCalendar.currentCalendar().components([.Day, .Month, .Year], fromDate: self)
let day = components.day
let month = components.month
let year = components.year
For convenience you can put this in an NSDate extension and make it return a tuple:
extension NSDate: Comparable {
var dayMonthYear: (Int, Int, Int) {
let components = NSCalendar.currentCalendar().components([.Day, .Month, .Year], fromDate: self)
return (components.day, components.month, components.year)
}
}
Now you have to write only:
let (day, month, year) = date.dayMonthYear
If you wanted to e.g. get only the the year you can write:
let (_, _, year) = date.dayMonthYear
You can use NSDateComponents to get this,
NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar];
NSDate *currDate = [NSDate date];
NSDateComponents *dComp = [calendar components:( NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit )
fromDate:currDate];
int day = [dComp day];
int month = [dComp month];
int year = [dComp year];
Put it in an extension and live your life 🍸🏖
extension Date{
var day:Int {return Calendar.current.component(.day, from:self)}
var month:Int {return Calendar.current.component(.month, from:self)}
var year:Int {return Calendar.current.component(.year, from:self)}
}
Date().day//22
Date().month//4
Date().year//2017
Swift 3.0 (It's an iteration of previous answers, but solves it for all your future app projects)
To those who just copy and paste directly from the web, like me, this is a small update for iOS 8
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDateComponents* components = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay fromDate:[NSDate date]];
[components day]; //Day
[components month];//Month
[components year];//Year
The difference is NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay NSMonthCalendarUnit | NSDayCalendarUnit | NSYearCalendarUnit | NSWeekdayCalendarUnit have been deprecated
U can try this .......
Mycal = [NSCalendar currentCalendar];
today = [NSDate date];
compA =[Mycal components:(NSMonthCalendarUnit | NSDayCalendarUnit | NSYearCalendarUnit | NSWeekdayCalendarUnit) fromDate:today];
FirstDateofMonth=[today dateByAddingTimeInterval:([compA day]-1)*(-24*60*60)];
compA =[Mycal components:(NSMonthCalendarUnit | NSDayCalendarUnit | NSYearCalendarUnit | NSWeekdayCalendarUnit) fromDate:FirstDateofMonth];
today = FirstDateofMonth;
compA = [Mycal components:(NSMonthCalendarUnit | NSDayCalendarUnit | NSYearCalendarUnit | NSWeekdayCalendarUnit) fromDate:today];
[compA setMonth:([compA month])];
[self DrawMonthInPortraitView];
[compA retain];
NSDate *currentDate = [NSDate date];
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDateComponents* components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:currentDate]; // Get necessary date components
[components month]; //gives you month
[components day]; //gives you day
[components year]; // gives you year
NSString *temp=[NSString stringWithFormat:#"Months:%d Day:%d Year:%d",[components month], [components day],[components year]];
NSLog(#"%#",temp);
let date = Date()
let calendar = Calendar.current
let year = calendar.component(.year, from: date)
let month = calendar.component(.month, from: date)
let day = calendar.component(.day, from: date)
print("hours = \(year):\(month):\(day)")
Let's say we are the 15/07/2010, I would like to get the first day of the previous week, which is the 5 of July. I have the following method but it does not work. Seems that I have a problem with the weekday attribute...
+ (NSDate *)getFirstDayOfPreviousWeek
{
// Get current date
NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *now = [NSDate date];
// Get today date at midnight
NSDateComponents *components = [cal components:( NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit | NSTimeZoneCalendarUnit) fromDate:now];
[components setHour:0];
[components setMinute:0];
[components setSecond:0];
NSInteger *dayNbr = [components weekday];
NSLog(#"week day:%#",dayNbr); // CRASH
NSDate *todayMidnight = [cal dateFromComponents:components];
// Get first day of previous week midnight
components = [[[NSDateComponents alloc] init] autorelease];
NSInteger *wd = [dayNbr intValue] * -1 + 1;
[components setWeekDay:wd];
[components setWeek:-1];
NSDate *newDate = [cal dateByAddingComponents:components toDate:todayMidnight options:0];
[cal release];
NSLog(#"new date:%#", newDate);
return newDate;
}
Could you please help ?
Thanks a lot,
Luc
I think it should be a lot easier
- (NSDate *)getFirstDayOfPreviousWeek
{
NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *now = [NSDate date];
NSLog(#"Current date: %#", now);
// required components for today
NSDateComponents *components = [cal components:( NSYearCalendarUnit | NSMonthCalendarUnit | NSWeekCalendarUnit | NSWeekdayCalendarUnit ) fromDate:now];
// adjust them for first day of previous week (Monday)
[components setWeekday:2];
[components setWeek:([components week] - 1)];
// construct new date and return
NSDate *newDate = [cal dateFromComponents:components];
NSLog(#"New date: %#", newDate);
return newDate;
}
Note this solution assumes the first day of the week is Monday.
The following Swift 3 Playground code shows how to get the first day of the previous week from any date:
import Foundation
let calendar = Calendar(identifier: .gregorian)
let intialDate = Date()
// Prepare the new date components
var newDateComponents = calendar.dateComponents([.year, .month, .weekOfMonth], from: intialDate)
newDateComponents.weekOfMonth = newDateComponents.weekOfMonth! - 1 // get previous week
newDateComponents.weekday = 2 // sunday is 1, monday is 2
// Get the new date
let newDate = calendar.date(from: newDateComponents)
print(newDate ?? "Could not retrieve a date")
If you need to repeat this operation, you may refactor your code into a function or a method:
import Foundation
func firstDayOfPreviousWeek(from date: Date) -> Date? {
let calendar = Calendar(identifier: .gregorian)
var newDateComponents = calendar.dateComponents([.year, .month, .weekOfMonth], from: date)
newDateComponents.weekOfMonth = newDateComponents.weekOfMonth! - 1
newDateComponents.weekday = 2
return calendar.date(from: newDateComponents)
}
Therefore, the following Playground code shows how to get the first day of the previous week from July 15, 2010:
import Foundation
func firstDayOfPreviousWeek(from date: Date) -> Date? {
let calendar = Calendar(identifier: .gregorian)
var newDateComponents = calendar.dateComponents([.year, .month, .weekOfMonth], from: date)
newDateComponents.weekOfMonth = newDateComponents.weekOfMonth! - 1
newDateComponents.weekday = 2
newDateComponents.timeZone = TimeZone(abbreviation: "GMT")
return calendar.date(from: newDateComponents)
}
let calendar = Calendar(identifier: .gregorian)
var july15Components = DateComponents()
july15Components.day = 15
july15Components.month = 7
july15Components.year = 2010
july15Components.timeZone = TimeZone(abbreviation: "GMT")
let july15 = calendar.date(from: july15Components)!
print(july15) // prints 2010-07-15 00:00:00 +0000
let newDate = firstDayOfPreviousWeek(from: july15)
print(newDate ?? "Could not retrieve a date") // prints 2010-07-05 00:00:00 +0000
What is the most efficient/recommended way of comparing two NSDates? I would like to be able to see if both dates are on the same day, irrespective of the time and have started writing some code that uses the timeIntervalSinceDate: method within the NSDate class and gets the integer of this value divided by the number of seconds in a day. This seems long winded and I feel like I am missing something obvious.
The code I am trying to fix is:
if (!([key compare:todaysDate] == NSOrderedDescending))
{
todaysDateSection = [eventSectionsArray count] - 1;
}
where key and todaysDate are NSDate objects and todaysDate is creating using:
NSDate *todaysDate = [[NSDate alloc] init];
Regards
Dave
I'm surprised that no other answers have this option for getting the "beginning of day" date for the objects:
[[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay startDate:&date1 interval:NULL forDate:date1];
[[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay startDate:&date2 interval:NULL forDate:date2];
Which sets date1 and date2 to the beginning of their respective days. If they are equal, they are on the same day.
Or this option:
NSUInteger day1 = [[NSCalendar currentCalendar] ordinalityOfUnit:NSDayCalendarUnit inUnit: forDate:date1];
NSUInteger day2 = [[NSCalendar currentCalendar] ordinalityOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitEra forDate:date2];
Which sets day1 and day2 to somewhat arbitrary values that can be compared. If they are equal, they are on the same day.
You set the time in the date to 00:00:00 before doing the comparison:
unsigned int flags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDateComponents* components = [calendar components:flags fromDate:date];
NSDate* dateOnly = [calendar dateFromComponents:components];
// ... necessary cleanup
Then you can compare the date values. See the overview in reference documentation.
There's a new method that was introduced to NSCalendar with iOS 8 that makes this much easier.
- (NSComparisonResult)compareDate:(NSDate *)date1 toDate:(NSDate *)date2 toUnitGranularity:(NSCalendarUnit)unit NS_AVAILABLE(10_9, 8_0);
You set the granularity to the unit(s) that matter. This disregards all other units and limits comparison to the ones selected.
For iOS8 and later, checking if two dates occur on the same day is as simple as:
[[NSCalendar currentCalendar] isDate:date1 inSameDayAsDate:date2]
See documentation
This is a shorthand of all the answers:
NSInteger interval = [[[NSCalendar currentCalendar] components: NSDayCalendarUnit
fromDate: date1
toDate: date2
options: 0] day];
if(interval<0){
//date1<date2
}else if (interval>0){
//date2<date1
}else{
//date1=date2
}
I used the Duncan C approach, I have fixed some mistakes he made
-(NSInteger) daysBetweenDate:(NSDate *)firstDate andDate:(NSDate *)secondDate {
NSCalendar *currentCalendar = [NSCalendar currentCalendar];
NSDateComponents *components = [currentCalendar components: NSDayCalendarUnit fromDate: firstDate toDate: secondDate options: 0];
NSInteger days = [components day];
return days;
}
I use this little util method:
-(NSDate*)normalizedDateWithDate:(NSDate*)date
{
NSDateComponents* components = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit)
fromDate: date];
return [calendar_ dateFromComponents:components]; // NB calendar_ must be initialized
}
(You obviously need to have an ivar called calendar_ containing an NSCalendar.)
Using this, it is easy to check if a date is today like this:
[[self normalizeDate:aDate] isEqualToDate:[self normalizeDate:[NSDate date]]];
([NSDate date] returns the current date and time.)
This is of course very similar to what Gregory suggests. The drawback of this approach is that it tends to create lots of temporary NSDate objects. If you're going to process a lot of dates, I would recommend using some other method, such as comparing the components directly, or working with NSDateComponents objects instead of NSDates.
The answer is simpler than everybody makes it out to be. NSCalendar has a method
components:fromDate:toDate:options
That method lets you calculate the difference between two dates using whatever units you want.
So write a method like this:
-(NSInteger) daysBetweenDate: (NSDate *firstDate) andDate: (NSDate *secondDate)
{
NSCalendar *currentCalendar = [NSCalendar currentCalendar];
NSDateComponents components* = [currentCalendar components: NSDayCalendarUnit
fromDate: firstDate
toDate: secondDate
options: 0];
NSInteger days = [components days];
return days;
}
If the above method returns zero, the two dates are on the same day.
From iOS 8.0 onwards, you can use:
NSCalendar *calendar = [NSCalendar currentCalendar];
NSComparisonResult dateComparison = [calendar compareDate:[NSDate date] toDate:otherNSDate toUnitGranularity:NSCalendarUnitDay];
If the result is e.g. NSOrderedDescending, otherDate is before [NSDate date] in terms of days.
I do not see this method in the NSCalendar documentation but it is in the iOS 7.1 to iOS 8.0 API Differences
For developers coding in Swift 3
if(NSCalendar.current.isDate(selectedDate, inSameDayAs: NSDate() as Date)){
// Do something
}
With Swift 3, according to your needs, you can choose one of the two following patterns in order to solve your problem.
#1. Using compare(_:to:toGranularity:) method
Calendar has a method called compare(_:to:toGranularity:). compare(_:to:toGranularity:) has the following declaration:
func compare(_ date1: Date, to date2: Date, toGranularity component: Calendar.Component) -> ComparisonResult
Compares the given dates down to the given component, reporting them orderedSame if they are the same in the given component and all larger components, otherwise either orderedAscending or orderedDescending.
The Playground code below shows hot to use it:
import Foundation
let calendar = Calendar.current
let date1 = Date() // "Mar 31, 2017, 2:01 PM"
let date2 = calendar.date(byAdding: .day, value: -1, to: date1)! // "Mar 30, 2017, 2:01 PM"
let date3 = calendar.date(byAdding: .hour, value: 1, to: date1)! // "Mar 31, 2017, 3:01 PM"
/* Compare date1 and date2 */
do {
let comparisonResult = calendar.compare(date1, to: date2, toGranularity: .day)
switch comparisonResult {
case ComparisonResult.orderedSame:
print("Same day")
default:
print("Not the same day")
}
// Prints: "Not the same day"
}
/* Compare date1 and date3 */
do {
let comparisonResult = calendar.compare(date1, to: date3, toGranularity: .day)
if case ComparisonResult.orderedSame = comparisonResult {
print("Same day")
} else {
print("Not the same day")
}
// Prints: "Same day"
}
#2. Using dateComponents(_:from:to:)
Calendar has a method called dateComponents(_:from:to:). dateComponents(_:from:to:) has the following declaration:
func dateComponents(_ components: Set<Calendar.Component>, from start: Date, to end: Date) -> DateComponents
Returns the difference between two dates.
The Playground code below shows hot to use it:
import Foundation
let calendar = Calendar.current
let date1 = Date() // "Mar 31, 2017, 2:01 PM"
let date2 = calendar.date(byAdding: .day, value: -1, to: date1)! // "Mar 30, 2017, 2:01 PM"
let date3 = calendar.date(byAdding: .hour, value: 1, to: date1)! // "Mar 31, 2017, 3:01 PM"
/* Compare date1 and date2 */
do {
let dateComponents = calendar.dateComponents([.day], from: date1, to: date2)
switch dateComponents.day {
case let value? where value < 0:
print("date2 is before date1")
case let value? where value > 0:
print("date2 is after date1")
case let value? where value == 0:
print("date2 equals date1")
default:
print("Could not compare dates")
}
// Prints: date2 is before date1
}
/* Compare date1 and date3 */
do {
let dateComponents = calendar.dateComponents([.day], from: date1, to: date3)
switch dateComponents.day {
case let value? where value < 0:
print("date2 is before date1")
case let value? where value > 0:
print("date2 is after date1")
case let value? where value == 0:
print("date2 equals date1")
default:
print("Could not compare dates")
}
// Prints: date2 equals date1
}
int interval = (int)[firstTime timeIntervalSinceDate:secondTime]/(60*60*24);
if (interval!=0){
//not the same day;
}
my solution was two conversions with NSDateFormatter:
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"yyyyMMdd"];
[dateFormat setTimeZone:[NSTimeZone timeZoneWithName:#"GMT"]];
NSDate *today = [NSDate dateWithTimeIntervalSinceNow:0];
NSString *todayString=[dateFormat stringFromDate:today];
NSDate *todayWithoutHour=[dateFormat dateFromString:todayString];
if ([today compare:exprDate] == NSOrderedDescending)
{
//do
}
The documentation regarding NSDate indicates that the compare: and isEqual: methods will both perform a basic comparison and order the results, albeit they still factor in time.
Probably the simplest way to manage the task would be to create a new isToday method to the effect of the following:
- (bool)isToday:(NSDate *)otherDate
{
currentTime = [however current time is retrieved]; // Pardon the bit of pseudo-code
if (currentTime < [otherDate timeIntervalSinceNow])
{
return YES;
}
else
{
return NO;
}
}
This is a particularly ugly cat to skin, but here's another way to do it. I don't say it's elegant, but it's probably as close as you can get with the date/time support in iOS.
bool isToday = [[NSDateFormatter localizedStringFromDate:date dateStyle:NSDateFormatterFullStyle timeStyle:NSDateFormatterNoStyle] isEqualToString:[NSDateFormatter localizedStringFromDate:[NSDate date] dateStyle:NSDateFormatterFullStyle timeStyle:NSDateFormatterNoStyle]];
NSUInteger unit = NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit;
NSDateComponents *comp = [cal components:unit
fromDate:nowDate
toDate:setDate
options:0];
NSString *dMonth;
dMonth = [NSString stringWithFormat:#"%02ld",comp.month];
NSString *dDay;
dDay = [NSString stringWithFormat:#"%02ld",comp.day + (comp.hour > 0 ? 1 : 0)];
compare hour as well to fix 1day difference