View Issue Details

IDProjectCategoryView StatusLast Update
0006218Compliance Test Tool (CTT) Unified Architecture3 - Feature Requestpublic2022-08-05 15:46
ReporterThomas Reuther Assigned ToAlexander Allmendinger  
PrioritynormalSeverityminorReproducibilityalways
Status assignedResolutionopen 
PlatformWindows 7OSWindows 7OS Version6.1.7601
Product Version1.03.341.396 
Summary0006218: Unable to create UaDateTime object from Long value
Description

Hello,

I want to create a deserializer for a custom data type (structure) which contains a DateTime. I want to use it in a custom test script. With the help of Part 6 document I could successfully decode the binary encoded ExtensionObject.

Example:
The date is: 01.01.1981
The binary encoding is: "000006853A07AA01"
The Long value is: 119916288000000000

Part 6 says: "A DateTime value shall be encoded as a 64-bit signed integer (see Clause 5.2.2.2) which
represents the number of 100 nanosecond intervals since January 1, 1601 (UTC)."

119916288000000000 (100 ns) => 11991628800000 ms => 11991628800 s => 138792 days => 380 years
1601 + 380 = 1981!
I am happy to have correctly decoded the date.

My problem is to convert the Long value into a UaDateTime object. My plan is to create a UaDateTime of "1601-01-01" and add that number of nanoseconds. But however I create a UaDateTime object it is of "0001-01-01" istead:

UaDateTime.fromString("1601-01-01T00:00:00.000Z") => "0001-01-01T00:00:00.000Z"
new UaDateTime() => "0001-01-01T00:00:00.000Z"
Constants.DateTime_Min() => "0001-01-01T00:00:00.000Z"

Is this only a problem of "toString()" method of that object or is the year actually set to "0001"?
I tried with diff() and msecsTo() methods:

var minDate = UaDateTime.fromString("1601-01-01T00:00:00.000Z")
var expectedDate = UaDateTime.fromString("1981-01-01T00:00:00.000Z");
UaDateTime.diff( minDate, expectedDate ) => "1981-01-01T00:00:00.000Z" (the difference is 1981 years!?!)
minDate.msecsTo( expectedDate ) => 80109568 (= 80109.568s = 22h 15min 9s 568ms)

And actually: when I add the number 11991628800000 (ms) to minDate:

minDate.addMilliSeconds( 11991628800000 )

I'll get "1601-01-01T22:15:09.568Z". I wonder how the year has changed from "0001" to "1601". But looking at the other parts of the date it seems that less than 24h were added.

Additional Information

Is there a problem with the UaDateTime class or do I used it in a wrong way? Is there a Calendar or other helper class? What is the recommend way to calculate a date from nanoseconds?

TagsNo tags attached.
Files Affected

Activities

Paul Hunkar

2020-11-23 14:07

administrator   ~0013284

Please attach the script code you are trying to use , we lack a point of reference. The CTT has no problems with UaDateTime as we use it.

Thomas Reuther

2020-11-24 11:02

reporter   ~0013293

It is not about an existing script. I want to create a custom script using custom types. One of these types consists of strings and dates. I can successfully encode/decode strings by a look into part 6 "Mappings". I would like to know how I can decode a date. From specification I know a date is encoded as Long, as number of 100 nanos since 1601-01-01. And I know how to convert the byte string into a Long. But then I want to create a DateTime from this number. But I miss such a method. I expect something like:

UaDateTime.fromLong(myLong)
or
UaDateTime.fromNanos(myLong)
or
var d = Constants.DateTime_Min();
d.addNanos(myLong);

Is there such a method which I haven't found? What I tried so far (see my first posting) doesn't work.

Paul Hunkar

2020-11-30 18:58

administrator   ~0013317

This is the definition of Part 6:
a) A date/time value is encoded as 0 if either
1) The value is equal to or earlier than 1601-01-01 12:00AM UTC.
2) The value is the earliest date that can be represented with the DevelopmentPlatform’s encoding.
b) A date/time is encoded as the maximum value for an Int64 if either
1) The value is equal to or greater than 9999-12-31 11:59:59PM UTC,
2) The value is the latest date that can be represented with the DevelopmentPlatform’s encoding.
c) A date/time is decoded as the earliest time that can be represented on the platform if either
1) The encoded value is 0,
2) The encoded value represents a time earlier than the earliest time that can be represented with the DevelopmentPlatform’s encoding.
d) A date/time is decoded as the latest time that can be represented on the platform if either
1) The encoded value is the maximum value for an Int64,
2) The encoded value represents a time later than the latest time that can be represented with the DevelopmentPlatform’s encoding.
These rules imply that the earliest and latest times that can be represented on a given platform are invalid date/time values and should be treated that way by applications.
A decoder shall truncate the value if a decoder encounters a DateTime value with a resolution that is greater than the resolution supported on the DevelopmentPlatform.

What you are missing is these exception (limits) - so again I ask if you could provide a more concrete example of the structure you are trying to test and the tests you are trying to run for it. To generate an encode number from anything by a string representation of the a date does not make sense since the base time can vary on development platforms (and there are rules on how to handle that). Again we do not have any test cases that would need the functionality you are describing or any structure that would need to be tested that have this type of data.

Thomas Reuther

2020-12-01 11:52

reporter   ~0013319

In a custom script I want to decode a custom data type, which is a structure of strings and a date. I successfully decoded the string part of it. The string can be decoded using UaByteSting.utf8ToString(). The length of a string can be decoded by UaByString.toUInt32().

But how to decode a date? For example I get "000006853A07AA01" (the date time fraction of the custom structure). I expect(ed) to find a helper function like UaByteString.toDateTime() which returns a UaDateTime object. But UaByteString only supports encoding/decoding of String and UInt32 by using get and set.

So I started with my own decoder. At first I convert that hex string into a Long. The Long representation of that byte string above is 119916288000000000. Now I expect a helper function to convert this Long value into a UaDateTime, for example UaDateTime.fromLong() or UaDateTime.fromNanos(). There are some addXxx() functions, but no addNanos(). Then I tried this:

var d = Constants.DateTime_Min();
d.addMillis(myLong / (10 1000 1000);

But it doesn't work. My question: Is there anything available that helps me converting a Long (=Int64) into a UaDateTime?

Our servers have a couple of custom structs which I want/need to use in custom scripts.

Paul Hunkar

2020-12-03 19:10

administrator   ~0013370

So after a discussion in the cmp group - we think this might be what you are having an issue with:
You have a custom structure
Mystruct{
[string] someString
[UaDateTime] myDateTime
[Float] myfloat
}
You would like to decode this structure in the CTT, and you are having a problem with the middle element in the structure, you have no problems with the string or Float. The write format for the UaDateTime is an Int64
What I tried to explain that looking at something other then current time can have issues, since the definition of UADateTime include variances for platforms - So looking at the resulting value (not as a datetime but as int64 is not correct. The stack on the platform on which the CTT is deployed, converts - based on platform - to a UaDateTime that is appropriate for the platform. Your structure is not being decoded by the stack, but passed to the application and thus are trying to decode it at the application level correct? I'm assumming the server contains the correct encoding information for the custom datatype? i.e. Can UAExpert or another standard client understand your DataType and expose it as a structure? If so I think the correct request is that the CTT should be enhance to allow automatic decoding of custom datatypes, since then the stack will handle the constraints a deployed platform might have.

Thomas Reuther

2020-12-07 12:43

reporter   ~0013377

Yes, I can decode the datetime part to Int64. And yes, UA Expert can display values of such variables. I wasn't aware of platform dependent issues. I use the Windows platform. I was also using Linux, but there is not update since CTT version 1.02.x. It would be great when CTT becomes able to decode custom structs. At first I would like to have a Calendar class to calculate dates:

'01.01.1601' + 119916288000000000 (nanos) = '01.01.1981'

and vice versa for encoding.

Paul Hunkar

2021-02-20 05:55

administrator   ~0013757

Updated the CTT to be able to decode custom structure in a future release (this will help with companion specification testing , not just vendor specific structures)

Issue History

Date Modified Username Field Change
2020-11-06 08:24 Thomas Reuther New Issue
2020-11-23 14:07 Paul Hunkar Status new => feedback
2020-11-23 14:07 Paul Hunkar Note Added: 0013284
2020-11-24 11:02 Thomas Reuther Note Added: 0013293
2020-11-24 11:02 Thomas Reuther Status feedback => new
2020-11-30 18:58 Paul Hunkar Assigned To => Paul Hunkar
2020-11-30 18:58 Paul Hunkar Status new => feedback
2020-11-30 18:58 Paul Hunkar Note Added: 0013317
2020-12-01 11:52 Thomas Reuther Note Added: 0013319
2020-12-01 11:52 Thomas Reuther Status feedback => assigned
2020-12-03 19:10 Paul Hunkar Status assigned => feedback
2020-12-03 19:10 Paul Hunkar Note Added: 0013370
2020-12-07 12:43 Thomas Reuther Note Added: 0013377
2020-12-07 12:43 Thomas Reuther Status feedback => assigned
2021-02-20 05:54 Paul Hunkar Category 1 - Script Issue => 3 - Feature Request
2021-02-20 05:55 Paul Hunkar Status assigned => acknowledged
2021-02-20 05:55 Paul Hunkar Note Added: 0013757
2021-02-20 05:56 Paul Hunkar Assigned To Paul Hunkar =>
2022-08-05 15:46 Paul Hunkar Assigned To => Alexander Allmendinger
2022-08-05 15:46 Paul Hunkar Status acknowledged => assigned