Thank you, this is good. I was modeling DateAndTime as UTCTime, which is a specified format for two digit years: http://www.obj-sys.com/asn1tutorial/node15.html. I noticed this other time representation while lookin... GeneralizedTime: http://www.obj-sys.com/asn1tutorial/node14.html. To meet that format with padding, I decided to convert to strings. Not pretty but there is a test! :)
Unfortunately the ASN.1 DER endoding for time is specific format. I coudl just throws milliseconds in an integer slot, but I wanted to meet the spec as well for a full ASN.1 tool. I am undecided whether to use ASN.1 for header encoding in SecureSession, or custom binary specification - I use the second option at this time. Yet I am in the middle of redefining that message protocol, so now would be the time to decide.
Fuel and I have a date coming up, for sure.
thank you, Robert
On 12/21/2015 03:34 PM, Sven Van Caekenberghe wrote:
Robert,
On 19 Dec 2015, at 07:09, Robert Withers robert.w.withers@gmail.com wrote:
A core part of communications, whether online or to persistence, is encoding, or marshalling. Let's do an example! Thank you for your thoughtful, earnest participation, as God wills it.
Here are 2 methods that encode and decode a DateAndTime object, but rather poorly. I've been going without much sleep for a bit and I can't figure it out. Here is the code in hopes that some will find this an interesting exercise in team and community building. For that intention, as a beginning. What's the best solution?
Let's show them how to code when given the space in the environment. Tnks! :)
In class ASN1UTCTimeType..
encodeValue: anObject withDERStream: derStream
| yy mo dd hh mm ss utcDateTime | yy := anObject year asString copyFrom: 3 to: 4. mo := anObject month asString padded: #left to: 2 with: $0. dd := anObject dayOfMonth asString padded: #left to: 2 with: $0. hh := anObject hour asString padded: #left to: 2 with: $0. mm := anObject minute asString padded: #left to: 2 with: $0. ss := anObject seconds asString padded: #left to: 2 with: $0. utcDateTime := (yy, mo, dd, hh, mm, ss, 'Z') asByteArray. derStream nextPutAll: utcDateTime.
decodeValueWithDERStream: derStream length: length
| aUTCDateTime | aUTCDateTime := (derStream next: length) asByteArray asString. ^ (DateAndTime readFromString: ( ((aUTCDateTime copyFrom: 1 to: 2) asInteger > 50 ifTrue: ['19'] ifFalse: ['20']), (aUTCDateTime copyFrom: 1 to: 2), '-', (aUTCDateTime copyFrom: 3 to: 4), '-', (aUTCDateTime copyFrom: 5 to: 6), 'T', (aUTCDateTime copyFrom: 7 to: 8), ':', (aUTCDateTime copyFrom: 9 to: 10), ':', (aUTCDateTime copyFrom: 11 to: 12))) offset: 0
-- . .. .. ^,^ robert
Like you say, this is *not* good, because it is pretty inefficient. You want to encode binary, yet you create a string representation. But even that is done badly ;-) Any you are introducing 2YK all over again.
Anyway, the solution is to encode the timestamp using one or more numbers, directly. From your code I assume you are only interested in second precision and the UTC/GMT/Z timezone. In that case either one rather large number (seconds since X, like unix time) or two smaller numbers (julian day number and seconds since midnight) are way more efficient.
For inspiration, have a look at Fuel's DateAndTime>>#serializeOn: (that also encodes nanoseconds and the timezone).
HTH,
Sven
squeak-dev@lists.squeakfoundation.org