Create next NSDate that matches day NSString - iphone

I would like to create an NSDate object that represents the next day that matches a NSString day.
For example. The NSString is MON or Monday I want to get the next NSDate that matches this day - it can be today aswell.
e.g.: NSString day = #"Tues";
result = 30 Aug

NSInteger desiredWeekday = 3; // Tuesday
NSRange weekDateRange = [[NSCalendar currentCalendar] maximumRangeOfUnit:NSWeekdayCalendarUnit];
NSInteger daysInWeek = weekDateRange.length - weekDateRange.location + 1;;
NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:NSWeekdayCalendarUnit fromDate:[NSDate date]];
NSInteger currentWeekday = dateComponents.weekday;
NSInteger differenceDays = (desiredWeekday - currentWeekday + daysInWeek) % daysInWeek;
NSDateComponents *daysComponents = [[NSDateComponents alloc] init];
daysComponents.day = differenceDays;
NSDate *newDate = [[NSCalendar currentCalendar] dateByAddingComponents:daysComponents toDate:[NSDate date] options:0];
NSLog(#"newDate: %#", newDate);
2011-08-30 18:42:09.443 Test[63789:707] newDate: 2011-09-05 22:42:09 +0000

Related

Comparing NSDate + Period

I have start date and a duration (period). For example startDate = '2014-02-12' period = 2. I desired dates 2014-02-12, 2014-02-14, 2014-02-16, .... I need to determine the current date is flagged during.
To check if the difference between the start date and the current date is an even
number of days, use NSDateComponents:
NSDate *startDate = ...;
NSDate *currentDate = [NSDate date];
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *diff = [cal components:NSDayCalendarUnit fromDate:startDate
toDate:currentDate options:0];
NSInteger days = diff.day;
if (days % 2 == 0) {
// even number of days between start date and current date
}
You can get the desired dates using
- (id)dateByAddingTimeInterval:(NSTimeInterval)seconds
with seconds = period*3600*24
Calc the days from startDate to givenData, check the result whether it can be divisible by the period.
+ (NSInteger)daysWithinEraFromDate:(NSDate *)startDate toDate:(NSDate *)endDate {
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
[gregorian setTimeZone:[NSTimeZone localTimeZone]];
// for timezone issue
NSDate *newDate1 = [startDate dateByAddingTimeInterval:[[NSTimeZone localTimeZone] secondsFromGMT]];
NSDate *newDate2 = [endDate dateByAddingTimeInterval:[[NSTimeZone localTimeZone] secondsFromGMT]];
NSInteger startDay = [gregorian ordinalityOfUnit:NSDayCalendarUnit
inUnit: NSEraCalendarUnit forDate:newDate1];
NSInteger endDay = [gregorian ordinalityOfUnit:NSDayCalendarUnit
inUnit: NSEraCalendarUnit forDate:newDate2];
return endDay - startDay;
}

How can I make an NSDate aim for the closest future match?

Here's an example of what I want. The user may set up an alarm in my app for 1 minute in the future, so they can test it out. The time might be 19:23, so they'll set the alarm to 19:24, in which case I want it to be triggered on the next occurrence of 19:24 - in 1 minute's time.
If they set the alarm for 8am, I don't want it to set to 8am on the current day, but on the next occurrence of 8am - on following day.
How can I get it to aim for the next occurrence of the time chosen?
Assuming that the alarm time is given as "hour" and "minute", the following code
should produce the desired result:
NSDate *now = [NSDate date];
// Example values for testing:
NSUInteger alarmHour = 10;
NSUInteger alarmMinute = 5;
// Compute alarm time by replacing hour/minute of the current time
// with the given values:
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *comp = [cal components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit
fromDate:now];
[comp setHour:alarmHour];
[comp setMinute:alarmMinute];
NSDate *alarm = [cal dateFromComponents:comp];
// If alarm <= now ...
if ([alarm compare:now] != NSOrderedDescending) {
// ... add one day:
NSDateComponents *oneDay = [[NSDateComponents alloc] init];
[oneDay setDay:1];
alarm = [cal dateByAddingComponents:oneDay toDate:alarm options:0];
}
More tersely, what #HotLicks suggests:
NSDate *userEnteredDate;
NSDate *now = [NSDate date];
if (now == [now laterDate:userEnteredDate]) {
NSDateComponents *components = [[NSCalendar currentCalendar] components:255 fromDate:userEnteredDate]; // 255= the important component masks or'd together
components.day += 1;
userEnteredDate = [[NSCalendar currentCalendar] dateFromComponents:components];
}
NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
NSDateFormatter *formatter_ = [[NSDateFormatter alloc]init];
NSDate *alarmDate = [formatter dateFromString:#"enter your users alarm time-examle(2345)"];
NSDate *currentDate = [NSDate date];
[formatter setDateFormat:#"HHmm"];
NSDate *finalDate;
if ([[formatter stringFromDate:currentDate] intValue] > [[formatter stringFromDate:alarmDate] intValue]) {
[formatter setDateFormat:#"HH:mm"];
[formatter_ setDateFormat:#"dd MM yyyy"];
NSDate *date = [currentDate dateByAddingTimeInterval:60*60*24*1];
finalDate = [formatter_ dateFromString:[NSString stringWithFormat:#"%# %#",[formatter stringFromDate:alarmDate],[formatter_ stringFromDate:date]]];
}else{
finalDate = [formatter_ dateFromString:[NSString stringWithFormat:#"%# %#",[formatter stringFromDate:alarmDate],[formatter_ stringFromDate:currentDate]]];
}

How to subtract 30 minutes from a date

I am getting date value date: 2013-06-07 18:30:00 +0000. I am trying to subtract 30 minutes from this, but it not giving proper time.
I've tried this
NSTimeInterval secondsPerHour = 60*30;
NSDate *newDate = [date dateByAddingTimeInterval:-secondsPerHour];
Reason : The negative of a unsigned int is a positive number. This should work:
NSDate *newDate = [date dateByAddingTimeInterval:-(NSTimeInterval)((u_int32_t)30*60)];
EDIT : Alternative use NSDateComponents.
NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
[dateComponents setMinute:-30];
NSDate *halfHourAgo = [[NSCalendar currentCalendar] dateByAddingComponents:dateComponents toDate:yourDateHere options:0];
NSLog(#"\ncurrentDate: %# \n halfHourAgo: %#", yourDateHere, halfHourAgo);
in Swift 5
let minus30Min = Date().addingTimeInterval(-30 * 60)
you can use:
NSDate *minusOneHr = [[NSDate date] dateByAddingTimeInterval:-30*60];
You could try NSDateComponents, something like that:
NSDate* yourDate = [NSDate dateWithTimeIntervalSinceNow:0]; // your date, to substract 30 mins
NSDateComponents *dc = [[NSCalendar currentCalendar] components:(NSYearCalendarUnit| NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit) fromDate:yourDate];
[dc setMinute:[dc minute] - 30];
NSDate* date = [[NSCalendar currentCalendar] dateFromComponents:dc]; // 30 mins before now
Or that:
NSDate* yourDate = [NSDate dateWithTimeIntervalSinceNow:0]; // your date, to substract 30 mins
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setMinute:-30];
NSDate* date = [[NSCalendar currentCalendar] dateByAddingComponents:components toDate:yourDate options:0]; // 30 mins before now
Copy paste this code in viewDidLoad and check the results first.
NSDate *today = [[NSDate alloc] init];
NSLog(#"Today %#", today);
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
[offsetComponents setMinute:-30]; // If you want to change Month,Year,Day,Hour etc. Just change the "setMinute" to setMonth,setYear,setDay,setHour
NSDate *dateComp = [gregorian dateByAddingComponents:offsetComponents toDate:today options:0];
NSLog(#"Desired Day %#", dateComp);
let dateMinusThirtyMinutes = Date().subtract(30.minutes)

iPhone: method to calculate days till next birthday not accurate --?

Here's a puzzler. I use the following to calculate the number of days between today's date and an upcoming birthday:
-(int) daysTillBirthday: (NSDate*)aDate {
// check to see if valid date was passed in
//NSLog(#"aDate passed in is %#",aDate);
if (aDate == nil) {
//NSLog(#"aDate is NULL");
return -1; // return a negative so won't be picked in table
}
//** HOW MANY DAYS TO BDAY
NSDate *birthDay = aDate; // [calendar dateFromComponents:myBirthDay];
//NSLog(#"birthDay: %#, today: %#",birthDay, [NSDate date]);
NSCalendar *calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
NSDateComponents *thisYearComponents = [calendar components:NSYearCalendarUnit fromDate:[NSDate date]];
NSDateComponents *birthDayComponents = [calendar components:NSMonthCalendarUnit|NSDayCalendarUnit fromDate:birthDay];
[birthDayComponents setYear:[thisYearComponents year]];
NSDate *birthDayThisYear = [calendar dateFromComponents:birthDayComponents];
//NSLog(#"birthDayThisYear: %#",birthDayThisYear);
NSDateComponents *differenceHours = [calendar components:NSHourCalendarUnit fromDate:[NSDate date] toDate:birthDayThisYear options:0];
NSDateComponents *differenceDays = [calendar components:NSDayCalendarUnit fromDate:[NSDate date] toDate:birthDayThisYear options:0];
// NSLog(#"difference days: %i, hours %i",[differenceDays day],[differenceHours hour]);
//*** I added this to try and correct the "error" ***
if ([differenceDays day] == 0) { // is it today, or tomorrow?
if (([differenceHours hour] <= 0) && ([differenceHours hour] >= -24)) { // must be today
//NSLog(#"TODAY");
return (0);
[calendar release];
}else if (([differenceHours hour] >= 0) && ([differenceHours hour] <= 24)) {
//NSLog(#"TOMORROW");
return (1);
[calendar release];
}
}
if ([differenceDays day] < 0) {
// this years birthday is already over. calculate distance to next years birthday
[birthDayComponents setYear:[thisYearComponents year]+1];
birthDayThisYear = [calendar dateFromComponents:birthDayComponents];
differenceDays = [calendar components:NSDayCalendarUnit fromDate:[NSDate date] toDate:birthDayThisYear options:0];
}
return ([differenceDays day]);
[calendar release];
}
Everything works, but the results are not accurate! I often find that birthdays that are close to today, but one day apart, result in [differenceDays day] being the same! i.e. if today is 6/6/2011 and I have two birthdays, one on 6/7/2011 and another 6/8/2011, then they are both shown as 1 day away!
Anyone have any better methods for accurately calculating this, or can spot the problem?
Many thanks.
NSCalendar provides a much easier way to do this:
NSDate *birthday = ...; // the birthday
NSDate *today = [NSDate date];
NSCalendar *c = [NSCalendar currentCalendar];
NSInteger birthdayDayOfYear = [c ordinalityOfUnit:NSDayCalendarUnit inUnit:NSYearCalendarUnit forDate:birthday];
NSInteger todayDayOfYear = [c ordinalityOfUnit:NSDayCalendarUnit inUnit:NSYearCalendarUnit forDate:today];
NSInteger different = birthdayDayOfYear - todayDayOfYear;
Basically, we're figuring out how far into the year today and the target date are (ie, today [5 Jun] is the 156th day of the year), and then subtract them to figure out how many days are in between them.
This method, of course, relies on the assumption that the target date is in the same year as the current date. I think it'd be fairly easy to work around that, however.
Another, even easier way to do this that will account for multi-year differences is like this:
NSDateComponents *d = [[NSCalendar currentCalendar] components:NSDayCalendarUnit fromDate:today toDate:birthday options:0];
NSInteger difference = [d day];
If you need to make sure that the birthday is in the future, that's easily accomplished as well:
NSDateComponents *year = [[[NSDateComponents alloc] init] autorelease];
NSInteger yearDiff = 1;
NSDate *newBirthday = birthday;
while([newBirthday earlierDate:today] == newBirthday) {
[year setYear:yearDiff++];
newBirthday = [[NSCalendar currentCalendar] dateByAddingComponents:year toDate:birthday options:0];
}
//continue on with the 2-line calculation above, using "newBirthday" instead.
update I updated the loop above to always increment from the original date n years at a time, instead of year-by-year. If someone is born on 29 Feb, incrementing by one year would yield 1 Mar, which would be wrong once you got to a leap year again. By jumping from the original date each time, we don't have this issue.
I do the exact same thing in one of my apps. Here is how I do it:
//This is the date your going to - in your case the birthday - note the format
NSString *myDateAsAStringValue = #"20110605";
// Convert string to date object
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"yyyyMMdd"];
NSDate *newDate = [dateFormat dateFromString:myDateAsAStringValue];
NSDateComponents *dateComp = [[NSDateComponents alloc] init];
NSCalendar *Calander = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *comps=[[NSDateComponents alloc] init];
unsigned int unitFlags = NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
dateComp = [Calander components:unitFlags fromDate:[NSDate date]];
[dateFormat setDateFormat:#"dd"];
[comps setDay:[[dateFormat stringFromDate:[NSDate date]] intValue]];
[dateFormat setDateFormat:#"MM"];
[comps setMonth:[[dateFormat stringFromDate:[NSDate date]] intValue]];
[dateFormat setDateFormat:#"yyyy"];
[comps setYear:[[dateFormat stringFromDate:[NSDate date]] intValue]];
[dateFormat setDateFormat:#"HH"];
[comps setHour:05];
[dateFormat setDateFormat:#"mm"];
[comps setMinute:30];
NSDate *currentDate=[Calander dateFromComponents:comps];
dateComp = [Calander components:unitFlags fromDate:newDate];
[dateFormat setDateFormat:#"dd"];
[comps setDay:[[dateFormat stringFromDate:newDate] intValue]];
[dateFormat setDateFormat:#"MM"];
[comps setMonth:[[dateFormat stringFromDate:newDate] intValue]];
[dateFormat setDateFormat:#"yyyy"];
[comps setYear:[[dateFormat stringFromDate:newDate] intValue]];
[dateFormat setDateFormat:#"HH"];
[comps setHour:05];
[dateFormat setDateFormat:#"mm"];
[comps setMinute:30];
NSDate *reminderDate=[Calander dateFromComponents:comps];
NSTimeInterval ti = [reminderDate timeIntervalSinceDate:currentDate];
int days = ti/86400;
return days;
I think I have found a solution. Checking the output carefully, it appears to all come down to the difference in HOURS. For example: comparing today with tomorrow's date might end up being, say, 18 hours away. This results in [difference day] being set at 0 i.e. it thinks tomorrow is today because it is less than 24 hours away.
You can see the fix below. I take the number of hours e.g. 18 and divide by 24 (to get the number of days). In this case 18/24 = 0.75. I then round this up i.e. to "1." So while [difference days] thinks tomorrow is today, by rounding up the hours, you know it is in fact tomorrow.
-(int) daysTillBirthday: (NSDate*)aDate {
// check to see if valid date was passed in
//NSLog(#"aDate passed in is %#",aDate);
if (aDate == nil) {
//NSLog(#"aDate is NULL");
return -1; // return a negative so won't be picked in table
}
//** HOW MANY DAYS TO BDAY
NSDate *birthDay = aDate; // [calendar dateFromComponents:myBirthDay];
NSCalendar *calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
NSDateComponents *thisYearComponents = [calendar components:NSYearCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit fromDate:[NSDate date]];
NSDateComponents *birthDayComponents = [calendar components:NSMonthCalendarUnit|NSDayCalendarUnit fromDate:birthDay];
NSInteger timeNow = [thisYearComponents hour];
[birthDayComponents setYear:[thisYearComponents year]];
[birthDayComponents setHour:timeNow];
NSDate *birthDayThisYear = [calendar dateFromComponents:birthDayComponents];
//NSLog(#"today %#, birthday %#",[NSDate date],birthDayThisYear);
NSDateComponents *difference = [calendar components:NSDayCalendarUnit fromDate:[NSDate date] toDate:birthDayThisYear options:0];
NSDateComponents *differenceHours = [calendar components:NSHourCalendarUnit fromDate:[NSDate date] toDate:birthDayThisYear options:0];
double daysFromHours = ((double)[differenceHours hour])/24; // calculate number of days from hours (and round up)
int roundedDaysFromHours = ceil(daysFromHours);
NSLog(#"daysFromHours %.02f, roundedDaysFromHours %i",daysFromHours,roundedDaysFromHours);
if ([difference day] < 0) {
// this years birthday is already over. calculate distance to next years birthday
[birthDayComponents setYear:[thisYearComponents year]+1];
birthDayThisYear = [calendar dateFromComponents:birthDayComponents];
difference = [calendar components:NSDayCalendarUnit fromDate:[NSDate date] toDate:birthDayThisYear options:0];
}
//NSLog(#"%i days until birthday", [difference day]);
return (roundedDaysFromHours);
[calendar release];
}

Find exact difference between two dates

I want some changes in the date comparison.
In my application I am comparing two dates and getting difference as number of Days, but if there is only one day difference the system shows me 0 as a difference of days.
NSDateFormatter *date_formater=[[NSDateFormatter alloc]init];
[date_formater setDateFormat:#"MMM dd,YYYY"];
NSString *now=[NSString stringWithFormat:#"%#",[date_formater stringFromDate:[NSDate date]]];
LblTodayDate.text = [NSString stringWithFormat:#"%#",[NSString stringWithFormat:#"%#",now]];
NSDate *dateofevent = [[NSUserDefaults standardUserDefaults] valueForKey:#"CeremonyDate_"];
NSDate *endDate =dateofevent;
NSDate *startDate = [NSDate date];
gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
unsigned int unitFlags = NSDayCalendarUnit;
NSDateComponents *components = [gregorian components:unitFlags fromDate:startDate toDate:endDate options:0];
int days = [components day];
I found some solutions that If we make the time as 00:00:00 for comparison then it will show me proper answer, I am right or wrong I don't know.
i think this is not correct make the time 00:00:00.
may be you get difference is less than 24 hour thats why it rounded off and you 0 day.
Alexander solution is right so use that solution like -
this works fine for me also.
NSDate *endDate=[dateFormat dateFromString:now];
NSTimeInterval interval = [CeremonyDate timeIntervalSinceDate:endDate];
int diff=interval/86400;//for converting seconds into days.
same problem of rounding a figure you get here but you can sort out that in an understable way.
I usually find out difference in seconds and calculate ceil(diffInSeconds / 86400).
Try this code for get two date and time different.
NSDateFormatter* dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setLocale:[[[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"] autorelease]];
[dateFormatter setDateFormat:#"mm:ss"];
NSDate* firstDate = [dateFormatter dateFromString:#"04:45"];
NSDate* secondDate = [dateFormatter dateFromString:#"05:00"];
NSTimeInterval timeDifference = [secondDate timeIntervalSinceDate:firstDate];
NSLog(#"%f",timeDifference);
i hope this code usefull for you.
Here a prefect solution to find difference between two dates
- (NSString *)calculateDuration:(NSDate *)oldTime secondDate:(NSDate *)currentTime
{
NSString *timeSincePost;
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSCalendarUnit unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
NSDateComponents *dateComponents = [calendar components:unitFlags fromDate:oldTime toDate:currentTime options:0];
NSInteger year = [dateComponents year];
NSInteger month = [dateComponents month];
NSInteger day = [dateComponents day];
NSInteger hour = [dateComponents hour];
NSInteger minute = [dateComponents minute];
NSInteger second = [dateComponents second];
if (year) {
timeSincePost = [NSString stringWithFormat:#"%ld%#", (long)year,[[kAppDelegate languageBundle] localizedStringForKey:#"y" value:#"" table:nil]];
}
else if (month) {
timeSincePost = [NSString stringWithFormat:#"%ld%#", (long)month,[[kAppDelegate languageBundle] localizedStringForKey:#"M" value:#"" table:nil]];
}
if(day) {
timeSincePost = [NSString stringWithFormat:#"%ld%#", (long)day,[[kAppDelegate languageBundle] localizedStringForKey:#"d" value:#"" table:nil]];
}
else if(hour) {
timeSincePost = [NSString stringWithFormat: #"%ld%#", (long)hour,[[kAppDelegate languageBundle] localizedStringForKey:#"H" value:#"" table:nil]];
}
else if(minute) {
timeSincePost = [NSString stringWithFormat: #"%ld%#", (long)minute,[[kAppDelegate languageBundle] localizedStringForKey:#"m" value:#"" table:nil]];
}
else if(second)
timeSincePost = [NSString stringWithFormat: #"%ld%#", (long)second,[[kAppDelegate languageBundle] localizedStringForKey:#"s" value:#"" table:nil]];
return timeSincePost;
}
and call above function with two parameter as NSDate
NSString *duration = [self calculateDuration:postDate secondDate:[NSDate date]];
lblPostTime.text = duration;
note:: postDate is FirstDate & second date is current date..