iPhone: How to get date and time from number of seconds? - iphone

I have time in seconds 1303093926 and I want to get date and time like
Sat, 09 Oct 2010 18:14:50 +0000

NSDate has a conversion method:
double seconds = 1303093926;
NSTimeInterval timeInterval = (NSTimeInterval)seconds;
NSDate *date = [NSDate dateWithTimeIntervalSince1970:timeInterval];
You can then use the NSDateFormatter class to convert the NSDate to a string in the format you want.

NSDate has several methods for creating date objects from second values. NSDate has four methods for doing exactly what you want:
+ (id)dateWithTimeInterval:(NSTimeInterval)seconds sinceDate:(NSDate *)date: If your number of seconds is based on some arbitrary date, you would use this method.
+ (id)dateWithTimeIntervalSince1970:seconds: If your number of seconds is based on the time since 1970, then you would use this method.
+ (id)dateWithTimeIntervalSinceNow:(NSTimeInterval)seconds: If the number of seconds is relative to the current time, use this. (Negative seconds are for dates prior to "now".)
+ (id)dateWithTimeIntervalSinceReferenceDate:(NSTimeInterval)seconds: If you know that your number of seconds is relative to the predefined "reference date", (1 January 2001, GMT) then you should use this method.
Another approach, is to use NSDateComponents to build your date object. From the NSDateComponents documentation:
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];
You can do the same with your number of seconds, using basic arithmetic to convert the seconds into years, months, days, hours, minutes and seconds.

Related

Math issue using timeIntervalSince 1970

I am trying to find how many milliseconds into the current day we are. I can't find a method to return the time in milliseconds ignoring date, so I figured I could calculate it off of the value returned by timeIntervalSince 1970 method.
I did this:
NSLog(#"%f", [[NSDate date] timeIntervalSince1970]);
2013-05-21 16:29:09.453 TestApp[13951:c07] 1369171749.453490
Now my assumption is that, since there are 86,400 seconds in a day I could divide this value by 86400 and get how many days have elapsed since 1970. Doing this gives me 15846.8952483 days. Now, if my assumption holds, I am 89.52483% through the current day. So multiple 24 hours by 86.52659% would give me a current time of the 21.4859592 hour or about 09:29 PM. As you can see from my NSLog this is about 5 hours from the real time, but I believe the interval returned is GMT so this would be 5 hours ahead of my time zone.
So I figured, well what the heck, I'll just roll with it and see what happens.
I cut off the decimal places by doing:
float timeSince1970 = [[NSDate date] timeIntervalSince1970]/86400.0;
timeSince1970 = timeSince1970 - (int)timeSince1970
Then calculate the milliseconds that have taken place thus far today:
int timeNow = timeSince1970 * 86400000;
NSLog(#"%i", timeNow);
2013-05-21 16:33:37.793 TestApp[14009:c07] 77625000
Then I convert the milliseconds (which still seem appropriate) to NSDate:
NSString *timeString = [NSString stringWithFormat:#"%d", timeNow];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"A"]
NSDate *dateNow = [dateFormatter dateFromString:timeString];
NSLog(#"%#", dateNow);
2013-05-21 16:29:09.455 TestApp[13951:c07] 2000-01-02 03:29:00 +0000
And there is my problem. Rather than returning a 2000-01-01 date with some hours and minutes attached, it is returning a 2000-01-02 date. Why!?
EDIT
I got it working by "removing" the extra 5 hours I noted in the above with:
int timeNow = (timeSince1970 * 86400000) - (5 * 60 * 60 * 1000);
I don't understand why this is necessary though. If someone can explain I'd greatly appreciate it.
EDIT 2
Perhaps I should be asking a more elementary question about how to accomplish the task I'm trying to accomplish. I care about times (for example, 4pm is important but I could care less about the date). I've been storing these in NSDates created by:
[dateFormatter setDateFormat:#"hh:mm a"];
[dateFormatter dateFromString#"04:00 PM"];
All this seems to be going fine. Now I want to compare current time to my saved time and find out if it is NSOrderedAscending or NSOrderedDescending and respond accordingly. Is there a better way to be accomplishing this?
You need to use NSCalendar to generate NSDateComponents based on right now, then set the starting hour, minute, and second all to 0. That will give you the beginning of today. Then you can use NSDate's -timeIntervalSinceNow method to get back the time elapsed between now and your start date.
NSCalendar *cal = [NSCalendar currentCalendar];
NSDate *now = [NSDate date];
// BUILD UP NSDate OBJECT FOR THE BEGINNING OF TODAY
NSDateComponents *comps = [cal components: (NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate: now];
comps.hour = 0;
comps.minute = 0;
comps.second = 0;
// USE CALENDAR TO GENERATE NEW DATE FROM COMPONENTS
NSDate *startOfToday = [cal dateFromComponents: comps];
// YOUR ELAPSED TIME
NSLog(#"%f", [startOfToday timeIntervalSinceNow]);
Edit 1
If you're just looking to compare some NSDateObjects you can see if the time interval between then and now is negative. If so, that date is in the past.
NSDate *saveDate = [modelObject lastSaveDate];
NSTimeInterval difference = [saveDate timeIntervalSinceNow];
BOOL firstDateIsInPast = difference < 0;
if (firstDateIsInPast) {
NSLog(#"Save date is in the past");
}
You could also use compare:.
NSDate* then = [NSDate distantPast];
NSDate* now = [NSDate date];
[then compare: now]; // NSOrderedAscending
The part of your question that says that you want to calculate "how many milliseconds into the current day we are" and then "4pm is important but I could care less about the date" makes it not answerable.
This is because "today" there could have been a time change, which changes the number of milliseconds since midnight (by adding or subtracting an hour, for instance, or a leap second at the end of a year, etc....) and if you don't have the date, you can't determine the number of milliseconds accurately.
Now, to address your edited question: If we assume today's date, then you need to use the time that you have stored and combine it with today's date to get a "specific point in time" which you can compare to the current date and time:
NSString *storedTime = #"04:00 PM";
// Use your current calendar
NSCalendar *cal = [NSCalendar currentCalendar];
// Create a date from the stored time
NSDateFormatter *dateFormatter = [NSDateFormatter new];
[dateFormatter setDateFormat:#"hh:mm a"];
NSDate *storedDate = [dateFormatter dateFromString:storedTime];
// Break it up into its components (ie hours and minutes)
NSDateComponents *storedDateComps = [cal components:NSHourCalendarUnit | NSMinuteCalendarUnit
fromDate:storedDate];
// Now we get the current date/time:
NSDate *currentDateAndTime = [NSDate date];
// Break it up into its components (the date portions)
NSDateComponents *todayComps = [cal components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit
fromDate:currentDateAndTime];
// Combine with your stored time
todayComps.hour = storedDateComps.hour;
todayComps.minute = storedDateComps.minute;
// Create a date from the comps.
// This will give us today's date, with the time that was stored
NSDate *currentDateWithStoredTime = [cal dateFromComponents:todayComps];
// Now, we have the current date and the stored value as a date, so it is simply a matter of comparing them:
NSComparisonResult result = [currentDateAndTime compare:currentDateWithStoredTime];
it is returning a 2000-01-02 date. Why!?
Because your dateFormatter uses the current system locale's timezone.
If you insert ...
dateFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
... your date formatter will interpret the string correctly. But why not creating the date directly:
NSDate *dateNow = [NSDate dateWithTimeIntervalSinceReferenceDate:timeNow];

NSDate dateByAddingTimeInterval subtracting days incorrectly changes time

Am I missing something about how NSDate dateByAddingTimeInterval works with days? Here is my code for subtracting 33 days from a specific date (AIDate). AIDate has a time value of 00:00 PST.
activityOne.ActivityDateTime = [AIDate dateByAddingTimeInterval:-33*24*60*60];
If the AIDate equals 4-9-2013 00:00 PST, the above code will subtract 33 days and 1 hour which works out to 3-6-2013 23:00 PST.
24*60*60 means 24 hours, and not 1 day.
There is a huge difference between those two when your calculation crosses the change from or to daylight saving time.
Coincidentally 33 days ago there was no daylight saving time in your timezone.
The correct way to do this is to use NSDateComponents. Like this:
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *offset = [[NSDateComponents alloc] init];
[offset setDay:-33];
NSDate *offsetedDate = [calendar dateByAddingComponents:offset toDate:[NSDate date] options:0];
NSDateComponents *dc = [[NSCalendar currentCalendar] components:NSDayCalendarUnit|NSMonthCalendarUnit|NSYearCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit|NSQuarterCalendarUnit fromDate:yourDate];
[dc setDay:dc.day - 33];
NSDate *noticeDate = [[NSCalendar currentCalendar] dateFromComponents:dc];

Date in CocoaTouch

I want to find the current date and the date that 10 days before from current date.I know how to find the current date.please anybody help me to find the date which 10 days before from current date..
Thanks in advance.
You can use NSDateComponents to subtract the days from the current date.
NSDate *today = [NSDate date];
NSDateComponents *sub_date = [[NSDateComponents alloc] init];
[sub_date setDay:-10];
NSDate *tenDaysAgo = [[NSCalendar currentCalendar] dateByAddingComponents:sub_date
toDate:today
options:0];
[sub_date release];
NSLog(#"Ten Days Ago: %#", tenDaysAgo);
You can use dateWithTimeInterval:sinceDate: to subtract 10 days from the current date.
Code example:
NSDate *todayDate = [NSDate date];
NSDate *tenDaysAgoDate = [NSDate dateWithTimeInterval:-864000 sinceDate:todayDate];
The 864000 represents the seconds in ten days, the negative sets the calculation to days AGO, instead of forward.

How to set variable with specified date and time?

I searched it a lot but coudn't find any instance of showing how to store the specified time. For example, i need to save time of 15:48 in code in a proper variable (i guess that should be NSDate object). That is needed because i want to hold the exact time to replace the method below with not the time interval since now but my exact specified time to fire notification. Thanks for the help.
NSDate *notificationDate = [NSDate dateWithTimeIntervalSinceNow:5];
notification.fireDate = notificationDate;
Use NSDateComponents:
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setHour:15]; // 15:48 from your example
[comps setMinute:48]; // 15:48 from your example
/// also set year, month and day
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *date = [gregorian dateFromComponents:comps];
[comps release];
You can also use NSDateCompnents to read the components from the current date and time - so if you want to set an NSDate to 15:48 today, you would first create an NSDate for now and then extract the day, month and year from it but overwrite the hour and minutes.
Use NSDateComponents to generate an NSDate object. I guess the Apple document is what you want http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSDateComponents_Class/Reference/Reference.html
Take a look at NSDateFormatter and especially - (NSDate *)dateFromString:(NSString *)string

NSDate troubles - or how to ignore date/timezone?

Alright I've given up on this. Here's what I'm trying to do: I have a sunrise, sunset, and the current time in a certain timezone. I want to know if it's day or night by figuring out if the current time lies between the sunrise and the sunset times.
Here's what I have:
NSLog(#"%# - %# - %#",currTime,sunrise,sunset);
NSDateFormatter *formatter1 = [[NSDateFormatter alloc]init];
NSDateFormatter *formatter2 = [[NSDateFormatter alloc]init];
[formatter1 setDateFormat:#"hh:mm a"];
[formatter2 setDateFormat:#"EEE, dd MMM yyyy h:mm a z"];
NSDate *rise = [formatter1 dateFromString:sunrise];
NSDate *set = [formatter1 dateFromString:sunset];
NSDate *time = [formatter2 dateFromString:currTime];
[formatter1 release];
[formatter2 release];
unsigned int flags = NSHourCalendarUnit | NSMinuteCalendarUnit;
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components1 = [calendar components:flags fromDate:rise];
NSDateComponents *components2 = [calendar components:flags fromDate:set];
NSDateComponents *components3 = [calendar components:flags fromDate:time];
NSDate *Sunrise = [calendar dateFromComponents:components1];
NSDate *Sunset = [calendar dateFromComponents:components2];
NSDate *Time = [calendar dateFromComponents:components3];
NSLog(#"\nSunrise: %# \nSunset:%# \nTime:%#",rise,set,time);
NSLog(#"\nSunrise: %# \nSunset:%# \nTime:%#",Sunrise,Sunset,Time);
Here's the first output:
Fri, 10 Jun 2011 4:00 am SAST - 7:46 am - 5:41 pm
And here's the second (before making it only concerned about the time, not date)
Sunrise: 1969-12-31 22:46:00 +0000
Sunset: 1970-01-01 08:41:00 +0000
Time: 2011-06-10 02:00:00 +0000
And finally here is the last output (notice how the times are messed up?):
Sunrise: 0001-12-31 22:27:01 +0000
Sunset: 0001-01-01 08:22:01 +0000
Time: 0001-01-01 01:41:01 +0000
So I wanted to pop those resulting dates into my method that checks whether it's in between the dates:
+(BOOL)date:(NSDate*)date isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate {
return (([date compare:beginDate] != NSOrderedAscending) && ([date compare:endDate] != NSOrderedDescending));
}
However, until I get the date problem figured out that method won't work. :/ I need help! What am I doing wrong?
Ok, so I gave up on trying to get NSDates to work for me. The timezone issues just killed my brain for the weekend. Anyway, I decided to use BoopMeister suggestion, but it doesn't work quite like I expect. Here's an example:
Using the setup from above, I added these lines:
NSInteger riseHour = [components1 hour];
NSInteger setHour = [components2 hour];
NSInteger timeHour = [components3 hour];
NSLog(#"Rise: %i Set: %i Time: %i",riseHour,setHour,timeHour);
Now, when I plug in these variables:
Current time: Fri, 10 Jun 2011 9:07 am CDT
Sunrise: 6:33 am
Sunset: 8:32 pm
However, when I output the strings from the methods above here's what I get:
Rise: 6 Set: 20 Time: 23
What the?
I would use the components you already have and not make new dates.
Starting at this point in your code:
NSDateComponents *riseComponents = [calendar components:flags fromDate:rise];
NSDateComponents *setComponents = [calendar components:flags fromDate:set];
NSDateComponents *timeComponents = [calendar components:flags fromDate:time];
And then something like
NSInteger riseHour = [riseComponents hour];
NSInteger setHour = [setComponents hour];
NSInteger timeHour = [timeComponents hour];
// Do some checks here
// If necessary do the same for the minutes ([components minute])
Comparing dates has been a performance issue in my app and since you already have the dateComponents it would be faster to make your own check and use the NSIntegers.
Okay, so as can be seen in the question, it gives the numerical presentation of the hours. Same works for the minutes. Build your checks after that.
What probably is the problem with the current time, is the calendar you use. It automatically converts the time to the time in the timezone of the calendar you use. You can also create a calendar with a string representation of the timezone. It's in the API of NSCalendar I think. Then after you made that calendar, then use that one for the current time.
One of the key things about NSDate is that it is in GMT. Always. However when you log it, it prints according to the user's locale.
Now when you do,
NSDateFormatter *formatter1 = [[NSDateFormatter alloc]init];
[formatter1 setDateFormat:#"hh:mm a"];
NSDate *rise = [formatter1 dateFromString:sunrise];
NSDate *set = [formatter1 dateFromString:sunset];
[formatter1 release];
You are just providing information about hour, minute and whether it is AM/PM. How is it to know which day the time belongs to. It fills this lack of information by defaulting to 01/01/1970 and timezone based on the user's locale. You do provide the timezone information in the current time which might or might not be the same as the user's locale.
To fix this, you must generate a string that includes the date and timezone info for the sunset time and pass it to the date formatter with the correct format to get the date. I am assuming you must've this (or how else will you know that it is the sunset or sunrise time for that day?). Since you know the place you should be able to get the timezone info as well. Once you've the correct information to build the dates with, every comparison method that you've used will work.