Comparing uipickerdate to current date - ios

Here is the code that I have for my two datepickers which I need to compare them to the current date with an if condition or a switch.
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
dateFormatter.timeZone=[NSTimeZone defaultTimeZone];
dateFormatter.timeStyle=NSDateFormatterShortStyle;
dateFormatter.dateStyle=NSDateFormatterShortStyle;
NSString *dateTimeString=[dateFormatter stringFromDate:startTime.date];
NSLog(#"Start time is %#",dateTimeString);
NSDateFormatter *dateFormatter2 = [[NSDateFormatter alloc]init];
dateFormatter2.timeZone=[NSTimeZone defaultTimeZone];
dateFormatter2.timeStyle=NSDateFormatterShortStyle;
dateFormatter2.dateStyle=NSDateFormatterShortStyle;
NSString *dateTimeString2=[dateFormatter2 stringFromDate:endTime.date];
NSLog(#"End time is %#",dateTimeString2);
in my .h
#property (weak, nonatomic) IBOutlet UIDatePicker *startTime;
#property (weak, nonatomic) IBOutlet UIDatePicker *endTime;
How do I do that? Do I need to store them to an NSDate or NSTime since I only really need the time?
Also, is there an If range in Objective C?
Thanks,

Just add this:
if ([[NSDate date] isEqualToDate:startTime.date]) {
NSLog(#"currentDate is equal to startTime");
}
if ([[NSDate date] isEqualToDate:endTime.date]) {
NSLog(#"currentDate is equal to endTime");
}
If you want to calculate interval between two dates use this method
- (NSTimeInterval)timeIntervalSinceDate:(NSDate *)anotherDate
if([startTime.date timeIntervalSinceDate:[NSDate date]] > 0)
{
//start time greater than today
}
else if([startTime.date timeIntervalSinceDate:[NSDate date]] < 0)
{
//start time less than today
}
else
{
//both dates are equal
}
For knowing when the application has entered background use notifications add this statement in your viewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(applicationEnteredBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];
Add function to cater the notification when it is posted
-(void)applicationEnteredBackground
{
//do all the above steps here when you want.
}
And in dealloc function of the class remove observer for notification
-(void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

The only dates I see in your code are startTime.date and endTime.date. I don't know where you are getting those, but they are presumably NSDates. The current date, on the other hand, is [NSDate date]. Hence you can compare using NSDate's compare: method or any of several other comparison methods (see the NSDate documentation).

NSDate implements isEqualToDate: which tests if two dates are the same down to the microsecond. It also implements earlierDate: and laterDate: which you can use to build a range check.
You could also build some helpers that let you control the sensitivity of equality check using timeIntervalSinceDate:. There's no date range object, but you could add a between check to your helpers, too...
#interfce NSDate (Comparison)
- (BOOL)isEqualToDate:(NSDate *)aDate within:(NSTimeInterval)tolerance;
- (BOOL)isBetween:(NSDate *)start and:(NSDate *)end within:(NSTimeInterval)tolerance;
#end
#implementation NSDate (Comparison)
- (BOOL)isEqualToDate:(NSDate *)aDate within:(NSTimeInterval)tolerance {
NSTimeInterval difference = [self timeIntervalSinceDate:aDate];
return fabs(difference) < tolerance;
}
- (BOOL)isBetween:(NSDate *)start and:(NSDate *)end within:(NSTimeInterval)tolerance {
NSTimeInterval startDifference = [self timeIntervalSinceDate:start];
if (startDifference < tolerance) return NO;
NSTimeInterval endDifference = [end timeIntervalSinceDate:self];
if (endDifference < tolerance) return NO;
return YES;
}
#end
I haven't tested these.

you can also do like below by using NSDate's compare: method,
NSDateFormatter* df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"MM-dd-yyyy"];
NSDate* date1 = [df dateFromString:#"12-23-2046"];
NSDate *date2 = [NSDate date];
if ([date1 compare:date2] == NSOrderedSame){
NSLog(#"Same");
}
if ([date2 compare:date1]==NSOrderedAscending ) {
NSLog(#"AScending");
}
if ([date2 compare:date1]== NSOrderedDescending) {
NSLog(#"Descending");
}
take your startTime,endTime instead of date1,hope it will helps you.

Related

Find nearest date in string array

So, I've got an sorted NSArray that contains NSString object (downloaded from a server), with the format: yyyy-MM-dd.
It's pretty much like this:
NSArray <NSString *> *dates = #[#"2017-06-25",
#"2017-06-26",
#"2017-06-27",
#"2017-06-28",
#"2017-06-30",
#"2017-07-01",
#"2017-07-02",
#"2017-07-03"];
So, today is 2017-06-29, and it's not in the array. How do I get the next nearest one? In this sample is 06-30, but it might be 07-01 if 06-30 doesn't exist...
Update
So people are asking me about what I've attempted to do. So it's like this (not very effective, but work)
Find if today is in the array (if yes, return)
Loop dates:
2.1 Convert dateString to date
2.2 Compare if date is greater than today => return if YES
If not found in step#2, return last object in dates array.
Actual code:
NSDateFormatter *formatter = [NSDateFormatter new];
formatter.dateFormat = #"yyyy-MM-dd";
NSDate *today = [NSDate date];
NSUInteger index = [dates indexOfObject:[formatter stringFromDate:today]];
// Step 1
if (index == NSNotFound) {
// Step 2: Loop converted
NSInteger i = 0;
for (NSString *date in dates) {
// Step2.1: find the next nearest date's index
NSDate *convertedDate = [formmater dateFromString:date];
// Step2.2: Compare
if ([convertedDate intervalSinceDate:today] > 0) {
index = i;
break;
}
i++;
}
// Step 3: Still not found, index = last index
if (index == NSNotFound) index = i-1;
}
return dates[index];
This doesn't look so good because I might reload the dates array pretty much. Can I have a better solution?
Your algorithm is not bad, though your code doesn't appear to implement it (no sort?). If you'd like to improve it consider this:
First there is probably little point in doing a first scan to check for an exact match - that is potentially a linear search (implemented by indexOfObject:) through an unordered array, and if it fails you have to scan again for a close match, just do them at the same time.
Second there is no advantage in sorting, which is at best O(NlogN), as a linear search, O(N), will find you the answer you need.
Here is a sketch:
Convert the date you are searching for from NSString to NSDate, call it, say, target
Set bestMatch, an NSString to nil. Set bestDelta, an NSTimeInterval, to the maximum possible value DBL_MAX.
Iterate over your dates array:
3.1. Convert the string date to an NSDate, say date
3.2. Set delta to the difference between date and target
3.3. If delta is zero you have an exact match, return it
3.4. If delta is better than bestDelta, update bestDelta and bestMatch
After iteration bestMatch is the best match or nil if there wasn't one.
That is a single iteration, O(N), early return on exact match.
HTH
Please find the simplest solution for your problem. Updated solution based on sorting order!
We can use NSPredicate Block to solve.
static NSDateFormatter* formatter = nil;
static NSDate* today = nil;
// return an NSDate for a string given in yyyy-MM-dd
- (NSDate *)dateFromString:(NSString *)string {
if (formatter == nil) {
formatter = [NSDateFormatter new];
formatter.dateFormat = #"yyyy-MM-dd";
}
return [formatter dateFromString:string];
}
// Helps to return today date.
-(NSDate*) getTodayDate {
if (today == nil) {
today = [NSDate date];
}
return today;
}
// Helps to find nearest date from Array using Predicate
-(NSString*)findNearestDate:(NSArray*)dateArray {
today = nil;
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(NSString *dateString, NSDictionary *bind){
// this is the important part, lets get things in NSDate form so we can use them.
NSDate *dob = [self dateFromString:dateString];
NSComparisonResult result = [[self getTodayDate] compare:dob];
if (result == NSOrderedSame || result == NSOrderedAscending) {
return true;
}
return false;
}];
// Apply the predicate block.
NSArray *futureDates = [dateArray filteredArrayUsingPredicate:predicate];
if ([futureDates count] > 0) {
// Sort the Array.
futureDates = [futureDates sortedArrayUsingSelector: #selector(compare:)];
return [futureDates objectAtIndex:0];
}
return nil;
}
NSArray <NSString *> *dates = #[#"2017-06-25",
#"2017-06-26",
#"2017-06-27",
#"2017-06-28",
#"2017-06-30",
#"2017-07-01",
#"2017-07-02",
#"2017-07-03"];
NSLog(#"Nearest Date: %#", [self findNearestDate:dates]);
Answer: Nearest Date: 2017-06-30
1. Input
So you have an array of NSString like this
// input
NSArray<NSString *> * words = #[#"2017-06-25",
#"2017-06-26",
#"2017-06-27",
#"2017-06-28",
#"2017-06-30",
#"2017-07-01",
#"2017-07-02",
#"2017-07-03"];
2. Converting the array of NSString into an array of NSDate
First of all you need to convert the each input string into an NSDate
NSMutableArray<NSDate *> * dates = [NSMutableArray new];
NSDateFormatter * dateFormatter = [NSDateFormatter new];
dateFormatter.dateFormat = #"yyyy-MM-dd";
for (NSString * word in words) {
[dates addObject:[dateFormatter dateFromString:word]];
}
3. Finding the nearestDate
Now you can find the nearest date
NSDate * nearestDate = nil;
NSTimeInterval deltaForNearesttDate = 0;
NSDate * now = [NSDate new];
for (NSDate * date in dates) {
NSTimeInterval delta = fabs([date timeIntervalSinceDate:now]);
if (nearestDate == nil || (delta < deltaForNearesttDate)) {
deltaForNearesttDate = delta;
nearestDate = date;
}
}
4. Conclusion
The result is into the nearestDate variable so
NSLog(#"%#", nearestDate);
Wed Jun 28 00:00:00 2017

How to set the maximum date in MDDatePicker in objective c

I am Setting Maximum date but not able to disable Remaining date
Example like - Date of Birth Selection.
Any one has idea about that.
thanks in Advance.
-(void) dateTextField:(id)sender
{
UIDatePicker *picker = (UIDatePicker*) dateOfBirthField.inputView;
// [picker setMaximumDate:[NSDate date]];
[picker setMinimumDate:[NSDate date]];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
NSDate *eventDate = picker.date;
[dateFormat setDateFormat:#"yyyy/MM/dd"];
NSString *dateString = [dateFormat stringFromDate:eventDate];
dateOfBirthField.text = [NSString stringWithFormat:#"%#",dateString];
}
MDDatePickerDialog class uses MDCalendar to manage its minimum date. If you will look at the implementation of MDCalendar you will find following implementation in initialize method:
_maximumDate = [NSDateHelper mdDateWithYear:2037 month:12 day:31];
First try setting this date to a static value of your choice to see this is the required variable, then you can move this property declaration to header file of MDCalendar to make this maximumDate variable accessible outside the class. As a next step you can make a property in MDDatePickerDialog to set maximum date in the same way it sets minimum date.
A part from MDDatePicker.m file
- (void)setMinimumDate:(NSDate *)minimumDate {
self.calendar.minimumDate = minimumDate;
}
P.S. Remember to handle the date validations like date should be valid and maximum date should not be earlier than minimum date etc.
Hope that helps!
You just have to add date whatever you want to make maximum, here I have to make only a week date should be selected from the current date, So here is the code which I've written, where you show the date picker just add one line:
- _datePicker.maximumDate = [[NSDate date] dateByAddingTimeInterval:60*60*24*7]; ;
After that search this method into MDCalender.m file and replace with this code.
- (BOOL)shouldSelectDate:(NSDate *)date {
BOOL result;
if ([self.maximumDate timeIntervalSince1970] >= date.timeIntervalSince1970 ) {
result =
(date.timeIntervalSince1970 >= self.minimumDate.timeIntervalSince1970);
return result;
}
return result;
}
It worked for me. Thanks

How to make register notification in Objective C?

I have an online radio. The radio has programs at different times, programs are displayed in a list.
My need is that when one tap and hold on the list of program he schedule a notification to the User.
examplo program in list:
Tap and hold is already running (code below):
-(void)registerHour:(UILongPressGestureRecognizer *)gestureRecognizer
{
CGPoint ponto = [gestureRecognizer locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:ponto];
if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
cell = [self.tableView cellForRowAtIndexPath:indexPath];
cell.imageAgendamento.hidden = false;
NSString *test = [ NSString stringWithFormat:#"%#",[[results objectAtIndex:indexPath.row] objectForKey:#"hour" ]];
NSLog(#"hour -> %#", test);
}
}
The test is where has the time of notification "09:00" (in direct
format JSON)
appDelegate.m i add:
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
}
Looked at several tutorials and researched in various places, I could not solve my problem any way. What I need to do to get this notification schedule?
You can send a 5 min delayed local notification using the code below:
NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
NSDate *currentDate = [NSDate date];
[dateComponents setMinute:5];
NSDate *fireDate = [gregorian dateByAddingComponents:dateComponents toDate:currentDate options:0];
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
// Configure the notification
// ....
//
localNotification.fireDate = fireDate;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
But I think what you need to do is using an NSTimer or simply the performSelector:withObject:afterDelay: method of NSObject.

error in using date picker

the application crashed when calling this function, how ever in iPhone it works fine , but in iPad the application crashes and say
note: i'm using ActionSheetDatePicker library
Thread 1: EXC_BAD_ACCESS (cod = 1 , address = 0x9e...)
when i debug i found selectedDate is nil in iPad , but works fine in iPhone
#pragma mark - Implementation
- (void)dateWasSelected:(NSDate *)selectedDate element:(id)element {
// self.selectedDate = selectedDate;
//may have originated from textField or barButtonItem, use an IBOutlet instead of element
//DATE TEXT FIELD HERE
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"YYYY-MM-dd"];
//Optionally for time zone converstions
[formatter setTimeZone:[NSTimeZone timeZoneWithName:#"..."]];
NSString *stringFromDate = [formatter stringFromDate:selectedDate];
self.textFieldBirthDate.text = stringFromDate ;
birthDate = stringFromDate ;
//"YYYY-MM-DD" the birthdate format
}
The git hub code which you provided is working fine for me and I did debug the code.
When user Taps on done button (After selecting the date) below code will be executed.
- (void)notifyTarget:(id)target didSucceedWithAction:(SEL)action origin:(id)origin {
if ([target respondsToSelector:action])
objc_msgSend(target, action, self.selectedDate, origin);
else
NSAssert(NO, #"Invalid target/action ( %s / %s ) combination used for ActionSheetPicker", object_getClassName(target), (char *)action);
}
Now here make sure you are getting value for self.selectedDate , if you are not getting then please do check that you are getting a breakpoint to below code when you just select a date by scrolling.
- (void)eventForDatePicker:(id)sender {
if (!sender || ![sender isKindOfClass:[UIDatePicker class]])
return;
UIDatePicker *datePicker = (UIDatePicker *)sender;
self.selectedDate = datePicker.date;
}
These codes are present in file
ActionSheetDatePicker.m
If you are getting the breakpoint here then make sure you are saving the date .Once you do check this the problem will be resolved.
Regards,
Anil

iOS: Tapku calendar library - allow selecting multiple dates for current month

I am using Tapku library for calendar implementation. I could see that there is a way to add Markers for predefined start and end date but I want to allow users to select/unselect any number of dates from current month only, and want to generate event for each action.
Moreover, I have switched off the month navigation functionality by returning nil for Left and Right arrow to display only current month but not able to remove events for few previous and next months Date tiles that gets displayed on current month. I can still select previous month's day 31st to navigate to previous month or select 1st on next month to navigate to next month. Can I restrict the date selection to only current month please?
Thanks.
The touches are handled in TKCalendarMonthView.m in the following method:
- (void) reactToTouch:(UITouch*)touch down:(BOOL)down
look at the block at row 563:
if(portion == 1)
{
selectedDay = day;
selectedPortion = portion;
[target performSelector:action withObject:[NSArray arrayWithObject:[NSNumber numberWithInt:day]]];
}
else if(down)
{
// this is the important part for you.
// ignore it by adding a return here (or remove the following three lines)
return;
[target performSelector:action withObject:[NSArray arrayWithObjects:[NSNumber numberWithInt:day],[NSNumber numberWithInt:portion],nil]];
selectedDay = day;
selectedPortion = portion;
}
The selecting/deselecting perhaps doesn't work as you expect. It's not like setDateSelected and setDateDeselected.. instead there is a single UIImageView*, which represents the selected state. And that view is moved around to the current position. You can search for self.selectedImageView in the code to see, what is happening.
So its not that easy to introduce multiple-date-selection. The architecture isn't built for that.
In TKCalendarMonthView there is a method name
-(void) reactToTouch:(UITouch*)touch down:(BOOL)down
in that method comment this line
[target performSelector:action withObject:[NSArray arrayWithObjects:[NSNumber numberWithInt:day],[NSNumber numberWithInt:portion],nil]];
this wont allow you to change month.
You can store all selected date in an array and pass all the values in
- (NSArray*)calendarMonthView:(TKCalendarMonthView *)monthView marksFromDate:(NSDate *)startDate toDate:(NSDate *)lastDate
The above method is used to put tiles but if u want selection image then u can replace it with tile image
You can also try this code:
You can do this by first entering the dates in to an array. code for this is.
- (void)calendarMonthView:(TKCalendarMonthView *)monthView didSelectDate:(NSDate *)d {
NSLog(#"selected Date IS - %#",inDate);
[myArray addObject:d];
for (id entry in myArray)
{
if (inDate == nil && outDate == nil)
{
inDate = d;
outDate = d;
}
if ([d compare:inDate] == NSOrderedAscending)
{
inDate = d;
}
if ([d compare:outDate] == NSOrderedDescending)
{
outDate = d;
}
d = nil;
}
}
After this you have to use a button click action by which you can make the dates selected between these two dates. Code for it is:
- (IBAction)goBtn:(id)sender
{
NSLog(#"startDate is: %#",inDate);
NSLog(#"endDate is: %#",outDate);
[calendar reload];
inDate = nil;
outDate = nil;
}
}
Then in one delegate method you just have to make an array containing all the dates between these two dates. It will be called just after the button click. Code for it is:
- (NSArray*)calendarMonthView:(TKCalendarMonthView *)monthView marksFromDate:(NSDate *)startDate toDate:(NSDate *)lastDate {
//***********
NSMutableArray *tempData = [[NSMutableArray alloc] init];
NSDate *nextDate;
for ( nextDate = inDate ; [nextDate compare:outDate] < 0 ; nextDate = [nextDate addTimeInterval:24*60*60] ) {
// use date
NSLog(#"%#",nextDate);
[tempData addObject:[NSString stringWithFormat:#"%#",nextDate]];
}
[tempData addObject:[NSString stringWithFormat:#"%#",outDate]];
//***********
NSMutableArray *marks = [NSMutableArray array];
NSCalendar *cal = [NSCalendar currentCalendar];
[cal setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSDateComponents *comp = [cal components:(NSMonthCalendarUnit | NSMinuteCalendarUnit | NSYearCalendarUnit |
NSDayCalendarUnit | NSWeekdayCalendarUnit | NSHourCalendarUnit | NSSecondCalendarUnit)
fromDate:startDate];
NSDate *d = [cal dateFromComponents:comp];
NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
[offsetComponents setDay:1];
while (YES) {
if ([d compare:lastDate] == NSOrderedDescending) {
break;
}
if ([tempData containsObject:[d description]]) {
[marks addObject:[NSNumber numberWithBool:YES]];
} else {
[marks addObject:[NSNumber numberWithBool:NO]];
}
d = [cal dateByAddingComponents:offsetComponents toDate:d options:0];
}
return [NSArray arrayWithArray:marks];
}
I hope, this helped you. Please let me know if you face any problem.

Resources