I have to prompt users for choosing a date from a CoCoa UIDatePicker but avoiding him to select sundays ans saturdays, since my goal is to make them select a date for an appointment
The best way should be disabling that dates, in the same way of minimumDate property, but I was not able to find how to do that
You could do something like this:
UIDatePicker *datePicker = [[UIDatePicker alloc] init];
[datePicker addTarget:self action:#selector(dateChanged:) forControlEvent:UIControlEventValueChanged];
Implementation for dateChanged:
- (void)dateChanged:(id)sender {
UIDatePicker *datePicker = (UIDatePicker *)sender;
NSDate *pickedDate = datePicker.date;
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *weekdayComponents = [gregorian components:NSWeekdayCalendarUnit fromDate:pickedDate];
NSInteger weekday = [weekdayComponents weekday];
[gregorian release];
if (weekday == 1 || weekday == 7) { // Sunday or Saturday
NSDate *nextMonday = nil;
if (weekday == 1)
nextMonday = [pickedDate dateByAddingTimeInterval:24 * 60 * 60]; // Add 24 hours
else
nextMonday = [pickedDate dateByAddingTimeInterval:2 * 24 * 60 * 60]; // Add two days
[datePicker setDate:nextMonday animated:YES];
return;
}
// Do something else if the picked date was NOT on Saturday or Sunday.
}
This way, when a date is picked that is either on a Saturday or Sunday, the date picker automatically selects the Monday after the weekend.
(Code untested!)
Related
I've done a lot of study on NSDate NSDateFormatter and NSCalendar but cannot figure out a way to find a particular day of a month.
For example,
I want to find the date of 2nd Monday of December (10/12/2012). I know how to find number of week or number of month but cannot figure out the way to do it.
Thanks.
// Set start date of the month you want
NSString *str = #"01 - 12 - 2012";
NSDateFormatter *formatter1 = [[[NSDateFormatter alloc] init] autorelease];
[formatter1 setDateFormat:#"dd - MM - yyyy"];
NSDate *date = [formatter1 dateFromString:str];
NSCalendar *gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
NSDateComponents *weekdayComponents = [gregorian components:(NSDayCalendarUnit | NSWeekdayCalendarUnit) fromDate:date];
// Get the weekday with sunday as one
NSInteger weekday = [weekdayComponents weekday];
int weekNumber = 2;
int dayOfweek = 2;
int x = (7 - weekday) * (weekNumber - 1) + dayOfweek;
// Add the no. of weeks - 1 or - 2 depending on the value of x.
// Also Add 1 as the start date is 1st Dec.
if(x < 7)
{
x += 7 * (weekNumber - 1) + 1;
}
else
{
x += 7 * (weekNumber - 2) + 1;
}
Try to find the particular day of the week from these codes then apply it for the month as well :)
Please refer to the following links :-
How do I get the day of the week with Cocoa Touch?
Number of days in the current month using iPhone SDK?
Hope They Help :)
Robin's and Gill's answers helped me get a solution to my problem. With some more editing I was able to get a solution to my problem.
Here is the code that I used to get the solution
-(void)findWeekDay:(NSInteger)weekDay forWeek:(NSInteger)week OfMonth:(NSInteger)month OfYear:(NSInteger)year
{
NSDateComponents *dateComp = [[NSDateComponents alloc]init];
[dateComp setYear:year];
[dateComp setMonth:month];
[dateComp setDay:1];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *firstDate=[gregorian dateFromComponents:dateComp]; //Sets first date of month.
firstDate=[self dateToGMT:firstDate];
NSLog(#"First date: %#",firstDate);
NSDateComponents *dateComp1 = [gregorian components:NSDayCalendarUnit|NSWeekdayCalendarUnit fromDate:firstDate];
NSInteger firstWeekDay=[dateComp1 weekday]; //Gets firstday of a week. 1-Sunday, 2-Monday and so on.
NSLog(#"First Week Day: %d",firstWeekDay);
NSRange daysInMonth = [gregorian rangeOfUnit:NSDayCalendarUnit inUnit:NSMonthCalendarUnit forDate:firstDate]; //To get number of days in that month
NSInteger x; //days to be added to first date
if (firstWeekDay < weekDay) {
x = (weekDay - firstWeekDay) + (7 * (week-1));
}
if (firstWeekDay > weekDay) {
x = (7 - firstWeekDay + weekDay) + (7 * (week-1));
}
if (firstWeekDay == weekDay) {
x = (7 * (week-1));
}
if (x > daysInMonth.length) {
NSLog(#"Invalid Date: %d",x);
}
else {
NSLog(#"Days to be added: %d",x);
NSDateComponents *dateComp2 = [[NSDateComponents alloc]init];
[dateComp2 setYear:0];
[dateComp2 setMonth:0];
[dateComp2 setDay:x];
NSDate *desiredDate = [gregorian dateByAddingComponents:dateComp2 toDate:firstDate options:0];
NSLog(#"Your desired date is: %#",desiredDate);
}
}
- (NSDate *)dateToGMT:(NSDate *)sourceDate {
NSTimeZone* destinationTimeZone = [NSTimeZone systemTimeZone];
NSInteger destinationGMTOffset = [destinationTimeZone secondsFromGMTForDate:sourceDate];
NSDate* destinationDate = [[NSDate alloc] initWithTimeInterval:destinationGMTOffset sinceDate:sourceDate];
return destinationDate;
}
Now to find 3rd Monday of December 2012 call the method as
[self findWeekDay:2 forWeek:3 OfMonth:12 OfYear:2012];
In my project I need to show the date 18 back and lock the 100 years I tried like this I got it but here am locking days and months for that year(1912) also I need to show all the days and months for that year(1912) and one more thing when I select date it is showing along with time i Don't wanna show the time can any one solve this issue
-(IBAction)donePickerView:(id)sender
{
NSDate *minDate1 =[datePickerView date];
NSString *theDate = [NSString stringWithFormat:#"%#",minDate1];
self.dob.text = theDate;
DatePicView.hidden = TRUE;
datePickerView.hidden =TRUE;
}
-(void)textFieldDidBeginEditing:(UITextField *)textField {
[self scrollViewToCenterOfScreen:textField];
scrlView.scrollEnabled = FALSE;
if (textField == dob)
{
DatePicView.hidden = FALSE;
datePickerView.hidden =FALSE;
NSCalendar * gregorian = [[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar];
NSDate * currentDate = [NSDate date];
NSDateComponents * comps = [[NSDateComponents alloc] init];
[comps setYear: -18];
NSDate * maxDate = [gregorian dateByAddingComponents: comps toDate: currentDate options: 0];
[comps setYear: -100];
NSDate * minDate = [gregorian dateByAddingComponents: comps toDate: currentDate options: 0];
[datePickerView setMinimumDate:minDate];
[datePickerView setMaximumDate:maxDate];
[datePickerView setDate:minDate];
[dob resignFirstResponder];
}
}
You set the maxDate to a -100 years.
So the maxDate is lower then the minDate, should these be the other way arround?
NSLog(#"Now: %#", currentDate);
NSLog(#"Max: %#", maxDate);
NSLog(#"Min: %#", minDate);
Now: 2012-10-18 10:04:43 +0000
Max: 1994-10-18 11:04:43 +0000
Min: 1912-10-18 11:45:11 +0000
This if you select 1980-12-12 this is lower then the max date and higher then the minimal date.
UIDatePicker *pickerView = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 0, 320, 300)];
// add this to display date only.
[pickerView setDatePickerMode:UIDatePickerModeDate];
[pickerView setMinimumDate:minDate];
[pickerView setMaximumDate:maxDate];
[pickerView setDate:minDate];
[[self view] addSubview:pickerView];
[pickerView setDatePickerMode:UIDatePickerModeDate];
I have one query regarding NSDate. I have a date i.e. "2011-10-04 07:36:38 +0000", and I want to check if this date is yesterday, or today or a future date.
How would I go about this?
Try this:
Note: Change the date format as per your need.
NSDateFormatter* df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"MM/dd/yyyy"];
NSDate* enteredDate = [df dateFromString:#"10/04/2011"];
NSDate * today = [NSDate date];
NSComparisonResult result = [today compare:enteredDate];
switch (result)
{
case NSOrderedAscending:
NSLog(#"Future Date");
break;
case NSOrderedDescending:
NSLog(#"Earlier Date");
break;
case NSOrderedSame:
NSLog(#"Today/Null Date Passed"); //Not sure why This is case when null/wrong date is passed
break;
}
See Apple's documentation on date calculations:
NSDate *startDate = ...;
NSDate *endDate = ...;
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSUInteger unitFlags = NSMonthCalendarUnit | NSDayCalendarUnit;
NSDateComponents *components = [gregorian components:unitFlags
fromDate:startDate
toDate:endDate options:0];
NSInteger months = [components month];
NSInteger days = [components day];
If days is between +1 and -1 then your date is a candidate for being "today". Obviously you'll need to think about how you handle hours. Presumably the easiest thing would be to set all dates to be 00:00.00 hours on the day in question (truncate the date using an approach like this), and then use those values for the calculation. That way you'd get 0 for today, -1 for yesterday, +1 for tomorrow, and any other value would likewise tell you how far things were in the future or the past.
Use any of the folowing according to ur need,
– earlierDate:
– laterDate:
– compare:
Refer this http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSDate_Class/Reference/Reference.html
-(NSString*)timeAgoFor:(NSString*)tipping_date
{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd"];
NSDate *date = [dateFormatter dateFromString:tipping_date];
NSString *key = #"";
NSTimeInterval ti = [date timeIntervalSinceDate:[NSDate date]];
key = (ti > 0) ? #"Left" : #"Ago";
ti = ABS(ti);
NSDate * today = [NSDate date];
NSComparisonResult result = [today compare:date];
if (result == NSOrderedSame) {
return[NSString stringWithFormat:#"Today"];
}
else if (ti < 86400 * 2) {
return[NSString stringWithFormat:#"1 Day %#",key];
}else if (ti < 86400 * 7) {
int diff = round(ti / 60 / 60 / 24);
return[NSString stringWithFormat:#"%d Days %#", diff,key];
}else {
int diff = round(ti / (86400 * 7));
return[NSString stringWithFormat:#"%d Wks %#", diff,key];
}
}
I have the hour and the minute as NSIntegers (I don't care about the seconds... it may be 00) and I have a UIDatePicker adjusted to display just time (UIDatePickerModeTime).
Simple question: how do I set an hour on the UIDatePicker? Hours are in the 24h format (as it comes from the picker naturally).
Suppose this:
NSInteger hour = 17;
NSInteger minute = 12;
[myTimePicker setDate: ????];
I know I have to convert that hour and minute to NSDate, but how do I do that without including a day? I just need time.
I have read this example, but it also considers the day.
How do I construct a NSDate of just time, so I can adjust my UIDatePicker?
thanks
You should be able to do this,
NSCalendar * gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
NSDateComponents * dateComponents = [[[NSDateComponents alloc] init] autorelease];
[dateComponents setHour:17];
[dateComponents setMinute:12];
myTimePicker.date = [gregorian dateFromComponents:dateComponents];
You can later get the hour and minute like this,
NSCalendar * gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
NSDateComponents * dateComponents = [gregorian components:(NSHourCalendarUnit|NSMinuteCalendarUnit) fromDate:myTimePicker.date];
int hour = [dateComponents hour];
int minute = [dateComponents minute];
I have a class that holds an start date and an end date, normally initialised to the firt and last second of the month.
The following function works correctly going from Nov 2010 forwards into December and back again however going backwards from November ends up with startDate set to
2010-09-30 23:00:00 GMT
Ie. a month and an hour ago.
Strangely the endDate is still correctly set to
2010-11-01 00:00:00 GMT
And going forward a month from this incorrect date also results in the correct time and date.
Is this a bug or am I doing something I shouldn't be ?
-(void) moveMonth:(NSInteger)byAmount { // Positive or negative number of months
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *components = [[[NSDateComponents alloc] init] autorelease];
// Update the start date
[components setMonth:byAmount];
NSDate *newStartDate = [cal dateByAddingComponents:components toDate:[self startDate] options:0];
[self setStartDate:newStartDate];
// And the end date
[components setMonth:1];
NSDate *newEndDate = [cal dateByAddingComponents:components toDate:[self startDate] options:0 ];
[self setEndDate:newEndDate];
}
SOLUTION: Answer correctly pointed out this is a DST issue
If you want to deal in absolute times and date then using the following avoids any DST being involved.
NSCalendar *cal = [[NSCalendar alloc ] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
NSTimeZone *zone = [NSTimeZone timeZoneWithName:#"GMT"];
[cal setTimeZone:zone];
It is probably not a bug but something related to DST changes in October-November period.
It would be easier to just grab the month and year of the current date, add/subtract the number of months difference, then generate a date from those new values. No need to worry about Daylight Saving changes, leap years, etc. Something like this ought to work:
-(void) moveMonth:(NSInteger)byAmount {
NSDate *now = [NSDate date];
NSCalendar *cal = [NSCalendar currentCalendar];
// we're just interested in the month and year components
NSDateComponents *nowComps = [cal components:(NSYearCalendarUnit|NSMonthCalendarUnit)
fromDate:now];
NSInteger month = [nowComps month];
NSInteger year = [nowComps year];
// now calculate the new month and year values
NSInteger newMonth = month + byAmount;
// deal with overflow/underflow
NSInteger newYear = year + newMonth / 12;
newMonth = newMonth % 12;
// month is 1-based, so if we've ended up with the 0th month,
// make it the 12th month of the previous year
if (newMonth == 0) {
newMonth = 12;
newYear = newYear - 1;
}
NSDateComponents *newStartDateComps = [[NSDateComponents alloc] init];
[newStartDateComps setYear: year];
[newStartDateComps setMonth: month];
[self setStartDate:[cal dateFromComponents:newDateComps]];
[newDateComps release];
// Calculate newEndDate in a similar fashion, calling setMinutes:59,
// setHour:23, setSeconds:59 on the NSDateComponents object if you
// want the last second of the day
}
Here is a way to do it properly. This method returns a new NSDate after adding/subtracting month "byAmount".
-(NSDate*) moveMonth:(NSInteger)byAmount {
NSDate *now = [NSDate date];
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setMonth:byAmount];
NSDate *newDate = [[NSCalendar currentCalendar] dateByAddingComponents:components toDate:now options:0];
return newDate;
}