How to convert DateTime of type DateTimeKind.Unspecified to DateTime.Kind.Utc in C# (.NET)
Asked Answered
H

5

66

I've inherited C# code that has an awful lot of DateTimes where the Kind property is DateTimeKind.Unspecified. These are fed into Datetime.ToUniversalTime() which gives back a UTC datetime (it adds 7 hours in my case). This is how ToUniversalTime() works; see MSDN. The problem is that these DateTimes are in fact already in UTC time. They are pulled out of a SQL Server Compact 4.0 database. They were stored there in UTC. My main question is:

  1. How do I modify the Kind property of a DateTime so that it's UTC and not Unspecified? I don't want to change the time or date. So for example, a date of April 1st 2013, 9:05 am with its Kind property of "Unspecified" should become a datetime of April 1st 2013, 9:05 UTC.

If I could be indulged with a follow up question(s), it would be:

  1. Are values necessarily returned from Sql Server Compact as "Unspecified"? Inside Sql Server Compact, they are being stored as type (datetime, not null). Looking at the code, it appears they are just put in the database, but there are no provisions to mark them as UTC or anything. Is there a better way to handle things? Is there a slick way to ensure the DateTimes come out of SQL Compact as UTC?

Please let me know if I can provide more details. I'm new to this code base and still getting my brain around it, so I'm having trouble describing the problem perfectly.

Dave

Herminahermine answered 26/10, 2016 at 21:55 Comment(0)
S
93

Do you maybe need something like this:

var unspecified = new DateTime(2016, 12, 12, 10, 10, 10, DateTimeKind.Unspecified);
var specified = DateTime.SpecifyKind(unspecified, DateTimeKind.Utc);

About SpecifyKind() method from MSDN:

The SpecifyKind method creates a new DateTime object using the specified kind parameter and the original time value.

It will create new object, new Kind and same time value. You cannot change Kind of existing object, you need to create new one with same values and different Kind.

Regarding to other question here are supported types in SQL Compact. And here is issue regarding to DateTimeOffset. It looks like that it is not supported yet in Sql Compact.

Singlestick answered 26/10, 2016 at 22:3 Comment(3)
Kat1330 Thanks for the prompt reply! I did look at SpecifyKind, but if I'm understanding the docs correctly (msdn.microsoft.com/en-us/library/…), this WILL change the DateTime. See in the examples towards the end, they have:Herminahermine
As I understood it creates new DateTime object with different Kind but with same time values. According to your question this is what you need? You cannot change Kind of DateTime object, you can only create new DateTime with same values and new Kind.Singlestick
Perfect Kat! I misread the docs. Yes, I believe that is the answer. I'll mark yours as answer. I'd like to leave the question open for 1 day as I'm curious if people have opinions on the second question: "Is there a slick way to ensure the DateTimes come out of SQL Compact as UTC?" Perhaps you have an opinion? For expediency right now, I'll probably just check in the code where it performs ToUniversalTime, and do a SpecifyKind in the case of Unspecified. But I'm curious if there's a better way. Perhaps in the EntityFramework code as I pull the values out of Compact SQL? Thanks!Herminahermine
D
9

You could combine the two above answers for a cleaner solution...

public static DateTime SetKind(this DateTime DT, DateTimeKind DTKind)
{        
    return DateTime.SpecifyKind(DT, DTKind);
}
Delfinadelfine answered 7/7, 2017 at 13:18 Comment(2)
Personally I don't find it cleaner, as it "hides" the fact that a new instance is created. By calling a method/extension on an existing instance one could expect that the instance itself will be updated which is not the case, so I'd avoid these kind of wrappers.Salto
@Salto DateTime instances are immutable, so this is similar to all other DateTime methods like AddDays which create a copy internally.Whitefaced
U
4

I use an extension method:

public static DateTime SetKind(this DateTime DT, DateTimeKind DTKind)
{        
    var NewDT = New DateTime(DT.Year, DT.Month, DT.Day, DT.Hour, DT.Minute, DT.Second, DT.Millisecond, DTKind);
    Return NewDT;
}

This is much shorter to use in LINQ than having to type out DateTime.SpecifyKind(unspecified, DateTimeKind.Utc) every time.

For example:

table.Where((x) x.StartTimeStampUTC.SetKind(DateTimeKind.Utc).ToString("G") = GUIStartTimeStampTxt.Text)
Ute answered 26/10, 2016 at 22:34 Comment(0)
C
1

To understand DateTimeKindand conversion, see the difference in code and result with and without DateTimeKind

var plainDate = new DateTime(2020, 1, 1, 0, 30, 0);
Console.WriteLine(plainDate);  // 2020-01-01 00:30:00
Console.WriteLine(plainDate.ToUniversalTime());  // 2019-12-31 23:30:00
Console.WriteLine(plainDate.ToLocalTime());  // 2020-01-01 01:30:00

Always specify the DateTimeKind parameter when creating DateTimes__. This helps the application understanding which kind of date is it managing.

var specificDate = new DateTime(2020, 1, 1, 0, 30, 0, DateTimeKind.Utc);
Console.WriteLine(specificDate); //2020-01-01 00:30:00
Console.WriteLine(specificDate.ToUniversalTime()); //2020-01-01 00:30:00
Console.WriteLine(specificDate.ToLocalTime()); //2020-01-01 00:30:00

DateTimeKind has only 3 possible values: Unspecified, Utc, Local

public enum DateTimeKind
{
    Unspecified,
    Utc,
    Local
}
Caesura answered 24/2, 2023 at 6:8 Comment(0)
V
0
public static DateTime SetKind(DateTime value)
{
     return  DateTime.SpecifyKind(value, DateTimeKind.Utc);          
}
Voorhees answered 8/2, 2023 at 16:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.