Difference between two date time stamp in Intersystems Cache - intersystems-cache

I would like to find out the number of hours and minutes between two date time stamp.
if for example
sDateTime = 2016-01-01 01:00
eDateTime = 2016-01-03 02:30
I would like it to output it as 49:30 (49hours and 30minutes)
I am unable to figure a method to work this out.
what I have so far:
Set oMNOF=##class(MNOF.MNOF).%OpenId(Id)
Set zstartDt=oMNOF.sDateTime
Set startDt=$PIECE(zstartDt,",",1)
Set startTime=$PIECE(zstartDt,",",2)
Set zendDt=oMNOF.eDateTime
Set endDt=$PIECE(zendDt,",",1)
Set endTime=$PIECE(zendDt,",",2)
set dateDiff=((endDt - startDt)) //2 days
set timeDiff=(endTime - startTime) //outputs 5400 seconds
set d = (dateDiff * 24 * 60 * 60)
set h = ((timeDiff - d) / 60)
set m = timeDiff - (d) - (h * 60)
Thank you for the help.

Another option:
USER>set mm=$system.SQL.DATEDIFF("mi","2016-01-02 01:00","2016-01-03 02:30")
USER>write "hours=", mm \ 60
hours=25
USER>write "minutes=", mm # 60
minutes=30

Hi thanks to all for the help.
I managed to come up with the below, appreciate if someone can improve on this.
<script language="cache" method="MGetData" arguments="pStartDt:%String,pEndDt:%String,pTimeField:%String" returntype="%Library.String">
set val1="00"
//HOUR: check if length equals 1
if $LENGTH($SYSTEM.SQL.FLOOR($system.SQL.DATEDIFF("ss",pStartDt,pEndDt)/3600))=1{
//add leading zero
set val1 ="0"_$SYSTEM.SQL.FLOOR($system.SQL.DATEDIFF("ss",pStartDt,pEndDt)/3600)
}
else{
//get without leading zero
set val1 = $SYSTEM.SQL.FLOOR($system.SQL.DATEDIFF("ss",pStartDt,pEndDt)/3600)
}
//MINUTES: check if length equals 1
if $LENGTH($SYSTEM.SQL.FLOOR($system.SQL.DATEDIFF("ss",pStartDt,pEndDt)/60) - ($SYSTEM.SQL.FLOOR($system.SQL.DATEDIFF("ss",pStartDt,pEndDt)/3600)*60))=1{
//add leading zero
set val2 ="0"_($SYSTEM.SQL.FLOOR($system.SQL.DATEDIFF("ss",pStartDt,pEndDt)/60) - ($SYSTEM.SQL.FLOOR($system.SQL.DATEDIFF("ss",pStartDt,pEndDt)/3600)*60))
}
else{
//get without leading zero
set val2 = ($SYSTEM.SQL.FLOOR($system.SQL.DATEDIFF("ss",pStartDt,pEndDt)/60) - ($SYSTEM.SQL.FLOOR($system.SQL.DATEDIFF("ss",pStartDt,pEndDt)/3600)*60))
}
//insert result data into the time field
Write "document.getElementById('"_pTimeField_"').value='"_val1_":"_val2_"';"
//Write "alert('"_val1_"^"_val2_"');"
QUIT 1

Related

How do i format time into seconds in lua?

So basically I'm confused on how I'd make it so that I can convert DD:HH:MM:SS to only seconds while taking into account the amount of numbers there are. (Sorry if I make 0 sense, you should definitely know what I mean by the example below.)
print("05:00":FormatToSeconds()) -- 5 minutes and 0 seconds
-- 300
print("10:30:15":FormatToSeconds()) -- 10 hours, 30 minutes and 15 seconds
-- 37815
print("1:00:00:00":FormatToSeconds()) -- 1 day
-- 86400
print("10:00:00:30":FormatToSeconds()) -- 10 days, 30 seconds
-- 864030
So on and so forth. I think that maybe using gmatch would work but still idk. Help would be greatly appreciated.
Edit:
So I've tried doing it with gmatch, but I don't know if this is the most fastest way of doing this (which it probably isn't), so any help would still be appreciated.
(My code)
function ConvertTimeToSeconds(Time)
local Thingy = {}
local TimeInSeconds = 0
for v in string.gmatch(Time, "%d+") do
if tonumber(string.sub(v, 1, 1)) == 0 then
table.insert(Thingy, tonumber(string.sub(v, 2, 2)))
else
table.insert(Thingy, tonumber(v))
end
end
if #Thingy == 1 then
TimeInSeconds = TimeInSeconds + Thingy[1]
elseif #Thingy == 2 then
TimeInSeconds = TimeInSeconds + (Thingy[1] * 60) + Thingy[2]
elseif #Thingy == 3 then
TimeInSeconds = TimeInSeconds + (Thingy[1] * 60 * 60) + (Thingy[2] * 60) + Thingy[3]
elseif #Thingy == 4 then
TimeInSeconds = TimeInSeconds + (Thingy[1] * 24 * 60 * 60) + (Thingy[2] * 60 * 60) + (Thingy[3] * 60) + Thingy[4]
end
return TimeInSeconds
end
print(ConvertTimeToSeconds("1:00:00:00"))
Don't worry about execution speed before doing any actual measurements unless you're designing a time-critical program. In any extreme situation you'd probably want to offload risky parts to a C module.
Your approach is just fine. There are parts you can clean up: you can just return the results of calculations as TimeInSeconds doesn't actually act as accumulator in your case; tonumber handles '00' just fine and it can ensure decimal integers with an argument (since 5.3).
I'd go the other way and describe factors in a table:
local Factors = {1, 60, 60 * 60, 60 * 60 * 24}
local
function ConvertTimeToSeconds(Time)
local Components = {}
for v in string.gmatch(Time, "%d+") do
table.insert(Components, 1, tonumber(v, 10))
end
if #Components > #Factors then
error("unexpected time component")
end
local TimeInSeconds = 0
for i, v in ipairs(Components) do
TimeInSeconds = TimeInSeconds + v * Factors[i]
end
return TimeInSeconds
end
Of course, both implementations have problem with pattern being naïve as it would match e.g., '00 what 10 ever 10'. To fix that, you could go another route of using string.match with e.g., '(%d+):(%d+):(%d+):(%d+)' and enforcing strict format, or matching each possible variant.
Otherwise you can go all in and use LPeg to parse the duration.
Another way would be to not use strings internally, but instead convert them into a table like {secs=10, mins=1, hours=10, days=1} and then use these tables instead - getting seconds from that representation would be straight-forward.

Best way to find time segments in a time frame

I am currently making an app where I have to retrieve allowances for certain hours worked.
For example, I work from 3:00 pm to 10:00 pm.
Between this time an allowance would be given between 8:00 pm - 10:00 pm 20% and from 10:00 pm to 11:00 pm 35%.
Until now I did not get much further than a rather complicated if construction.
if startUur <= 20 && eindUur >= 22 || 20..<22 ~= startUur || 20..<22 ~= eindUur || startUur > 20 && eindUur <= 22 && startMinuut > 0 || startUur < 20 {
//code to calculate allowance
}
I have been looking for a good and better way to do this, but I cannot find it.
Is there a better way or am I bound to such a way with an if construction?
struct TimeAndMoneyFrame {
var timeHourStart:Int = 0
var timeHourEnd:Int = 0
var percentage: Double = 0
}
extension TimeAndMoneyFrame {
func timeLength() -> Int {
return timeHourEnd - timeHourStart
}
}
let 2000to2200 = TimeAndMoneyFrame(timeHourStart = 20, timeHourEnd = 22, percentage = 0.2)
let 2200to2300 = TimeAndMoneyFrame(timeHourStart = 22, timeHourEnd = 23, percentage = 0.35)
let timeArray:[TimeAndMoneyFrame] = [2000to2200]
//Assuming 'startUur' means startingHour
//Assuming 'eindUur' means endingHour
let startUur:Int = someHour // You define some hour
let eindUure:Int = someHour // You define some hour
let hourlyRateOfPay: Double = somePay // You define some pay
var totalPay: Double = 0
for time in timeArray {
let start = time.timeHourStart
let end = time.timeHourEnd
let percent = time.percentage
//Encompasses entirely
if(start > startUur && end < eindUur) {
totalPay += (hourlyRateOfPay * (1 + percent) * time.timeLength())
}
//Only encompassed the left side - i.e., their time worked ends within this time frame
else if(start > startUur) {
let timeWithinThisFrame = eindUur - start
totalPay += (hourlyRateOfPay * (1 + percent) * (timeWithinThisFrame/time.timeLength())
}
//Only encompassed right side - i.e., the beginning of the starts within this time frame
else if(eindUur < end) {
let timeWithinThisFrame = end - startUur
totalPay += (hourlyRateOfPay * (1 + percent) * (timeWithinThisFrame/time.timeLength())
}
}
So, we can break this problemn up into a couple problems.
1) Defining a struct/class that encompasses a time frame with an associated percentage
2) The algorithm necessary to calculate the total pay
I have a base assumption.
1) You say allowances - a person gets 35% if they work from 2200-2300 - I took this as a bonus so say 1.35% of the normal hourly rate. If this is not the case, the idea of consuming time frames one at a time would be the same. The only difference might be the totalPay calculation.
My algorithm goes through each time frame and determines if the current time intercepts any of the time frames. If it does, I calculate how much it intercepts and calculate the rate of pay.
Note: I coded all of this on SO - there might be some syntax issues.

Tableau - How to calculate date/time difference and result in full date/time?

I'm trying to calculate a difference between connection time and disconnected time. See image below. But DATEPART formula that I'm using only allows me to use one parameter (hour, minute, second,...)
However, as in the image, I have an ID where disconnection at 3/1/17 2:35:22PM and connection back at 3/2/17 1:59:38 PM
Ideal Response: 23 hours, 24 minutes and 16 seconds
but using the formula:
ZN(LOOKUP(ATTR(DATEPART('minute', [Disconnected At])),-1)-(ATTR(DATEPART('minute', [Connected At]))))
it isn't doing the trick.
Could someone help me to achieve my ideal response? Or similar result that would give me the completeness of date and time?
Thank You
Tableau ScreenShot
Use DATEDIFF by seconds between your two dates. Then create a calc field as follows:
//replace [Seconds] with whatever field has the number of seconds in it
//and use a custom number format of 00:00:00:00 (drop the first 0 to get rid of leading 0's for days)
IIF([Seconds] % 60 == 60,0,[Seconds] % 60)// seconds
+ IIF(INT([Seconds]/60) %60 == 60, 0, INT([Seconds]/60) %60) * 100 //minutes
+ IIF(INT([Seconds]/3600) % 24 == 0, 0, INT([Seconds]/3600) % 24) * 10000 //hours
+ INT([Seconds]/86400) * 1000000 // days
for more information, check out this blog post where I got this from. http://drawingwithnumbers.artisart.org/formatting-time-durations/

Matlab: Converting Timestamps to Readable Format given the Reference Date-Time

I have a text file that contains timestamps out of a camera that captures 50 frames per second .. The data are as follows:
1 20931160389
2 20931180407
3 20931200603
4 20931220273
5 20931240360
.
.
50 20932139319
... and so on.
It gives also the starting time of capturing like
Date: **02.03.2012 17:57:01**
The timestamps are in microseconds not in milliseconds, and MATLAB can support only till milliseconds but its OK for me.
Now I need to know the human format of these timestamps for each row..like
1 20931160389 02.03.2012 17:57:01.045 % just an example
2 20931180407 02.03.2012 17:57:01.066
3 20931200603 02.03.2012 17:57:01.083
4 20931220273 02.03.2012 17:57:01.105
5 20931240360 02.03.2012 17:57:01.124
and so on
I tried this:
%Refernce Data
clc; format longg
refTime = [2012,03,02,17,57,01];
refNum = datenum(refTime);
refStr = datestr(refNum,'yyyy-mm-dd HH:MM:SS.FFF');
% Processing data
dn = 24*60*60*1000*1000; % Microseconds! I have changed this equation to many options but nothing was helpful
for i = 1 : size(Data,1)
gzTm = double(Data{i,2}); %timestamps are uint64
gzTm2 = gzTm / dn;
gzTm2 = refNum + gzTm2;
gzNum = datenum(gzTm2);
gzStr = datestr(gzNum,'yyyy-mm-dd HH:MM:SS.FFF'); % I can't use 'SS.FFFFFF'
fprintf('i = %d\t Timestamp = %f\t TimeStr = %s\n', i, gzTm, gzStr);
end;
But I got always strange outputs like
i = 1 Timestamp = 20931160389.000000 TimeStr = **2012-03-08 13:29:28.849**
i = 2 Timestamp = 20931180407.000000 TimeStr = **2012-03-08 13:29:29.330**
i = 3 Timestamp = 20931200603.000000 TimeStr = **2012-03-08 13:29:29.815**
The output time is about some hours late/earlier than the Referenced Time. The day is different.
The time gap between each entry in the array should be nearly 20 seconds..since I have 50 frames per second(1000 millisecond / 50 = 20) ..and the year,month, day,hour,minute and seconds should also indicate the initial time given as reference time because it is about some seconds earlier.
I expect something like:
% just an example
1 20931160389 02.03.2012 **17:57:01.045**
2 20931180407 02.03.2012 **17:57:01.066**
Could one help me please..! Where is my mistake?
It looks like you can work out the number of microseconds between a record and the first record:
usecs = double(Data{i,2}) - double(Data{1,2});
convert that into seconds:
secsDiff = usecs / 1e6;
then add that to the initial datetime you'd calculated:
matDateTime = refNum + secsDiff / (24*60*60);

Comparing two Date values in ActionScript - possible to compare whole day values?

I need to be able to compare the number of whole days between two dates in ActionScript, is this possible?
I'd like to test if one date is 7 days or less after today, and if so is it one day or less (if it's before today this also counts).
The workaround I have in place is using the .time part of the date field:
// Get the diffence between the current date and the due date
var dateDiff:Date = new Date();
dateDiff.setTime (dueDate.time - currentDate.time);
if (dateDiff.time < ( 1 * 24 * 60 * 60 * 1000 ))
return "Date is within 1 day");
else if (dateDiff.time < ( 7 * 24 * 60 * 60 * 1000 ))
return "Date is within 7 days");
As I say - this is only a workaround, I'd like a permanent solution to allow me to check the number of whole days between 2 dates. Is this possible?
Thanks
var daysDifference:Number = Math.floor((dueDate.time-currentDate.time)/(1000*60*60*24));
if (daysDifference < 2)
return "Date is within 1 day";
else if (daysDifference < 8)
return "Date is within 7 days";