-2

I have DatetimeOffset value stored as below in my database table :

2002-08-27 07:49:20.3190000 -11:00

Now this is how i write this value in a binary file :

DateTimeOffset d = "2002-08-27 07:49:20.3190000 -11:00";
BinaryWriter w ;
w.Write(d.Ticks);

Now when i try to read this value using binary reader then it is generating incorrectly like below based on Ticks :

BinaryReader r;
var dateTime = DateTime.FromBinary(r.ReadInt64());
return new DateTimeOffset(dateTime);

Output : 8/27/2002 7:49:20 AM +05:30

How this is happening?

How to construct exact DatetimeOffset object properly based on Ticks?

Ehsan Sajjad
  • 61,834
  • 16
  • 105
  • 160
I Love Stackoverflow
  • 6,738
  • 20
  • 97
  • 216
  • What timezone do you live in? Could you simplify your code example above even further by removing the `BinaryWriter` / `BinaryReader`? – mjwills Jan 22 '19 at 10:41
  • 2
    A `DateTimeOffset` includes time zone information that is not part of the ticks. By writing just the ticks and not the tz, you get the same data as if you were using a `DateTime` – vc 74 Jan 22 '19 at 10:42
  • @mjwills But how does that matter?I have values stored in my tables so i am just trying to write it and then read it again for some purpose.Sorry if i have miss something related to DatetimeOffset datatype because i have not worked with it in the past – I Love Stackoverflow Jan 22 '19 at 10:43
  • 1
    `But how does that matter?` I am trying to teach you how to fish. You may also find https://learn.microsoft.com/en-us/dotnet/api/system.datetimeoffset.ticks?view=netframework-4.7.2#remarks of interest. – mjwills Jan 22 '19 at 10:44
  • Possible duplicate of [Best practices with saving datetime & timezone info in database when data is dependant on datetime](https://stackoverflow.com/questions/44965545/best-practices-with-saving-datetime-timezone-info-in-database-when-data-is-dep) – mjwills Jan 22 '19 at 10:47
  • 2
    To a certain extent, you are lucky this works **at all**. The thing you are writing is completely different to the thing you are reading. `DateTime.FromBinary` is designed to read data generated using `DateTime.ToBinary`. It just so happens that `DateTimeOffset.Ticks` generates data that is _roughly_ equivalent to it. – mjwills Jan 22 '19 at 10:54
  • BinaryWriter doesnt have any method to write datetimeoffser hence i have only 1 option left that is to write Ticks of write method and same i need to do when reading.Is there any other way to read and write datetimeoffset value? – I Love Stackoverflow Jan 22 '19 at 10:56
  • Have you considered serialising to JSON instead? https://stackoverflow.com/a/25105519/34092 – mjwills Jan 22 '19 at 11:02
  • @MrBean There are several ways, DT+TZ as longs, string using round trip format... – vc 74 Jan 22 '19 at 11:03

1 Answers1

1

You need to store both the UTC ticks and the timezone offset:

DateTimeOffset d = "2002-08-27 07:49:20.3190000 -11:00";
BinaryWriter w;
w.Write(d.Ticks);
w.Write(d.Offset.Ticks);

BinaryReader r;
var dateTime = new DateTime(r.ReadInt64());
var offset = new TimeSpan(r.ReadInt64());
return new DateTimeOffset(dateTime, offset);
vc 74
  • 37,131
  • 7
  • 73
  • 89
  • Upvoted for your kind efforts towards helping me.Thank you so much.Is it possible to combine both the UTC ticks and the timezone offset and just write it once instead writing twice? – I Love Stackoverflow Jan 22 '19 at 10:52
  • Your writer probably supports streaming, writing twice is not an issue. If you really want to store a single value, you can convert the `DateTimeOffset` to a string using the round trip format. – vc 74 Jan 22 '19 at 11:01
  • I am using this class from .net Library : https://learn.microsoft.com/en-us/dotnet/api/system.io.binarywriter?view=netframework-4.7.2 – I Love Stackoverflow Jan 22 '19 at 11:02
  • I mean, the `Stream` to which your writer writes, not the `BinaryWriter` itself. – vc 74 Jan 22 '19 at 11:08
  • I wanted to ask you that suppose if i have a datetimeoffser value stored inside database table so it is possible to read it using base DbDataReader class method GetDatetime and then construct datetimeoffset object? – I Love Stackoverflow Jan 22 '19 at 11:53
  • If the data is stored as a timestamp in the db, it may contain tz information which can be read by DbDataReader. If it's stored as a plain date/time, you have to know which time zone the data/time is associated to and build the `DateTimeOffset` manually. – vc 74 Jan 22 '19 at 12:05
  • Also, look [at the source for `DateTimeOffset`](https://referencesource.microsoft.com/#mscorlib/system/datetimeoffset.cs). It stores a datetime (64 bits) and an offset (16 bits). So you could use less bits for the offset portion. (You need 80 bits total, not 128). Also it implements `ISerializable`, so you don't really have to do this work manually. Just use a `BinaryFormatter`. – Matt Johnson-Pint Jan 22 '19 at 18:31