Get time difference between two times in swift 3 - swift3

I have 2 variables where I get 2 times from datePicker and I need to save on a variable the difference between them.
let timeFormatter = DateFormatter()
timeFormatter.dateFormat = "HHmm"
time2 = timeFormatter.date(from: timeFormatter.string(from: datePicker.date))!
I have tried to get the timeIntervalSince1970 from both of them and them substract them and get the difference on milliseconds which I will turn back to hours and minutes, but I get a very big number which doesn't corresponds to the actual time.
let dateTest = time2.timeIntervalSince1970 - time1.timeIntervalSince1970
Then I have tried using time2.timeIntervalSince(date: time1), but again the result milliseconds are much much more than the actual time.
How I can get the correct time difference between 2 times and have the result as hours and minutes in format "0823" for 8 hours and 23 minutes?

The recommended way to do any date math is Calendar and DateComponents
let difference = Calendar.current.dateComponents([.hour, .minute], from: time1, to: time2)
let formattedString = String(format: "%02ld%02ld", difference.hour!, difference.minute!)
print(formattedString)
The format %02ld adds the padding zero.
If you need a standard format with a colon between hours and minutes DateComponentsFormatter() could be a more convenient way
let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.hour, .minute]
print(formatter.string(from: time1, to: time2)!)

TimeInterval measures seconds, not milliseconds:
let date1 = Date()
let date2 = Date(timeIntervalSinceNow: 12600) // 3:30
let diff = Int(date2.timeIntervalSince1970 - date1.timeIntervalSince1970)
let hours = diff / 3600
let minutes = (diff - hours * 3600) / 60

To get duration in seconds between two time intervals, this can be used -
let time1 = Date(timeIntervalSince1970: startTime)
let time2 = Date(timeIntervalSince1970: endTime)
let difference = Calendar.current.dateComponents([.second], from: time1, to: time2)
let duration = difference.second

Now you can do it in swift 5 this way,
func getDateDiff(start: Date, end: Date) -> Int {
let calendar = Calendar.current
let dateComponents = calendar.dateComponents([Calendar.Component.second], from: start, to: end)
let seconds = dateComponents.second
return Int(seconds!)
}

Related

Postgresql - Looping based on timestamp

i am working on a scenario where need to run a particular code block for 5 mins.
I tried various options but no luck till now.
Could you please guide me.
Attaching the half-baked block:
DO
$do$
DECLARE
i int;
startTime TIMESTAMP;
endTime TIMESTAMP;
BEGIN
i := 1;
startTime := now();
endTime := now() + (1 * interval '5 minute');
RAISE NOTICE 'City Name:(%)(%)',statement_timestamp(),now() + (1 * interval '5 minute');
WHILE statement_timestamp() < endTime LOOP
RAISE NOTICE 'City Name:(%)(%)(%)',endTime,now(), statement_timestamp();
-- example:
--create table if not exists test12345(id int,start_dt TIMESTAMP,end_dt TIMESTAMP);
insert into test12345
select i,startTime,endTime;
--RAISE NOTICE startTime;
RAISE NOTICE 'City Name:(%)', statement_timestamp();
--startTime := statement_timestamp();
END LOOP;
END;
$do$;
thanks in advance.

Adding seconds to time variable

*data final;
set final;
duration = redate-ondate;
dudays = floor(duration/86400);
duhrs = floor((duration-(dudays*86400))/3600);
dumins = floor((duration-(dudays*86400+duhrs*3600))/60);
****************Set up new variable duration**************;
attrib dur length=$11.;
if ae_term ne 'None' and dudays ne . then
dur = left(put(dudays,z2.))||':'||left(put(duhrs,z2.))||':'||left(put(dumins,z2.));
else dur = '';
run;*
I have this code but need to calculate seconds and concatenate to dur as I have an adverse event that is less than a minute so won't display. What's the most efficient way to do this?
You can calculate the remaining seconds and then append to your time string like this:
dusec = duration-(dudays*86400+duhrs*3600+dumins*60);
if ae_term ne 'None' and dudays ne . then
dur = left(put(dudays,z2.))||':'||left(put(duhrs,z2.))||':'||left(put(dumins,z2.)||':'||left(put(dusec,z2.)));
One note - using put(dudays,z2.) assumes your duration is never more than 99 days.
Ok, this should simplify things somewhat:
dudays = FLOOR(duration/86400);
duhrs = FLOOR(MOD(duration,86400)/3600);
dumins = FLOOR(MOD(duration,3600)/60);
dusec = MOD(duration,60);
The difference between two datetime values is a number of seconds (so it is also a datetime value). You can use the DATEPART() and TIMEPART() function to divide into the number of days and seconds since midnight. The TOD11.2 format will display seconds in HH:MM:SS.mm style.
length dur $20;
if n(redate,ondate)=2 and ae_term not in (' ','None') then do;
duration = redate-ondate;
dur = catx(':',datepart(duration),put(timepart(duration),tod11.2));
end;

How to remove weekdays in duration data type NAV

How can i remove weekdays in the data type duration in CAL ?
for example:
duration := datetime2 - datetime1
But duration do contains Saturdays and Sundays. How can i remove them ?
Simple answer: you can not.
But you can use the Date virtual table. Something like this:
Date.SETRANGE("Period Type", Date."Period Type"::Date);
Date.SETFILTER("Period Start", '%1..%2', DT2DATE(datetime1), DT2DATE(datetime2));
Date.SETRANGE("Period No.", 1, 5); // only days 1 - 5 = weekdays
EXIT(Date.COUNT); // returns number of days
You can then convert the number of days to a duration with a simple multiplication. A Duration is nothing more than the number of milliseconds.
1 hour = 3600000ms.
Therefore:
MESSAGE('%1', NoOfDays);
dur := NoOfDays * 24 * 3600 * 1000;
MESSAGE('%1', dur);

Adding minutes by literals

ho could I manipulate some Int adding them as minutes and sum them? the result should be in hours and minutes just like 1:15 or 6:30.
My playground gives 1.25 but I expected 1.15
struct standardDayOfWork {
var dailyHours : Double = 0
}
var dayToUse = standardDayOfWork()
enum hourFractions : Double {
case quarter = 15
case half = 30
case threeQuarter = 45
case hour = 60
}
dayToUse.dailyHours += hourFractions.half.rawValue
dayToUse.dailyHours += hourFractions.half.rawValue
dayToUse.dailyHours += hourFractions.quarter.rawValue
var total = dayToUse.dailyHours / 60 //1.25
Because in the decimal system a quarter is 0.25.
To get numeric 1.15 you could use this weird expression:
var total = Double(Int(dayToUse.dailyHours) / 60) + (dayToUse.dailyHours.truncatingRemainder(dividingBy: 60) / 100.0)
Or if you can live with a formatted "hh:mm" string I'd recommend
let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.hour, .minute]
formatter.string(from: dayToUse.dailyHours * 60)

Making Date With Given Numbers

I have the following Swift (Swift 3) function to make a date (Date) with date components (DateComponents).
func makeDate(year: Int, month: Int, day: Int, hr: Int, min: Int, sec: Int) -> NSDate {
let calendar = NSCalendar(calendarIdentifier: .gregorian)!
let components = NSDateComponents()
components.year = year
components.month = month
components.day = day
components.hour = hr
components.minute = min
components.second = sec
let date = calendar.date(from: components as DateComponents)
return date! as NSDate
}
If I use it, it will return a GMT date.
override func viewDidLoad() {
super.viewDidLoad()
let d = makeDate(year: 2017, month: 1, day: 8, hr: 22, min: 16, sec: 50)
print(d) // 2017-01-08 13:16:50 +0000
}
What I actually want to return is a date (2017-01-08 22:16:50) literally based on those numbers. How can I do that with DateComponents? Thanks.
The function does return the proper date. It's the print function which displays the date in UTC.
By the way, the native Swift 3 version of your function is
func makeDate(year: Int, month: Int, day: Int, hr: Int, min: Int, sec: Int) -> Date {
var calendar = Calendar(identifier: .gregorian)
// calendar.timeZone = TimeZone(secondsFromGMT: 0)!
let components = DateComponents(year: year, month: month, day: day, hour: hr, minute: min, second: sec)
return calendar.date(from: components)!
}
But if you really want to have UTC date, uncomment the line to set the time zone.
NSDate doesn't know anything about time zones. It represents a point in time independent of any calendars or time zones. Only when printing it out like you did here it is converted to GMT. That's OK though - this is only meant for debugging. For real output use a NSDateFormatter to convert the date to a string.
As a hacky solution you might of course just configure your calendar to use GMT when creating your date object from your components. That way you will get the string you expect. Of course any other calculation with that date then might end up wrong.