Struggling to store a date for later use - objective-c

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"];

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

current Date and Time - NSDate

I need to display the current Date and Time.
I have used ;
NSDate *currentDateNTime = [NSDate date];
I want to have the current date and time (Should display the system time and not GMT time).
The output should be in a NSDate format and not NSString.
for example;
NSDate *currentDateNTime = [NSDate date];
// Do the processing....
NSDate *nowDateAndTime = .....; // Output should be a NSDate and not a NSString
Since all NSDate is GMT referred, you probably want this:
(don'f forget that the nowDate won't be the actual current system date-time, but it's "shifted", so if you will generate NSString using NSDateFormatter, you will see a wrong date)
NSDate* currentDate = [NSDate date];
NSTimeZone* currentTimeZone = [NSTimeZone timeZoneWithAbbreviation:#"GMT"];
NSTimeZone* nowTimeZone = [NSTimeZone systemTimeZone];
NSInteger currentGMTOffset = [currentTimeZone secondsFromGMTForDate:currentDate];
NSInteger nowGMTOffset = [nowTimeZone secondsFromGMTForDate:currentDate];
NSTimeInterval interval = nowGMTOffset - currentGMTOffset;
NSDate* nowDate = [[NSDate alloc] initWithTimeInterval:interval sinceDate:currentDate];
Every moment in time is the same moment in time everywhere around the world —- it is just expressed as different clock times in different timezones. Therefore, you can't change the date to some other date that represents the time in your timezone; you must use an NSDateFormatter that you feed with the timezone you are in. The resulting string is the moment in time expressed in the clock time of your position.
Do all needed calculations in GMT, and just use a formatter for displaying.
Worth reading
Does [NSDate date] return the local date and time?
Some useful resources for anyone coming to this more recently:
Apple date and time programming guide do read it if you're doing anything serious with dates and times.
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/DatesAndTimes/DatesAndTimes.html#//apple_ref/doc/uid/10000039i?language=objc
Useful category on NSDate with lots of utilities does allow a ~new~ date to be generated based on an existing date.
https://github.com/erica/NSDate-Extensions
There's also a swift version of the category
https://github.com/erica/SwiftDates
You need an NSDateFormatter and call stringFromDate this method to get a string of your date.
NSDateFormatter *dateformater = [[NSDateFormatter alloc] init];
[dateformater setDateFormat:#"yyyyMMdd,HH:mm"];
NSString *str = [dateformater stringFromDate: currentDateNTime];
use this method
-(NSDate *)convertDateToDate:(NSDate *) date
{
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
NSDate *nowDate = [[[NSDate alloc] init] autorelease];
[formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
[formatter setDateFormat:#"yyyy-MM-d H:m:s"];
NSString * strdate = [formatter stringFromDate:date];
nowDate = [formatter dateFromString:strdate];
return nowDate;
}
this may return you what you want.
i hope you this may help you.

NSString parse to find date

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]);

What's the best/easiest way to compare two times in Objective-C?

I've got a string representation of a time, like "11:13 AM." This was produced using an NSDateFormatter and the stringFromDate: method.
I'd like to compare this time to the current time, but when I use the dateFromString: method to turn the string back into a date, a year, month and day are added - which I don't want. I just need to know if right now is < or > the time stored in the string.
What's going to be the best way to handle that? Thanks in advance for your help.
Instead of using the string representation, use the NSDate you got from the picker. You can convert that hour/min/sec using NSDateComponents, then also convert [NSDate date] to NSDateComponents. Compare the hours/minutes/seconds of the two sets of components.
EDIT -- use a utility function for things like this that converts the hr/min/sec components of NSDate into a secondsOfTheDay (seconds since midnight).
You can directly use two time of day values since they are both seconds since midnight. Simple integers can be easily compared and stored and manipulated. You don't have to use NSDate all the time.
//----------------------------------------------------------------------------
// extracts hour/minutes/seconds from NSDate, converts to seconds since midnight
//----------------------------------------------------------------------------
unsigned secondOfTheDay( NSDate* time )
{
NSCalendar* curCalendar = [NSCalendar currentCalendar];
const unsigned units = NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
NSDateComponents* comps = [curCalendar components:units fromDate:time];
int hour = [comps hour];
int min = [comps minute];
int sec = [comps second];
return ((hour * 60) + min) * 60 + sec;
}
If I understand the problem correctly, you’re using the dateFromString: method of NSDateFormatter. This is giving you the correct time, but with a default date of January 1, 1970, which is useless to compare against the current date/time.
This is easy to solve. Use setDefaultDate: to set the default date to today.
NSDate *now = [NSDate date];
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
[formatter setDateFormat:#"hh:mm a"];
[formatter setDefaultDate:now];
NSDate *theDate = [formatter dateFromString:#"11:13 AM"];
NSComparisonResult theResult = [theDate compare:now];
Can you reuse the string formatter that you used to create the string? So, let's say you created the string like this:
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init];
[formatter setDateFormat:#"HH:mm a"];
NSString *dateAsString = [formatter stringFromDate:[NSDate date]];
You can get an NSDate like this:
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init];
[formatter setDateFormat:#"HH:mm a"];
NSDate *date = [formatter dateFromString:dateAsString];
The day, month, year and timezone information will not be kept, but you'll have an NSDate object with the values of 1/1/1970 and GMT for the timezone offset.
At this point you can use the compare: (which is typically reserved for sorting operations) or the laterDate: or earlierDate: methods.
Be careful using NSDateFormatter like this, as you may run into issues with internationalization.
If you need to add information about the current date to the date you get from dateFromString:, such as the month day and year, you'll need to use NSCalendar's dateByAddingComponents:toDate:options: method.
If the string was originally created from an NSDate, then you'll want to use that original NSDate to compare against [NSDate date] using NSDate's compare: method (or some variant, such as earlierDate: or laterDate:).
You should use 24-hour based NSDateFormatter and compare as strings ("09:00am" > "08:00pm", but "09:00" < "20:00") . But in general it is right to operate with NSDate instances instead of strings