How to display dates and times in clients timezone - c#

Suppose the server is located in USA (MST) and an user from Chennai (IST) is making a payment. Both the server and user are in different timezones. The MST (Mountain Standard Time) is 7 hours behind GMT (Greenwich Meridian Time) and the IST (Indian Standard Time) is 5.30 hours ahead of GMT, that is both the server and user have a time difference of 12:30 hours. If the user is making the payment on 9/20/2011 9:00 AM then the time at the server is 8/20/2011 8:30 PM. So which time you have to record in the database? If the application stores the user’s time in the database then if someone from US is seeing the transaction will likely see a wrong time i.e. 8/20/2011 8:30 PM. The other option is storing the server’s time in the database (that what we normally do), then the user will be unhappy seeing a wrong time.
Can you please help me. Much appriciated.

I always use the UTC time to record everything, in any computer/server around the word.
DateTime.UtcNow
Then when I show the date and time to some user, I just change it base on their local time zone.

On saving any dates convert it into UTC and save into database, fore eg;
var now = DateTime.Now;
var Date = now.ToUniversalTime();
OR
var Date = DateTime.UtcNow;
and on displaying dates get the current Timezone of user and use it to convert the UTC date ,
var _Timezone = // store timezone id here
var southPole = TimeZoneInfo.FindSystemTimeZoneById(_Timezone);
DateTime userTime = TimeZoneInfo.ConvertTimeFromUtc(Date , southPole);
You can store the Timezone of different users in a database or get the current Timezone of the user logged in;
var _Timezone = new Date().getTimezoneOffset();
This method is not applicable in server side,
NOTE
You can get list of timezones from this code,
var timeZones = System.TimeZoneInfo.GetSystemTimeZones();
foreach ( var timeZone in timeZones )
{
Console.WriteLine( "{0} - {1}", timeZone.Id, timeZone.DisplayName );
}

Related

DateTime.Now vs DateTime.UtcNow on Azure server hosting my site and db

I've been struggling with utc and local time for a while. I have an app that creates events (classes) and when the host creates an event (class), they set the event date and time. So, on the server side I save both the local date time for the event and the UTC date time for the event.
But now is where I keep confusing myself.
Example: If a user visits the hosts page to see all the hosts events (classes), how would I look up the host's events if I'm using a date time in the query and the user visiting the page is a different time zone from the host.
Currently I'm doing something like this:
var events = host.Events.Where(j => j.EventDateTime >= DateTime.Now
&& j.EventStatus == EventStatus.Active).ToList()
But now I'm frustrated over the DateTime.Now, because it's the date time of the Azure server and this query compares the local event date time to a UTC date time.
So my question is,
Should I try to figure out what the UTC date time is and pass that in before adding the offset to the DateTime.Now?
Or should I run the query using the UTC date times? Which would be something like this:
var events = host.Events.Where(j => j.UtcEventDateTime >= DateTime.UtcNow
&& j.EventStatus == EventStatus.Active).ToList()
Note that the DateTime.Now on the server means the server now datetime not the user Now, which might get you confused especially on the cloud when the application is distributed on multiple services, or when you change the location of your service.
It is always recommended to save dates in UTC format and you can add to this the offset based on each user zone for display, this will make sure that your date data are consistent and easy to compare and filter.
Many people had same questions like yours such as this good one:
DateTime.Now vs. DateTime.UtcNow
Also you might find Datetimeoffset a different way to save your date, just make sure you understand it very well before adding it in action:
DateTime vs DateTimeOffset

Timezone issue when searching SQL Server from C#

I have a search model that sends a date range to a stored procedure. The stored procedure returns back results. This works fine where I am in Central Time.
However we have users in India and they could input valid dates of lets say '08/15/2017 23:00' and in the table for them the date is '08/14/2017' so they don't get any data returned.
If they input 08/14/2017 they get the wrong data. Data from 08/13/2017
How can I address the issue of time zone in c# before sending it to the stored procedure?
I have tried this with no luck
public DateTime AdjustForTimezone(DateTime date)
{
TimeZoneInfo timeInfo = TimeZoneInfo.FindSystemTimeZoneById(TimeZone.CurrentTimeZone.StandardName);
var newDate = TimeZoneInfo.ConvertTimeToUtc(date);
return newDate;
}
SqlCommand cmd = new SqlCommand("getTableData", connection);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
SqlCommandBuilder.DeriveParameters(cmd);
cmd.Parameters[1].Value = AdjustForTimezone(dateModel.FromDate);
cmd.Parameters[2].Value = AdjustForTimezone(dateModel.toDate);
Client to Server
The clients should send date time instances to the server with a UTC value or with the current offset from UTC.
The database should persist the DateTime (or DateTimeOffset) as DateTime/2 (or use DateTimeOffset).
Server to Client
The server should send the date time information to the client with the UTC value (or offset from UTC). It is the client's responsibility to apply the client's desired offset when the date time is presented (ie. do it in the presentation layer as late as possible).
Serialization
If you have to serialize your date times use ISO8601 notation.
By applying the above rules you now have stored your date time values in a way that they are comparable and unambiguous. They can now be filtered, sorted, etc.
If you are filtering be sure to take the date time filter parameters from the client and apply the same rules. Searching in eastern USA time zone for records that fall on the date 2017-02-06 should be translated into records with a date range between 2017-02-06T05:00:00 and 2017-02-07T05:00:00 as that time zone is UTC−05:00 at that point in time.
Side Notes
That there are exceptions to the rule like storing a birth date.
Personally I prefer storing DateTime/2 as UTC over DateTimeOffset both in code and in the data store.

Converting Times Between Time Zones in C#

I have a C# MVC Web application hosted in a remote server. I don't know the exact location of that.
The users of that application are all from (UTC + 06.00) Dhaka. When a user inserts a new record, I want the inserted datetime from his local time e.i (UTC + 06.00) Dhaka.
How can I do it?
The following code solves my problem-
DateTime utcTime = DateTime.UtcNow;
TimeZoneInfo BdZone = TimeZoneInfo.FindSystemTimeZoneById("Bangladesh Standard Time");
DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(utcTime, BdZone);
You can follow below approach:
Step 1:
You can store UTC time in database. If you are using SQL then you can use GETUTCDATE() to get UTC date.
Step 2
Please use Javascript to set a cookie, storing the browser timezone. (You can use scripts like jsTimeZoneDetect to get timezone name)
Step 3
Backend C# code:
Pull timezone from cookie.
Get the inserted utcTime from database and store in local variable(utcTime is the local variable name i used).
Use below mentioned code to convert UTC time to local time.
TimeZoneInfo tzoneinfo = TimeZoneInfo.FindSystemTimeZoneById("browser timezone name");
DateTime localTime = TimeZoneInfo.ConvertTimeFromUtc(utcTime, tzoneinfo);
Finally localtime is the end result. :)
Hope this will help you
Thank you
You should use global time zone of your ASP.NET application. Check this. This will work unless you use only C# datatime function. Once you have some complex code in SQL Server which will use GETTIME function. You will also rely on SQL Server timezone.
You should handle the internal datetime in UTC and convert the timezone only in UI.

MySQL Datetime showing incorrect time. ASP.NET C#

I added to my MySQL table a column called "registerdate", the datatype of this column is Datetime (I tried also TIMESTAMP) and in DEFAULT I have CURRENT_TIMESTAMP.
The datetime comes automatically after registration, its showing the correct day month and year but its showing incorrect hour (-10 hours).
I hope someone knows how to fix it, thanks for helping.
From the MySQL documentation on TimeStamp (emphasis mine):
MySQL converts TIMESTAMP values from the current time zone to UTC for storage, and back from UTC to the current time zone for retrieval. (This does not occur for other types such as DATETIME.) By default, the current time zone for each connection is the server's time.
https://dev.mysql.com/doc/refman/5.5/en/datetime.html
Before you save the data into database, try to save with Culture Info like below
DateTime dt = DateTime.Now;
// CultureInfo for German in Germany.
CultureInfo ci = new CultureInfo("de-DE");
Console.WriteLine(dt.ToString("d", ci));

Saving user selected date as utc and query against db with utc fields

I am a little bit confused what is the correct approach.
My app will be a global app meaning places (owners of events) with different timezones will be interacting with it and I want to keep things simple.
My app allows places(owner of events) to create events on a calendar (by obviously picking datetime) and then save to db. (StartDateTime, EndDateTime)
Then users (event attendees) will view events happening near them.
What I have done so far is create 2 fields called StartDateTimeUTC, EndDateTimeUTC in my table and I have for each user allowed them to have a default timezoneid set.
When creating new events, i read their timezone, convert the datetime they have selected to UTC
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"); //gotten from db
DateTime startDateTimeUserSelected = new DateTime(2016, 4, 14, 2, 15, 0); //user picked from a datetimepicker
DateTime endDateTimeUserSelected = new DateTime(2016, 4, 14, 4, 15, 0); //user picked from a datetimepicker
var starDateTimeUTC = TimeZoneInfo.ConvertTimeToUtc(startDateTimeUserSelected, tz);
var endDateTimeUTC = TimeZoneInfo.ConvertTimeToUtc(endDateTimeUserSelected, tz);
Then I save those to to my db fields, great now i got my user selected date as utc and saved to db.
Now I want to query the db for all events that happen today but I need to get the LOCAL TIME for the current user (based on their timezone)
var currentTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, tz); //tz being read from db for particular user
And then I can use the currentTime to find and query my db for all events happening today.
Just of the app
Place creates events for their users (place can be anywhere in the world) using the backend, users using app on their mobile will view what events are happening at different places around them (same timezone)
Question
Is this the correct way to deal with timezones without having to worry about daylight savings? or do I have to do more for an app that shows events to user based on their local time, and keeping everything in sync.
or should i just store everything as none UTC and determine user's current datetime from browser for places (owner of events) to query against db, and edit/add events. And determine users (attendees)'s time from the mobile device.
If I go with UTC i have keep track of timezone both for the Places and attendees and make sure all comparisons are done via UTC.
If i just enter everything as NONE utc, i dont have to worry about any conversion other than the fact that I need to read users CURRENT DATETIME from either browser/mobile device.
Have i missed anything?
When I was working with Azure Table Storage (NOSQL) I encountered this same roadblock since ATS always store all date time fields as UTC.
On the database table I had 3 fields:
TerminalUtcTime DATETIME
TerminalTimezone CHAR(6)
TerminalLocalTime CHAR(12)
The goal is to NEVER compute the terminal's local time using UTC and timezone. Because the effects of daylight
savings time (summer time), etc. is not reflected on the timezone as
well as UTC time.
On my experience, we had to forward the terminal's local time as is to some bank web service which is very strict. We had to send data as accurate as possible.
On the client:
DateTime terminalUtcTime = DateTime.Now.ToUniversalTime();
string terminalTimeZone = // Get from TimeZoneInfo.Local and format to ±hh:mm like +08:45 or -10:00 (format varies on how you may want it to be)
// Getting the timezone can be tricky because the hh and mm separator can be changed in the control panel so I had to use substrings instead
DateTime terminalLocalTime = DateTime.Now.ToLocalTime();
On the server:
You just need to save the terminalUtcTime as TerminalUtcTime,
terminalTimezone as TerminalTimezone and the terminalLocalTime as string.
terminalLocalTime.ToString("yyyyMMddHHmmssfff"); // Saves up to the milliseconds
Now, if needed, you can retrieve the DateTime instance of the terminal's local time. No need to compute, etc. I use DateTime.ParseExact(var, "yyyyMMddHHmmssfff");
Yes, you have to add a new field on the table but it saves you all the worries. This is the approach on a database that only allows UTC time, but if you are using MySql, MSSQL, etc. that allows saving of non-UTC time then that may work for you as well and saves up all the trouble.

Categories