Set NSDates days to same value - ios

I want to compare 2 specific days, but, i want to compare month and year, not days. For example, i got one date something like 2016-08-16, and other date like 2016-08-10, i need to compare dates and got equality, because their month are equal.
Therefore, i need a way to make both NSDates with equal days, so i need to make 2016-08-10 to be 2016-08-00. After that i can modify second date as well and make comparison.
I have simple code snipper for equality, but i suppose it consider days and hours, etc. as well:
if ([dateOld compare:dateNew] == NSOrderedDescending) {
NSLog(#"date1 is later than date2");
} else if ([dateOld compare:dateNew] == NSOrderedAscending) {
NSLog(#"date1 is earlier than date2");
} else {
NSLog(#"dates are the same");
}
To make it work i need to "zero" days and time of NSDates. Is there any way to do that?

See this SO answer: Comparing certain components of NSDate?
NSCalendar *calendar = [NSCalendar currentCalendar];
NSInteger desiredComponents = (NSMonthCalendarUnit | NSYearCalendarUnit);
NSDate *firstDate = ...; // one date
NSDate *secondDate = ...; // the other date
NSDateComponents *firstComponents = [calendar components:desiredComponents fromDate:firstDate];
NSDateComponents *secondComponents = [calendar components:desiredComponents fromDate:secondDate];
NSDate *truncatedFirst = [calendar dateFromComponents:firstComponents];
NSDate *truncatedSecond = [calendar dateFromComponents:secondComponents];
NSComparisonResult result = [truncatedFirst compare:truncatedSecond];
if (result == NSOrderedAscending) {
//firstDate is before secondDate
} else if (result == NSOrderedDescending) {
//firstDate is after secondDate
} else {
//firstDate is the same month/year as secondDate
}

If you have two dates,
NSDate *now = // some date
NSDate *other = // some other date
You can do this comparison as:
if ([[NSCalendar currentCalendar] compareDate:now toDate:other toUnitGranularity:NSCalendarUnitMonth] == NSOrderedSame) {
NSLog(#"Same month");
} else {
NSLog(#"Different month");
}

Related

Get last tuesday in month ios

Can get last weekday in the month through NSDateComponents? For example: last monday in month or last friday in month. etc
Just another way to solve. Find the first day of the next month, then search backwards for Tuesday.
let calendar = NSCalendar.currentCalendar()
let today = NSDate()
let components = calendar.components([.Year, .Month], fromDate: today)
components.month += 1
// If today is 2016-07-12 then nextMonth will be the
// first day of the next month: 2016-08-01
if let nextMonth = calendar.dateFromComponents(components) {
// Search backwards for weekday = Tuesday
let options: NSCalendarOptions = [.MatchPreviousTimePreservingSmallerUnits, .SearchBackwards]
calendar.nextDateAfterDate(nextMonth, matchingUnit: .Weekday, value: 3, options: options)
}
Here's a solution; tested, and fairly robust, I think.
We'll let NSCalendar walk through the month, a day at a time, and pull out all matching weekdays as NSDates. Then you can answer questions like, "The 3rd Wednesday of this month"
I believe the comments are clear about what is happening, and why.
If you need further clarification, I'll be happy to do so.
//What weekday are we interested in? 1 = Sunday . . . 7 = Saturday
NSInteger targetWeekday = 1;
//Using this methodology, GMT timezone is important to set
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
calendar.timeZone = [NSTimeZone timeZoneWithAbbreviation:#"GMT"];
//set the components to the first of the current month
NSDateComponents *startComponents = [calendar components:NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];
startComponents.day = 1;
//the enumeration starts "afterDate", so shift the start back one day (86400 seconds) to include the 1st of the month
NSDate *startDate = [[calendar dateFromComponents:startComponents] dateByAddingTimeInterval:-86400];
//the enumeration searches for a match; we'll match at the midnight hour and find every occurance of midnight
NSDateComponents *dayByDay = [[NSDateComponents alloc] init];
dayByDay.hour = 0;
//I've opted to put all matching weekdays of the month into an array, so you can find any instance easily
__block NSMutableArray *foundDates = [NSMutableArray arrayWithCapacity:5];
[calendar enumerateDatesStartingAfterDate:startDate
matchingComponents:dayByDay
options:NSCalendarMatchPreviousTimePreservingSmallerUnits
usingBlock:^(NSDate *date, BOOL exactMatch, BOOL *stop){
NSDateComponents *thisComponents = [calendar components:NSCalendarUnitMonth | NSCalendarUnitWeekday fromDate:date];
//as long as the month stays the same... (or the year, if you wanted to)
if (thisComponents.month == startComponents.month) {
//does this date match our target weekday search?
if (thisComponents.weekday == targetWeekday) {
//then add it to our result array
[foundDates addObject:date];
}
//once the month has changed, we're done
} else {
*stop = YES;
}
}];
//Now, with our search result array, we can find the 1st, last, or any specific occurance of that weekday on that month
NSLog(#"Found these: %#", foundDates);
So, if you only wanted the last one, then just use [foundDates lastObject]
Try this code. This works for me.
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *comps = [gregorian components:NSWeekdayCalendarUnit fromDate:[NSDate date]];
int weekday = [comps weekday];
int lastTues;
int lastSatDay;
if (weekday==1) {
lastTues=5;
lastSatDay=1;
}
else if (weekday==2)
{
lastTues=6;
lastSatDay=2;
}
else if (weekday==3)
{
lastTues=7;
lastSatDay=3;
}
else if (weekday==4)
{
lastTues=1;
lastSatDay=4;
}
else if (weekday==5)
{
lastTues=2;
lastSatDay=5;
}
else if (weekday==6)
{
lastTues=3;
lastSatDay=6;
}
else if (weekday==7)
{
lastTues=4;
lastSatDay=7;
}
NSDate *lastTuesDay = [[NSDate date] addTimeInterval:-3600*24*(lastTues)];
NSDate *lastSaturday = [[NSDate date] addTimeInterval:-3600*24*(lastSatDay)];

Compare NSDate times

I'd like to compare two different times in an if statement. Fort example
if (10:37 > 09:00) // DO SOMETHING
Is there a way to do this using NSDate and NSDateFormatter?
NSDate *date1;
NSDate *date2;
if([date1 laterDate:date2] == *it will return the later date, either date1 or date2*)
Try this
//Date formatter - to format the sample dates using for comparison
NSDateFormatter *dateformatter = [[NSDateFormatter alloc]init];
[dateformatter setDateFormat:#"HH:MM:SS"];
// Creating 2 sample dates
NSDate *date1 = [dateformatter dateFromString:#"10:10:10"];
NSDate *date2 = [dateformatter dateFromString:#"10:10:20"];
if (NSOrderedDescending == [date1 compare:date2])// Here comparing the dates
{
NSLog(#"date1 later than date 2");
}
else
{
NSLog(#"date2 later than date 1");
}
You need to use timeIntervalSinceDate api for comparing two different times.
As I understand your question, you only have times, not dates. Actually than NSDate isn't the best choice, as it represents exactly one moment in time for all eternity.
If you only have times or recurring dates, NSDateComponents are the better choice. You can define what components is used, in your case hour and minute.
NSDateComponents have one caveat: no compare: method, but you can easily compare as
if (date1Comps.hour < date2Comps.hour) {
NSLog(#"date 1 earlier");
} else if(date1Comps.hour > date2Comps.hour) {
NSLog(#"date 2 earlier");
} else {
if (date1Comps.minute < date2Comps.minute) {
NSLog(#"date 1 earlier");
} else if(date1Comps.minute > date2Comps.minute){
NSLog(#"date 2 earlier");
} else {
NSLog(#"same hour, same minute");
}
}
here is the full code including creating components from dates.
NSString *date1String = #"2014-07-18T10:30";
NSString *date2String = #"2014-07-18T10:45";
NSDateFormatter *f = [[NSDateFormatter alloc] init];
[f setDateFormat:#"yyyy-MM-dd'T'HH:mm"];
NSDate *date1 = [f dateFromString:date1String];
NSDate *date2 = [f dateFromString:date2String];
NSDateComponents *date1Comps = [[NSCalendar currentCalendar] components:(NSCalendarUnitHour|NSCalendarUnitMinute) fromDate:date1];
NSDateComponents *date2Comps = [[NSCalendar currentCalendar] components:(NSCalendarUnitHour|NSCalendarUnitMinute) fromDate:date2];
if (date1Comps.hour < date2Comps.hour) {
NSLog(#"date 1 earlier");
} else if(date1Comps.hour > date2Comps.hour) {
NSLog(#"date 2 earlier");
} else {
if (date1Comps.minute < date2Comps.minute) {
NSLog(#"date 1 earlier");
} else if(date1Comps.minute > date2Comps.minute){
NSLog(#"date 2 earlier");
} else {
NSLog(#"same hour, same minute");
}
}
or similar: order the date components in an array
NSArray *times = [#[date1Comps, date2Comps] sortedArrayUsingComparator:^NSComparisonResult(NSDateComponents *date1Comps, NSDateComponents *date2Comps) {
if (date1Comps.hour < date2Comps.hour) {
return NSOrderedAscending;
} else if(date1Comps.hour > date2Comps.hour) {
return NSOrderedDescending;
} else {
if (date1Comps.minute < date2Comps.minute) {
return NSOrderedAscending;
} else if(date1Comps.minute > date2Comps.minute){
return NSOrderedDescending;
}
}
return NSOrderedSame;
}];
You can save this comparison block and reuse it. Than it won't matter much that there is no easy compare method.
NSDateComponents *components = [[NSCalendar currentCalendar] components:NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit fromDate:[NSDate date]];
NSInteger todayHour = [components hour];
NSInteger currentMinute = [components minute];
if (currentHour < 7 || (currentHour > 21 || currentHour == 21 && (currentMinute > 0 || currentMinute > 0))) {
// Do your task
}
This may helps you :)

Match a given day and month in any year in an NSDate?

I’d like to set up an NSDate object which can tell me whether a specified date is between two other dates, but disregard year. I have a little something in my app which does something special at Christmas and I’d like to future-proof it for subsequent years. I’m using the following code to check if the current date is between December 1st and December 31st, but I’ve had to specify the year (2013).
I’m not too sure how to go about modifying it to work for any year – since the dates are converted into plain numeric values, can it even be done?
+ (NSDate *)dateForDay:(NSInteger)day month:(NSInteger)month year:(NSInteger)year
{
NSDateComponents *comps = [NSDateComponents new];
[comps setDay:day];
[comps setMonth:month];
[comps setYear:year];
return [[NSCalendar currentCalendar] dateFromComponents:comps];
}
- (BOOL)laterThan:(NSDate *)date
{
if (self == date) {
return NO;
} else {
return [self compare:date] == NSOrderedDescending;
}
}
- (BOOL)earlierThan:(NSDate *)date
{
if (self == date) {
return NO;
} else {
return [self compare:date] == NSOrderedAscending;
}
}
It sounds like all you need to be able to do is determine if an NSDate falls in December. I believe you can do it like this:
NSDate * now = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *nowComponents = [gregorian components:NSMonthCalendarUnit fromDate:now];
if ([nowComponents month] == 12) {
// It's December, do something
}
If you don't want to be limited to an entire month you could get the month and day components of your current date.
To tell if a date is later in the year than some given date I'd use something like this:
// yearlessDate is in the form MMddHHmmss
+BOOL date:(NSDate*)theDate isLaterInYearThan:(NSString*)yearlessDate {
NSDateFormatter* fmt = [[NSDateFormatter alloc] init];
fmt.dateFormat = #"MMddHHmmss";
NSString* theDateFormatted = [fmt stringFromDate:theDate];
return [theDateFormatted compareTo:yearlessDate] == NSOrderedDescending;
}
The usual caveats apply re timezone, 12/24 device setting, etc. It would be most optimal to make the DateFormatter a static object.

How do I accommodate opening and closing dates NSDate comparator on separate days?

Comparing dates is quite complex. I have an app that is comparing opening and closing dates for stores and it works great for times in the same day, i.e. opening a 8am and closing at 5pm the same day.
Here is the code that compares the time:
if ([self timeCompare:openDate until:closeDate withNow:now]) {
NSLog(#"TIMECOMPARATOR = timeCompare>OPEN");
status = YES;
} else {
NSLog(#"TIMECOMPARATOR = timeCompare>CLOSED");
status = NO;
}
return status;
This calls the following method:
+(BOOL)timeCompare:(NSDate*)date1 until:(NSDate*)date2 withNow:(NSDate*)now{
NSLog(#"TIMECOMPARE = open:%# now:%# close:%#", date1, now, date2);
return ([date1 compare:now] == NSOrderedAscending && [date2 compare:now] == NSOrderedDescending);
}
The problem comes when the closing time is "assumed" by a person but of course not by a computer, to close at the next day, such as 7am to 2am. I obviously mean the next day. How do I accommodate for this to signal the computer to be the next day?
Compare the date's unix time. It will be accurate regardless of date as it is constantly increasing.
First you have to convert the strings "7:00 AM", "10:00 PM" to a NSDate from the current day. This can be done e.g. with the following method:
- (NSDate *)todaysDateFromAMPMString:(NSString *)time
{
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
[fmt setLocale:[NSLocale localeWithLocaleIdentifier:#"en_US_POSIX"]];
// Get year-month-day for today:
[fmt setDateFormat:#"yyyy-MM-dd "];
NSString *todayString = [fmt stringFromDate:[NSDate date]];
// Append the given time:
NSString *todaysTime = [todayString stringByAppendingString:time];
// Convert date+time string back to NSDate:
[fmt setDateFormat:#"yyyy-MM-dd h:mma"];
NSDate *date = [fmt dateFromString:todaysTime];
return date;
}
Then you can proceed as in https://stackoverflow.com/a/20441330/1187415:
// Some example values:
NSString *strOpenTime = #"10:00 PM";
NSString *strCloseTime = #"2:00 AM";
NSDate *openTime = [self todaysDateFromAMPMString:strOpenTime];
NSDate *closeTime = [self todaysDateFromAMPMString:strCloseTime];
if ([closeTime compare:openTime] != NSOrderedDescending) {
// closeTime is less than or equal to openTime, so add one day:
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *comp = [[NSDateComponents alloc] init];
[comp setDay:1];
closeTime = [cal dateByAddingComponents:comp toDate:closeTime options:0];
}
NSDate *now = [NSDate date];
if ([now compare:openTime] != NSOrderedAscending &&
[now compare:closeTime] != NSOrderedDescending) {
// Shop is OPEN
} else {
// Shop is CLOSED
}
This is an app design question, not a coding question. You need to define a clear vocabulary for the user to communicate what they mean. I would suggest adding a UISwitch to the screen, with 2 positions on it: "Today" and "Tomorrow". You can add some program logic that takes a guess as to times where you think the user is talking about a date tomorrow, and set the default switch to the "tomorrow" state in that case, but the user should be able to tell you what they mean.
How about you just add a check whether all the three NSDate are having the same date (DDMMYYYY) value?

Compare two time values in ios? [duplicate]

This question already has answers here:
Comparing time and date in objective C
(2 answers)
Closed 9 years ago.
In my app i want to check whether the current time is before or after the time saved in a variable.
like my time1 is time1=#"08:15:12"; and my time2 is time2=#"18:12:8";
so i wanna compare between time1 and time2.Currently these variables are in NSString Format.
Following are the code used to get time,and i dont know how to compare them.
CODE:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = #"HH:MM:SS";
[dateFormatter setTimeZone:[NSTimeZone systemTimeZone]];
NSLog(#"ewetwet%#",[dateFormatter stringFromDate:now]);
Please help me
Use the following code to do the convert from the nsstring to nsdate and compare them.
NSString *time1 = #"08:15:12";
NSString *time2 = #"18:12:08";
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"HH:mm:ss"];
NSDate *date1= [formatter dateFromString:time1];
NSDate *date2 = [formatter dateFromString:time2];
NSComparisonResult result = [date1 compare:date2];
if(result == NSOrderedDescending)
{
NSLog(#"date1 is later than date2");
}
else if(result == NSOrderedAscending)
{
NSLog(#"date2 is later than date1");
}
else
{
NSLog(#"date1 is equal to date2");
}
// Use compare method.
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSDate *startDate = [formatter dateFromString:#"2012-12-07 7:17:58"];
NSDate *endDate = [formatter dateFromString:#"2012-12-07 7:17:59"];
if ([startDate compare: endDate] == NSOrderedDescending) {
NSLog(#"startDate is later than endDate");
} else if ([startDate compare:endDate] == NSOrderedAscending) {
NSLog(#"startDate is earlier than endDate");
} else {
NSLog(#"dates are the same");
}
// Way 2
NSTimeInterval timeDifference = [endDate timeIntervalSinceDate:startDate];
double minutes = timeDifference / 60;
double hours = minutes / 60;
double seconds = timeDifference;
double days = minutes / 1440;
NSLog(#" days = %.0f,hours = %.2f, minutes = %.0f,seconds = %.0f", days, hours, minutes, seconds);
if (seconds >= 1)
NSLog(#"End Date is grater");
else
NSLog(#"Start Date is grater");
First you need to convert your time string to NSDate => Converting time string to Date format iOS.
Then use following code
NSDate *timer1 =...
NSDate *timer2 =...
NSComparisonResult result = [timer1 compare:timer2];
if(result == NSOrderedDescending)
{
// time 1 is greater then time 2
}
else if(result == NSOrderedAscending)
{
// time 2 is greater then time 1
}
else
{
//time 1 is equal to time 2
}
You can use this link
According to Apple documentation of NSDate compare:
Returns an NSComparisonResult value that indicates the temporal ordering of the receiver and another given date.
- (NSComparisonResult)compare:(NSDate *)anotherDate
Parameters anotherDate
The date with which to compare the receiver. This value must not be nil. If the value is nil, the behavior is undefined and may change in future versions of Mac OS X.
Return Value
If:
The receiver and anotherDate are exactly equal to each other, NSOrderedSame
The receiver is later in time than anotherDate, NSOrderedDescending
The receiver is earlier in time than anotherDate, NSOrderedAscending
In other words:
if ([date1 compare:date2]==NSOrderedSame) ...
Note that it might be easier to read and write this :
if ([date2 isEqualToDate:date2]) ...
See Apple Documentation about this one. If you feel any problem you can also use this link here. Here you can go through Nelson Brian answer.
I have done this at my end as follows-
NSDate * currentDateObj=#"firstDate";
NSDate * shiftDateFieldObj=#"SecondDate";
NSTimeInterval timeDifferenceBetweenDates = [shiftDateFieldObj timeIntervalSinceDate:currentDateObj];
You can also get time interval according to time difference between dates.
Hope this helps.

Resources