Convert from UTC C# SQL - c#

Using a combination of server-side C#, SQL database, and the dayjs client-side library dayjs I am unable to convert the date stored as UTC in the database UTC to local time.
My theory is to store all date-times in the database as UTC. Use the client (browser) to determine the user timezone (automatically or store it for each user), then let the browser, via dayjs convert from UTC time to local time.

This is NOT a dayjs problem but the way dates are stored in SQL and pulled via C#.
In order for dayjs to convert the DateTime on the client app the date must be returned from the server in a very specific format.
If you are using DateTime C# and SQL datatypes and using just pulling the DateTime straight from the database to a DTO the date will be returned to the client like this:
noteDate: "2022-01-06T22:31:34.81"
In order for dayjs.tz() method to work the date DateTime must be returned from the server in this format:
noteDate: "2022-01-06T22:31:34.81Z"
Then this code will property convert from UTC to local time:
let date = "2022-01-06T20:14:18.917Z";
let timeZoneGuess = dayjs.tz.guess();
date = dayjs(date).tz(timeZoneGuess);
To get this format to the client I had to add additional information to the DateTime before returning the note.NoteDate to the client.
note.NoteDate = DateTime.SpecifyKind(note.NoteDate, DateTimeKind.Utc);
When storing the DateTime in SQL I am using c# DateTime and SQL DateTime datatypes. When setting the note.NoteDate I call note.NoteDate = DateTime.UtcNow but apparently SQL does not save the "Z" part of the UTC date.
I would like to see if anyone else has this same issue and if there are better ways to solve it.

Related

Passing dates from db RESTful web API Best Practices

So I have 2 types of dates in my db, date (yyyy-mm-dd) and datetimeoffset (yyyy-mm-ddThh:mm:ss.ms+Z), and I was wondering what is the best practice to deal with it when I'm taking the data from the DB and passing it as a json to the UI/mobile.
I used to always parse dates to datetimeoffset so normal dates will be something like 2018-09-24T00:00:00.000+00:00 instead of simply 2018-09-24 but it works perfectly with datetimeoffset that are already saved like that in the DB
In multiple ways you can handle this situation.
1 : From API side always give predefined date format value
Example yyyy-mm-ddThh:mm:ss.ms+Z
And from the client side based on conditions you can convert it.
2: Keep different View models/ Properties may be for storing yyyy-mm-dd you can give string data type and for yyyy-mm-ddThh:mm:ss.ms+Z just DateTime . and based on your db you can write a condition and map the particular data.
3: Keep a single property for returning the date and make it as string
Example : Public string CurrentDate{get;set;} and you can simply map the database values(Conversion should be done). In this case client no need to worry about the date conversions they can simply show what ever you are passing from the api.
Note : The method 3 is not preferable because in the case in some places the user may see yyyy-mm-dd in some other places yyyy-mm-ddThh:mm:ss.ms+Z.
Take a look at SQL Server Data Type Mappings
You will see that SQL Server's Date, DateTime and DateTime2 all map to .Net's DateTime data type,
and DateTimeOffset maps to DateTimeOffset.
SQL Server Database Engine type .NET Framework type
date (SQL Server 2008 and later) DateTime
datetime DateTime
datetime2 (SQL Server 2008 and later) DateTime
datetimeoffset (SQL Server 2008 and later) DateTimeOffset

Getting different date in jsonFormat from client side at server side in MVC

I am using Knockout js at client side and MVC C# at server side. I am passing the date in form of 2019-04-25T03:27:00.000Z (UTC +5:30). on server side i am using DateTime (Used DateTimeOffset, but since same issue i have changed it to DateTime) and getting the different date {4/25/2019 8:57:00 AM}.
Problem:
1. If i am changing the timezone of client side system then on server side it always comes the Date with time added with +5.30.
I have to ignore the Timestamp on client side or server side both so that i can get exact date what client is sending to server.
I had a similar problem, so this is probably what is going on:
DateTime has a "Kind" property that indicates whether the date/time is local, UTC, or "unknown". When the controller method has a DateTime parameter, it sets it to the appropriate value with a "Kind" value of "Local". In other words, it is the same time as the client transmitted, but offset by the timezone.
To get back to UTC on the server, use the DateTime ToUniveralTime() method. Note that this will only work correctly if the DateTime Kind value is either Local or Utc.
Example:
public void GetDateRangeReadings(DateTime startDate)
{
startDate = startDate.ToUniversalTime();

Change the date format in SQL Server 2012

I have a SQL Server 2012 Express database that has been installed on a server in Germany. I created a database and have now realised the date formats are incorrect. I need to show each date as dd/mm/yyyy.
When I run dbcc useroptions (after making some changes to the server), I get the following -
language dateformat
-------------------------
British dmy
When I run select GetDate() in a new query, it shows the date as follows -
2014-08-28 13:53:10.550
The bottom line issue is when I enter 28/08/2014 in to a textbox on a web forms project, it errors
String was not recognized as a valid DateTime.
selP.StartDate = Convert.ToDateTime(tbStartDate.Text);
Any ideas why this is happening? I have created a new user since changing the settings to British and dmy, which still produces the same error.
SQL Server doesn't store a DateTime in any string format - it's stored as an 8 byte numerical value.
The various settings (language, date format) only influence how the DateTime is shown to you in SQL Server Management Studio - or how it is parsed when you attempt to convert a string to a DateTime.
There are many formats supported by SQL Server - see the MSDN Books Online on CAST and CONVERT. Most of those formats are dependent on what settings you have - therefore, these settings might work some times - and sometimes not.
The way to solve this is to use the (slightly adapted) ISO-8601 date format that is supported by SQL Server - this format works always - regardless of your SQL Server language and dateformat settings.
The ISO-8601 format is supported by SQL Server comes in two flavors:
YYYYMMDD for just dates (no time portion); note here: no dashes!, that's very important! YYYY-MM-DD is NOT independent of the dateformat settings in your SQL Server and will NOT work in all situations!
or:
YYYY-MM-DDTHH:MM:SS for dates and times - note here: this format has dashes (but they can be omitted), and a fixed T as delimiter between the date and time portion of your DATETIME.
This is valid for SQL Server 2000 and newer.
If you use SQL Server 2008 or newer and the DATE datatype (only DATE - not DATETIME!), then you can indeed also use the YYYY-MM-DD format and that will work, too, with any settings in your SQL Server.
Don't ask me why this whole topic is so tricky and somewhat confusing - that's just the way it is. But with the YYYYMMDD format, you should be fine for any version of SQL Server and for any language and dateformat setting in your SQL Server.
The recommendation for SQL Server 2008 and newer is to use DATE if you only need the date portion, and DATETIME2(n) when you need both date and time. You should try to start phasing out the DATETIME datatype if ever possible
The proper way to achieve that is to set the culture of your web application.
How to: Set the Culture and UI Culture for ASP.NET Web Page Globalization
IN SQL, you need to cast that string as a DATETIME before inserting or updating the database.
CAST('28/08/2014' AS DATETIME)
You can change the format a date is displayed in using the CONVERT. For example, the following will display the date in UK short format (dd/mm/yyyy)
SELECT CONVERT(varchar(50), GetDate(), 103)
If you are doing this in C#, you need to detect the local culture and cast the string to a datetime as approporate.
//You can set the culture on the current thread:
Thread.CurrentThread.CurrentCulture = CultureInfo.InstalledUICulture; // or new CultureInfo("en-GB"); //dd/MM/yyyy
//or you can pass it to the DateTime.Parse method. Something like this:
DateTime startDate = DateTime.Parse(tbStartDate.Text, CultureInfo.InstalledUICulture);
DateTime startDate = DateTime.ParseExact(tbStartDate.Text,"dd/MM/yyyy",System.Globalization.CultureInfo.CurrentUICulture.DateTimeFormat)
Actually the GETDATE() function returns the system date and time in the format 'yyyy-mm-dd hh:mi:ss.mmm' irrespective of the Dateformat.Date format for SQL server is in U.S. date format MM/DD/YY, unless a localized version of SQL Server is installed which seems to be the case here.
Use
SET DATEFORMAT <format>
which sets the order of the date parts (month/day/year) for entering datetime or smalldatetime data. Valid parameters include mdy, dmy, ymd, ydm, myd, and dym. The U.S. English default is mdy.
This method allows you use a date format for dates sent to SQL Server of d/m/y, but it is connection dependent. If a new connection is made to SQL Server or if the server is stopped and restarted, the date format will go back to dmy which is default in your case.
selP.StartDate=tbStartDate.Text.ToString("dd/MM/yyyy")
SELECT CONVERT(varchar(50), GetDate(), 103)
SELECT CONVERT(varchar(50), JoiningDate, 103)from Employee where EmpId='1001'

Issue with dates in WCF service and in JavaSerializer decoder

One of the nastiest problems working across time zones :)
Here is my problem:
I have code that passes date into WCF via JSON object and I use "short" format where it contains only milliseconds since 1970 with no time zone. This DateTime parsed by WCF just FINE
I store date into SQL Server Database. Example: 2011-06-07 22:17:01.113 - date as I see it in SQL Server and this is perfectly fine since I store everything in UTC. So, it's (-5) time zone and date looks right.
I load date field into my object using EF and inside object property says it is 22:17 and Kind=Unspecified which is OK again, it is loaded from SQL, I know it is UTC but code doesn't know that so it loads this date as Unspecified.
I return this object to WCF client. It can be XML or it can be JSON. Here is what happen. When I JSON(this is what client specifies) - I get this: 1307503021113-0500 for date. If we convert first portion to DateTime using SQL:
SELECT DATEADD(ss, 1307503021,
'1970-01-01')
2011-06-08 03:17:01.000
Part above already wrong, no? If we apply -5hr adjustment we will be back to 22:17pm which already utc time? This part already confusing to me. But what even worse - when I deserialize using JavaScriptSerializer - I see DateTime value in newly inflated object saying UTC kind and 3:17am
var oSerializer = new JavaScriptSerializer();
var returnValue = (T)oSerializer.Deserialize(s, typeof(T));
I'm all puzzled already and I wonder if it's possible to force WCF and other serializer/deserializers to NOT do any time offsets and stuff? I'd rather format all dates for display manually and I want to store UTC dates in database.
UPDATE:
Looks like WCF thinks that if DateKind is Unspecified than it's LOCAL.
I did this: After I got objects from EF I specified Kind:
foreach (var tu in tripUpdates)
{
tu.DeviceTime = DateTime.SpecifyKind(tu.DeviceTime, DateTimeKind.Utc);
}
That fixed it - now when WCF serves object it doesn't include timezone which is GREAT. Now my main question is there any way to specify Kind on EF entities somehow so I don't have to manually specifiy kind for every date in service?
When you get the datetime via a SELECT statement always set the DateTime.Kind to UTC. This way WCF/XML will not try to adjust the time.

Read a DateTime object in a different time zone

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

Categories

Resources