ruby on rails int to minutes::seconds::milliseconds - ruby-on-rails

I have this line, which shows the minutes and seconds. But I have to add milliseconds to it as well for greater accuracy. How do I add that in this line, or is there an easier way to get the desired result?
#duration = [cd.ExactDuration/60000000, cd.ExactDuration/1000000 % 60].map{|t| t.to_s.rjust(2, '0') }.join(':'))
The exact duration type is saved in microseconds. So the first converts to microseconds to minutes, the second part is microseconds to seconds. Now I need to add milliseconds.

cd.ExactDuration/1000 % 1000 should do the trick.
Of course you may also want to tweak the formatting, since that's a datum you don't want to right-justify in a 2-wide field;-). I'd suggest sprintf for string-formatting, though I realize its use is not really intuitive unless you come from a C background.

Related

Parse time string to hours, minutes and seconds in Lua

I am currently working on a plugin for grandMA2 lighting control using Lua. I need the current time. The only way to get the current time is the following function:
gma.show.getvar('TIME')
which always returns the current system time, which I then store in a variable. An example return value is "12h54m47.517s".
How can I separate the hours, minutes and seconds into 3 variables?
If os.date is available (and matches gma.show.getvar('TIME')), this is trivial:
If format starts with '!', then the date is formatted in Coordinated Universal Time. After this optional character, if format is the string "*t", then date returns a table with the following fields: year, month (1–12), day (1–31), hour (0–23), min (0–59), sec (0–61, due to leap seconds), wday (weekday, 1–7, Sunday is 1), yday (day of the year, 1–366), and isdst (daylight saving flag, a boolean). This last field may be absent if the information is not available.
local time = os.date('*t')
local hour, min, sec = time.hour, time.min, time.sec
This does not provide you with a sub-second precision though.
Otherwise, parsing the time string is a typical task for tostring and string.match:
local hour, min, sec = gma.show.getvar('TIME'):match('^(%d+)h(%d+)m(%d*%.?%d*)s$')
-- This is usually not needed as Lua will just coerce strings to numbers
-- as soon as you start doing arithmetic on them;
-- it still is good practice to convert the variables to the proper type though
-- (and starts being relevant when you compare them, use them as table keys or call strict functions that check their argument types on them)
hour, min, sec = tonumber(hour), tonumber(min), tonumber(sec)
Pattern explanation:
^ and $ pattern anchors: Match the full string (and not just part of it), making the match fail if the string does not have the right format.
(%d)+h: Capture hours: One or more digits followed by a literal h
(%d)+m: Capture minutes: One or more digits followed by a literal m
(%d*%.?%d*)s: Capture seconds: Zero or more digits followed by an optional dot followed by again zero or more digits, finally ending with a literal s. I do not know the specifics of the format and whether something like .1s, 1.s or 1s is occasionally emitted, but Lua's tonumber supports all of these so there should be no issue. Note that this is slightly overly permissive: It will also match . (just a dot) and an s without any leading digits. You might want (%d+%.?%d+)s instead to force digits appearing before & after the dot.
Lets do it with string method gsub()
local ts = gma.show.getvar('TIME')
local hours = ts:gsub('h.*', '')
local mins = ts:gsub('.*%f[^h]', ''):gsub('%f[m].*', '')
local secs = ts:gsub('.*%f[^m]', ''):gsub('%f[s].*', '')
To make a Timestring i suggest string method format()
-- secs as float
timestring = ('[%s:%s:%.3f]'):format(hours, mins, secs)
-- secs not as float
timestring = ('[%s:%s:%.f]'):format(hours, mins, secs)

F# - convert time in microsecond to day of the week

I am trying to learn F# and was wondering if i have a json object which has time in microseconds as int. I want to get the day, date and time out of this and was wondering how to do it.
I actually happen to have needed to do this recently. You'll almost certainly want to use the .NET time objects (DateTime, DateTimeOffset, TimeSpan) in some capacity. Here's what I went with:
let TicksPerMicrosecond =
TimeSpan.TicksPerMillisecond / 1000L
let FromUnixTimeMicroseconds (us: int64) =
DateTimeOffset.FromUnixTimeMilliseconds 0L + TimeSpan.FromTicks(us * TicksPerMicrosecond)
From TimeSpan.TicksPerMillisecond we can calculate how many are in a microsecond (if I remember correctly it's 10, but this way it doesn't seem as "magic"). Then I can convert the microseconds value into ticks and add it to the epoch date.
To get the day of the week (assuming the time zone is UTC), you'd just use DateTimeOffset.DayOfWeek.

How do I display fractions of a second in my time formatting function?

I'm using Rails 5. I have a method that is supposed to help display a duraiton in milliseconds in a more readable format (hours:minutes:seconds) ...
def time_formatted time_in_ms
regex = /^(0*:?)*0*/
Time.at(time_in_ms/1000).utc.strftime("%H:%M:%S").sub!(regex, '')
end
This works basically fine, but it doesn't work completely accurately when the time in milliseconds contains fractions of a second. That is, if the time in milliseconds is
2486300
The above displays
41:26
but really it should display
41:26.3
How can I adjust my function so it will also display fractions of a second, assuming there are any?
For accuracy make sure you're returning a float (I've used to_f to do this).
Append the argument to strftime with ".%1N" for 1-digit milliseconds.
def time_formatted time_in_ms
regex = /^(0*:?)*0*/
Time.at(time_in_ms.to_f/1000).utc.strftime("%H:%M:%S.%1N").sub!(regex, '')
end
time_formatted 2486300
#=> "41:26.3"
For more information see Time#strftime in the official Ruby documentation.

adding a big offset to an os.time{} value

I'm writing a Wireshark dissector in lua and trying to decode a time-based protocol field.
I've two components 1)
local ref_time = os.time{year=2000, month=1, day=1, hour=0, sec=0}
and 2)
local offset_time = tvbuffer(0:5):bytes()
A 5-Byte (larger than uint32 range) ByteArray() containing the number of milliseconds (in network byte order) since ref_time. Now I'm looking for a human readable date. I didn't know this would be so hard, but 1st it seems I cannot simple add an offset to an os.time value and 2nd the offset exceeds Int32 range ...and most function I tested seem to truncate the exceeding input value.
Any ideas on how I get the date from ref_time and offset_time?
Thank you very much!
Since ref_time is in seconds and offset_time is in milliseconds, just try:
os.date("%c",ref_time+offset_time/1000)
I assume that offset_time is a number. If not, just reconstruct it using arithmetic. Keep in mind that Lua uses doubles for numbers and so a 5-byte integer fits just fine.

How do I convert a floating point number into erlang time format (and vice versa)?

I am trying to convert an erlang time format tuple, {megasec,sec,microsec}, into a floating point number and back again.
I can do this one way, e.g.:
{Megasec,Sec,Usec} = erlang:now().
Total = Megasec*1000000+Sec+Usec/1000000.
1352802601.427
But I am struggling to convert this number back to the time format. I have a general idea to divide by 1000000 and round but I get rounding errors. e.g.
Mega = erlang:round(Total/1000000).
1353
If I could get this accurately I could apply similar steps to get Seconds and Microseconds.
Any ideas?
You can use erlang:trunc instead of erlang:round.
Following #Falco Hirschenberger's suggestion here's how I did it:
Mega = erlang:trunc(Total/1000000).
1352
Sec = erlang:trunc(Total - Mega*1000000).
802601
Usec = erlang:round((Total - Mega*1000000 - Sec)*1000000).
427000
Note. I had to use erlang:round to get Usec (else the answer would have been 427000.0457763672 - I think this is due to a rounding error introduced when I divided by 1000000)

Resources