I have been playing with NSDate and NSTimeInterval to try and get the time passed since a specific date, but I am not having much luck.
I want to specify an exact constant date (Jan 5th 2012 2PM) and calculate the time passed in Years, Hours, Min, Sec and display this on the screen as a counter.
It seems simple enough; however, browsing through code has yet to prove successful for me.
I also want to see total time in a years months days mins secs format. I appreciate any help, thanks!
This an example I have found that I don't know how to customize:
NSCalendar *c = [NSCalendar currentCalendar];
NSDate *d1 = [NSDate date];
NSDate *d2 = [NSDate dateWithTimeIntervalSince1970:1340323201];//2012-06-22
NSDateComponents *components = [c components:NSHourCalendarUnit fromDate:d2 toDate:d1 options:0];
NSInteger diff = components.minute;
NSDayCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit
Like tkanzakic said,
NSDateComponents* components = [c components:(NSYearCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit) fromDate:d1 toDate:d2 options:0] ;
NSLog(#"%ld years, %ld hours, %ld minutes, %ld seconds", components.year, components.hour, components.minute, components.second) ;
Related
I want to get how many seconds are remaining to complete an hour. No matter which what time it is?
if its 05:01:00 then it should give 3540 seconds
and if its 11:58:40 then it gives 80 seconds and so on. I try to find it on google but could not able to find it.
Thanks in advance.
NSCalendar has got methods to do that kind of date math:
NSDate *now = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
// find next date where the minutes are zero
NSDate *nextHour = [calendar nextDateAfterDate:now matchingUnit:NSCalendarUnitMinute value:0 options:NSCalendarMatchNextTime];
// get the number of seconds between now and next hour
NSDateComponents *componentsToNextHour = [calendar components:NSCalendarUnitSecond fromDate:now toDate:nextHour options:0];
NSLog(#"%ld", componentsToNextHour.second);
#Vadian's answer is very good. (voted)
It requires iOS 8 or later however.
There are other ways you could do this using NSCalendar and NSDateComponents that would work with older OS versions.
You could use componentsFromDate to get the month, day, year, and hour from the current date, then increment the hour value and use the NSCalendar method dateFromComponents: to convert your to adjusted components back to a date.
NSDate *date1 = [NSDate dateWithString:#"2010-01-01 00:00:00 +0000"];
NSDate *date2 = [NSDate dateWithString:#"2010-02-03 00:00:00 +0000"];
NSTimeInterval secondsBetween = [date2 timeIntervalSinceDate:date1];
Fill in with the correct times and dates to get the difference in seconds
Edit: An alternative method is to work out the currenthour and return as an integer. Then add one to the NSInteger returned as below (you will have to make sure to handle the case where it is after midnight though!)
NSDateComponents *components = [[NSCalendar currentCalendar] components:NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit fromDate:[NSDate date]];
NSInteger currentHour = [components hour];
I need to get the progress of the current day (For example from 6am and 11pm). I have tried many things and the only code I can get working so far is this code:
//Get the seconds between two days
//Get todays date
NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];
//Set todays date in a NSCalendar object
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDate *date1 = [gregorian dateFromComponents:components];
//Get tomorrows date
NSDateComponents *components1 = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];
components1.day++;
//Set tomorrows date in a NSCalendar object
NSDate *date2 = [gregorian dateFromComponents:components1];
NSTimeInterval secondsBetween = [date2 timeIntervalSinceDate:date1];
NSLog(#"Test: %f", secondsBetween);
This code will get the amount of seconds between two days in total (which doesn't really matter as it's a constant). How do I get the progress between two different times? As the user will be allowed to change the times it counts between I need to be able to calculate this on the fly in a NSTimer.
Edit: I want to know how to use a ProgressView to display the percentage between two times. E.g. The ProgressView would be 50% if it was 9AM and the times were 6AM and 12PM.
The difference in seconds between two dates is
[date2 timeIntervalSinceDate:date1];
That seems to be all you need for your problem.
you only set day/month/year -- set hours/minutes/seconds too.
right now the dates always point to 00:00:00 and not to any TIME
No problem. I use the following method to determine the difference between NSDate values:
- (NSInteger)secondsBetweenDate:(NSDate*)fromDateTime andDate:(NSDate*)toDateTime {
NSDate *fromDate;
NSDate *toDate;
NSCalendar *calendar = [NSCalendar currentCalendar];
//Returns by reference the starting time and duration for the given dates (with second precision).
[calendar rangeOfUnit:NSCalendarUnitSecond startDate:&fromDate
interval:NULL forDate:fromDateTime];
[calendar rangeOfUnit:NSCalendarUnitSecond startDate:&toDate
interval:NULL forDate:toDateTime];
//Returns the difference between the two dates (with second precision)
NSDateComponents *difference = [calendar components:NSCalendarUnitSecond
fromDate:fromDate toDate:toDate options:0];
//returns the number of seconds
return [difference second];
}
To test the above code, I've used an easier way to create two points in time (rather than many lines you've used above). This is simply used to test and you'll obviously use real values in your actual code
NSDate * myDate1 = [NSDate date]; // date as of right now
NSDate * myDate2 = [[NSDate alloc] initWithTimeIntervalSinceNow:1 * 24 * 60 * 60]; // exactly 24 hours into the future
NSLog(#"Second Between: %ld",(long)[self secondsBetweenDate:myDate1 andDate:myDate2]);
//OUTPUT: Seconds: 86400
You can easily tweak the values above to test certain ranges. For reference, this is what each number stands for:
1 (days) * 24 (hours) * 60 (minutes) * 60 (seconds)
OK, with that sorted you just need to figure out how much time has progressed since your starting time. You can do that with two calls to the method created at the start of this post:
//Assuming dates are sourced from some other code
NSDate * startTime // Set elsewhere in the code
NSDate * currentTime // Set elsewhere in the code
NSDate * endTime // Set elsewhere in the code
long fullDuration = [self secondsBetweenDate:startTime andDate:endTime];
long timeElapsed = [self secondsBetweenDate:startTime andDate:currentTime];
float percentComplete = (float) timeElapsed / (float) fullDuration;
Now, since we're going to be using ProgressView I'm keep this percent value as a number between 0 and 1 and the variable as a float.
Finally, assuming you already have the following done:
Added a ProgressView object to your storyboard
Added an outlet to to the object called something like progressViewOutlet
All you need to do is send the update regularly using your timer using the following code:
self.progressViewOutlet.progress = percentComplete;
You can grab my source code below. Let me know if you have any questions
https://dl.dropboxusercontent.com/u/43038596/testDates.zip
I'm trying to write an application that will send the user an alert in the Notification Center 60 hours before the date arrives. Here is the code:
localNotif.fireDate = [eventDate dateByAddingTimeInterval:-60*60*60];
I was wondering if the -60*60*60 formula will work to alert them 60 hours prior to the date? I'm not sure at all how the formula works, I would like to set it up to alert 10 minutes before the date for testing purposes, then change it back to 60 hours once I confirm that everything is correct. Does any one know the formula to use for both of these?
Any help is much appreciated, thank you!
A crude but easy-to-code way is to add/subtract seconds from an NSDate directly:
NSDate *hourLaterDate = [date dateByAddingTimeInterval: 60*60];
NSDate *hourEarlierDate = [date dateByAddingTimeInterval: -60*60];
You can see how it works by logging the dates:
NSDate *now = [NSDate date];
NSDate *hourLaterDate = [now dateByAddingTimeInterval: 60*60];
NSLog(#"%# => %#", now, hourLaterDate);
In this approach a date is interpreted as a number of seconds since the reference date. So, internally it's just a big number of type double.
A tedious-to-code but pedantically correct way to do these calculations is by interpreting dates as dates expressed in a calendar system. The same thing achieved as calendrical calculations:
NSDateComponents *hour = [[NSDateComponents alloc] init];
[hour setHour: 1];
NSCalendar *calendar= [[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar];
NSDate *hourLaterDate = [calendar dateByAddingComponents: hour
toDate: date
options: 0];
[hour release];
[calendar release];
These calculations take into account time zones, daylight saving time, leap years, etc. They can also be more expressive in terms of what you're calculating.
Before using any of these approaches you have to decide what exactly you need: a timestamp or a full-blown calendar date.
Is there any way to find out an accurate difference between two NSDate?
I have found solutions but they aren't accurate enough. I need to take into account daylight saving, the fact that different months have a different number of days, etc.
A simple calculation such as /60/60/24 etc. to work out minutes, hours and days doesn't take them into account.
Lets say I need to work out the difference between the time right now ([NSDate date]) and December 25th 10:22PM (date chosen by user using date picker [datePicker date]) just as an example, how would I do this?
Knowing the exact time difference isn't the key, so long as I have an accurate difference of days, months and years, it will do.
From Apple's Date & Time Programming Guide:
Listing 12 Getting the difference between two dates
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];
NSDate is completely independent of Timezone. Daylight saving doesn't even come into the picture for NSDate. Only when you convert NSDate into a human readable format (MM/DD/YY, HH:MM:SS format or the like), does Time Zone come into picture.
Make sure that you take into account correct timezone, day-light saving setting when you create NSDate(s). Subsequently, the method, [date1 timeIntervalSinceDate:date2] should always give you accurate time difference.
So, the more accurate question you meant to ask was: How can I get a nicely formatted days, months, years from a difference between two dates. First you want to get the nsTimerInterval (time difference in seconds) and then format it:
How do I break down an NSTimeInterval into year, months, days, hours, minutes and seconds on iPhone?
Small update on the code for latest iOS:
NSDate *startDate = ...;
NSDate *endDate = ...;
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSUInteger unitFlags = NSCalendarUnitMonth | NSCalendarUnitDay;
NSDateComponents *components = [gregorian components:unitFlags
fromDate: startDate
toDate:endDate options:0];
NSInteger months = [components month];
NSInteger days = [components day];
My region format is US, and I'm getting different week numbers from the ones I get on Mac OSx which is also in US.
I'm using iOS 5 and have not programmed on iOS before this sdk version. So I just want to make sure I'm not doing something wrong. Whit this code below I'm getting for the last week of the year the number 53 which I think is wrong. My first day of the week is set to sunday.
Please advice, thank you.
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDate *date = [NSDate date];
NSDateComponents *dateComponents = [calendar components:( NSWeekCalendarUnit) fromDate:date ];
int week = (int)[dateComponents week];
NSLog(#"%i", week);
Being [NSDate date] december 8, it returns week number 50, but on Mac OSX I get week 49
First off, I see you changed your code to get rid of the 'gregorianCalendar' nonsense. Good.
When I tried your code in a test app:
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *dateComponents = [calendar components:( NSWeekCalendarUnit) fromDate:[NSDate date]];
int week = (int)[dateComponents week];
[calendar release];
NSLog( #"week is %d", week);
return week;
I'm getting 49 (which makes sense to me).
If you're getting 53, then you're passing in the wrong date.
Did you check the locale? There are cases where the week numbers differ between the US and Europe for example.