How to convert UTCDateTime to Hexidecimal and back?

M

Mark B

I want to convert a simple UTC DateTime value (e.g. 2009-11-20 3:32:00 PM)
to a hexidecimal value or whatever else takes the smallest amount of
characters. The reason I want it small is because I want it in a URL
parameter so smaller the better in terms of aesthetic look. I'll also need
to convert it back to date time.

Can anyone help me out with the code for this?
 
P

Peter Duniho

Mark said:
I want to convert a simple UTC DateTime value (e.g. 2009-11-20 3:32:00
PM) to a hexidecimal value or whatever else takes the smallest amount of
characters. The reason I want it small is because I want it in a URL
parameter so smaller the better in terms of aesthetic look. I'll also
need to convert it back to date time.

Can anyone help me out with the code for this?

I think the simplest approach would be to just use the DateTime.Ticks
value, formatted as hex or Base64 (the latter being slightly more
efficient than hex, character-count-wise...hex would take 16 characters,
Base64 only 11).

Depending on the precision you need, you could pick an arbitrary
reference date and count some larger unit from that date, so that you
could store the value as an Int32 instead of Int64. For example, if the
units (maximum precision) is seconds, then an Int32 can give you over 68
years worth of range (136 years if you use the full rane of Int32, or
perhaps more conveniently just use a UInt32 instead).

A 32-bit number you can represent in just 8 hex digits, or 6 Base64 digits.

And of course, if you only need a smaller range, and/or less precision,
you can represent the DateTime in even fewer characters.

Hopefully the above gives you the basic idea. If you need something
more specific, you need to ask a more specific question, including
details such as the specific range you need to represent and what
precision is required.

Pete
 
M

Mark B

Thanks.

I wrote the following and it works. However as you said Base64 would be
shorter. If you are able to say what changes I'd need to make to change it
to Base64 I'd appreciate it. I only need precision to seconds. The datetime
values will always be greater than 1/1/2000. It is for a transaction
timestamp so I guess we shouldn't really have an upper limit unless we plan
to make a code change in a hundred years...

Here's the code:

class cDateMethods
{
public string mConvertUTCDateTimeToHex(DateTime dtDateTimeIn)
{
//Convert DateTime to Hex
long decValue = dtDateTimeIn.Ticks;
string hexValue = decValue.ToString("X");
return hexValue;
}

public DateTime mConvertHexToUTCDateTime(string strHex)
{
//Convert Hex To UTCDateTime
long decValue = long.Parse(strHex,
System.Globalization.NumberStyles.HexNumber);
DateTime dt = new DateTime(decValue);
return dt;
}

public DateTime mTest()
{
//Convert Hex To UTCDateTime
DateTime test = DateTime.UtcNow;
string strHex = mConvertUTCDateTimeToHex(test);
DateTime test2 = mConvertHexToUTCDateTime(strHex);

return test2;

}
 
P

Peter Duniho

Mark said:
Thanks.

I wrote the following and it works. However as you said Base64 would be
shorter. If you are able to say what changes I'd need to make to change
it to Base64 I'd appreciate it.

You can use the Convert class to convert to and from Base64. See the
ToBase64String() and FromBase64String() methods.

You can calculate an integer count of seconds by using the
DateTime.TotalSeconds property. For example:

DateTime dtBase = new DateTime(2000, 1, 1);
DateTime dtValue = ...;
int seconds = (int)(dtValue.TotalSeconds - dtBase.TotalSeconds);

Then just store the value of "seconds" instead of the Ticks. Convert
back simply by calling dtBase.AddSeconds() with your parsed "seconds"
value from the URL.

Pete
 
M

Mark B

Thanks. I have re-coded as below and mTest() works -- it returns the current
date/time. I have a few questions:

1) It always seems to put two equal signs at the end of the string no matter
what: "BJ+UEg==". Should I truncate them from the URL since they seem to be
superfluous and then add them back later when perform
mConvertBase64StringToUTCDateTime()?

2) The PC's that use the code could be anywhere in the world with any
Language setting (e.g Chinese, Arabic, English etc) . I'll assume the code
below would be Region independant?

3) I saw some code comments on the net that said the LittleEndian test was
needed in case the system archicture is different. As above, the users could
be on different PC's around the world. Do I need to uncomment the code and
if so would I then need to put it in mConvertBase64StringToUTCDateTime()
too?

TIA -- I am quite new to C#.



class cDateMethods
{
public string mConvertUTCDateTimeToBase64String(DateTime
dtDateTimeIn)
{
//Convert DateTime to Base64String
DateTime dtBase = new DateTime(2000, 1, 1); //Base
time
TimeSpan dtDifference = dtDateTimeIn.Subtract(dtBase);
int totalSeconds = (int) dtDifference.TotalSeconds;
byte[] totalSecondsArray = BitConverter.GetBytes(totalSeconds);
//if (BitConverter.IsLittleEndian)
//{
// Array.Reverse(totalSecondsArray);
//}
string strBase64 = Convert.ToBase64String(totalSecondsArray);

return strBase64;

}

public DateTime mConvertBase64StringToUTCDateTime(string
strBase64String)
{
//Convert Base64String To UTCDateTime
byte[] totalSecondsArray =
Convert.FromBase64String(strBase64String);
int totalSeconds = BitConverter.ToInt32(totalSecondsArray,0);
DateTime dtBase = new DateTime(2000, 1, 1);
DateTime dtDateValue = dtBase.AddSeconds(totalSeconds);

return dtDateValue;
}


public DateTime mTest()
{
//Convert Base64String To UTCDateTime
DateTime test = DateTime.UtcNow;
string strBase64 = mConvertUTCDateTimeToBase64String(test);
DateTime test2 = mConvertBase64StringToUTCDateTime(strBase64);

return test2;

}

}
 
P

Peter Duniho

Mark said:
Thanks. I have re-coded as below and mTest() works -- it returns the
current date/time. I have a few questions:

1) It always seems to put two equal signs at the end of the string no
matter what: "BJ+UEg==". Should I truncate them from the URL since they
seem to be superfluous and then add them back later when perform
mConvertBase64StringToUTCDateTime()?

Yes. For details, see http://tools.ietf.org/html/rfc3548

Basically, the '=' character is used to make sure the data is a multiple
of 24 bits (LCM of 6 and 8). Since you know the length of the data in
advance, it's safe to not store the padding, replacing it before
converting back (actually, it's possible the FromBase64String() method
will fill it in as necessary if you pass it an incomplete string...I
don't remember, but it's worth a try).
2) The PC's that use the code could be anywhere in the world with any
Language setting (e.g Chinese, Arabic, English etc) . I'll assume the
code below would be Region independant?

Yes. While the string returned is Unicode (just like any .NET string),
it will always use the characters from the range 32-127; i.e. valid
ASCII characters.
3) I saw some code comments on the net that said the LittleEndian test
was needed in case the system archicture is different. As above, the
users could be on different PC's around the world. Do I need to
uncomment the code and if so would I then need to put it in
mConvertBase64StringToUTCDateTime() too?

It depends on the context. If this is data that can cross between
architectures, then yes...you should detect and handle endianness
correctly. But, if you're embedding it in a URL, that suggests the same
entity (e.g. web server) that issues the encoded data is going to be the
entity that receives and decodes that data later.

If you do decide you need to handle endianness, keep in mind:

-- Little-endian is more common in the .NET world, so unless you
have specific knowledge to the contrary about the prevalent architecture
your code will run on, you should probably encode the data as
little-endian, swapping bytes only if the architecture is big-endian.

-- Here, you are encoding just a single 32-bit integer, and so
reversing the entire byte array is fine. But obviously if you apply
this technique to longer collections of data, you need to make sure you
are reversing bytes at the individual data element level (e.g. every 4
bytes if it's an array of 32-bit integers, etc.).

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top