Skip to content

DateTimeOffset - ToLocalTime().DateTime and ToUniversalTime().DateTime return wrong DateTimeKind #100667

Open
@mrpmorris

Description

@mrpmorris

Description

I have an instance of DateTimeOffset retrieve from an API. I now need to use this internally as a UTC DateTime to query against a SQL Server database column that has a type datetime2(7).

My problem is that the date.Kind is set to Unspecified, so it is assumed to be in local time, and then the value is adjusted for the query.

So I find myself having to do this...

DateTime fromUtc = DateTime.SpecifyKind(query.From.ToUniversalTime().DateTime, DateTimeKind.Utc);

Instead of this

DateTime fromUtc = query.From.ToUniversalTime().DateTime;

Which is something I cannot rely on other developers on the system remembering to do, and might not have reared its head if we hadn't got such excellent unit tests.....or the UK hadn't shifted into Daylight Savings this week :)

Reproduction Steps

See expected behaviour for unit tests.

Expected behavior

public class DateTimeOffsetTests
{
    [Fact]
    public void WhenConvertingToUniversalTime_ThenTheDateTimeShouldBeDateTimeKindUtc()
    {
        DateTimeOffset subject = DateTimeOffset.Parse("2024-04-01T12:34:56+10:00").ToUniversalTime();
        Assert.Equal(DateTimeKind.Utc, subject.DateTime.Kind);
    }

    [Fact]
    public void WhenConvertingToLocalTime_ThenTheDateTimeShouldBeDateTimeKindLocal()
    {
        DateTimeOffset subject = DateTimeOffset.Parse("2024-04-01T12:34:56+10:00").ToLocalTime();
        Assert.Equal(DateTimeKind.Local, subject.DateTime.Kind);
    }
}

Actual behavior

The DateTime returned always has Kind == DateTimeKind.Unspecified

Regression?

It seems it has always been this way.

Known Workarounds

DateTime.SpecifyKind

Configuration

No response

Other information

If this cannot be done due to it being a breaking change, may I recommend DateTimeOffset has two new properties

  • public DateTime LocalDateTime => ...
  • public DateTime UniversalDateTime => ...

These could set the DateTime.Kind appropriately, and then ToLocalTime() and ToUniversalTime() could (optionally) be marked as obsolete.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions