Calculating wage by hours worked - math

Hey all, i am trying to figure out how to calculate the wage for an employee when they clock out. This is the code i am currently using:
Dim theStartTime As Date
Dim theEndTime As Date
Dim totalTime As String
theStartTime = "16:11:06"
theEndTime = "18:22:01"
totalTime = Format(CDbl((theEndTime - theStartTime) * 24), "#0.0")
So workable hours would be: 2h 11m
Right now, with my calculation code above, i get 2.2. What would i need to add in order to get it to calculate the correct time of 2:11 instead of 2:20?
David

Note that 2.2 hours is not 2:20, it's 2:12.
Change
Format(CDbl((theEndTime - theStartTime) * 24), "#0.0")
to
Format(theEndTime - theStartTime, "h:mm")
You're getting the right value, just rounding it off when you print. theEndTime - theStartTime is a time span equal to the difference between the two times. As you discovered, multiplying it by 24 will give you the number of hours different. However, you then have to divide by 24 again to use date/time formatting.
Check out all the ways to format dates and time in VB6.

First, I highly suggest going to the .NET framework (with it's easy-to-use TimeSpan class) if possible.
But, dealing in VB6 you should be able to use the DATEDIFF function (and it's been many years since I've touched VB6 so the specific syntax might be a bit off
Dim iHours As Integer, iMins As Integer
iMins = DateDiff("n", theStartTime, theEndTime)
iHours = iMins / 60
iMins = iMins Mod 60

You should also try casting it to the Currency type which can represent all numeric values (within 4 digits to the left of decimal point and 15 digits to the right).
Format(CCur((theEndTime - theStartTime) * 24), "#0.00")

Related

Time difference in SQLite

Here comes a head scratcher.
Using the expression:
cast((julianday(arrtime)-julianday(deptime))*24*60 as integer)
to calculate the difference of 2021-05-01 00:19 and 2021-05-01 01:29, gives me 69 minutes?
I can do better than that!
Any idea how to get around?
The problem with the value that you get is that julianday() returns a not exactly accurate floating point number and after the calculations and before casting to an integer, the result is 69.999999850988.
This value, when casting is applied will be truncated to the integer 69.
One solution would be to round the result to an integer instead of casting:
ROUND((julianday(arrtime)-julianday(deptime)) * 24 * 60)
or, since your dates do not contain seconds, use strftime() with '%s' as the format, which returns the number of seconds since 1970-01-01 00:00:00:
(strftime('%s', arrtime) - strftime('%s', deptime)) / 60
See a simplified demo.

Timestamp field in a dbf file (dBase 7 format) is not making sense

I've looked at both [1] and [2] and I'm completely confused (and since the dbf file is a version
4 file, [1] should apply well). For one thing why does [1] state that the timestamp's date portion is the # of days since 1/1/4713 BC? That's just very puzzling. Secondly, assuming that it is the # of days since 4713 BC, I'm having some trouble with the value I am getting.
First off, my dbf file has a timestamp field which has an 8 byte long value. The actual
date is 2000/8/16 17:21:41. In the dbf file, the 8 byte sequence is as follows
0x42ccb20e0340df00.
From [1], it says the first 4 bytes are for the date, and 2nd 4 bytes for the time. If the original
byte sequence is actually little-endian (0x42ccb20e) then that should be 0x0eb2cc42 which
comes to the value of 246598722. So date is 0x0eb2cc42 (246598722) and time is 0x00df4003
(14630915).
I must be missing something here or calculating something wrong. 246598722 is equivalent to 675612 years(assuming 1yr = 365 days, as adding leap years would confuse me..and shouldn't really be that much off).
From [2], I shouldn't use 01/01/4173bc as the basis but 12/31/1899 (well, 1/1/1900). But then, the date value I have isn't even in the range of what [2] shows.
Now if I take the actual value (2000/8/16) and use [1] and [2], I get the following:
method [1]: 2450501 days : (2000 - -4713) * 365 + (8 * 30) + 16
method [2]: 36756 days : [100 * 365 + 8 * 30 + 16] (over counting the # of days)
The dbf file isn't corrupted (otherwise, if I look at the timestamp in dBase, it'd crap out
and display something crazy).
I've thought of using big-endian, but that makes even less sense as the values are even larger. I've even thought of the possibility that it's actually the # of seconds elapsed since either date, but that makes the values with even less sense. i.e. 246598722 = # of seconds elapsed (counting back from 2000/8/16) will make the base year as 1812. (calculations: 246898722 / (3600 * 365) = 187.8985, so 2000 - 187.8985 = 1812.1015)
Can someone point out where I'm doing this wrong?
Thanks!
[1] - https://www.dbase.com/Knowledgebase/INT/db7_file_fmt.htm
[2] - Convert dBase Timestamp
For any dBASE questions, I would recommend to go to the dBASE newsgroups, they have a very helpful and knowledgeable community.
I've finally found the answer thanks to [3].
Basically, the timestamp 8 byte sequence is used as a whole with the following notes:
It's stored in big-endian.
The last byte is not used.
It's a Julian Day Number.
So in my case, it's 0x42ccb20e0340df00 and truncating the last byte,
I get 0x42ccb20e0340df.
Then the following python code gets the correct info:
import datetime
base = 0x42cc418ba99a00
frm_date = int('42ccb20e0340df', 16)
final_ts = (frm_date - base) / 500
final_date = datetime.datetime.utcfromtimestamp(final_ts)
which outputs 2000-8-16 17:21:41 and some milliseconds, which I just ignore.
So I'm guessing the theory is that the above code moves the 'base' date to
1970/1/1 from 1/1/1, which helps since utcfromtimestamp() doesn't
work with any value prior to 1970/1/1.
My confusion stems from the fact it doesn't use 4713BC as the
base year, instead it uses 1/1/1, though I'm still trying to figure out how to get the value 0x42cc418ba99a00 for 1970/1/1.
[3] - https://stackoverflow.com/a/60424157/10860403

MomentJS - making fromNow() round down

I was using the following code to calculate the age of a person:
var year = 1964;
var month = 1;
var day = 20;
var age = moment(year + '-' + month + '-' + date, 'YYYY-MM-DD').fromNow(true);
The problem with fromNow() is that it rounds the number up or down depending on the decimal point. I would like it to only round down. In the above example the person's real age is 51 but it's returning 52 because his age is actually something like 51.75.
If I use diff() instead it rounds down which is perfect. But it doesn't give me the pretty text 51 years old.
var age = moment().diff([year, month - 1, date], 'years');
My question is, is there a way to make fromNow() round down?
You can configure a custom rounding function:
moment.relativeTimeRounding(Math.floor)
The provided solution is correct but I thought I'd add a little explanation as this was the first google result.
Say I have a scenario where I want dates that were 1m 30s ago to display a minute ago rather than two minutes ago:
const minuteAndAHalfAgo = new Date();
minuteAndAHalfAgo.setMinutes(minuteAndAHalfAgo.getMinutes() - 1);
minuteAndAHalfAgo.setSeconds(minuteAndAHalfAgo.getSeconds() - 30)
moment.relativeTimeRounding(Math.floor);
console.log(moment(minuteAndAHalfAgo).fromNow()); // a minute ago
the relativeTimeRounding function takes a function as an argument which in our case is Math.floor which means the relative time evaluation will be rounded down. This can be found in the docs https://momentjs.com/docs/#/customization/relative-time-rounding/ - you can also specify a relativeTimeThreshold — the point at which to round the number.

Julia: conversion between different time periods

Full disclosure: I've only been using Julia for about a day, so it may be too soon to ask questions.
I'm not really understanding the utility of the Dates module's Period types. Let's say I had two times and I wanted to find the number of minutes between them. It seems like the natural thing to do would be to subtract the times and then convert the result to minutes. I can deal with not having a Minute constructor (which seems most natural to my Python-addled brain), but it seems like convert should be able to do something.
The "solution" of converting from Millisecond to Int to Minute seems a little gross. What's the better/right/idiomatic way of doing this? (I did RTFM, but maybe the answer is there and I missed it.)
y, m, d = (2015, 03, 16)
hr1, min1, sec1 = (8, 14, 00)
hr2, min2, sec2 = (9, 23, 00)
t1 = DateTime(y, m, d, hr1, min1, sec1)
t2 = DateTime(y, m, d, hr2, min2, sec2)
# println(t2 - t1) # 4140000 milliseconds
# Minute(t2 - t1) # ERROR: ArgumentError("Can't convert Millisecond to Minute")
# minute(t2 - t1) # ERROR: `minute` has no method matching
# minute(::Millisecond)
# convert(Minute, (t2-t1)) # ERROR: `convert` has no method matching
# convert(::Type{Minute}, ::Millisecond)
delta_t_ms = convert(Int, t2 - t1)
function ms_to_min(time_ms)
MS_PER_S = 1000
S_PER_MIN = 60
# recall that division is floating point unless you use div function
return div(time_ms, (MS_PER_S * S_PER_MIN))
end
delta_t_min = ms_to_min(delta_t_ms)
println(Minute(delta_t_min)) # 69 minutes
(My apologies for choosing a snicker-inducing time interval. I happened to convert two friends' birthdays into hours and minutes without really thinking about it.)
Good question; seems like we should add it! (Disclosure: I made the Dates module).
For real, we had conversions in there at one point, but then for some reason or another they were taken out (I think it revolved around whether inexact conversions should throw errors or not, which has recently been cleaned up quite a bit in Base for Ints/Floats). I think it definitely makes sense to add them back in. We actually have a handful in there for other operations, so obviously they're useful.
As always, it's also a matter of who has the time to code/test/submit and hopefully that's driven by people with real needs for the functionFeel free to submit a PR if you're feeling ambitious!

Converting a 19 digits time stamp to a real time (from .zvi file format)

After a long day of research,
Is anybody knows how to convert a 19 digits time stamp from the metadata of .zvi file (produce by axiovision, Zeiss) to a real time format ? (The output probably includes milliseconds)
An example time-stamp is: 4675873294709522577
Thanks !
Arnon
Matlab solution:
The main issue is not the x2mdate conversion (which simply adds the number of days between the year zero, when Matlab starts counting, and the year 1900, when Excel/zvi starts counting), but the same class issue as described above. This conversion to double can be done with typecast in Matlab:
myZVI = 4675946358764751269;
timestampDouble = typecast(int64(myZVI),'double');
myTime = datestr(timestampDouble + 693960, 'dd-mmm-yyyy HH:MM:SS.FFF');
693960 is the number of days between year zero and 1900; if you don't need an absolute date but just the difference between two timestamps, you don't even need this; for instance the interval between two of my video frames can be calculated like this:
myZVI2 = 4675946358764826427;
timestampDouble2 = typecast(int64(myZVI2),'double');
myTimeDifference = datestr(timestampDouble2 - timestampDouble,'SS.FFF');
hope this helps:-)
This is a Microsoft OLE Automation Date. But you've read it as a 64-bit long integer instead of the 64-bit double that it should be.
You didn't specify a language, so I will pick C#:
long l = 4675873294709522577L;
byte[] b = BitConverter.GetBytes(l);
double d = BitConverter.ToDouble(b, 0);
Debug.WriteLine(d); // 41039.901598693
DateTime dt = DateTime.FromOADate(d);
Debug.WriteLine(dt); // 5/10/2012 9:38:18 PM
More information in this thread.
An OLE Automation Date is basically the number of whole 24-hour days since 1/1/1900 without any particular time zone reference.

Resources