I am trying to convert some minutes and hours to milliseconds but the code below does not work.
I have tried lower numbers and it seamed to kind of work, is there a number limit in ahk?
ConvertedTimeInMilliSeconds := %Hours% * 3600000 + %Minutes% * 60000
I was expecting Hours to be 7200000 if the input would be two but instead its blank.
This is a common misunderstanding at the beginning.
I'll make this example, this are valid syntaxes:
Command, OutputVar, %InputVar%
Function(OutputVar, InputVar)
OutputVar := Function(InputVar)
OutputVar = %InputVar% Literal text
OutputVar := InputVar . " Literal text"
So in your code above, remove the % because you used an := assignment. Assigning through = can be always worked around into := and is probably the most recommended.
Variable names in an expression are not enclosed in percent signs:
Hours = 15
Minutes = 48
ConvertedTimeInMilliSeconds := (Hours * 3600000) + (Minutes * 60000)
MsgBox, % ConvertedTimeInMilliSeconds
or use a function:
MsgBox, % ConvertTimeInMilliSeconds(15, 48)
ConvertTimeInMilliSeconds(Hours, Minutes){
TimeInMilliSeconds := (Hours * 3600000) + (Minutes * 60000)
return TimeInMilliSeconds
}
Related
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.
How to calculate hours and mins from decimal number using crystal report formula
Hours and mins
42.00
397.00
2.20
63.40
2.36
1.30
0.50
----------------
508.76
----------------
Sum of values 508.76
I want to convert it into 509.16 -> 509 Hours 16 mins
Explanation In the 76 mins -> 60 mins converted to 1 hr so 509 hrs
remaining 16 mins displayed as mins so 509.16
Achieve using this method: 508 + (76/60) = 509, 76%60 = 16
76/60 Quotient 1, it added to integer part 508 + 1 now 509 hrs
76%6 Remainder 16, it will be 16 mins
tried this code for get fraction value
local numbervar sum_hours := sum({Command.TotalHours});
local numbervar fraction;
fraction := sum_hours - truncate(sum_hours);
it gives 0.76, how to get 76
can anyone explain with complete code how to write below expression and get result using crystal report formula
split 508.76 into 508 and 76 and calculate using below method
508 + (76/60) = 509, 76%60 = 16
I think the easiest approach to your problem would be to convert the individual values so the time they represent is expressed in minutes instead of "hours.minutes".
This formula takes a value of 5.38 (5 hours, 38 minutes) and converts it to minutes by splitting the value into a string array using the decimal as a delimiter. It then multiplies the hours by 60 to convert it to minutes, and adds the remaining minutes.
Whileprintingrecords;
Shared NumberVar value:= 5.38;
Shared StringVar array x := split(ToText(value),".");
Shared NumberVar hours := ToNumber(x[1]) * 60;
Shared NumberVar minutes := ToNumber(x[2]);
hours + minutes;
Once you have all of your data converted to minutes, you can easily sum them, then convert it back to hours and minutes with this formula. Replace {#Test} with the fieldname that contains the total value (in minutes) that you want to convert back to "minutes.hours".
WhilePrintingRecords;
ToNumber(ToText(Truncate({#Test}/60),0,"") & "." & ToText({#Test}Mod 60,0,""));
To transform 0.76 to 76, multiply by 100:
local numbervar sum_hours := 508.76; //sum({Command.TotalHours});
local numbervar fraction;
local numbervar hours;
local numbervar minutes;
fraction := sum_hours - truncate(sum_hours);
hours := truncate(sum_hours) + (fraction mod 60);
minutes := remainder(fraction * 100, 60);
ToText(hours,0) + ' hours and ' + ToText(minutes,0) + ' minutes'
I was looking for an inbuild ahk function that allows the user to add days, months, years or even time to an existing day thus converting it correctly to a new month if the day count reaches 32. I didn't find anything, so I came up with this little solution:
; returns an array [year, month, day, hour, minute, second]
DateTimeAdd(v_a_now,yearPlus=0,monthPlus=0,dayPlus=0,hrPlus=0,minPlus=0,secPlus=0) {
daysInMonth := { 1:31, 2:28, 3:31, 4:30, 5:31, 6:30, 7:31, 8:31, 9:30, 10:31, 11:30, 12:31 }
; Parse data from an A_NOW type format
; If you pass your custom "A_NOW" format remember that numbers < 10 are expected to have a leading 0
day := SubStr(v_a_now,7,2) + dayPlus
month := SubStr(v_a_now,5,2) + monthPlus
year := SubStr(v_a_now,1,4) + yearPlus
hours := SubStr(v_a_now,9,2) + hrPlus
minutes := SubStr(v_a_now,11,2) + minPlus
seconds := SubStr(v_a_now,13,2) + secPlus
; Start formatting
if(seconds >= 60) {
tadd := seconds / 60
seconds -= Floor(tadd) * 60
minutes += Floor(tadd)
}
if(minutes >= 60) {
tadd := minutes / 60
minutes -= Floor(tadd) * 60
hours += Floor(tadd)
}
if(hours >= 24) {
tadd := hours / 24
hours -= Floor(tadd) * 24
day += Floor(tadd)
}
; We have to format the month first in order to be able to format the days later on
if(month >= 13) {
tadd := month / 12
month -= Floor(tadd) * 12
year += Floor(tadd)
}
; Assmuning the number of days is an absurd number like 23424 we need to go through each month and subtract the max. amount of days from that month
cond := true
while(cond) {
; Get the number of max. days in this current month (sadly no loop years included :< )
max_days_in_this_month := daysInMonth[month]
; If the number of days i.e. 42 is great than 31 for example in January
if(day > max_days_in_this_month) {
; Subtract max. allowed days in month from day
day -= max_days_in_this_month
; New Year?
if(month == 12) {
month := 1
year++
} else {
month++
}
} else {
cond := false
}
}
; Add leading zero to numbers
return_array := [year, month, day, hours, minutes, seconds]
i := 2
while(i != return_array.MaxIndex()+1) {
thisIteration := return_array[i]
if(thisIteration <= 9) {
return_array[i] := "0" thisIteration
}
i++
}
; Done formatting
; For testing
;~ msg := return_array[1] "/" return_array[2] "/" return_array[3] " " return_array[4] ":" return_array[5] ":" return_array[6]
;~ msgbox % msg
return return_array
}
Sadly this function does not take loop years into aspect. Do you guys know any better alternatives?
Check out EnvAdd at https://autohotkey.com/docs/commands/EnvAdd.htm
EnvAdd, Var, Value, TimeUnits
equivalent to
Var += Value, TimeUnits
EnvAdd sets a date variable Var (in YYYYMMDDHH24MISS format) to the sum of itself plus the given date value Value using the timeunits parameter.
Example:
newDate := %A_Now% ; or whatever your starting date is
EnvAdd, newDate, 20, days
NewDate += 11, days
MsgBox, %newDate% ; The answer will be the date 31 days from now.
Using Crystal Reports version 8 and I need to convert a numbervar to stringvar. I have tried ToText() (with all variations of capitalization) and CStr() (also with various capitalizations) and each time CR tells me "A number is required here" and moves the cursor to the beginning of my else block. Ultimately trying to convert hours and minutes both stored as NumberVars to strings so I can display "8h 30m" instead of 8.50.
Here is what I have for the formula so far:
if {Collect2000Log.LogCode} = "0002" then 0
else
(
NumberVar OldTime := ((DateDiff("n",{#NextTime},{Collect2000Log.LogWhen})/60)*-1);
NumberVar Hours;
NumberVar Minutes;
StringVar strHours;
StringVar strMinutes;
StringVar NewTime;
//Extract the number of hours
Hours := Int(OldTime);
//Get the decimal portion for minutes
Minutes := Remainder(OldTime, 1) * 100;
//Divide the minutes by 60 to increase the number of hours
Hours := Hours + Int(Minutes / 60);
//Get the remainder for the number of minutes left over
Minutes := Remainder(Minutes, 60);
//Convert hours & mins to strings
strHours := ToText(Hours);
strMinutes := ToText(Minutes):
NewTime := strHours & "h " & strMinutes & "m";
);
And now when I add this formula CR says "The end ) is missing" and I'm stumped. I was able to get around that once but now not looking so hopeful.
Any help would be much appreciated!
Problem is simple... In an IF and Else you need to return same data type but you are returning a number through IF and a String through Else hence the error a Number is required at the starting of the else block.. so convert the output of If to string like below.
if {Collect2000Log.LogCode} = "0002"
then ToText(0)
else
(
NumberVar OldTime := ((DateDiff("n",{#NextTime},{Collect2000Log.LogWhen})/60)*-1);
NumberVar Hours;
NumberVar Minutes;
StringVar strHours;
StringVar strMinutes;
StringVar NewTime;
//Extract the number of hours
Hours := Int(OldTime);
//Get the decimal portion for minutes
Minutes := Remainder(OldTime, 1) * 100;
//Divide the minutes by 60 to increase the number of hours
Hours := Hours + Int(Minutes / 60);
//Get the remainder for the number of minutes left over
Minutes := Remainder(Minutes, 60);
//Convert hours & mins to strings
strHours := ToText(Hours);
strMinutes := ToText(Minutes):
NewTime := strHours & "h " & strMinutes & "m";
);
I'm trying to convert a value in Cross-tab of Crystal report into a MM:SS format. I used the following steps: Right-click summary > Format Field > Display String > x+2
WhilePrintingRecords;
NumberVar curr := CurrentFieldValue;
NumberVar mins := Truncate(curr / 60);
NumberVar secs := Remainder(curr, 60);
ToText(mins, 0, "") & ":" & ToText(secs, 0, "")
The results are ok when the secs is not 0. Example: `4:30'
But, I am having problems when secs is 0, the result is (for 4 minutes): 4:0
I would like to have the output as 4:00, with the seconds display as always a 2 digit number.
Thank you for all your help
You my ElapsedTime function in conditional-formatting expression.
I used this instead, and it worked :)
NumberVar curr := CurrentFieldValue;
NumberVar mins := Truncate(curr / 60);
NumberVar secs := Remainder(curr, 60);
ToText(mins, 0, "") & ":" & ToText(secs, '00')