Unix Timestamp: Difference between using ToUnixTimeMilliseconds and TimeSpan.TotalMilliseconds












6














I am converting a DateTime to Unix time. As I understand these two ways should return teh same result.



Option 1



DateTime dtfoo = new DateTime(2010, 10, 20);
DateTimeOffset dtfoo2 = new DateTimeOffset(dtfoo).ToUniversalTime();
long afoo = dtfoo2.ToUnixTimeMilliseconds();


Option 2



DateTime dtfoo = new DateTime(2010, 10, 20);
DateTimeOffset dtfoo2 = new DateTimeOffset(dtfoo).ToUniversalTime();
long afoo = (Int64)(dtfoo2.Subtract(new DateTime(1970, 1, 1))).TotalMilliseconds;


Option 1 returns 1287525600000 and Option2 returns 1287529200000.



Why am I getting different results?










share|improve this question
























  • FYI, the source for ToUnitTimeMilliseconds is here: github.com/dotnet/corefx/blob/master/src/Common/src/CoreLib/…
    – Evan Trimboli
    Nov 15 at 21:30










  • What happens if you Subtract(new DateTime(1970, 1, 1).ToUniversalTime())?
    – CompuChip
    Nov 15 at 21:32










  • The source code tells: " Truncate sub-millisecond precision before offsetting by the Unix Epoch to avoid the last digit being off by one for dates that result in negative Unix times". Is it because of this truncate that I am loosing precision?
    – user9923760
    Nov 15 at 21:34






  • 1




    The issue is to do with local/universal DateTime objects in use in your code, and how new DateTimeOffset(dateTime) works if you do not specify an offset. I've got a small example here and will post an answer in full this evening.
    – John
    Nov 16 at 6:42






  • 1




    I'd recommend instead using an ISO8601 date time (i.e. DateTime.UtcNow.ToString("o")) instead. momentjs works well with them and, to be honest, it's the future vs unix timestamp.
    – John
    Nov 19 at 8:49
















6














I am converting a DateTime to Unix time. As I understand these two ways should return teh same result.



Option 1



DateTime dtfoo = new DateTime(2010, 10, 20);
DateTimeOffset dtfoo2 = new DateTimeOffset(dtfoo).ToUniversalTime();
long afoo = dtfoo2.ToUnixTimeMilliseconds();


Option 2



DateTime dtfoo = new DateTime(2010, 10, 20);
DateTimeOffset dtfoo2 = new DateTimeOffset(dtfoo).ToUniversalTime();
long afoo = (Int64)(dtfoo2.Subtract(new DateTime(1970, 1, 1))).TotalMilliseconds;


Option 1 returns 1287525600000 and Option2 returns 1287529200000.



Why am I getting different results?










share|improve this question
























  • FYI, the source for ToUnitTimeMilliseconds is here: github.com/dotnet/corefx/blob/master/src/Common/src/CoreLib/…
    – Evan Trimboli
    Nov 15 at 21:30










  • What happens if you Subtract(new DateTime(1970, 1, 1).ToUniversalTime())?
    – CompuChip
    Nov 15 at 21:32










  • The source code tells: " Truncate sub-millisecond precision before offsetting by the Unix Epoch to avoid the last digit being off by one for dates that result in negative Unix times". Is it because of this truncate that I am loosing precision?
    – user9923760
    Nov 15 at 21:34






  • 1




    The issue is to do with local/universal DateTime objects in use in your code, and how new DateTimeOffset(dateTime) works if you do not specify an offset. I've got a small example here and will post an answer in full this evening.
    – John
    Nov 16 at 6:42






  • 1




    I'd recommend instead using an ISO8601 date time (i.e. DateTime.UtcNow.ToString("o")) instead. momentjs works well with them and, to be honest, it's the future vs unix timestamp.
    – John
    Nov 19 at 8:49














6












6








6


1





I am converting a DateTime to Unix time. As I understand these two ways should return teh same result.



Option 1



DateTime dtfoo = new DateTime(2010, 10, 20);
DateTimeOffset dtfoo2 = new DateTimeOffset(dtfoo).ToUniversalTime();
long afoo = dtfoo2.ToUnixTimeMilliseconds();


Option 2



DateTime dtfoo = new DateTime(2010, 10, 20);
DateTimeOffset dtfoo2 = new DateTimeOffset(dtfoo).ToUniversalTime();
long afoo = (Int64)(dtfoo2.Subtract(new DateTime(1970, 1, 1))).TotalMilliseconds;


Option 1 returns 1287525600000 and Option2 returns 1287529200000.



Why am I getting different results?










share|improve this question















I am converting a DateTime to Unix time. As I understand these two ways should return teh same result.



Option 1



DateTime dtfoo = new DateTime(2010, 10, 20);
DateTimeOffset dtfoo2 = new DateTimeOffset(dtfoo).ToUniversalTime();
long afoo = dtfoo2.ToUnixTimeMilliseconds();


Option 2



DateTime dtfoo = new DateTime(2010, 10, 20);
DateTimeOffset dtfoo2 = new DateTimeOffset(dtfoo).ToUniversalTime();
long afoo = (Int64)(dtfoo2.Subtract(new DateTime(1970, 1, 1))).TotalMilliseconds;


Option 1 returns 1287525600000 and Option2 returns 1287529200000.



Why am I getting different results?







c# datetime unix-timestamp






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 16 at 6:28









Soner Gönül

79.8k26147271




79.8k26147271










asked Nov 15 at 21:25









user9923760

1079




1079












  • FYI, the source for ToUnitTimeMilliseconds is here: github.com/dotnet/corefx/blob/master/src/Common/src/CoreLib/…
    – Evan Trimboli
    Nov 15 at 21:30










  • What happens if you Subtract(new DateTime(1970, 1, 1).ToUniversalTime())?
    – CompuChip
    Nov 15 at 21:32










  • The source code tells: " Truncate sub-millisecond precision before offsetting by the Unix Epoch to avoid the last digit being off by one for dates that result in negative Unix times". Is it because of this truncate that I am loosing precision?
    – user9923760
    Nov 15 at 21:34






  • 1




    The issue is to do with local/universal DateTime objects in use in your code, and how new DateTimeOffset(dateTime) works if you do not specify an offset. I've got a small example here and will post an answer in full this evening.
    – John
    Nov 16 at 6:42






  • 1




    I'd recommend instead using an ISO8601 date time (i.e. DateTime.UtcNow.ToString("o")) instead. momentjs works well with them and, to be honest, it's the future vs unix timestamp.
    – John
    Nov 19 at 8:49


















  • FYI, the source for ToUnitTimeMilliseconds is here: github.com/dotnet/corefx/blob/master/src/Common/src/CoreLib/…
    – Evan Trimboli
    Nov 15 at 21:30










  • What happens if you Subtract(new DateTime(1970, 1, 1).ToUniversalTime())?
    – CompuChip
    Nov 15 at 21:32










  • The source code tells: " Truncate sub-millisecond precision before offsetting by the Unix Epoch to avoid the last digit being off by one for dates that result in negative Unix times". Is it because of this truncate that I am loosing precision?
    – user9923760
    Nov 15 at 21:34






  • 1




    The issue is to do with local/universal DateTime objects in use in your code, and how new DateTimeOffset(dateTime) works if you do not specify an offset. I've got a small example here and will post an answer in full this evening.
    – John
    Nov 16 at 6:42






  • 1




    I'd recommend instead using an ISO8601 date time (i.e. DateTime.UtcNow.ToString("o")) instead. momentjs works well with them and, to be honest, it's the future vs unix timestamp.
    – John
    Nov 19 at 8:49
















FYI, the source for ToUnitTimeMilliseconds is here: github.com/dotnet/corefx/blob/master/src/Common/src/CoreLib/…
– Evan Trimboli
Nov 15 at 21:30




FYI, the source for ToUnitTimeMilliseconds is here: github.com/dotnet/corefx/blob/master/src/Common/src/CoreLib/…
– Evan Trimboli
Nov 15 at 21:30












What happens if you Subtract(new DateTime(1970, 1, 1).ToUniversalTime())?
– CompuChip
Nov 15 at 21:32




What happens if you Subtract(new DateTime(1970, 1, 1).ToUniversalTime())?
– CompuChip
Nov 15 at 21:32












The source code tells: " Truncate sub-millisecond precision before offsetting by the Unix Epoch to avoid the last digit being off by one for dates that result in negative Unix times". Is it because of this truncate that I am loosing precision?
– user9923760
Nov 15 at 21:34




The source code tells: " Truncate sub-millisecond precision before offsetting by the Unix Epoch to avoid the last digit being off by one for dates that result in negative Unix times". Is it because of this truncate that I am loosing precision?
– user9923760
Nov 15 at 21:34




1




1




The issue is to do with local/universal DateTime objects in use in your code, and how new DateTimeOffset(dateTime) works if you do not specify an offset. I've got a small example here and will post an answer in full this evening.
– John
Nov 16 at 6:42




The issue is to do with local/universal DateTime objects in use in your code, and how new DateTimeOffset(dateTime) works if you do not specify an offset. I've got a small example here and will post an answer in full this evening.
– John
Nov 16 at 6:42




1




1




I'd recommend instead using an ISO8601 date time (i.e. DateTime.UtcNow.ToString("o")) instead. momentjs works well with them and, to be honest, it's the future vs unix timestamp.
– John
Nov 19 at 8:49




I'd recommend instead using an ISO8601 date time (i.e. DateTime.UtcNow.ToString("o")) instead. momentjs works well with them and, to be honest, it's the future vs unix timestamp.
– John
Nov 19 at 8:49












2 Answers
2






active

oldest

votes


















3














Notice: I am in UTC+9, and the root of your issues come from timezone offsets, so understand that the unix times I see may differ slightly from your own.





The difference lies in how you're handling your date objects. I'm assuming from the resultant difference that your timezone is CET (or you were using rextester, which I believe is in Germany).



Consider the following code:



var dtfoo = new DateTime(2010, 10, 20);
var dtfoo2 = new DateTimeOffset(dtfoo);
var dtfoo3 = dtfoo2.ToUniversalTime();



  1. The first line creates a DateTime with a DateTimeKind of "Unspecified".

  2. The second line creates a DateTimeOffset object from this. Because the DateTimeKind is Unspecified, the system time offset from UTC is used.

  3. The third line converts this date into UTC.


Quoting the documentation for #2:




If the value of DateTime.Kind is DateTimeKind.Local or DateTimeKind.Unspecified, the DateTime property of the new instance is set equal to dateTime, and the Offset property is set equal to the offset of the local system's current time zone.




Now let's write out the roundtrip format date string for 1-3:



2010-10-20T00:00:00.0000000
2010-10-20T00:00:00.0000000+09:00
2010-10-19T15:00:00.0000000+00:00


I'm in UTC+9, so the DateTimeOffset was rightly created with an offset of +9h. Converting that to universal takes us to 3pm on the 19th. Unfortunately, this causes the output of .ToUnixTimeMilliseconds() to be 1287500400000, which is 2010-10-19T15:00:00Z. The value has become dependent on the machine's timezone.



So, now let's take a look at your second example:



DateTime dtfoo = new DateTime(2010, 10, 20);
DateTimeOffset dtfoo2 = new DateTimeOffset(dtfoo).ToUniversalTime();
long afoo = (Int64)(dtfoo2.Subtract(new DateTime(1970, 1, 1))).TotalMilliseconds;


OK, let's split this into the different parts so that we can see what time the system thinks they represent (remember that I'm in UTC+9):





  1. new DateTime(2010, 10, 20).ToString("o") - 2010-10-20T00:00:00.0000000


  2. new DateTimeOffset(dtfoo).ToString("o") - 2010-10-20T00:00:00.0000000+09:00


  3. new DateTimeOffset(dtfoo).ToUniversalTime() - 2010-10-19T15:00:00.0000000+00:00


  4. new DateTime(1970, 1, 1).ToString("o") - 1970-01-01T00:00:00.0000000


So you're effectively performing this calculation:



(DateTimeOffset.Parse("2010-10-19T15:00:00.0000000+00:00") - DateTime.Parse("1970-01-01T00:00:00.0000000")).TotalMilliseconds


This outputs 1287532800000, which equates to 2010-10-20T00:00:00Z. This gives you the correct result because of how the subtraction is done:




  1. The DateTime is implicitly cast to a DateTimeOffset, equivalent to new DateTimeOffset(DateTime.Parse("1970-01-01T00:00:00.000000")) - this means that both input dates have been through the same timezone changes.

  2. The two dates for subtraction are both converted to DateTime objects by calling the DateTimeOffset's .UtcDateTime property.


So how can we fix your original example? We can take the local timezone offset out of the equation by specifying the offset when constructing the DateTimeOffset:



DateTime dtfoo = new DateTime(2010, 10, 20);
DateTimeOffset dtfoo2 = new DateTimeOffset(dtfoo, TimeSpan.Zero).ToUniversalTime();
long afoo = dtfoo2.ToUnixTimeMilliseconds();


This now gives us the same value as we got in the previous test: 1287532800000. If we simplify this by using DateTimeOffset.Parse we should confirm that we're on the right track:



Console.WriteLine(DateTimeOffset.Parse("2010-10-20T00:00:00Z").ToUnixTimeMilliseconds());


And we can see that this also outputs 1287532800000.



So, to conclude, your issue stems from how the DateTimeOffset(datetime) constructor handles dates with DateTimeKind Unspecified or Local. It skews your resulting universal time depending on your machine's timezone. This leads to an incorrect unix time offset. To solve it simply create your DateTimeOffset in one of the ways I have described above.






share|improve this answer































    0














    The difference could be because ToUnixTimeMilliseconds does not take leap seconds in to account.



    here is what documentation says:



    https://docs.microsoft.com/en-us/dotnet/api/system.datetimeoffset.tounixtimemilliseconds?view=netframework-4.7.2




    Unix time represents the number of seconds that have elapsed since
    1970-01-01T00:00:00Z (January 1, 1970, at 12:00 AM UTC). It does not
    take leap seconds into account. This method returns the number of
    milliseconds in Unix time.




    Where as TimeSpan.TotalMilliseconds did not speak about that.



    https://docs.microsoft.com/en-us/dotnet/api/system.timespan.totalmilliseconds?view=netframework-4.7.2




    This property converts the value of this instance from ticks to
    milliseconds. This number might include whole and fractional
    milliseconds.







    share|improve this answer





















    • It does not take leap seconds into account: what are they exactly meaning?
      – user9923760
      Nov 15 at 23:22






    • 2




      Here are more details en.wikipedia.org/wiki/Leap_second
      – Naidu
      Nov 15 at 23:23






    • 2




      If the issue was leap seconds, then I would expect a difference of a few seconds (27), not exactly 1 hour.
      – Hans Kesting
      Nov 16 at 15:29










    • Isn't it 37..... I see 36difference (excluding zeros)
      – Naidu
      Nov 16 at 15:30













    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53328114%2funix-timestamp-difference-between-using-tounixtimemilliseconds-and-timespan-tot%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    3














    Notice: I am in UTC+9, and the root of your issues come from timezone offsets, so understand that the unix times I see may differ slightly from your own.





    The difference lies in how you're handling your date objects. I'm assuming from the resultant difference that your timezone is CET (or you were using rextester, which I believe is in Germany).



    Consider the following code:



    var dtfoo = new DateTime(2010, 10, 20);
    var dtfoo2 = new DateTimeOffset(dtfoo);
    var dtfoo3 = dtfoo2.ToUniversalTime();



    1. The first line creates a DateTime with a DateTimeKind of "Unspecified".

    2. The second line creates a DateTimeOffset object from this. Because the DateTimeKind is Unspecified, the system time offset from UTC is used.

    3. The third line converts this date into UTC.


    Quoting the documentation for #2:




    If the value of DateTime.Kind is DateTimeKind.Local or DateTimeKind.Unspecified, the DateTime property of the new instance is set equal to dateTime, and the Offset property is set equal to the offset of the local system's current time zone.




    Now let's write out the roundtrip format date string for 1-3:



    2010-10-20T00:00:00.0000000
    2010-10-20T00:00:00.0000000+09:00
    2010-10-19T15:00:00.0000000+00:00


    I'm in UTC+9, so the DateTimeOffset was rightly created with an offset of +9h. Converting that to universal takes us to 3pm on the 19th. Unfortunately, this causes the output of .ToUnixTimeMilliseconds() to be 1287500400000, which is 2010-10-19T15:00:00Z. The value has become dependent on the machine's timezone.



    So, now let's take a look at your second example:



    DateTime dtfoo = new DateTime(2010, 10, 20);
    DateTimeOffset dtfoo2 = new DateTimeOffset(dtfoo).ToUniversalTime();
    long afoo = (Int64)(dtfoo2.Subtract(new DateTime(1970, 1, 1))).TotalMilliseconds;


    OK, let's split this into the different parts so that we can see what time the system thinks they represent (remember that I'm in UTC+9):





    1. new DateTime(2010, 10, 20).ToString("o") - 2010-10-20T00:00:00.0000000


    2. new DateTimeOffset(dtfoo).ToString("o") - 2010-10-20T00:00:00.0000000+09:00


    3. new DateTimeOffset(dtfoo).ToUniversalTime() - 2010-10-19T15:00:00.0000000+00:00


    4. new DateTime(1970, 1, 1).ToString("o") - 1970-01-01T00:00:00.0000000


    So you're effectively performing this calculation:



    (DateTimeOffset.Parse("2010-10-19T15:00:00.0000000+00:00") - DateTime.Parse("1970-01-01T00:00:00.0000000")).TotalMilliseconds


    This outputs 1287532800000, which equates to 2010-10-20T00:00:00Z. This gives you the correct result because of how the subtraction is done:




    1. The DateTime is implicitly cast to a DateTimeOffset, equivalent to new DateTimeOffset(DateTime.Parse("1970-01-01T00:00:00.000000")) - this means that both input dates have been through the same timezone changes.

    2. The two dates for subtraction are both converted to DateTime objects by calling the DateTimeOffset's .UtcDateTime property.


    So how can we fix your original example? We can take the local timezone offset out of the equation by specifying the offset when constructing the DateTimeOffset:



    DateTime dtfoo = new DateTime(2010, 10, 20);
    DateTimeOffset dtfoo2 = new DateTimeOffset(dtfoo, TimeSpan.Zero).ToUniversalTime();
    long afoo = dtfoo2.ToUnixTimeMilliseconds();


    This now gives us the same value as we got in the previous test: 1287532800000. If we simplify this by using DateTimeOffset.Parse we should confirm that we're on the right track:



    Console.WriteLine(DateTimeOffset.Parse("2010-10-20T00:00:00Z").ToUnixTimeMilliseconds());


    And we can see that this also outputs 1287532800000.



    So, to conclude, your issue stems from how the DateTimeOffset(datetime) constructor handles dates with DateTimeKind Unspecified or Local. It skews your resulting universal time depending on your machine's timezone. This leads to an incorrect unix time offset. To solve it simply create your DateTimeOffset in one of the ways I have described above.






    share|improve this answer




























      3














      Notice: I am in UTC+9, and the root of your issues come from timezone offsets, so understand that the unix times I see may differ slightly from your own.





      The difference lies in how you're handling your date objects. I'm assuming from the resultant difference that your timezone is CET (or you were using rextester, which I believe is in Germany).



      Consider the following code:



      var dtfoo = new DateTime(2010, 10, 20);
      var dtfoo2 = new DateTimeOffset(dtfoo);
      var dtfoo3 = dtfoo2.ToUniversalTime();



      1. The first line creates a DateTime with a DateTimeKind of "Unspecified".

      2. The second line creates a DateTimeOffset object from this. Because the DateTimeKind is Unspecified, the system time offset from UTC is used.

      3. The third line converts this date into UTC.


      Quoting the documentation for #2:




      If the value of DateTime.Kind is DateTimeKind.Local or DateTimeKind.Unspecified, the DateTime property of the new instance is set equal to dateTime, and the Offset property is set equal to the offset of the local system's current time zone.




      Now let's write out the roundtrip format date string for 1-3:



      2010-10-20T00:00:00.0000000
      2010-10-20T00:00:00.0000000+09:00
      2010-10-19T15:00:00.0000000+00:00


      I'm in UTC+9, so the DateTimeOffset was rightly created with an offset of +9h. Converting that to universal takes us to 3pm on the 19th. Unfortunately, this causes the output of .ToUnixTimeMilliseconds() to be 1287500400000, which is 2010-10-19T15:00:00Z. The value has become dependent on the machine's timezone.



      So, now let's take a look at your second example:



      DateTime dtfoo = new DateTime(2010, 10, 20);
      DateTimeOffset dtfoo2 = new DateTimeOffset(dtfoo).ToUniversalTime();
      long afoo = (Int64)(dtfoo2.Subtract(new DateTime(1970, 1, 1))).TotalMilliseconds;


      OK, let's split this into the different parts so that we can see what time the system thinks they represent (remember that I'm in UTC+9):





      1. new DateTime(2010, 10, 20).ToString("o") - 2010-10-20T00:00:00.0000000


      2. new DateTimeOffset(dtfoo).ToString("o") - 2010-10-20T00:00:00.0000000+09:00


      3. new DateTimeOffset(dtfoo).ToUniversalTime() - 2010-10-19T15:00:00.0000000+00:00


      4. new DateTime(1970, 1, 1).ToString("o") - 1970-01-01T00:00:00.0000000


      So you're effectively performing this calculation:



      (DateTimeOffset.Parse("2010-10-19T15:00:00.0000000+00:00") - DateTime.Parse("1970-01-01T00:00:00.0000000")).TotalMilliseconds


      This outputs 1287532800000, which equates to 2010-10-20T00:00:00Z. This gives you the correct result because of how the subtraction is done:




      1. The DateTime is implicitly cast to a DateTimeOffset, equivalent to new DateTimeOffset(DateTime.Parse("1970-01-01T00:00:00.000000")) - this means that both input dates have been through the same timezone changes.

      2. The two dates for subtraction are both converted to DateTime objects by calling the DateTimeOffset's .UtcDateTime property.


      So how can we fix your original example? We can take the local timezone offset out of the equation by specifying the offset when constructing the DateTimeOffset:



      DateTime dtfoo = new DateTime(2010, 10, 20);
      DateTimeOffset dtfoo2 = new DateTimeOffset(dtfoo, TimeSpan.Zero).ToUniversalTime();
      long afoo = dtfoo2.ToUnixTimeMilliseconds();


      This now gives us the same value as we got in the previous test: 1287532800000. If we simplify this by using DateTimeOffset.Parse we should confirm that we're on the right track:



      Console.WriteLine(DateTimeOffset.Parse("2010-10-20T00:00:00Z").ToUnixTimeMilliseconds());


      And we can see that this also outputs 1287532800000.



      So, to conclude, your issue stems from how the DateTimeOffset(datetime) constructor handles dates with DateTimeKind Unspecified or Local. It skews your resulting universal time depending on your machine's timezone. This leads to an incorrect unix time offset. To solve it simply create your DateTimeOffset in one of the ways I have described above.






      share|improve this answer


























        3












        3








        3






        Notice: I am in UTC+9, and the root of your issues come from timezone offsets, so understand that the unix times I see may differ slightly from your own.





        The difference lies in how you're handling your date objects. I'm assuming from the resultant difference that your timezone is CET (or you were using rextester, which I believe is in Germany).



        Consider the following code:



        var dtfoo = new DateTime(2010, 10, 20);
        var dtfoo2 = new DateTimeOffset(dtfoo);
        var dtfoo3 = dtfoo2.ToUniversalTime();



        1. The first line creates a DateTime with a DateTimeKind of "Unspecified".

        2. The second line creates a DateTimeOffset object from this. Because the DateTimeKind is Unspecified, the system time offset from UTC is used.

        3. The third line converts this date into UTC.


        Quoting the documentation for #2:




        If the value of DateTime.Kind is DateTimeKind.Local or DateTimeKind.Unspecified, the DateTime property of the new instance is set equal to dateTime, and the Offset property is set equal to the offset of the local system's current time zone.




        Now let's write out the roundtrip format date string for 1-3:



        2010-10-20T00:00:00.0000000
        2010-10-20T00:00:00.0000000+09:00
        2010-10-19T15:00:00.0000000+00:00


        I'm in UTC+9, so the DateTimeOffset was rightly created with an offset of +9h. Converting that to universal takes us to 3pm on the 19th. Unfortunately, this causes the output of .ToUnixTimeMilliseconds() to be 1287500400000, which is 2010-10-19T15:00:00Z. The value has become dependent on the machine's timezone.



        So, now let's take a look at your second example:



        DateTime dtfoo = new DateTime(2010, 10, 20);
        DateTimeOffset dtfoo2 = new DateTimeOffset(dtfoo).ToUniversalTime();
        long afoo = (Int64)(dtfoo2.Subtract(new DateTime(1970, 1, 1))).TotalMilliseconds;


        OK, let's split this into the different parts so that we can see what time the system thinks they represent (remember that I'm in UTC+9):





        1. new DateTime(2010, 10, 20).ToString("o") - 2010-10-20T00:00:00.0000000


        2. new DateTimeOffset(dtfoo).ToString("o") - 2010-10-20T00:00:00.0000000+09:00


        3. new DateTimeOffset(dtfoo).ToUniversalTime() - 2010-10-19T15:00:00.0000000+00:00


        4. new DateTime(1970, 1, 1).ToString("o") - 1970-01-01T00:00:00.0000000


        So you're effectively performing this calculation:



        (DateTimeOffset.Parse("2010-10-19T15:00:00.0000000+00:00") - DateTime.Parse("1970-01-01T00:00:00.0000000")).TotalMilliseconds


        This outputs 1287532800000, which equates to 2010-10-20T00:00:00Z. This gives you the correct result because of how the subtraction is done:




        1. The DateTime is implicitly cast to a DateTimeOffset, equivalent to new DateTimeOffset(DateTime.Parse("1970-01-01T00:00:00.000000")) - this means that both input dates have been through the same timezone changes.

        2. The two dates for subtraction are both converted to DateTime objects by calling the DateTimeOffset's .UtcDateTime property.


        So how can we fix your original example? We can take the local timezone offset out of the equation by specifying the offset when constructing the DateTimeOffset:



        DateTime dtfoo = new DateTime(2010, 10, 20);
        DateTimeOffset dtfoo2 = new DateTimeOffset(dtfoo, TimeSpan.Zero).ToUniversalTime();
        long afoo = dtfoo2.ToUnixTimeMilliseconds();


        This now gives us the same value as we got in the previous test: 1287532800000. If we simplify this by using DateTimeOffset.Parse we should confirm that we're on the right track:



        Console.WriteLine(DateTimeOffset.Parse("2010-10-20T00:00:00Z").ToUnixTimeMilliseconds());


        And we can see that this also outputs 1287532800000.



        So, to conclude, your issue stems from how the DateTimeOffset(datetime) constructor handles dates with DateTimeKind Unspecified or Local. It skews your resulting universal time depending on your machine's timezone. This leads to an incorrect unix time offset. To solve it simply create your DateTimeOffset in one of the ways I have described above.






        share|improve this answer














        Notice: I am in UTC+9, and the root of your issues come from timezone offsets, so understand that the unix times I see may differ slightly from your own.





        The difference lies in how you're handling your date objects. I'm assuming from the resultant difference that your timezone is CET (or you were using rextester, which I believe is in Germany).



        Consider the following code:



        var dtfoo = new DateTime(2010, 10, 20);
        var dtfoo2 = new DateTimeOffset(dtfoo);
        var dtfoo3 = dtfoo2.ToUniversalTime();



        1. The first line creates a DateTime with a DateTimeKind of "Unspecified".

        2. The second line creates a DateTimeOffset object from this. Because the DateTimeKind is Unspecified, the system time offset from UTC is used.

        3. The third line converts this date into UTC.


        Quoting the documentation for #2:




        If the value of DateTime.Kind is DateTimeKind.Local or DateTimeKind.Unspecified, the DateTime property of the new instance is set equal to dateTime, and the Offset property is set equal to the offset of the local system's current time zone.




        Now let's write out the roundtrip format date string for 1-3:



        2010-10-20T00:00:00.0000000
        2010-10-20T00:00:00.0000000+09:00
        2010-10-19T15:00:00.0000000+00:00


        I'm in UTC+9, so the DateTimeOffset was rightly created with an offset of +9h. Converting that to universal takes us to 3pm on the 19th. Unfortunately, this causes the output of .ToUnixTimeMilliseconds() to be 1287500400000, which is 2010-10-19T15:00:00Z. The value has become dependent on the machine's timezone.



        So, now let's take a look at your second example:



        DateTime dtfoo = new DateTime(2010, 10, 20);
        DateTimeOffset dtfoo2 = new DateTimeOffset(dtfoo).ToUniversalTime();
        long afoo = (Int64)(dtfoo2.Subtract(new DateTime(1970, 1, 1))).TotalMilliseconds;


        OK, let's split this into the different parts so that we can see what time the system thinks they represent (remember that I'm in UTC+9):





        1. new DateTime(2010, 10, 20).ToString("o") - 2010-10-20T00:00:00.0000000


        2. new DateTimeOffset(dtfoo).ToString("o") - 2010-10-20T00:00:00.0000000+09:00


        3. new DateTimeOffset(dtfoo).ToUniversalTime() - 2010-10-19T15:00:00.0000000+00:00


        4. new DateTime(1970, 1, 1).ToString("o") - 1970-01-01T00:00:00.0000000


        So you're effectively performing this calculation:



        (DateTimeOffset.Parse("2010-10-19T15:00:00.0000000+00:00") - DateTime.Parse("1970-01-01T00:00:00.0000000")).TotalMilliseconds


        This outputs 1287532800000, which equates to 2010-10-20T00:00:00Z. This gives you the correct result because of how the subtraction is done:




        1. The DateTime is implicitly cast to a DateTimeOffset, equivalent to new DateTimeOffset(DateTime.Parse("1970-01-01T00:00:00.000000")) - this means that both input dates have been through the same timezone changes.

        2. The two dates for subtraction are both converted to DateTime objects by calling the DateTimeOffset's .UtcDateTime property.


        So how can we fix your original example? We can take the local timezone offset out of the equation by specifying the offset when constructing the DateTimeOffset:



        DateTime dtfoo = new DateTime(2010, 10, 20);
        DateTimeOffset dtfoo2 = new DateTimeOffset(dtfoo, TimeSpan.Zero).ToUniversalTime();
        long afoo = dtfoo2.ToUnixTimeMilliseconds();


        This now gives us the same value as we got in the previous test: 1287532800000. If we simplify this by using DateTimeOffset.Parse we should confirm that we're on the right track:



        Console.WriteLine(DateTimeOffset.Parse("2010-10-20T00:00:00Z").ToUnixTimeMilliseconds());


        And we can see that this also outputs 1287532800000.



        So, to conclude, your issue stems from how the DateTimeOffset(datetime) constructor handles dates with DateTimeKind Unspecified or Local. It skews your resulting universal time depending on your machine's timezone. This leads to an incorrect unix time offset. To solve it simply create your DateTimeOffset in one of the ways I have described above.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 16 at 14:36

























        answered Nov 16 at 14:18









        John

        11.3k31736




        11.3k31736

























            0














            The difference could be because ToUnixTimeMilliseconds does not take leap seconds in to account.



            here is what documentation says:



            https://docs.microsoft.com/en-us/dotnet/api/system.datetimeoffset.tounixtimemilliseconds?view=netframework-4.7.2




            Unix time represents the number of seconds that have elapsed since
            1970-01-01T00:00:00Z (January 1, 1970, at 12:00 AM UTC). It does not
            take leap seconds into account. This method returns the number of
            milliseconds in Unix time.




            Where as TimeSpan.TotalMilliseconds did not speak about that.



            https://docs.microsoft.com/en-us/dotnet/api/system.timespan.totalmilliseconds?view=netframework-4.7.2




            This property converts the value of this instance from ticks to
            milliseconds. This number might include whole and fractional
            milliseconds.







            share|improve this answer





















            • It does not take leap seconds into account: what are they exactly meaning?
              – user9923760
              Nov 15 at 23:22






            • 2




              Here are more details en.wikipedia.org/wiki/Leap_second
              – Naidu
              Nov 15 at 23:23






            • 2




              If the issue was leap seconds, then I would expect a difference of a few seconds (27), not exactly 1 hour.
              – Hans Kesting
              Nov 16 at 15:29










            • Isn't it 37..... I see 36difference (excluding zeros)
              – Naidu
              Nov 16 at 15:30


















            0














            The difference could be because ToUnixTimeMilliseconds does not take leap seconds in to account.



            here is what documentation says:



            https://docs.microsoft.com/en-us/dotnet/api/system.datetimeoffset.tounixtimemilliseconds?view=netframework-4.7.2




            Unix time represents the number of seconds that have elapsed since
            1970-01-01T00:00:00Z (January 1, 1970, at 12:00 AM UTC). It does not
            take leap seconds into account. This method returns the number of
            milliseconds in Unix time.




            Where as TimeSpan.TotalMilliseconds did not speak about that.



            https://docs.microsoft.com/en-us/dotnet/api/system.timespan.totalmilliseconds?view=netframework-4.7.2




            This property converts the value of this instance from ticks to
            milliseconds. This number might include whole and fractional
            milliseconds.







            share|improve this answer





















            • It does not take leap seconds into account: what are they exactly meaning?
              – user9923760
              Nov 15 at 23:22






            • 2




              Here are more details en.wikipedia.org/wiki/Leap_second
              – Naidu
              Nov 15 at 23:23






            • 2




              If the issue was leap seconds, then I would expect a difference of a few seconds (27), not exactly 1 hour.
              – Hans Kesting
              Nov 16 at 15:29










            • Isn't it 37..... I see 36difference (excluding zeros)
              – Naidu
              Nov 16 at 15:30
















            0












            0








            0






            The difference could be because ToUnixTimeMilliseconds does not take leap seconds in to account.



            here is what documentation says:



            https://docs.microsoft.com/en-us/dotnet/api/system.datetimeoffset.tounixtimemilliseconds?view=netframework-4.7.2




            Unix time represents the number of seconds that have elapsed since
            1970-01-01T00:00:00Z (January 1, 1970, at 12:00 AM UTC). It does not
            take leap seconds into account. This method returns the number of
            milliseconds in Unix time.




            Where as TimeSpan.TotalMilliseconds did not speak about that.



            https://docs.microsoft.com/en-us/dotnet/api/system.timespan.totalmilliseconds?view=netframework-4.7.2




            This property converts the value of this instance from ticks to
            milliseconds. This number might include whole and fractional
            milliseconds.







            share|improve this answer












            The difference could be because ToUnixTimeMilliseconds does not take leap seconds in to account.



            here is what documentation says:



            https://docs.microsoft.com/en-us/dotnet/api/system.datetimeoffset.tounixtimemilliseconds?view=netframework-4.7.2




            Unix time represents the number of seconds that have elapsed since
            1970-01-01T00:00:00Z (January 1, 1970, at 12:00 AM UTC). It does not
            take leap seconds into account. This method returns the number of
            milliseconds in Unix time.




            Where as TimeSpan.TotalMilliseconds did not speak about that.



            https://docs.microsoft.com/en-us/dotnet/api/system.timespan.totalmilliseconds?view=netframework-4.7.2




            This property converts the value of this instance from ticks to
            milliseconds. This number might include whole and fractional
            milliseconds.








            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 15 at 23:16









            Naidu

            4,9093817




            4,9093817












            • It does not take leap seconds into account: what are they exactly meaning?
              – user9923760
              Nov 15 at 23:22






            • 2




              Here are more details en.wikipedia.org/wiki/Leap_second
              – Naidu
              Nov 15 at 23:23






            • 2




              If the issue was leap seconds, then I would expect a difference of a few seconds (27), not exactly 1 hour.
              – Hans Kesting
              Nov 16 at 15:29










            • Isn't it 37..... I see 36difference (excluding zeros)
              – Naidu
              Nov 16 at 15:30




















            • It does not take leap seconds into account: what are they exactly meaning?
              – user9923760
              Nov 15 at 23:22






            • 2




              Here are more details en.wikipedia.org/wiki/Leap_second
              – Naidu
              Nov 15 at 23:23






            • 2




              If the issue was leap seconds, then I would expect a difference of a few seconds (27), not exactly 1 hour.
              – Hans Kesting
              Nov 16 at 15:29










            • Isn't it 37..... I see 36difference (excluding zeros)
              – Naidu
              Nov 16 at 15:30


















            It does not take leap seconds into account: what are they exactly meaning?
            – user9923760
            Nov 15 at 23:22




            It does not take leap seconds into account: what are they exactly meaning?
            – user9923760
            Nov 15 at 23:22




            2




            2




            Here are more details en.wikipedia.org/wiki/Leap_second
            – Naidu
            Nov 15 at 23:23




            Here are more details en.wikipedia.org/wiki/Leap_second
            – Naidu
            Nov 15 at 23:23




            2




            2




            If the issue was leap seconds, then I would expect a difference of a few seconds (27), not exactly 1 hour.
            – Hans Kesting
            Nov 16 at 15:29




            If the issue was leap seconds, then I would expect a difference of a few seconds (27), not exactly 1 hour.
            – Hans Kesting
            Nov 16 at 15:29












            Isn't it 37..... I see 36difference (excluding zeros)
            – Naidu
            Nov 16 at 15:30






            Isn't it 37..... I see 36difference (excluding zeros)
            – Naidu
            Nov 16 at 15:30




















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53328114%2funix-timestamp-difference-between-using-tounixtimemilliseconds-and-timespan-tot%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

            ComboBox Display Member on multiple fields

            Is it possible to collect Nectar points via Trainline?