How to calculate and display 4 other days from the day i add in date picker and set local notification to it? - xcode

In my App, When i select a day in the datepicker it should automatically calculate and display 4 other days and also it should notify on the corresponding days. For Eg. if i enter 19-08-2014, it should calculate and display the 3rd day, the 7th day, the 14th day and the 21st day from 19-08-2014(the day i entered in datepicker).
How would i achieve this. Any help would be greatly appreciated.
I have added my current code for your reference. This doesnt serve my purpose.
Kindly Help.
(IBAction)save:(UIButton *)sender {
NSDate *pickerDate = [self.picker date];
UILocalNotification *localNotif = [[UILocalNotification alloc]init];
//localNotif.alertBody = _enterText.text;
localNotif.alertBody = #"Please Take Your Rabipur Dosage";
localNotif.fireDate = pickerDate;
localNotif.timeZone = [NSTimeZone defaultTimeZone];
localNotif.soundName = (UILocalNotificationDefaultSoundName);
localNotif.applicationIconBadgeNumber = 1;
//localNotif.repeatInterval = NSDayCalendarUnit;
[[UIApplication sharedApplication]scheduleLocalNotification:localNotif];
[self dismissViewControllerAnimated:YES completion:nil];
}

Create an NSDateComponents object with the date difference you want to add, and add it to pickerDate via NSCalendar -dateByAddingComponents:toDate:options. Then create your notification based on the resulting date.
In this case, something like this:
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
[offsetComponents setDay:3];
NSDate *reminderDate = [gregorian dateByAddingComponents:offsetComponents toDate:pickerDate options:0];
Repeat for 7th, 14th, and 21st day.

Related

Get first day in a month from NSCalendar

I have this subset of a method that needs to get day one of the current month.
NSDate *today = [NSDate date]; // returns correctly 28 february 2013
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [[NSDateComponents alloc] init];
components.day = 1;
NSDate *dayOneInCurrentMonth = [gregorian dateByAddingComponents:components toDate:today options:0];
dayOneInCurrentMonth then prints out 2013-03-01 09:53:49 +0000, the first day of the next month.
How do I get day one of the current month?
Your logic is wrong: Instead of setting the date's day to 1, you're adding a day to the current date.
Try something like that:
NSDate *today = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [gregorian components:(NSEraCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit) fromDate:today];
components.day = 1;
NSDate *dayOneInCurrentMonth = [gregorian dateFromComponents:components];
You want [NSCalender dateFromComponents:] instead:
NSDate *dayOneInCurrentMonth = [gregorian dateFromComponents:components];
Easy way of getting to the 1st from a given date:
NSDate *first = [gregorian dateBySettingUnit:NSCalendarUnitDay value:1 ofDate:date options:0];
Easy Way to get first and last date of previous month is :
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *comp = [gregorian components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay ) fromDate:[NSDate date]];
//TO GET PREVIOUS MONTH LAST DAY
[comp setMonth:[comp month]];
[comp setDay:1];
NSDate *tDateMonth = [gregorian dateFromComponents:comp];
NSLog(#"LAST DAY OF PREVIOUS MONTH ; %#", tDateMonth);
//TO GET PREVIOUS MONTH FIRST DAY
[comp setMonth:[comp month]-1];
[comp setDay:3];
NSDate *td = [gregorian dateFromComponents:comp];
NSLog(#"FIRST DAY OF PREVIOUS MONTH ; %#", td);
Hope this helps
By creating new variable is expensive on memory usage, it's better using date formatter to get the first day of the current month
today = [NSDate date];
firstDayDateFormatter = [[NSDateFormatter alloc] init];
[firstDayDateFormatter setDateFormat:#"01-MM-yyyy"];
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd-MM-yyyy"];
[dateFormatter setLocale:[NSLocale localeWithLocaleIdentifier:#"en_US"]];
firstDayOfTheMonth = [mdfDateFormat dateFromString:[firstDayDateFormatter stringFromDate:today]];
NSDate *startDate = nil;
[[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitMonth startDate:&startDate interval:NULL forDate:date];
return startDate;

NSDate / NSCalender count days in year

I am making an app that calculates salaries based on the years somebody is working for a firm. The user enter 2 dates, the first one is the day he started working (let's say 1/12/2010) and the second is the end date (let's say 1/02/2012). So far i know the total days he worked but i want to be more specific in order to calculate that he worked:
30 days in 2010 * 30$ per day = 90$
365 days in 2011 * 35$ per day = 12775$
32 days in 2012 * 40$ per day = 1280$
It's the first time i am working with dates and calendars and as you can guess i am totally unfamiliar with them.
Try this code :
-(NSInteger)daysBetweenTwoDates:(NSDate *)fromDateTime andDate:(NSDate*)toDateTime{
NSDate *fromDate;
NSDate *toDate;
NSCalendar *calendar = [NSCalendar currentCalendar];
[calendar rangeOfUnit:NSDayCalendarUnit startDate:&fromDate interval:NULL forDate:fromDateTime];
[calendar rangeOfUnit:NSDayCalendarUnit startDate:&toDate interval:NULL forDate:toDateTime];
NSDateComponents *difference = [calendar components:NSDayCalendarUnit fromDate:fromDate toDate:toDate options:0];
return [difference day]+1;//+1 as if start and end both date are same, so 1 day worked.
}
- (IBAction)calculate:(id)sender {
NSDate *startDate=[self.startDate dateValue];//taking from datepicker
NSDate *endDate=[self.endDate dateValue];//taking from datepicker
NSTimeZone *gmt=[NSTimeZone timeZoneWithAbbreviation:#"GMT"];
NSDateFormatter *dateFormatterYYYY=[NSDateFormatter new];
[dateFormatterYYYY setTimeZone:gmt];
[dateFormatterYYYY setDateFormat:#"YYYY"];
NSDateFormatter *dateFormatterDDMMYYYY=[NSDateFormatter new];
[dateFormatterDDMMYYYY setDateFormat:#"dd/mm/YYYY"];
[dateFormatterDDMMYYYY setTimeZone:gmt];
//1. startDate to 31/12/StartDateYear
//2. loop to endDateYear
//3. 01/01/endDateYear to endDate
/* step 1 */
//find 31/12/StartDateYear
NSLog(#"YYYY ; %#",[dateFormatterYYYY stringFromDate:startDate]);
NSString *lastDateOfStartYearString=[NSString stringWithFormat:#"31/12/%#",[dateFormatterYYYY stringFromDate:startDate]];
NSDateFormatter *dateFormatddMMyyyy=[NSDateFormatter new];
[dateFormatddMMyyyy setDateFormat:#"dd'/'MM'/'yyyy"];
NSDate *lastDateOfStartYear=[dateFormatddMMyyyy dateFromString:lastDateOfStartYearString];
//no. of days
NSInteger year=[[dateFormatterYYYY stringFromDate:startDate]integerValue];
NSInteger days=[self daysBetweenTwoDates:startDate andDate:lastDateOfStartYear];
//add in dictionary
NSMutableDictionary *daysForYearDictionary=[NSMutableDictionary new];
[daysForYearDictionary setValue:#(days) forKey:[NSString stringWithFormat:#"%ld",year]];
/* step 2*/
NSInteger nextYearAfterStart=[[dateFormatterYYYY stringFromDate:startDate]integerValue]+1;
NSInteger previousYearBeforeEnd=[[dateFormatterYYYY stringFromDate:endDate]integerValue]-1;
for (NSInteger yearCounter=nextYearAfterStart; yearCounter<=previousYearBeforeEnd; yearCounter++) {
NSString *firstDateString=[NSString stringWithFormat:#"1/1/%ld",yearCounter];
NSDate *firstDate=[dateFormatddMMyyyy dateFromString:firstDateString];
NSString *lastDateString=[NSString stringWithFormat:#"31/12/%ld",yearCounter];
NSDate *lastDate=[dateFormatddMMyyyy dateFromString:lastDateString];
//no. of days
days=[self daysBetweenTwoDates:firstDate andDate:lastDate];
//add in dictionary
[daysForYearDictionary setValue:#(days) forKey:[NSString stringWithFormat:#"%ld",yearCounter]];
}
/* step 3 */
//find 1/1/EndDateYear
NSString *firstDateOfStartYearString=[NSString stringWithFormat:#"1/1/%#",[dateFormatterYYYY stringFromDate:endDate]];
NSDate *firstDateOfEndYear=[dateFormatddMMyyyy dateFromString:firstDateOfStartYearString];
//no. of days
year=[[dateFormatterYYYY stringFromDate:endDate]integerValue];
days=[self daysBetweenTwoDates:firstDateOfEndYear andDate:endDate];
//add in dictionary
[daysForYearDictionary setValue:#(days) forKey:[NSString stringWithFormat:#"%ld",year]];
//printing
for (NSString *yearStr in daysForYearDictionary) {
NSLog(#"Year : %#, Days Worked : %#",yearStr,[daysForYearDictionary valueForKey:yearStr]);
}
}

NSDate hours are not correct after constructing date from components

I'm trying to construct a date from two different dates. When I break down both dates into their respective components and re-assemble them into the new date.. everything seems to be correct except the hours. Im sure its something simple that has to do with the timezone or the NSGregorianCalendar, but I am new to iOS, and programming NSCalendar. Im hoping someone will catch the simple mistake Im making.
//grab today's date so we can brek it down into components
NSDate *todayDate = [NSDate date];
NSLog(#"Todays Date: %#", todayDate);
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
//break down the stored date into components
NSDateComponents *theTime = [gregorian components:(NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:storedIncorrectDate];
NSLog(#"Incorrect Calendar Components %#", theTime);
NSDateComponents *todayCalendarComponents = [gregorian components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:todayDate];
NSInteger currentYear = [todayCalendarComponents year];
NSLog(#"The Year: %i", currentYear);
NSInteger currentMonth = [todayCalendarComponents month];
NSLog(#"The Month: %i", currentMonth);
NSInteger currentDay = [todayCalendarComponents day];
NSLog(#"The Day: %i", currentDay);
NSLog(#"Today's Calendar Components %#", todayCalendarComponents);
NSInteger theHours = [theTime hour];
NSLog(#"Hours: %i", theHours);
NSInteger theMinutes = [theTime minute];
NSLog(#"Minutes: %i", theMinutes);
NSInteger theSeconds = [theTime second];
NSLog(#"Seconds: %i", theSeconds);
//build my new date and store it before we play the affirmation.
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setHour:theHours];
[components setMinute:theMinutes];
[components setSecond:theSeconds];
[components setYear:currentYear];
[components setMonth:currentMonth];
[components setDay:currentDay];
[components setTimeZone:[NSTimeZone localTimeZone]];
NSLog(#"The Components: %#", components);
NSCalendar *updatedCal = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *revisedCorrectedDate = [updatedCal dateFromComponents:components];
NSLog(#"The Hours: %i", theHours);
NSLog(#"The New and Corrected Date: %#", revisedCorrectedDate);
The result of the log printing the revisedCorrectedDate shows everything correct that I set except the hours. This has to be a simple fix.. I just don't see it. Thank you in advance!
Are you sure it's incorrect? When I run this code, I get:
2012-06-03 18:13:36.130 Untitled[39805:707] The New and Corrected
Date: 2012-06-04 01:13:36 +0000
It's currently 6/3/12 18:13:36 here, and the date displayed is 6/4/12 01:13:36, which is the correct time, in UTC (notice the +0000 at the end).

Interval between 2 NSDates

I am trying to calculate an interval between now and a user defined date in days so that the results appear in a label on tapping a button.
The difference is always -4080 I am not sure what is wrong with my equation.
Thank you for your help
- (void)LabelChange2:(id)sender{
NSDateFormatter *df3 = [[NSDateFormatter alloc] init];
df3.dateStyle = NSDateFormatterMediumStyle;
labelDOB.text = [NSString stringWithFormat:#"%#",
[df3 stringFromDate:datepick.date]];
}
NSDate * df3 = [datePick date];
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *comps = [gregorian components: NSDayCalendarUnit
fromDate: [NSDate date]
toDate: df3
options: 0];
int days = [comps day];
labelResult.text = [NSString stringWithFormat:#"%i", days];
Your code works fine. However if I run the code with the datePick pointer set to nil I will get an answer of -4080 from this code. You should check your connections to the UIDatePicker.

Is there a better way to find midnight tomorrow?

Is there a better way to do this?
-(NSDate *)getMidnightTommorow {
NSCalendarDate *now = [NSCalendarDate date];
NSCalendarDate *tomorrow = [now dateByAddingYears:0 months:0 days:1 hours:0 minutes:0 seconds:0];
return [NSCalendarDate dateWithYear:[tomorrow yearOfCommonEra]
month:[tomorrow monthOfYear]
day:[tomorrow dayOfMonth]
hour:0
minute:0
second:0
timeZone:[tomorrow timeZone]];
}
Note that I always want the next midnight, even if it happens to be midnight when I make that call, however if it happens to be 23:59:59, I of course want the midnight that is coming in one second.
The natural language functions seem flaky, and I'm not sure what Cocoa would do if I pass 32 in the "day" field. (If that'd work I could drop the [now dateByAddingYears:...] call)
From the documentation:
Use of NSCalendarDate strongly
discouraged. It is not deprecated yet,
however it may be in the next major OS
release after Mac OS X v10.5. For
calendrical calculations, you should
use suitable combinations of
NSCalendar, NSDate, and
NSDateComponents, as described in
Calendars in Dates and Times
Programming Topics for Cocoa.
Following that advice:
NSDate *today = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [[NSDateComponents alloc] init];
components.day = 1;
NSDate *tomorrow = [gregorian dateByAddingComponents:components toDate:today options:0];
[components release];
NSUInteger unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
components = [gregorian components:unitFlags fromDate:tomorrow];
components.hour = 0;
components.minute = 0;
NSDate *tomorrowMidnight = [gregorian dateFromComponents:components];
[gregorian release];
[components release];
(I'm not sure offhand if this is the most efficient implementation, but it should serve as a pointer in the right direction.)
Note: In theory you can reduce the amount of code here by allowing a date components object with values greater than the range of normal values for the component (e.g. simply adding 1 to the day component, which might result in its having a value of 32). However, although dateFromComponents: may tolerate out-of-bounds values, it's not guaranteed to. You're strongly encouraged not to rely on it.
Nope - it'll be the same way you use to find midnight today.
NSCalendar *gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
NSDate *tomorrow = [NSDate dateWithTimeIntervalSinceNow:(24 * 60 * 60)];
NSDateComponents *components = [gregorian components:(NSYearCalendarUnit |
NSMonthCalendarUnit |
NSDayCalendarUnit)
fromDate:tomorrow];
NSDate *midnight = [gregorian dateFromComponents:components];
[NSDate dateWithNaturalLanguageString:#"midnight tomorrow"];
Convert your current date and time to a Unix date (seconds since 1970) or DOS style (since 1980), then add 24 hours and convert it back. Then reset the hours, minutes and seconds to zero to get to midnight.
You could try this way:
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:1];
NSDate *tomorrow = [calendar dateByAddingComponents:comps toDate:[NSDate date] options:0]; //it gives us tomorrow with current time
NSDate *midnight = [calendar startOfDayForDate:tomorrow]; //here we get next midnight
It is also easy to retrieve the seconds interval if needed to set up an NSTimer:
double intervalToMidnight = midnight.timeIntervalSinceNow;

Resources