NSDateFormatter subtraction - iphone

I have a datepicker for the field "From" and "To" and I want the result of the subtraction.
for example: toValue-fromValue and the result would be in hours.
How to do that?

The difference of the two NSdate objects can be calculated using timeIntervalSinceDate:
NSTimeInterval diff = [toDate timeIntervalSinceDate:fromDate];
The result is given in seconds. Then, you calculate the hours like this:
NSInteger hours = diff / 3600;

If you have two NSDate objects you can compare them using the timeIntervalSinceDate method
NSDate* fromDate = //Get from date picker
NSDate* toDate = //Get from date picker
NSTimeInterval = [fromDate timeIntervalSinceDate:toDate];
NSInteger hours = timeInterval / 60*60; //60 seconds per minute, 60 minutes per hour

Related

Days between two dates and store in variable

How can i store the calculated days between two dates in a variable so i can store the "days" in CloudKit
My code are (working to calculate days between dates):
let calendar = NSCalendar.currentCalendar()
let components = calendar.components([.Day], fromDate: datepicked, toDate: enddate, options: [])
print("DAYS LEFT :" , components)
Result are :
DAYS LEFT : <NSDateComponents: 0x7fd399ccb890>
Day: 1095
⌥-click on the variable components and then on NSDateComponents in the popup view.
In the documentation you can see that there is a property day to get the value of the .Day component.
var day: Int
So simply write
let day = components.day
I here have a piece of code which calculates the hours between two times in Objective-C. I'm sure you can rewrite this to make it days.
- (void)updateTimer {
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"dd-MM-yyyy HH:mm:ss"];
/* instead of conceptDate the date of the started and stopped time will be used when the database is edited so
date is nog a seperate column but is included in the colums start and stop to display working times that exceed
the 00.00 timestamp or take multiple days (for somewhat reason)*/
NSDate *date1 = [df dateFromString:[NSString stringWithFormat:#"%# %#", [self conceptDate], startedTime]];
NSDate *date2 = [df dateFromString:[NSString stringWithFormat:#"%# %#", [self conceptDate], [self getCurrentTime]]];
NSTimeInterval interval = [date2 timeIntervalSinceDate:date1];
if( interval < 0 ) {
interval = [date1 timeIntervalSinceDate:date2];
}
int hours = (int)interval / 3600; // integer division to get the hours part
int minutes = (interval - (hours*3600)) / 60; // interval minus hours part (in seconds) divided by 60 yields minutes
int seconds = (interval - (hours*3600) - (minutes*60)); // interval minus hours part (in seconds) divided by 60 yields minutes
NSString *timeDiff = [NSString stringWithFormat:#"%02d:%02d:%02d", hours, minutes, seconds];
_workingTime.text = [NSString stringWithFormat:#"%#",timeDiff];
}
I hope this helps. Currently the time difference is stored in _workingTime object but can of course be stored in another string variable.
If you want to get days between two days then you should try this.
func daysFrom(FromDate:NSDate,ToDate:NSDate) -> Int{
return NSCalendar.currentCalendar().components(NSCalendarUnit.Calendar.exclusiveOr(NSCalendarUnit.Day), fromDate: date, toDate: ToDate, options: NSCalendarOptions.WrapComponents).day
}
Swift 4
func days(from:Date,to:Date) -> Int {
return Calendar.current.dateComponents([.day], from: from, to: to).day!
}

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

Xcode - NSTimeInterval Years double value, how to get MORE decimals?

i wan't to know exactly how many years it is between 2 NSDate's. (current Date and Date picker date)
i'm using NSTimeInterval (seconds) how to make it to years?
This code will make the value to Years:
NSTimeInterval distanceBetweenDates = [now timeIntervalSinceDate:date];
double secondsInAnYear = 31536000;
double YearsBetweenDates = distanceBetweenDates / secondsInAnYear;
NSString *dateString = [NSString stringWithFormat:#"%f", YearsBetweenDates];
labelView.text = dateString;
but i just get 6 decimals!
i want more than 6 decimals. How?
Take a look at -[NSCalendar (NSDateComponents *)components:(NSUInteger)unitFlags fromDate:(NSDate *)startingDate toDate:(NSDate *)resultDate options:(NSUInteger)opts]. This does the calculation correctly. You can't assume a year always is exactly 31536000 seconds (leap year, or even those leap second(s) that get added occasionally).
Have you tried using %lf which is the designated specifier for long float/double values?
NSString *dateString = [NSString stringWithFormat:#"%lf", YearsBetweenDate];

NSTimeInterval 15mins before

I have one variable startDate which is in NSTimeInterval.
How can I get NSTimeInterval just 15mins before to actual startDate ?
NSTimeInterval reqStartDate = startDate - (15*60);

UIDatePicker: time mode: initialize the time (gotta be simple)

All,
This seems like such a simple thing, but I cannot find* the right method to create a UIDatePicker, in time mode, and have it initialized to a specific time. I don't want date -- just time (think alarm clock). I have created a NSDate object:
NSDate * date = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate: (NSTimeInterval) delta];
pickerView = [[UIDatePicker alloc] init]; // which should be 'now' right?
pickerView.datePickerMode = UIDatePickerModeTime; // which creates just the clock
[pickerView setDate:date];
and in the first line, the interval (delta) is zero. It displays 7:00PM.
This has gotta be so simple that I'm missing it, but I can't find the right way -- anyone?
Thank you in advance!
:bp:
*yes, I have looked, but apparently not in the correct places :(
Take the time zone into account. You will get 0AM only if you are at UTC.
Thank you dkk -- I appreciate your help. The real answer was to not use a DatePicker, but to use a PickerView (w/o the date). That made things simpler and do-able.
Thanks again.
NSDate *date = [NSDate date];
date = [[NSCalendar autoupdatingCurrentCalendar] dateFromComponents:[[NSCalendar autoupdatingCurrentCalendar] components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:date]];
date = [date dateByAddingTimeInterval:60 * 60 * 21];
pickerView.date = date;
The steps here with the date are
initialise date with the current date
get the date at midnight
add a time interval to the date (60 seconds * 60 minutes * hour). In this case 21 = 9pm
This works for UIDatePicker with datePickerMode of UIDatePickerModeTime & UIDatePickerModeCountDownTimer