In my app i am showing, the list of months in table view. For each month there are few events in it for some dates. So my question is how to compare the dates in my array with the dates of month to show the events in their respective months only.
you can use NSDateComponents for that:
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDateComponents* components =
[calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:yourDate];
[components month];// gives you month
Compare this month with the Array index for example or another way you prefer.
In your case probably you only need to compare the year and month component of the date.
There's probably many ways for implementing this.
This is what i would have tried. Convert your date in tableview in yyyy-MM Format and also the event dates in the same format probably the way given below.
NSDateFormatter *dateFormatter1 = [[NSDateFormatter alloc] init];
[dateFormatter1 setDateFormat:#"yyyy-MM"];
dateFormatter1.timeZone = [NSTimeZone timeZoneWithAbbreviation:#"GMT"];
NSDate *monthDate=[NSDate date];
NSString *strMonthDate=[dateFormatter1 stringFromDate:monthDate];
NSLog(#"%#",strMonthDate);
Compare this monthDate string with your eventDate string using normal NSString comparison methods.
Related
This question already has answers here:
How do I add 1 day to an NSDate?
(30 answers)
Closed 10 years ago.
Here is the code from where I can get todays date as a string:
NSString *string;
NSDateFormatter *formatter;
string = [formatter stringFromDate: [NSDate date]];
formatter = [[[NSDateFormatter alloc] init] autorelease];
[formatter setDateFormat: #"yyyy-MM-dd "];
string = [formatter stringFromDate: [NSDate date]];
But now I want such that I will put this string as a parameter and a method will return the date of the day after 10 days of this date as a string. But I couldn't find any solution for it. Can anybody help me?
My answer will be a bit longer and probably slightly OT but I think it is better to provide you a knowledge of the concepts inside date management instead of a "copy and paste" answer.
Date management in fact even if intuitive is a quite complex task. In order to do this properly with Cocoa you must understand a few basic concepts.
The "date" concept itself is just a numerical representation of how many seconds elapsed from a reference date. This is an absolute measure and nothing can change it: if you say that now is time 0, in 10 seconds it will be time 10, and so on. It is represented by Cocoa with "NSDate".
Now to translate the "numerical date" to a "calendar date" you need to apply this numerical date to a "calendar" ("NSCalendar" Cocoa class). Clearly there are many types of calendars around so what you have to do is to pick the right calendar you want to use and then apply the numerical date to it: the effective result will be a "calendarized date". Note that the same "numerical date", which is common to all calendars as it is an absolute measure, will provide different results on different calendars. A calendar is all in all a complex algorithm or table that maps every single numerical date to a specific "calendar date".
The components that make a calendar date are called "date components" and are represented by the Cocoa class "NSDateComponents". As you may have understood, you cannot directly put in relation a "Date component" with a "Date" but you need to mediate them through the "Calendar". That's why all methods that put in relation the "Date" and "NSDateComponents" classes are defined in the "NSCalendar" class and this explains why a specific "NSDateComponents" instance is associated to a specific "NSCalendar" instance.
Finally your last step is to convert the "date component" to a "human readable format". To do this you use the "NSDateFormatter" object. While it would be more appropriate to link the date formatter to the date components, in order to facilitate the translation from a date to a string and vice versa NSDateFormatter methods play directly with NSDate objects instead of NSDateComponents. Obviously the NSDateFormatter class must be associated to a specific calendar (and be careful: it is initialized with a default calendar).
Now that you have this baggage of information you can easily understand how to proceed. Your task is to convert a date in "string format" to a date, in the same format, after 10 days.
So the tasks to be accomplished are (the code is below):
1. identify the Calendar you want to use
2. create a NSDateFormatter that accepts your input string and link the Calendar to it
3. use NSDateFormatter to import the string to a "NSDate"
4. use the NSCalendar to convert the date to a NSDateComponents object
5. add 10 days to the "day" component of NSDateComponents; don't take care of "end of month" or "end of year", because NSDateComponents + NSCalendar know how to do it!
6. use NSCalendar again to convert the new recalculated NSDateComponents instance to NSDate
7. use the NSDateFormatter you defined before to convert the new NSDate to a NSString.
You may ask: why I cannot just sum to my imported NSDate 10*24*60*60 seconds? while in most cases this solution will work, there are some cases where this operation will provide an incorrect result. E.g. in the daylight saving switch you revert the clock by 1 hour, that is 60*60 = 3600 seconds. This means that in your Calendar a 1 hr range of seconds will be mapped to two different date/times (1 hr before and 1 hr after the switch). This information is not known to NSDate but it is known by NSCalendar. You can visually see what's happening in this way: imagine an infinitely long line (the line of time) where every single "tick" in the line is 1 second. If you keep the "point in time" where you are now this tick will be associated to a specific date and time in your calendar and clock. Imagine now to identify the point in this timeline where you do the daylight saving switch and suppose you need at that time to revert your clock to 1 hour before. What you do is to cut the timeline in two pieces, then take the second half and overlap its first hour with the last hour of the first half. You will see then that the time is still going on but your calendar in this 1 hour overlap will be associated to two given range of times! this is an information known to your calendar + locale + time zone only, not to NSDate alone (by the way I intentionally skipped any discussion here about the "time zones" and "locale": they're relevant because time zone takes care of associating an absolute time to a effective time of day, while the locale can change some calendar rules, e.g. the daylight saving switch).
NSString *startDateStr = #"2013-02-25";
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.calendar=calendar;
[dateFormatter setDateFormat:#"yyyy-MM-dd"];
NSDate *startDate = [dateFormatter dateFromString:startDateStr];
NSDateComponents *startComponents = [calendar components:NSDayCalendarUnit|NSMonthCalendarUnit|NSYearCalendarUnit fromDate:startDate];
startComponents.day+=10;
NSDate *endDate = [calendar dateFromComponents:startComponents];
NSString *endDateStr = [dateFormatter stringFromDate:endDate];
NSLog(#"Date %# + 10 days gives %#",startDateStr,endDateStr);
Note that the above calculations could have been simplified using the NSCalendar's dateByAddingComponents:toDate:options: but I preferred the first method to give you a better picture of the interaction between the classes.
NSDate *now = [NSDate date];
NSDate *newDate1 = [now dateByAddingTimeInterval:60*60*24*10];
This will return date after 10 days.
Convert your fromDate string to a Date type and use the below function and pass the days parameter as 10:
NSString *fromDateString = #"Your_date_string";
// Convert string to date object
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"YOUR_DATE_FORMAT"];
NSDate *fromDate = [dateFormat dateFromString:dateStr];
[dateFormat release];
+ (NSDate *) getDate:(NSDate *)fromDate daysAhead:(NSUInteger)days
{
NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
dateComponents.day = days;
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *previousDate = [calendar dateByAddingComponents:dateComponents
toDate:fromDate
options:0];
[dateComponents release];
return previousDate;
}
Code for 10 days after date ::
NSDateFormatter *entryDateFormat;
entryDateFormat = [[NSDateFormatter alloc]init];
[entryDateFormat setDateFormat:#"dd-MM-yyyy HH:mm:ss"];
NSString *s = [NSString stringWithFormat:#"%#", [entryDateFormat stringFromDate:[[NSDate date] dateByAddingTimeInterval:60*60*24*10]]];
NSLog(#" --> %#", s);
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to compare two NSDate objects in objective C
1---> I'm new to Objective-C and stuck at a point. The concept is of type booking slots/reservation, which means cannot book a slot at previous time and previous date. I have to compare today's date with a particular date may be less than today's date or greater than today's date.
For getting current date I have done this :
NSDate *date = [NSDate date];
NSDateFormatter *formatter = nil;
formatter=[[NSDateFormatter alloc] init];
[formatter setDateFormat:#"yyyy-MM-dd"];
I have a date which is to be compared with todays date in UItextField which is also in yyyy-MM-dd format.
Now I have to compare today's date with the textField date.But I'm not getting it ..
if(textfielddate<currentdate)
{
NSLog(#"You cannot book a slot at past date);
}
but here it is not getting compared..
2---> I need to compare a time in 24hr format with currenttime which is also in 24hr format..
I have a particular time in a string variable 12:00,11:00,15:00 etc .Now I need to compare this with the current time in 24 hr format .
if([time <= currenttime] && [textFielddate==currentdate])
{
NSLog(#"You cannot book a slot at past time ");
}
How can I do it?
BEst way is to use NSCompariosnResult
[date1 compare:date2];
then check whether ascending or descending or equal.
Regards
Deepak
For Checking whether the date entered in the UITextField is previous or not.
You can create a new date using the values entered in the textfield. Suppose the value entered is 06-Nov-2012 then from that textfield you have to get the day, month and year components in integers programmatically.
Get the hours, minutes and seconds also in integers for the time for which you need to check that it is a previous time or not. Create a date with desired time using:
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:iDay];
[comps setMonth:iMonth];
[comps setYear:iYear];
[comps setHour:iHour];
[comps setMinute:iMinutes];
[comps setSecond:iSeconds];
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *dateToCheck = [gregorian dateFromComponents:comps];
[comps release];
Once date is created you can check whether the date is previous one or not using :
double timestamp = [dateToCheck timeIntervalSinceDate:[NSDate date]];
if(timestamp < 0)
{
// The date is previous one
}
How do I get date from the day of the year?
for e.g., if I give day as "1" then date should be "January 1"
How do I get that in iPhone? I have found answer in javascript but I want to know how to do the achieve same thing in Objective?
I guess this code will work for you:
I have created a sample function where a textfield gives input values for how many days to add. And a button to calculate final day. Here is the button event logic.
NSDateComponents *dateComponent = [[NSDateComponents alloc] init];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"yyyy-mm-dd"];
NSDate *newDate = [formatter dateFromString:#"2012-01-01"];
// add days to current date
dateComponent.day = [dayTextField.text intValue];
// get a new date by adding components
newDate = [[NSCalendar currentCalendar] dateByAddingComponents: dateComponent toDate:newDate options:0];
[finalDate setText:[NSString stringWithFormat:#"%#", newDate]];
Here dayTextField.text is the text which says how many number of days want to calculated. (For example 125 days) and finalDate is an label which displays final generated date (means date after 125 days since 1 Jan 2012).
Benefit of this code is, any time you can change the start day parameter. For example, for other requirement, i need to count my days from "31 May 1999" then i will change it easily in one line and the same code will work.
Enjoy Coding :)
NSCalendar *gregorian =
[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSUInteger dayOfYear =
[gregorian ordinalityOfUnit:NSDayCalendarUnit
inUnit:NSYearCalendarUnit forDate:[NSDate date]];
[gregorian release];
return dayOfYear;
Take from the post:
How do you calculate the day of the year for a specific date in Objective-C?
I am writing an app which uses core-data to store my data. Included in this is a date field of which I am only interested in the date not the time.
I need to select records based on the date (not time) and so I have created a category on NSDate to return a date, normalised to a set time as follows:
+ (NSDate *)dateWithNoTime:(NSDate *)dateTime {
if( dateTime == nil ) {
dateTime = [NSDate date];
}
NSDateComponents* comps = [[NSCalendar currentCalendar] components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:dateTime];
NSDate *dateOnly = [[NSCalendar currentCalendar] dateFromComponents:comps];
[dateOnly dateByAddingTimeInterval:(60.0 * 60.0 * 12.0)]; // Push to Middle of day.
return dateOnly;
}
I then use this when I add data to the core-data store (I have a setter which uses this method to set the primitive date value) and then I use this method to create a date that I use to compare the dates when performing a fetch request. So in theory this should always work - ie pick out the dates I'm looking for.
I'm slightly nervous though as I'm not totally sure what effect changing time-zone or locale will have. Will it still work ?
What is considered best practice when storing and searching on a date only when you aren't interested in the time.
Cheers.
EDIT
After reading the discussion recommended I think that I should modify my code to be as follows. The thinking being that if I ensure that I push it to a specific calendar system and a specific timezone (UTC) then the dates should always be the same regardless of where you are when you set the date and when you read the date. Any comments on this new code appreciated.
+ (NSDate *)dateWithNoTime:(NSDate *)dateTime {
if( dateTime == nil ) {
dateTime = [NSDate date];
}
NSCalendar *calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
[calendar setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"UTC"]];
NSDateComponents *components = [[[NSDateComponents alloc] init] autorelease];
components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit
fromDate:dateTime];
NSDate *dateOnly = [calendar dateFromComponents:components];
[dateOnly dateByAddingTimeInterval:(60.0 * 60.0 * 12.0)]; // Push to Middle of day.
return dateOnly;
}
You have a few issues to deal with here. First, as you noted, timezones. You also need to worry about daylight savings, which change the concept of “midday.”
Take a look at this discussion on CocoaDev where an Apple Engineer gives some answers and discusses some best practices.
A simpler solution is to use a predicate that looks for dates within a certain range.
Use NSCalendarComponent to create a start date and an end date for you "day" and then include those in the predicate.
NSPredicate *p=[NSPredicate predicateWithFormat:#"$# <= date <= $#",startDate,endDate];
That will provide the maximum flexibility without to much complexity. Date and time programing is deceptively complex. Be prepared to do some work.
I also ended up in a scenario where I needed to have an NSDate to compare a date without taking into consideration time.
I hade a filter mechanisme and as part of the UI, if the user chose today the minimum date as start date and the end date as today, I would display "All time periods" as opposed to a string in the format:
1/5/2006 - 24/12/2009
So I needed to take todays date using +date of NSDate, and compare it to the end date. That end date came from a UIDatePicker set to without time, but +date returned the date and time of right now.
So I wrote this short handy method, it receives a date object, uses NSDateComponents and the NSCalendar class to extract the day, month and year.
These 3 parameters are then used to create a new NSDate using NSDateFormatter's -dateFromString: method, the result is an NSDate corresponding to the same "date" (in the traditional human concept) as the parameter date but without time.
- (NSDate *)strictDateFromDate:(NSDate *)date{
NSUInteger flags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
NSDateComponents *components = [[NSCalendar currentCalendar] components:flags
fromDate:[NSDate date]];
NSString *stringDate = [NSString stringWithFormat:#"%d/%d/%d", components.day, components.month, components.year];
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
formatter.dateFormat = #"dd/MM/yyyy";
return [formatter dateFromString:stringDate];
}
I hope you can use and enjoy this function in future.
In my date picker i can select a date from the list.
I save it in my string pickUpDateTime
self.pickUpDateTime = [NSString stringWithString:[apiFormat stringFromDate:d]];
I'm having a problem where the user is able to pick a date in the past. Is there some way to get the current day and check that its in the future?
My string holds the date like this 2010-11-04.
The user shouldnt be able to select a day in the past or the current day.
Thanks
-Code
You can get the current date and time with:
NSDate *now = [NSDate date];
Compare the 2 dates with:
if ([d compare:now] == NSOrderedDescending) {
// d is later than now
} else {
// d is earlier than or equal to now
}
If you're using a UIDatePicker, just set
datePicker.minimumDate = [NSDate dateWithTimeIntervalSinceNow:24*3600];
e.g. to allow dates starting tomorrow. Working back from the date string "2010-11-04" to a NSDate object is possible but cumbersome. (but if you insist, have a look at NSDateFormatter)
Lots of answers above give good advice about working with NSDates in general; things are a tiny bit more complicated if you want to round to the start of the day to say e.g. 'at least tomorrow' rather than 'at least 24 hours away'.
In general terms:
get an instance of NSCalendar to represent the Gregorian calendar
use the NSCalendar to convert an NSDate into an NSDateComponents representing just the day, month and year
use the NSCalendar to convert the NSDateComponents back into an NSDate
use arithmetic as recommended elsewhere to increment the NSDate a day into the future, for example
I have to dash, but relevant methods are:
NSCalendar +currentCalendar or -initWithCalendarIdentifier:NSGregorianCalendar to be extra safe
NSCalendar -components:fromDate: (the first parameter is a flag field indicating which bits of the date you need to be filled in) and -dateFromComponents:
NSDate -timeIntervalSinceDate:
NSDateFormatter *df = [[NSDateFormatter alloc] init];
df.dateStyle = NSDateFormatterMediumStyle;
NSString *tempStr=[NSString stringWithFormat:#"%#",[df stringFromDate:datePicker.date]];
txtBirth.text=tempStr;
NSString *birthDate = tempStr;
NSDate *todayDate = [NSDate date];
int time = [todayDate timeIntervalSinceDate:[df dateFromString:birthDate]];
int numberOfDays = time/86400;
hear number of data return data difference.....