Add nanoseconds from Win32 epoch to Go time - datetime

I'm trying to process some WMI counters using Go (as part of learning Go) and am trying to figure out how to generate the necessary time object.
The base is the Win32 epoch (1601-01-01) and a sample timestamp is 13224382394716547600ns (or rather, 132243823947165476 100ns units).
Here's what I've tried:
test 1 (add nanoseconds)
win_epoch := time.Date(1601,1,1, 0, 0, 0, 0, time.UTC)
current_ts_1 := win_epoch.Add(13224382394716547600*time.Nanosecond)
test 2 (add days)
win_epoch := time.Date(1601,1,1, 0, 0, 0, 0, time.UTC)
current_ts_2 := win_epoch.AddDate(0,0,(132243823947165476/10000000 / 3600 / 24))
current_ts_1 in test 1 fails with an overflow error.
current_ts_2 in test 2 only gives me resolution at the date level.
Ideally I'd be able to get the millisecond resolution on this. Does there exist a way to not overflow the Duration being passed to .Add() and still get this resolution?

This conversion requires dealing with some huge numbers. Your example time
13,224,382,394,716,547,600 is too big to fit into an int64 (max 9,223,372,036,854,775,807) but does fit into a unit64.
You cannot use time.Duration when dealing with this because that is a int64 nanosecond count; as the docs say "The representation limits the largest representable duration to approximately 290 years". This is why your first attempt fails.
However there is another way of creating a time that will work better here func Unix(sec int64, nsec int64) Time. This takes data in the unix format and this is the time since January 1, 1970 UTC (or 11644473600000000000 represented as ns since the windows epoch).
Using this information it's possible to perform the conversion:
func main() {
const unixTimeBaseAsWin = 11644473600000000000 // The unix base time (January 1, 1970 UTC) as ns since Win32 epoch (1601-01-01)
const nsToSecFactor = 1000000000
timeToConvert := uint64(13224382394716547600)
unixsec := int64(timeToConvert - unixTimeBaseAsWin ) / nsToSecFactor
unixns := int64(timeToConvert % nsToSecFactor)
time := time.Unix(unixsec, unixns)
fmt.Println(time.Local())
}
Note: I have checked this with a few figures but would suggest further testing before you rely upon it.

Related

Initalizing 0 UTC Time generates a negative time when printed

In the provided code snippet the t2 time initialized explicitly to 0 UTC is negative when printed.
I don't understand why that is, could someone explain it for me?
func main() {
const IsoDatetimeFormat = "2006-01-02T15:04:05"
t1 := time.Time{}
t2 := time.Date(0, 0, 0, 0, 0, 0, 0, time.UTC)
fmt.Println(t1.Format(IsoDatetimeFormat))
fmt.Println(t2.Format(IsoDatetimeFormat))
}
Output:
0001-01-01T00:00:00
-0001-11-30T00:00:00
playground link
time.Time documents that the zero value for time.Time represents / means January 1, year 1, 00:00:00.000000000 UTC:
The zero value of type Time is January 1, year 1, 00:00:00.000000000 UTC. As this time is unlikely to come up in practice, the IsZero method gives a simple way of detecting a time that has not been initialized explicitly.
There is no year 0, so if you use year, month and day values smaller than 1, they will roll over to negative. The time package accepts and normalizes values given outside of valid ranges. Quoting from time.Date():
The month, day, hour, min, sec, and nsec values may be outside their usual ranges and will be normalized during the conversion. For example, October 32 converts to November 1.
The zero value to be January 1, year 1 was an arbitrary choice. As to reasoning why year 1 was chosen:
// The zero value for a Time is defined to be
// January 1, year 1, 00:00:00.000000000 UTC
// which (1) looks like a zero, or as close as you can get in a date
// (1-1-1 00:00:00 UTC), (2) is unlikely enough to arise in practice to
// be a suitable "not set" sentinel, unlike Jan 1 1970, and (3) has a
// non-negative year even in time zones west of UTC, unlike 1-1-0
// 00:00:00 UTC, which would be 12-31-(-1) 19:00:00 in New York.

Round Julia's Millisecond type to nearest Second or Minute

I would like to calculate the difference between a pair of DateTimes that is rounded to the nearest second or minute.
initial = now()
println(typeof(initial))
sleep(12)
final = now()
difference = final - initial
println(typeof(difference))
gives
DateTime
Base.Dates.Millisecond
The latter type is pretty difficult to use since almost all convenience types are for DateTimes. What is the recommend way to convert difference to seconds or fractional minutes? Is this possible without dropping down to integers? I would prefer to avoid that since it is more error prone.
Since difference represents a duration between dates rather than a particular time, it makes sense for it to just be a duration in milliseconds. Additionally, DateTime and Base.Dates.Millisecond objects are internally represented with an Int64, so everything's already an integer.
julia> moment = now()
2016-12-22T22:54:57.393
julia> dump(moment)
DateTime
instant: Base.Dates.UTInstant{Base.Dates.Millisecond}
periods: Base.Dates.Millisecond
value: Int64 63618130497393
julia> dump(now()-moment)
Base.Dates.Millisecond
value: Int64 29820
Divide the value in milliseconds by 1000 to get seconds, or by 60,000 to get minutes. Use round() to round to the nearest second or minute.
julia> d = (now() - moment).value/60_000
3.9330833333333333
julia> e = round(d)
4.0
Then multiply by 1000 or 60,000 and feed it back into Dates.Millisecond to turn the rounded figure back into the appropriate object:
julia> Dates.Millisecond(60_000e)
240000 milliseconds
Rounding a Date or DateTime object to a given time interval is much simpler, as you can just use round() according to the documentation and it will dispatch to a relevant method:
julia> floor(Date(1985, 8, 16), Dates.Month)
1985-08-01
julia> ceil(DateTime(2013, 2, 13, 0, 31, 20), Dates.Minute(15))
2013-02-13T00:45:00
julia> round(DateTime(2016, 8, 6, 20, 15), Dates.Day)
2016-08-07T00:00:00

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.

How can I find the time difference in seconds between two dates in prolog?

How can I find the time difference in seconds between two dates in prolog?
datetime(2001,03,04,23,00,32).
datetime(2001,03,04,23,01,33).
timediff(D1,D2,Sec).
Sec=61
SWI-Prolog offers several predicates that convert human-readable time representations into seconds from Epoch (at 1970-01-01). Having the time represented as a number of seconds turns the difference calculation into a simple subtraction operation. For example:
timediff(DateTime1, DateTime2, Sec) :-
date_time_stamp(DateTime1, TimeStamp1),
date_time_stamp(DateTime2, TimeStamp2),
Sec is TimeStamp2 - TimeStamp1.
Usage:
?- timediff(date(2001, 03, 04, 23, 0, 32, 0, -, -),
date(2001, 03, 04, 23, 1, 33, 0, -, -), Sec).
Sec = 61.0.
This gets a little awkward what with the months not being the same length and leap years having extra days.
To start you off, I'm going to give you a version of a predicate that will only take into account hours, minutes, and seconds:
timediff(time(Hours1, Minutes1, Seconds1), time(Hours2, Minutes2, Seconds2), Seconds) :-
Seconds is Seconds1-Seconds2 + 60*(Minutes1-Minutes2 + 60*(Hours1-Hours2)).
If you could run convert_time/2 or convert_time/8 backwards, this process would be much easier, as it would allow you to use the operating system's time conversion routines instead of writing your own.

Resources