简体   繁体   中英

Store DateTime according to Current CultureInfo ASP.NET Core

My application server in a location different from where most of my application users currently are.

While storing datetime values, I realize that if I simply do this

`TimeAdded=DateTime.Now`, 

the Time is stored according to the server location time regardless of the fact that I have done the following in my Startup.cs class

 var cultureInfo = new CultureInfo("en-NG");
 cultureInfo.NumberFormat.CurrencySymbol = "NGN";

 CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
 CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;

The location of my users is on UTC+1 while the server is currently located in a location that is on UTC-8

Is there a way to make my datetime values to be stored in the database (SQL Server) in accordance with the CurrentCultureInfo set in startup.cs class?

I have only currently resorted to storing the datetime Values as UTC and convert it on to the equivalent UTC+1 value after retrieving the values from the database.

So, I do

TimeAdded=DateTime.UtcNow;

And after retrieving the value for display to users, I convert it by

TimeAdded=TimeAdded.AddHours(1)

I wish to get a better way go about this is there is.

Thank you

Is there a way to make my datetime values to be stored in the database (SQL Server) in accordance with the CurrentCultureInfo?

Datetimes are stored in binary format in SQL Server without any culture information. However SQL Server can store date and time information with time offsets. SQL Server has the datetimeoffset type. I think storing dates with culture information doesn't solve the problem of showing the date and time in the local time zone of the user because culture info can correspond to more than one time zone. For example here in Spain we have two time zones and USA has several time zones.

And after retrieving the value for display to users, I convert it by

TimeAdded=TimeAdded.AddHours(1)

I wish to get a better way go about this is there is.

Don't do that, because what happens on daylight saving time? And you are assuming all your users are in the same time zone.

I recommend you to store the datetime in UTC because it's not ambiguous, it has only one interpretation. Then you have to translate that date time into the local date time of the user time zone for displaying. If you know the time zone of the user you can do the following:

var usertimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(userTimeZoneId);
var userLocalDateTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, usertimeZoneInfo);

The IANA time zone of the user can be figured out using some JavaScript. This answer shows you how to do that.

And the IANA time zone can be translated to windows time zone id. Please, see this answer . It shows you how to do it.

On the other hand, if you are fetching the data by calling some Web API from the browser. you don't really need to do too much. You just need to make sure the data is serialized as it was UTC date. Yes, you are storing UTC dates on the database but when you retrieve them from the database you get DateTimeKind.Unspecified dates and then those dates are not serialized correctly to JSON. If you are using Newtosoft.Json to serialize, you can specify SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc

If you are using System.Text.Json then you have to write custom JsonConverter for DateTime .

Here you a have a JsonConverter for serializing DateTimeKind.Unspecified dates as they were UTC:

public class JsonDateConverter : JsonConverter<DateTime>
{
    public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var d = reader.GetDateTime();
        return d;
    }

    public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
    {
        if (value.Kind == DateTimeKind.Unspecified)
        {
            value = new DateTime(value.Ticks, DateTimeKind.Utc);
        }
        writer.WriteStringValue(value);
    }
}

Then you write some Javascript to parse dates just after the data has been retrieved from web API:

obj.theDate = obj.TheDate && new Date(obj.TheDate);

You need to do it because DateTime is serialized as string when serializing to JSON. And you want theDate to be a JavaScript date.

After that, theDate is the user time zone local time date. To check it write the following:

console.log(obj.theDate);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM