1

My database has columns defined as "Date" and others defined as "DateTime." Is there an easy way to declare that dates should remain unchanged irrespective of the timezone. While "DateTime" fields may be shown in the client's local timezone?

SQLServer Code:
CREATE TABLE Test(
  MyDate date,
  MyDateTime datetime,
);
INSERT INTO Test VALUES(cast('12/14/2020' as date),cast('12/14/2020' as date));

Model:
public class TestModel {
  [DataType(DataType.Date)]
  [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
  public DateTime? MyDate {get;set;}

  [DataType(DataType.DateTime)]
  [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy HH:mm}")]
  public DateTime? MyDateTime {get;set;}
}

Model Query (Dapper):
using(SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["MyDatabase"].ToString())
  return con.query<TestModel>("SELECT * FROM Test", null, null, true, 0, CommandType.Text);

View Layer Render:
<td>@Html.DisplayFor(m => item.MyDate)</td>
<td>@Html.DisplayFor(m => item.MyDateTime)</td>

If the client is in a timezone one hour behind, they see: 12/13/2020, 12/13/2020 23:00

Instead, they should see: 12/14/2020, 12/13/2020 23:00


Edit on 12/18/2020: Dapper encodes the data into TestModel with a DateTime.Kind of Unspecified. Following the example here: Get DateTime as UTC with Dapper I can tinker with the returned DateTime object. However, the TZ conversion still happens changing the Date when rendered on the client side.


If possible, I would like to implement a generic override class at the project level to enforce this as there are several hundred instances affected.

DKATyler
  • 914
  • 10
  • 16
  • you have to use UTC time on database, and then change it according when you show it. – Aristos Dec 15 '20 at 01:23
  • @Aristos Doesn't quite work unfortunately. Setting the IIS & SQLServer TZ to UTC means that all U.S. TZs Dates are off by one day (UTC -X). Now, moving the servers to the "NUT" timezone (UTC-11) would resolve it except for the Oceania TZ (UTC+14). However, our hosting provider will not allow us to set the server TZ. – DKATyler Dec 15 '20 at 08:41
  • I may have found a solution via: https://stackoverflow.com/questions/12510299/get-datetime-as-utc-with-dapper. If I mark the DateTime.Kind as "Local" then no DateTime conversions occur. Needs testing & Implementation first. – DKATyler Dec 15 '20 at 08:43
  • Hi. You've shown us your SQL schema, class model, and view, but not shown how you populate your model. Please update your question to show the middle parts. :) – Matt Johnson-Pint Dec 17 '20 at 19:21
  • @Aristos - UTC is not a panacea. In the case of date-only values, it's exactly the *wrong* thing to do. – Matt Johnson-Pint Dec 17 '20 at 19:23
  • @MattJohnson-Pint UTC is the same date time that all computers have around the word and have no processing at all - so is the base for datetime to do anything - and then adapt it to the user. How ever I do not say that I know everything (and not an expert as you are in datetime),so please if you have some articles that you can share it with me to read i will do it for sure with glad to expand my knowledge. – Aristos Dec 18 '20 at 02:05
  • With regard to date+time, I know of four really good blog posts about that: [1](https://codeblog.jonskeet.uk/2019/03/27/storing-utc-is-not-a-silver-bullet/) [2](http://www.creativedeletion.com/2015/03/19/persisting_future_datetimes.html) [3](https://zachholman.com/talk/utc-is-enough-for-everyone-right) [4](https://engineering.q42.nl/why-always-use-utc-is-bad-advice/). With regard to date-only values, I'm having trouble locating blog posts, but there are a few S.O. posts: [1](https://stackoverflow.com/a/49923086/634824) [2](https://stackoverflow.com/a/52229618/634824). I may blog about this... – Matt Johnson-Pint Dec 18 '20 at 18:20
  • In general, the key concept is that a "date" is different than a "time" or a "datetime". Think of a "date" as a logical division of a year. It is best visualized as a square on a paper calendar. Humans have been using those for centuries, and there are no time zones involved with such devices. Another way to look at it is that a date-only value is not pinned to a particular time zone. It is ambiguous by nature. Common example: birthdates. A birthdate is not the same thing as the instant of your birth. See my blog: https://codeofmatt.com/handling-birthdays-and-other-anniversaries/ – Matt Johnson-Pint Dec 18 '20 at 18:24
  • @MattJohnson-Pint You understand the problem! If an entry is encoded as a "date", we do in fact mean "New Year's Day" is Jan 1. Not December 31st if you're in Alaska, not Jan 2nd if you're in Oceania. It's always Jan 1. – DKATyler Dec 18 '20 at 20:49
  • Fun fact: Jan 1st 10am UTC is 3 different dates depending on TZ (Dec 31st UTC-11, Jan 1 UTC+0, and Jan 2 UTC+14) – DKATyler Dec 18 '20 at 20:55
  • @DKATyler - Yes, that is correct. Looking at your edit, you are showing server-side rendering, but you mention client-side rendering. `DateTime` with `Unspecified` kind is correct, and won't be altered by the server. If however you're passing that over an API and rendering it client-side with JavaScript, then that's a very different case that you're not showing us here. – Matt Johnson-Pint Dec 18 '20 at 21:09
  • Also, you should be using `yyyy-MM-dd` format when working with your DB, and in any API response. Reserve using locale specific formats for end-user display only. – Matt Johnson-Pint Dec 18 '20 at 21:10
  • 1
    ! I think you've just pointed me where I should be looking. The application has a 50-50 mixture of client & server side rendering. I assumed both were broken but, you're right! Just the the ones that receive JSON Dates "/Date(1573624800000)/". So, all this time the error was in one of the javascript libs. – DKATyler Dec 18 '20 at 22:07

0 Answers0