I'm battling with my model for storing dates in a web application used in different time zones. At the moment, all dates are stored in UTC dates. So, lets say I am allowing the user to save a Transaction date, and a field on the screen is "Transaction Date". I default it to DateTime.UTCNow. SQL Server is in the United States, and I am in Australia.
So, what I have done now, is when I present the default transaction date, I add the GMT Offset to the UTC Now date:
var usersCurrentDate = DateTime.UtcNow.AddSeconds(GmtOffset.Value);
Where GmtOffset is a value in seconds, difference from GMT.
This code works - the user get's presented with the current date/time in their zone.
My issue is - how I should store this. Going to the UI, I do the above conversion. Should I then have a converted on the way to the database that converts the date entered by the user, back into UTC date/time?
In that case, I am always sure that all dates in the database are UTC dates. And then when ever I get the data from the database, I need to remember to translate into Local time? So, have a function that takes a Local time (As entered by the user) and converts it to the UTC?
Something like:
public DateTime UserDateToUTC(DateTime userDate)
{
return DateTime.UtcNow.AddSeconds(GmtOffset.Value * -1);
}
Is this an acceptable pattern?
Related
I want to add posted date of product to database. I am using DateTime.UtcNow but it shows wrong date if date is wrong on computer. How can I solve this problem?
I have "prodpostDate" column in the "product" table and its type is nvarchar.
DateTime aDate = DateTime.UtcNow;
item.prodpostDate= aDate.ToString("dddd, dd MMMM yyyy");
_context.Products.Add(item);
The date is not wrong. The date is exactly what it should be. When you call Now functions, it pulls the date and time from the computer that executes the code. If the date is wrong on the computer, you need to update it/change the timezone.
Expanding on the comment below:
If you want the date and time regardless of a users local settings, you cannot get the date time from their local machine which is what happens if you call a Now function from code ran on the client. You need to make a call to a different source to get it. If you are using an API, you could make a call to it from your client to get the current date and time. Even better than that, if you end up sending a request to the server for an update, just don't send a date time and let the server get it and populate it. Or if you are doing a database update, let the database get the date time on update/insert.
I have an entity with a DateTimeOffset (since .NET doesn't have a Date class) that is supposed to store a date (no time).
The problem is that, when I set the date to, for example, "2017-9-1" in the database it's saved as "2017-08-31 22:00:00+00" (2 hours less)
I think it applies the offset of my time zone to UTC.
I would like to store like to store "2017-9-1" in the database. The first thing I thought is to add 2 hours to every DateTimeOffet, but it feels bogus.
Is there a better way to work with dates than this?
I'm not quite sure, but add "0:" before the date on the format string, I think that should put it to your current time, otherwise it will default to UTC.
Like this:
[DisplayFormat(DataFormatString = "{0:yyyy/dd/MM}")]
If you are using MS Sql, you can use the Date variable to store just date. You can annotate the entities DateTimeOffset property database type.
[Column(TypeName="date")]
In our Entity Framework app we are storing datetimes as UTC. The client uses a reflection utility to convert object graphs to their users timezone, and then back to utc when submitting changes to the server.
The utility works fine, but i'm considering a cleaner approach where I add a unmapped TimeZoneInfo property on the base class with a default value set to UTC, and then for each datetime property i would modify it like so:
private DateTime _endTime;
public DateTime EndTime
{
get
{
return _endTime.ConvertFromUtc(TimeZone);
}
set
{
_endTime = value.ConvertToUtc(TimeZone);
}
}
The idea is that the backing field is always stored as a UTC value. If the TimeZone proeprty is set to UTC, then the ConvertTo/From extension methods will not do any conversion and will simply return the backing fields value. Whereas, if the TimeZone is set to anything else then the conversion will take place, leaving the backing field in UTC.
What i'm wondering is if there are issues i'm not thinking of. For instance, I'm assuming it would serialize with a value based on the current TimeZone property...is that true? Also, would this work for code first entities in EF? My hope is that if the TimeZone is changed it would not trigger a change in the dbcontext. Are there any other considerations that i'm missing that would make this a bad idea, and what would a DDD implementator think?
Edit
To clarify the use case a little more, the service layer will retrieve the values from the db, serialize, and send it to the MVC Controller. The service layer does not know of the users timezone. In my mvc app the web controller cached the user timezone at logon. This controller will then use that value to set the TimeZone property on the object. It will then submit it to the client via JSON. The TimeZone property on the base class represents the current timzone of the object, not the users timezone. The values are always stored as UTC and the controller which sends the data to the client is responsible to make sure it is set to the correct timezone.
The biggest reason i am considering this is for business logic. The object in question is a schedule which has a start and end time. There are three requirements that would be easier to perform if the object were set to the users timezone. For instance, schedules cannot span weeks, so if it starts on Saturday (end of week) and ends on Sunday (start of week) it must be split into two different schedules. For some reason i have a more difficult time when working with datetime logic, and so anything i can do to simplify it is a plus for maintenance.
The thing is that your application's timezone will be the web server's timezone! If the user is visiting your site from another timezone, the conversion will be wrong.
You need to make your page determine via the browser what their timezone is and use that for conversions.
If you need the user's current time, you can use this:
Date.now()
// Or this if you need support for old browsers, like IE8
new Date().getTime()
That will give you UTC time in milliseconds since January 1st 1970. You will have to later convert that to C# time by doing this in your application:
DateTime date = new DateTime(valueFromJS * 10000 + 621355860000000000);
If you don't need the current time but a date+time entered by the user in a date picker, then you should create a date object in the browser from that and send the getTime() of that object. This way your web server always receives UTC time and it's up to the browser do the appropriate conversion.
You can also use new Date().getTimezoneOffset(), which will return the amount of minutes UTC is ahead of the user timezone. So if the user is in GMT -4, that function will return 240. If for some reason you need that in the web server, you can send that value from the browser. Alternatively, if your application has users, you can even store that as a setting and simply use that.
Now, to display the date in the browser's timezone, you have to either know beforehand the user's timezone (from a previous request or a user setting) or just send it in UTC and then convert that via JavaScript in the browser.
There are also useful libraries to deal with timezone problems. For example:
http://momentjs.com/timezone/
http://tzdata-javascript.org
I do not think my question was well worded, nor thought out. I decided to implement the above idea into part of my project and found that it just creates more confusion than it's worth. It's also adds too much risk, especially if used in objects that are persisted to the db, where a programmer may fail to convert the object back to utc.
Instead i am adding a much, much simpler way by adding an extension method to easily calculate based on a specified timezone. The extension method assumes the datetime object is in UTC:
public static DateTime? As(this DateTime? dt, TimeZoneInfo targetTimeZone)
{
if (dt.HasValue)
return dt.Value.As(targetTimeZone);
else
return dt;
}
public static DateTime As(this DateTime dt, TimeZoneInfo targetTimeZone)
{
return TimeZoneInfo.ConvertTimeFromUtc(dt, targetTimeZone);
}
This ensures the underlying object is not mutated unnecessarily.
In SharePoint 2010, when I created a datetime filed to a custom list, the value shown in the list view under Modified is:
Date : 18/6/2013 13:00
But yet when I programmatically access the field which I assume is SPListItem.FieldValue["Date"], it returned:
18/6/2013 4:00:00
What should I do to make to display the correct time? Or is this possible at all?
Thanks.
SP 2010 stores date list column values in UTC time (not local time). When you retrieve it programmatically (via SPListItem), it converts the value to your local timezone. You can always use the .NET DateTime methods, such as ToUniversalTime() to convert back to UTC which should match what you see in the UI.
I have following scenario:
USA: database & application server
Europe: client
The server reads a date time (e.g. 12:00) object from the database and send it to a client in Europe. The problem is now, the client displays this date time in the time zone of the client (e.g. 18:00), but we need the time in the database, independent of the time zone of the server. On the client we don't know from which time zone this value is.
So how can we achieve this?
your tags tell the answer.
use the TimeZone Class.
http://msdn.microsoft.com/en-us/library/system.timezone.touniversaltime.aspx
also: Creating a DateTime in a specific Time Zone in c# fx 3.5
So in your DB, times should be UTC. from there you can do anything what you want.
Can't you simply use DateTime.ToUniversalTime()?
http://msdn.microsoft.com/en-us/library/system.datetime.touniversaltime.aspx
Alternatively, if you don't want UTC, you can find out the timezone of your server and do something like:
DateTime dt;
TimeZoneInfo timezone_EST =
TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime dt_EST = TimeZoneInfo.ConvertTime(dt, timezone_EST);
If you're storing the DateTime data in SQL 2008, take a look at new datetimeoffset type which will store timezone information as well as the date and time themselves