I have a current NSString in the format of 2010-04-23 00:00:00 and then I'm trying to get the number of days passed from the current day. However, I'm not sure how to handle when the user changes their locale to Thailand for example.
Here is some of the code.
NSString *start = #"2010-04-23 00:00:00";
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
NSDate *date = [formatter dateFromString:start];
//Region Format Thailand
NSDate *today = [[NSDate alloc] init];
NSTimeInterval difference = [today timeIntervalSinceDate:start];
int numberOfDays = difference / 86400;
What would be the correct way to handle this situation so the number of days difference is accurate?
Dates are complicated.
If you want a difference in days, hours, minutes, seconds, that's easy: Convert everything to NSDate, calculate the difference in seconds, convert to days, hours, minutes, seconds.
Anything else, you need to first define what results you actually want. Today at 1am and 11pm is the same day, but today 11pm and tomorrow 1am are different days - even though in the first case the difference is 22 hours, in the second case just two hours. So you have to define what you want. You have to define for which case you want a result of "0 days" and for which case you want a result of "1 days".
And if you change time zones, some dates will move to a different day, some won't.
It's up to you to decide what result you want. In any case, I'd convert all dates to the relevant time zone, extract the day, and calculate days differences from that.
You need to convert the date into epoch time.
- (NSTimeInterval)timeIntervalSince1970
After you do that you can use the below code, to find the time difference in seconds and compare them.
NSDate* date1 = [NSDate date];
NSDate* date2 = [NSDate date];
NSTimeInterval secs = [date1 timeIntervalSinceDate:date2];
if (secs < 0)
{
NSLog("less");
}
else if (secs > 0)
{
NSLog("greater");
}
else
{
NSLog(#"same");
return NSOrderedSame;
}
Related
There is a object called Place. user can add place to favorite and also user can remove place from the favorite. once user added to the favorite I save date on the database. when user remove from the favorite I retrieve date from the db. and compare particular object with array of objects. but it gives NSOrderedAscending when comparing same object.
NSDate *date1 = obj1.date; // same date
NSDate *date2 = obj2.date; // same date
// compare using date
NSComparisonResult result = [date2 compare:date1];
any help would be appreciate. Thanks.
Try do this:
-(NSDate *)clearSecondsFromDate:(NSDate *)date
{
NSTimeInterval timeInterval = [date timeIntervalSinceReferenceDate];
timeInterval -= fmod(timeInterval, 60);
NSDate *clearDate = [NSDate dateWithTimeIntervalSinceReferenceDate:: timeInterval];
return clearDate;
}
If you want to compare two dates are equivalent to the same second, then get the number of seconds since some epoch and round off the fractional part:
BOOL same = round([date1 timeIntervalSince1970]) ==
round([date2 timeIntervalSince1970]);
Or convert to an integer:
BOOL same = (unsigned long)[date1 timeIntervalSince1970] ==
(unsigned long)[date2 timeIntervalSince1970];
(you can also use [NSDate timeIntervalSinceReferenceDate] if you like, as well).
NSDate doesn't just contain day and seconds, it has a resolution better than microseconds. Your NSDates are probably some fraction of a second apart. Try to log [date1 timeIntervalSinceDate:date2].
So most likely your dates are just not the same. If you are sorting dates, and you want to have dates within the same second considered equal, take
double seconds1 = round ([date1 timeIntervalSinceReferenceDate]);
double seconds2 = round ([date2 timeIntervalSinceReferenceDate]);
which takes the time in a date and rounds it to the nearest second, and compare those values.
This question already has answers here:
how to split strings in objective c
(4 answers)
Closed 8 years ago.
NOTE: I have used the share knowledge feature to answer this question as a whole and not simply one question which is commonly asked - "Splitting strings"
2 questions I have come across but never together are:
How do I split Strings? (I acknowledge this question alone has been answered a few times)
How do I calculate the difference between 2 times as strings and display in time format (00:00:00)?
The purpose of this question is to help people who are storing times are strings in core data to be able to calculate the difference between the two. I used the "share knowledge" feature to answer this question and have not simply answered. Please see below.
Since you're coming from strings, you'll need to change them to NSDate objects. You'll use a formatter to do so.
NSDateFormatter *df = [[NSDateFormatter alloc]init];
[df setDateFormat:#"HH:mm:ss"];
// I don't know what date format you're coming from, you should of course use yours. check out the doc for more info.
NSDate *date1 = [dateFormat dateFromString:string1];
NSDate *date2 = [dateFormat dateFromString:string2];
Now you have date objects that are coming from your strings.
If you want to know the time between time dates (in seconds or other)
(from this post)
NSTimeInterval distanceBetweenDates = [date1 timeIntervalSinceDate:date2];
double secondsInAnHour = 3600;
NSInteger hoursBetweenDates = distanceBetweenDates / secondsInAnHour;
NSTimeInterval gives you the difference in seconds, you can just calculate from there if you want hours, days, etc.
But sometimes, you might only need to know if a date is before or after another. Then you should use date compare, which returns a NSOrderingDesc or Asc or Same , like this:
//Then the comparison will tell which is earlier/later/same:
if ([date1 compare:date2] == NSOrderedDescending) {
NSLog(#"date1 is later than date2");
} else if ([date1 compare:date2] == NSOrderedAscending) {
NSLog(#"date1 is earlier than date2");
} else {
NSLog(#"dates are the same");
}
First we establish the format of the date like so. I am using HH:MM:SS format. Format yours to suit your saved string.
NSDateFormatter *dateFormat = [[NSDateFormatter alloc]init];
[dateFormat setDateFormat:#"HH:mm:ss"];
The second part is referencing your strings. I create a new reference just to keep it tidy when converting String Date to NSDate. In my example I have declared a reference to Core Data in my .h file so I reference as follows.
NSString * StringTime1 = self.coreDataReference.time1;
NSString * StringTime2 = self.coreDataReference.time2;
Convert the strings to date:
NSDate *time1 = [dateFormat dateFromString:StringTime1];
NSDate *time2 = [dateFormat dateFromString:StringTime2];
I next get the difference by getting the time interval between the times. I am comparing the latest saved time (time2) against the first save time (time1). This method essentially subtracts whatever time is allocated second from the first, which in this case tim2 subtracts time1. You will see why in a moment.
NSTimeInterval distanceBetweenDates = [time2 timeIntervalSinceDate:time1];
For displaying purposes, I convert the time which is now a double (NSTimeInterval is a double, check https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_DataTypes/Reference/reference.html for more information) and then convert them into hours, minutes and second values.
int timeInt = (int) distanceBetweenDates;
//I convert the values into the time value
int hours = timeInt / 3600;
int minutes = (timeInt / 60) % 60;
int seconds = timeInt % 60;
FInally we display the results in log and if you have a label display there as well.
NSLog(#"The total time is: %02u:%02u:%02u", hours, minutes, seconds);
NSString * time = [NSString stringWithFormat:#"%02u:%02u:%02u", hours, minutes, seconds];
self.totalLoginTimeLabel.text = time;
I hope this helps anyone investigating.
The whole code here:
-(void) calculateTimeIntervalFromStrings{
NSDateFormatter *dateFormat = [[NSDateFormatter alloc]init];
[dateFormat setDateFormat:#"HH:mm:ss"];
NSString * StringTime1 = self.coreDataReference.time1;
NSString * StringTime2 = self.coreDataReference.time2;
NSDate *time1 = [dateFormat dateFromString:StringTime1];
NSDate *time2 = [dateFormat dateFromString:StringTime2];
NSTimeInterval distanceBetweenDates = [time2 timeIntervalSinceDate:time1];
int timeInt = (int) distanceBetweenDates;
//I convert the values into the time value
int hours = timeInt / 3600;
int minutes = (timeInt / 60) % 60;
int seconds = timeInt % 60;
NSLog(#"The total time is: %02u:%02u:%02u", hours, minutes, seconds);
NSString * time = [NSString stringWithFormat:#"%02u:%02u:%02u", hours, minutes, seconds];
self.timeDifferenceLabel.text = time;
}
To call this method, place in your viewDidLoad method like so:
[self calculateTimeIntervalFromStrings];
I am trying to implement some pseudo code I have for the date picker. However I am unsure of how to add a minute value to adjust an NSDate object.
Here is the pseudo code:
//minTime is an NSDate object
minTime = currentTime + 30mins - (currentTime % 15)
(currentTime % 15) means that the user can only select in 15mins intervals, and must be 15mins from the current 15min interval. For example, if its 10:50, the user should only be able to select 11:15 from the UIDatePicker. If is 10:20, the user should only be able to select 10:45.
I know how to get the currentTime using [NSDate date] but I do not know how to add mins to it and adjust it.
It is not considered good practice to work with time intervals when working with dates and times. The best solution is to use NSDateComponents to add time periods.
NSDateComponents* dc = [NSDateComponents new];
dc.minutes = 15;
NSDate* newDate = [[NSCalendar currentCalendar] dateByAddingComponents:dc toDate:oldDate options:0];
You can add some minutes to a NSDate using :
NSDate *nowDate = [NSDate date];
NSDate *nowDateAnd2moreMinutes = [nowDate dateByAddingTimeInterval:2*60]; //This add 2 minutes (2 * 60sec)
More information in apple documentation.
Edit I wrote a little function that add minutes :
+(NSDate) addMinutes:(int) minutes toDate:(NSDate) date{
return [date dateByAddingTimeInterval:minutes*60];
}
Bonus : Function that add minutes and seconds to a date
+(NSDate) addMinutes:(int) minutes andSeconds:(int) sec toDate:(NSDate) date{
return [date dateByAddingTimeInterval:(minutes*60)+sec];
}
I have a UIDatePicker mm/dd/yy. It works fine, but there is one problem: I set minimum and maximum date to it, and when user tries to choose the forbidden day, month or year, the [datePicker date] property begins working wrong. It returns you the current day - 1 or current month - 1 or current year - 1. I added some pictures, so you can see the situation.
This is correct
This is wrong (After choosing the forbidden date)
Does somebody know, how can I fix this ? Thanks !
UPD:
Code
[self.myDatePicker setMinimumDate:[NSDate date]];
[self.myDatePicker setMaximumDate:[[NSDate date] addTimeInterval:2 * 365.25 * 24 * 60 * 60]]; // to get upto 5 years
NSDate * now = [[NSDate alloc] init];
[self.myDatePicker setDate: now animated: YES];
self.myDatePicker.timeZone = [NSTimeZone localTimeZone];
self.myDatePicker.calendar = [NSCalendar currentCalendar];
Just add one line of code for setting your timezone.
self.datePicker.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
0 is for GMT 00 . Add according to your time zone.
My solution was to set the returned date to 12:00 AM as NSDates work in UTC
NSDate * adjustedDate = [[NSCalendar currentCalendar] dateBySettingHour:12 minute:0 second:0 ofDate:sender.date options:0];
Also for date calculations you shoud use NSCalender methods and not addTimeInterval
It is deffinately something with the timezones and/or Daylight Saving Times. But it must be very subtle, as the code looks fine (beside the interval). Now to my question about if you are in russia:
This year the Kremlin did several back and forth swings on keeping daylight saving times forever. Actually I am not sure, what they decided at last. But maybe it isnt reflected correctly in Cocoa. The the video WWDC 2011 Video "Session 117 - Performing Calendar Calculations" , the presenter even mentions that things like that can happen.
Please try to work with dates with manually set times to noon, as this would keep you out of such mess.
The world just saw a similar misbehavior in iOS 6: the DND-Always-Active bug. I bet this was for a wrong date format (YYYY instead of yyyy)
Also try to set the timezone property on the picker at the very first thing and assign a manually instantiated Gregorian calendar to it.
Check if you use the wrong formatting symbols with big letters: "YYYY".
Replace them with "yyyy".
I ran into the same trouble and this is what i derived:
Don't use [date description] to check NSDate if you want correct representation for your system. Use NSDateFormatter, because it shows date based on your system preferences (in simulator it will be simulators preferences).
For example:
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateStyle:NSDateFormatterShortStyle];
[df setTimeStyle:NSDateFormatterNoStyle];
NSLog(#"date for locale is %#", [df stringFromDate:date]);
Try this,
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
formatter.string(from: yourPicker.date)
Might be due to TimeZone...
Set your time zone.
For me this problem is resolved by adding this line
datePicker.date.addingTimeInterval(TimeInterval(TimeZone.current.secondsFromGMT()))
This line adds up the seconds in dateTime of UIDatePicker and dateTime will be equal to current dateTime
Boolean futureevent;
- (void)viewDidLoad
{
futureevent = false;
}
int intervall = (int) [currentdate timeIntervalSinceDate: datePicker.date] / 60;
if (intervall < 1200 && intervall > 0)
{
futureevent = true;
NSDate *newDate1 = [datePicker.date dateByAddingTimeInterval:60*60*24*1];
birthdate = [newDate1.description substringToIndex:spaceRange.location];
}
else
{
if (futureevent)
{
NSDate *newDate1 = [datePicker.date dateByAddingTimeInterval:60*60*24*1];
birthdate = [newDate1.description substringToIndex:spaceRange.location];
}
else
{
birthdate = [datePicker.date.description substringToIndex:spaceRange.location];
}
}
It does not return wrong date. What actually happens is, when you select a so called forbidden date, the date picker gets reset to maximum or minimum allowed date with first moment of the day i.e 12:00AM.
So if you are at a place where time zone is for example, 2 hours ahead of GMT, the date returned by date picker will be yesterday's 10:00PM GMT. So here, you might think it is returning yesterday's date but if you convert it to your time zone, you will get today's date only but time component will be 12:00AM.
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.