I am developing one ios app now. I have feature in which i have to display a continuous days the app is used.
Means if i use app for 3 days constantly i have to display 3.
And if i have not used it for one day. The counter should reset.
I am using this function to calculate days.
- (int)daysBetween:(NSDate *)dt1 and:(NSDate *)dt2 {
NSUInteger unitFlags = NSDayCalendarUnit;
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [calendar components:unitFlags fromDate:dt1 toDate:dt2 options:0];
return [components day];
}
I am saving last used date. and pass two parameter last used date and current date in it.
But by this function if i used app at 11.30 PM and again used it at 1.00 AM it will not increment day.
You get this because you are not considering the time part of the dates, you need to use rangeOfUnit:.
I suggest to use the #Brain functions mentioned in this SO question:
Number of days between two NSDates
Related
I use the following to obtain a week number from an NSDate:
[[calendar components: NSWeekCalendarUnit fromDate:date] week]
Unfortunately, I get different values in different iOS versions. Values returned by iOS 4.* and 5 differ by 1. Is there any way to retrieve week number consistently?
Since iOS5 NSCalender dosent seem to be defining accordingly to ISO 8601 as default.
You need to set your calender with method "setMinimumDaysInFirstWeek" to get expected week number result.
[yourCalender setMinimumDaysInFirstWeek:4];
"4" means Thursday in this case.
http://en.wikipedia.org/wiki/ISO_week_date
"The first week of a year is the week that contains the first Thursday of the year."
I don't know why it's not defined as "4" as default in iOS5. Just one of those wierd "bugs" i guess ;)
And yes, this will work in both iOS 4 and 5.
iOS5 appears to be wrong, Bug ID# 10412573.
Summary:
iOS5 NSDateComponents week reports the incorrect week with both NSWeekCalendarUnit and NSWeekOfYearCalendarUnit.
Steps to Reproduce:
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *date = [NSDate date];
NSLog(#"week: %i", [[calendar components: NSWeekCalendarUnit fromDate:date] week]);
NSLog(#"week: %i", [[calendar components: NSWeekOfYearCalendarUnit fromDate:date] weekOfYear]);
Expected Results:
The same week number on iOS4 and iOS5. For 11/8/2011 the week should be 45.
Actual Results:
The same week number on iOS5. For 11/8/2011 the week should be 46.
Regression:
iOS4 is correct, iOS5 is incorrect.
Week numbering is standardized by ISO 8601.
I bet that iOS5 is correct and that a bug has been filed for iOS4.
A possible solution is to add a workaround that fixes the iOS4 bug.
I have to convert a Double value into a Date value in Objective-C
I tried many ways but im not getting it.
date=var1/24;
Here var1 is a double value which should be divided by 24 and stored as a Date into the variable date. How can I do this using Objective-C?
I created the date variable like this:
NSDate *date=[[NSDate alloc]init];
date=(nsdate)var1/24;
How can I do this?
Its a Double Variable.. which will be containing values upto 24 it will be representing HOURS from TODAY..
OK, so you have a relative value that you want to add to an absolute value. Additional work is required.
First, you must decide "What is today?". Is it 12:01am? If it is, in which time zone? GMT? Something else? You have to know this, because 12:01am GMT is not the same thing as 12:01am EDT. So: what is today?
Once you've decided where you're going to be measuring time from, you have to construct an NSDate representing that point in time.
For example:
NSDate *rightNow = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:NSUIntegerMax fromDate:rightNow];
This will give you an NSDateComponents object, which is an object that represents a point in time relative to a calendar. In this case, we're using the "current calendar" (probably the Gregorian calendar, but not necessarily), and the default time zone is your current time zone. If you need to have it be relative to a different time zone, you can create a new NSTimeZone object and use -[NSCalendar setTimeZone:] to set the calendar's time zone (before asking for the date components).
Now that you've got the date components, we can "reset" things to the appropriate time:
[components setHour:0];
[components setMinute:0];
[components setSecond:0];
Then we can turn it back into an NSDate to make it an absolute point in time:
NSDate *startingPoint = [calendar dateFromComponents:components];
NOW we have our starting point, and can deal with the "hours from today". First, we'll create a date components object to represent however many hours the difference is:
NSInteger hourDelta = var1 / 24;
NSDateComponents *delta = [[NSDateComponents alloc] init];
[delta setHour:hourDelta];
Now, we'll add this relative difference to our absolute starting date:
NSDate *finalDate = [calendar dateByAddingComponents:delta toDate:startingPoint options:0];
And because we're good citizens, we'll clean up our memory (unless you're using Garbage Collection or compiling with ARC):
[delta release];
Some important notes:
All of the manipulations are done via the NSCalendar object, because the NSCalendar is what defines what a "day" means and what an "hour" is. You think "there are 24 hours in a day and 60 minutes in an hour...", but that's not necessarily true. I can create my own calendar that has 10 hours in a day, and 10 minutes in an hour. If I want, I can define a "day" as something other than "one full rotation of the Earth". The NSCalendar define all these rules. Thus, all relative manipulations of dates (adding "hours" and "days" or whatever) must be done via the calendar.
There are methods on NSDate like -dateByAddingTimeInterval:, but this is for when you're dealing with absolute intervals and not relative amounts.
It depends of what you want to do exactly, but a direct cast as (nsdate)var1/24 will definitely NOT work!!!
Anway, what does your variable var1 represent exactly? Minutes ? Seconds ? Hours ? From which reference date? Today? The UNIX Epoch? Is it a UNIX timestamp (seconds since 01/01/1970)? Just asking to "convert a number to a date" means nothing on its own ;-)
Depending on the answer to those questions, you may use either NSDateComponents to produce a date giving the different date components (month, day, hours, minutes, seconds, …), or create a NSDate from a UNIX timestamp using dateWithTimeIntervalSince1970... or use any other method from NSDate or NSDateComponents depending on your needs.
Whatever your problem is, do read* the Date and TIme Programming Guide!! Everything is explained here about date manipulation; it will contain everything you need to answer your question.
I can't seem to figure out why the day doesn't change when I get to the 6th of November, 2011. All I'm doing is iterating through the days. Any help would be appreciated. Here is my code:
NSCalendar* calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents* comp = [[NSDateComponents alloc] init];
[comp setDay:2];
[comp setMonth:11];
[comp setYear:2011];
NSDate* date = [calendar dateFromComponents:comp];
for (int i = 0; i < 7; i++) {
NSDate* d = [date dateByAddingTimeInterval:((3600 * 24) * i)];
NSDateComponents* dComponents = [calendar components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:d];
int day = [dComponents day];
NSLog(#"\nDate: %#\nDay: %i", [d description], day);
}
This is my output:
Date: 2011-11-02 06:00:00 +0000
Day: 2
Date: 2011-11-03 06:00:00 +0000
Day: 3
Date: 2011-11-04 06:00:00 +0000
Day: 4
Date: 2011-11-05 06:00:00 +0000
Day: 5
Date: 2011-11-06 06:00:00 +0000
Day: 6
Date: 2011-11-07 06:00:00 +0000
Day: 6
Date: 2011-11-08 06:00:00 +0000
Day: 7
Thanks!
Welcome to the wonderful world of date calculations!
#Vladimir is correct. November 6th happens to have ~90,000 seconds in it because that's the day (in the US on the Gregorian calendar) that Daylight Savings Time takes effect. Accept his answer; it's the right one.
This one is to educate you a bit more, because this is a hard topic.
An NSDate represents an absolute point in time. This point is immutable. It will exist regardless of whether humans and their time measurements exist.
A "day" is a relative value. It is relative to many things, such as:
The planet earth. A martian day is not the same thing as an earth day
The calendar of the person doing the calculation. Not all calendars measure time in the same way.
Thus, it is impossible to take a relative value and add it to an absolute value without more context. You have no idea what the relative value is relative to. You make the assumption that everyone is using the same point of reference as you, and that assumption is wrong. For example:
The current year is 2011. But is it? "2011" is relative to the Gregorian calendar. What if you're not using the Gregorian calendar?
The current year is 23. But that's only if you're using the Japanese calendar and specifically using the Japanese era names.
The current year is 5771. But that's only if you're using the Hebrew calendar. And the turnover for the next year (5772) is not the same turnover as the next Gregorian year.
The current year is (probably) 1432. If you're a Muslim.
The current year is 4344, if you're Korean.
And so on and so on.
As a general rule, most calendars are solar based, meaning that one orbit around the sun is equivalent to one "year" in that calendar. But this makes things REALLY complicated, because the number of rotations the Earth makes (a "day") in its orbit around the Sun is not an integral (whole) number. It's something like 365.24 rotations. Enter leap days! But only in certain calendars! In other calendars, we have whole leap months! Or leap seconds. Or leap hours. Or leap-whatever-time-unit-you-wants. And don't even get me started on time zones.
So, how do you deal with this?
The simple answer: YOU DON'T. People much smarter than you or I have already written the code to handle all of this for us.
BEHOLD:
NSCalendar
NSDateComponents
An NSCalendar encapsulates all of the rules and regulations for calculating time (on Earth) according to that system of measurement. NSDateComponents encapsulates the relative nature of measuring time.
So you have an absolute point in time (an NSDate), and you want to know what day of the week it corresponds to. Here's what you do:
Get the appropriate calendar object. For almost everything you'll ever do, this is probably [NSCalendar currentCalendar].
Using the calendar, you say "i want such-and-such 'date components' from this absolute point in time"
The calendar's going to churn and burn and give you back an NSDateComponents that signify whatever information you're looking for.
Or let's say you have an absolute point in time and you want to know "what's the absolute point in time 1 week later?". Who knows how long a week is? I don't. It's usually 7 days, but it doesn't have to be. That's just what I'm familiar with. But I'm sure there are calendars out there that are based on non-7-day weeks. So you make an NSDateComponents object, lash it up to mean "1 week", and say "calendar: I have this date and this relative amount. Add them and tell me the new date" and it does that.
<update>
However, adding date components to dates can also be problematic. For example, what if you want to find the last day of every month this year? (We'll assume the Gregorian calendar here) So you start with an NSDate that happens to fall on Jan 31 and you add "1 month" to it. What do you get? Feb 28! So then you add one month to that. What do you get? Mar 28! That's not the end of the month anymore!
The way to fix that is to always compute the new date from the original date. So instead of adding 1 month to each successive date, you add "n" months to the original date. And that will work correctly.
</update>
You can see how this is a difficult topic. In case you haven't, here's one last hint:
THIS IS A DIFFICULT TOPIC
The sooner you learn to do things correctly, the happier you and your code will be. :)
November, 6 is a day when time changed due to the Day Saving Time so that day actually lasts 25 hours and incorrect result is probably comes from that (in general adding time intervals to a date is unreliable because of calendar irregularities and bahaviour may depend on many parameters: current calendar, time zone, locale settings etc).
The more correct way to iterate through days (per wwdc11 video "Performing Calendar Calculations"(iTunes link)) is to add appropriate number of date components to a starting date on each iteration:
...
NSDateComponents *addComponents = [[NSDateComponents alloc] init];
for (int i = 0; i < 7; i++) {
[addComponents setDay: i];
NSDate* d = [calendar dateByAddingComponents:addComponents toDate:date options:0];
NSDateComponents* dComponents = [calendar components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:d];
int day = [dComponents day];
NSLog(#"\nDate: %#\nDay: %i", [d description], day);
}
I am creating a calendar based app.
I have two dates say present date, and future date(due date), now i need to show the difference between these two dates in terms of days, hours, minutes & seconds and i want to show a timer which will continues to decrement second by second as the time increases and ultimately reaches to zero when due date comes.Basically it will be showing that how much days, hrs and seconds are left for the event.
How can I do that, please help me.
It would be a great help if i can get a similar kind of sample code.
Many Thanks in advance.
iPhone Developer
Maybe It can be helpful to you - http://blog.webscale.co.in/?p=244
Basically you want to use NSTimeInterval and NSDate to calculate the difference in time. For example:
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"MM/dd/yyyy"];
NSDate *now = [NSDate date];
NSDate *futureDate = [dateFormat dateFromString:#"07/15/2015"];
// Now we can calculate the time interval, which really is an integer
// This is the number of seconds between the 2 dates, so with math you can calculate
// what you need. Remember, when you do dateFromString, the time is midnight 00:00:00
// however, *now is set to the current time. You may want to work on that a bit
NSTimeInterval timeDifference = [futureDate timeIntervalSinceDate:now];
// Also note, if you swap the order and do now timeIntervalSinceDate:futureDate, you
// get a negative number.
I need to set a NSDate to a specific date, time and timezone for an iPhone App.
The example code below works fine on iOS 4 as the setTimeZone was introduced with iOS 4. How could I easily set a NSDate to a date, time and timezone without using setTimeZone so it can be used on iOS 3.0 devices?
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setYear:2010];
[comps setMonth:8];
[comps setDay:24];
[comps setHour:17];
[comps setMinute:5];
[comps setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"UTC"] ];
NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *referenceTime = [cal dateFromComponents:comps];
Guess this should be simple, but somehow NSDate, components and calendars and I are not good friends...
I wonder if you could set the time zone on the NSCalendar object that you use to create the NSDate from the NSDateComponents. I haven't tried this and don't know if it'll work, but it's probably worth a try.
NDates have no concept of time zones in and of themselves. They're basically seconds since a certain arbitrary date at GMT. As such, you can't give them a time zone. If time zone is important, you'll need to track both the time and the time zone.