NSString parse to find date - objective-c

I am pulling information from a database that contains dates formatted weird.
When they are pulled they are in the format of:
DayOfWeek, Month Date
I am attempting to use EventKit to have the option to add the date to the users calendar.
I can't seem to find the best way to go about doing this.
Any help or point in the right direction would be very much appreciated!!

You want to use an NSDateFormatter:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = #"EEEE, MMMM d";
NSDate *date = [dateFormatter dateFromString:#"Tuesday, March 3"];
"DayOfWeek, Month Date" is ambiguous, so I did my best to guess what you meant. If I was wrong, you'll need to change the format string a bit. Here is a reference on the strings you can use.

Your problem is that this database has ambiguous dates. It does not have a year information.
NSDateFormatters don't guess date information. They create dates from the information you provide. And since this information is missing the year will be 1970 (as in: the same year as the reference data).
Because the format that is saved in the database is totally stupid I assume that those dates always are within the next 365 days. So in theory you wouldn't have to save a year info.
You could then use something like this to figure out the NSDate from that totally ambiguous date information.
The idea is to transfer the date from 1970 (created from your string) to the current year. And if it would be in the past for current year (e.g. today is 31 March a date with "Foo, March 30" would be in the past) move it to next year.
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = #"EEEE, MMMM d";
// the following line is important if you want that your code runs on device that are not english!
dateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US"];
NSDate *date = [dateFormatter dateFromString:#"Wednesday, March 30"];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [calendar components:NSMonthCalendarUnit|NSDayCalendarUnit fromDate:date];
NSDateComponents *todayComponent = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:[NSDate date]];
NSInteger proposedYear = [todayComponent year];
// if supposed date would be in the past for the current year move it into next year
if ([components month] < [todayComponent month]) {
proposedYear++;
}
if ([components month] == [todayComponent month] && [components day] < [todayComponent day]) {
proposedYear++;
}
[components setYear:proposedYear];
date = [calendar dateFromComponents:components];
// just for logging, so you are sure that you use the correct year:
[dateFormatter setDateFormat:#"EEEE, MMMM d yyyy"];
NSLog(#"%#", [dateFormatter stringFromDate:date]);

Related

Convert the exact NSString value to NSDate [duplicate]

This question already has an answer here:
returns a date an hour in the future
(1 answer)
Closed 7 years ago.
This is my code.
NSString *dateString = #"2015-06-03 02:19:37";
NSDateFormatter *formatter = [NSDateFormatter new];
[formatter setDateFormat:#"yyyy-MM-dd hh:mm:ss"];
NSLog(#"converted date = %#",[formatter dateFromString:dateString]);
The output of the code above is: "converted date = 2015-06-02 18:19:37 +0000". I know that this is because it converts the NSString with respect to GMT, but what i wanted to happen is NSDate must be 2015-06-03 02:19:37, same with dateString
I know that this is because [the NSDateFormatter] converts the NSString with respect to GMT…
No, you're wrong. NSDateFormatter defaults to using your current time zone.
What you're not understanding is that "2015-06-02 18:19:37 +0000" is the same date and time as "2015-06-03 02:19:37" (in your local time zone, which must be GMT+0800).
Also, the description that you logged is just one representation of the date. The date does not have a year, month, day-of-month, hour, minute, second, or any of that. A date object just represents a moment in time. Such moments don't have any of that and neither do NSDate objects. Only representations of moments have those things, and they are only arrived at by processing the date through a specific calendar and time zone. In any case, any given date has multiple representations. Just because the description that gets logged happens to choose a representation that you weren't expecting doesn't mean the date is wrong.
You have implicitly requested a conversion from an NSDate object to a string when you logged it. That's because logging always involves strings. The string-formatting code used by NSLog() and the %# format specifier uses the -description method. You are never going to be able to force NSDate's implementation of -description to use your time zone, so don't try.
If you really need a string representation (and you're not just debugging) and you want it in some specific time zone or otherwise want to dictate the format, don't rely on the -description method like you are. Instead, use a date formatter to convert from NSDate to an NSString explicitly, and configure the date formatter to produce the representation that you want.
But don't confuse the need to do that with the date being wrong.
What I really wanted to do is to check if the given NSDate is already past 9PM EST (-4GMT), while i'm on +8GMT timezone.
So, use NSCalendar, NSTimeZone, and NSDateComponents to construct an NSDate for 9PM EST (on the current day, I suppose you mean) and then compare the dates.
NSDate* date = /* ... */;
NSCalendar* calendar = [[NSCalendar alloc] initWithIdentifier:NSCalendarIdentifierGregorian];
calendar.timeZone = [NSTimeZone timeZoneWithName:#"America/New_York"];
NSDate* deadline = [calendar dateBySettingHour:21 minute:0 second:0 ofDate:date options:0];
if ([date compare:deadline] == NSOrderedDescending)
/* date is after deadline */;
Here I used the convenience method -dateBySettingHour:minute:second:ofDate:options: and avoided direct use of NSDateComponents. If your needs differ, you might have to convert the date to date components using the calender, modify the components, convert them back to a date, and then compare.
Use the NSDateComponents class to build the date from the information in the string. The documentation explicitly provides an example of this:
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:6];
[comps setMonth:5];
[comps setYear:2004];
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *date = [gregorian dateFromComponents:comps];
[comps release];
NSDateComponents *weekdayComponents =
[gregorian components:NSWeekdayCalendarUnit fromDate:date];
int weekday = [weekdayComponents weekday];
call this method with your string value...
- (NSDate *)dateFromString:(NSString *)date
{
static NSDateFormatter *dateFormatter;
if (!dateFormatter)
{
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"]];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
[dateFormatter setDateFormat:#"dd-MM-yyyy"];
}
NSLog(#"Date: %#",date);
return [dateFormatter dateFromString:date];
}
RESULT : Date: 2015-06-03 02:19:37
NSString *dateString = #"2015-06-03 02:19:37";
NSDateFormatter *f = [[NSDateFormatter alloc] init];
[f setDateFormat:#"yyyy-MM-dd"];
NSDate *startDate = [f dateFromString:dateString];
You will get the NSDate here(startDate).... May this help to you.....

How to model date at different precision as either year or month/year or day/month/year in Cocoa?

I want to give the possibility to a user to enter a date at different precision:
only as year or
as month and year or
as day, month and year.
What is the best way to do this in Cocoa (and store it in Core Data).
How can i validate the input in a NSTextField (is a NSTextField the best option)?
How can i search for corresponding items based on search field entries in the same manner?
An NSDate will always have the year, month, day and time. You can use the code below to return a date with the specified values:
- (NSDate *)dateWithYear:(NSInteger)year Month:(NSInteger)month Day:(NSInteger)day {
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [[NSDateComponents alloc] init];
components.year = year;
components.month = month;
components.day = day;
return [calendar dateFromComponents:components];
}
If you want to change the display of the date, you can use NSDateFormatter:
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy"]; // shows only year
[dateFormatter setDateFormat:#"MMM yyyy"]; //shows month & year
To convert the date into a string using the formatter use:
NSString *dateString = [formatter stringFromDate:date];
read more on Date Formatting here: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/DataFormatting/Articles/dfDateFormatting10_4.html

Wrong Days Between Dates for Month of March

I have a very interesting problem: When calculating the number of days between two dates, my calculator gives the wrong results for the month of March only. I have two text fields, one for each date. If I enter 3/7/12 in date1, and 3/13/12 in date2, the result is 7, which is correct (I am counting the first day as well). But when I enter date1 = 3/7/12 and date2 = 3/14/12, the result is still 7, but it should be 8. Likewise, if I enter date1 = 3/7/12 and date2 = 3/23/12, the result should be 17, but it is 16. If I change the month to April so that date1 = 4/7/12 and date2 = 4/23/12, the result is 17. Every month is working as intended, only the month of March is giving me wrong results. Does anyone have any idea what I am missing? Is this a timezone problem? How do I fix it? Here is my code:
NSDateFormatter *dateFormatter1 = [[NSDateFormatter alloc] init];
[dateFormatter1 setDateFormat:#"MM/dd/yyyy"];
NSDate *startdate1 = [dateFormatter1 dateFromString: date1.text];
NSDateFormatter *dateFormatter2 = [[NSDateFormatter alloc] init];
[dateFormatter2 setDateFormat:#"MM/dd/yyyy"];
NSDate *enddate2 = [dateFormatter2 dateFromString: date2.text];
int start1 = [startdate1 timeIntervalSince1970];
int end2 = [enddate2 timeIntervalSince1970];
double difference12 = end2-start1;
int days12;
days12 =(int)((double)difference12/(3600.0*24.00)+1);
result12.text = [[NSString alloc] initWithFormat:#"%i", days12]
If you use NSCalendar, you won't need to deal with Daylight Savings Time calculation.
int days = [[[NSCalendar currentCalendar] components:NSDayCalendarUnit
fromDate:startDate1
toDate:endDate2
options:0] day] + 1;
Most like this is a daylight savings issue (March 11th, 2012). Set the date formatters' timezones to:
[NSTimeZone timeZoneForSecondsFromGMT:0];
This should fix the issue.
To add to others, please do not rely on number of seconds in a day being 86400 all the time, it won't. Be sure to watch Session 211 Performing Calendar Calculations from WWDC 2011.
You can think of NSDate as a point in time. If you want to calculate number of days between two dates, this is a calendar issue and there are more than one calendars (like the Mayan calendar).
What you need is NSDateComponents:
NSDate *dateToday = [NSDate date];
NSDateComponents *dateBComponent = [[NSDateComponents alloc] init];
[dateBComponent setDay:-10];
NSDate *date10DaysAgo = [[NSCalendar currentCalendar] dateByAddingComponents:dateBComponent
toDate:dateToday
options:0];
NSCalendar *calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
NSDateComponents *components = [calendar components:NSDayCalendarUnit
fromDate:date10DaysAgo
toDate:dateToday
options:0];
NSLog(#"Difference: %d", components.day);

Struggling to store a date for later use

Hi I'm very new to iOS programming and am playing around with dates (todays date and a date 1 year from now).
Here's the code i'm dabbling with.
NSCalendar * calendar = [NSCalendar currentCalendar];//Create a calendar
NSDate *todaysDate = [[NSDate alloc]init]; //get todays date
NSString *dateToday = [NSString stringWithFormat:#"%#",todaysDate];//convert it to a string
NSDateFormatter *df = [[NSDateFormatter alloc] init];// create a formatter
[df setDateFormat:#"yyyy-MM-dd HH:mm:ss ZZZ" ];//input how the date looks as a string
myDate = [df dateFromString: dateToday];// change it back to a proper NSDate
NSDateComponents *components = [[NSDateComponents alloc] init]; // create the components
[components setYear:1];//add 1 year
nextYear = [calendar dateByAddingComponents:components toDate:todaysDate options:0]; // build the year from component into a variable
dateNextYear = [NSString stringWithFormat:#"%#",nextYear];//convert it to a string
NSDateFormatter *yearFormat = [[NSDateFormatter alloc] init];// create a formatter
[yearFormat setDateFormat:#"yyyy-MM-dd HH:mm:ss ZZZ" ];//input how the date looks as a string
myDateInTheFuture = [yearFormat dateFromString: dateNextYear];// change it back to a proper NSDate
NSLog(#" next years date is %# ", myDateInTheFuture);
[yearFormat release];
[components release];
[todaysDate release];
I can get the current date and the future date 1 year from now, but i'm unsure how i would store the future date for comparison, i know i can use the "compare" item for NSDate to check, but when i set the future date to a variable every time it runs it stays relative 1 year apart from what i'm checking it against which is todays date.
Its 3am where i am and my brain is mush so apologises in advance if this is the simplest thing ever and i just can't see it.
Its my first post so go easy on me please.
Thanks
I am not entirely sure what you are trying to do, but this is what I gather:
You want to take the current date, add a year to it, and manipulate the resulting date.
Please notify me if this is not correct.
For this, try the following:
NSDate *todayDate = [NSDate date]; //Create a date that is set to today
NSDate *resultingDate = [calendar dateByAddingTimeInterval:31556926; //Take the current date and add the amount of seconds in a year to it
If you want to store this permanently, use the NSUserDefaults:
to set:
[userDefaults setObject:resultingDate forKey:#"storedDate"];
Hope this helps,
HBhargava
to get:
NSDate *returnedDate = [userDefaults dateForKey:#"storedDate"];

How to know list of Mondays dates in a month using NSCalendar?

I would like to know the dates of all Monday's in a month using NSCalendar in Objective-C. So Please help me.
Thanks in advance
I blogged a solution for this a few months ago
http://brandontreb.com/case-of-the-mondays/
From https://discussions.apple.com/thread/1700102?start=0&tstart=0 and the Apple NSCalendar reference:
How about using something like this -
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setYear:1965]; // Year of the calendar month
[comps setMonth:1]; // Month
[comps setDay:6]; // Any day
NSDate *date = [gregorian dateFromComponents:comps];
[comps release];
Then, once you have the NSDate, do this:
NSDate * testDate = [NSDate date];
NSString * weekdayString = [testDate descriptionWithCalendarFormat:#"%A" timeZone:nil
locale:[[NSUserDefaults standardUserDefaults] dictionaryRepresentation]];
NSLog(#"Day of the week: %#", weekdayString);
// weekdayString should look like "Monday", etc.
So, you can loop through the month's days until;
[weekdayString isEqualToString:#"Monday"] // or your desired day
And then just add 7 days to get the other 4 or so dates.
This may not be the prettiest solution, but it should work.