Was there a change in timezone for ToLocalTime - asp.net-core-3.0

Currently I'm using ToLocalTime to convert the UTC date received from my backend. Is there a way to setup my ASP.NET Core 3.0 web site to use a specific timezone when calling ToLocalTime (instead of depending on the host region) -- or should I implement my own method/extension to converting to the time I need?

Official documentation of DateTime.ToLocalTime states:
Note that the exact output depends on the current culture and the local time zone of the system on which it is run.
You can use the TimeZoneInfo static method ConvertTimeFromUtc to convert an instance of DateTime (Note: if it's Kind property is Local you'll get an exception!) from Utc to whatever local time you want (Another note: the Kind property of the result is either Utc or Unspecified - depending on the target TimeZoneInfo).
Code example (copied from documentation page):
DateTime timeUtc = DateTime.UtcNow;
try
{
TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
DateTime cstTime = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, cstZone);
Console.WriteLine("The date and time are {0} {1}.",
cstTime,
cstZone.IsDaylightSavingTime(cstTime) ?
cstZone.DaylightName : cstZone.StandardName);
}
catch (TimeZoneNotFoundException)
{
Console.WriteLine("The registry does not define the Central Standard Time zone.");
}
catch (InvalidTimeZoneException)
{
Console.WriteLine("Registry data on the Central Standard Time zone has been corrupted.");
}

Related

Configure that Newtonsoft serializer serializes a date respecting the local time

I send javascript dates to the server via:
let start = new Date().toISOString()
This date string is sent as UTC date string.
On server side I have convert this utc date everywhere to the local date (CH/DE/AT) via myDate.ToLocalTime() which I want to save in the database.
I do not want this manual conversion at many places.
How can I fix this with newtonsoft json serializer ?
That I get always the current local time I do:
var cultureInfo = new CultureInfo("de-DE");
CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;
in my Startup.cs
You can add the below in your ConfigureServices method:
services.AddMvc()
.AddJsonOptions(o =>
{
o.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local;
}
See DateTimeZoneHandling setting.
The DateTimeZoneHandling Enumeration defines DateTimeZoneHandling.Local as follows:
Local - Treat as local time. If the DateTime object represents a
Coordinated Universal Time (UTC), it is converted to the local time.

Parse ISO 8601 date time from JSON object to local time

I have a Json object that was returned from my other process, the content of the object as below:
{
"nextDrawTime": "2017-07-10T05:33:44.914Z",
"winnerSelectionProcess": {
"mode": "idle"
}
}
My problem is, when I parsing this object using Json.NET like this, it returned wrong date time:
dynamic Jobj = JsonConvert.DeserializeObject(myJson);
Console.Write(Jobj["nextDrawTime"].ToString());
The date time out put is: 15/07/2017 5:33:44 AM, which is wrong, how do convert this back to local time?
You can use the setting DateTimeZoneHandling = DateTimeZoneHandling.Local when deserializing. As explained in the docs, this setting will
Treat [dates and times] as local time. If the DateTime object represents a Coordinated
Universal Time (UTC), it is converted to the local time.
I.e.:
var settings = new JsonSerializerSettings
{
DateTimeZoneHandling = DateTimeZoneHandling.Local,
};
dynamic Jobj = JsonConvert.DeserializeObject(myJson, settings);
Or, you could always call DateTime.ToLocalTime() after parsing:
var localNextDrawTime = ((DateTime)Jobj["nextDrawTime"]).ToLocalTime();
Sample fiddle (where the problem is a little hard to reproduce since dotnetfiddle's local time is, in fact, UTC.)

Determine Time Offset given Olson TZID and local DateTime?

I need to determine Time Offset given Olson TZID of an event and a DateTime of an event.
I suppose I can do it with a help of Noda Time, but I'm new here and need help - an example of actual API call sequence to perform this task.
A few more details of what we're using and doing.
We're running ASP.NET + SQL Server based Web site. Users of our site enter and save events which are happening at various locations. For each event Lat/Long and DateTime with time offset (of that event) are among required fields.
There are various scenarios of data entry, sometimes Lat/Long is entered first, sometimes DateTime is. System allows to determine Lat/Long from an address or a map point. We want Time Offset to be consistent with Lat/Long in most of the cases because we normally expect DateTime being entered as local to that event.
We use SQL Server DateTimeOffset field to store data.
We don't want to depend on third-party web services to determine an offset, but prefer our system to do that.
I'm free to download and use any necessary tools or data. I already downloaded shapefiles from http://efele.net/maps/tz/ and used Shape2SQL http://goo.gl/u7AUy to convert them to SQL Server table with TZIDs and GEOMs.
I know how to get TZID from Lat/Long by querying that table.
What I need, again, is to determine Time Offset from TZID and DateTime.
Thank you for Jon Skeet and Matt Johnson for providing an answer on Noda Time Google Group http://goo.gl/I9unm0. Jon explained how to get Microsoft BCL DateTimeOffset value given Olson TZID and NodaTime LocalDateTime values. Matt pointed to an example of determining if DST is active given ZonedDateTime: What is the System.TimeZoneInfo.IsDaylightSavingTime equivalent in NodaTime?
I'm going to write a blog post summarizing my experience of getting Olson TZID from Lat/Long, parsing DateTime string into LocalDateTime and determining DateTimeOffset. I'll show there how GetTmzIdByLocation(latitude, longitude) and GetRoughDateTimeOffsetByLocation(latitude, longitude) methods work and why I needed both (first method doesn't work for locations on ocean). Once I write this post I'll add a comment here.
Note, that parsing DateTime string in a code below is not optimal yet; as Matt explained in a Google Group post (link above) it's better to use Noda Time tools than BCL. See a related question at http://goo.gl/ZRZ7XP
My current code:
public object GetDateTimeOffset(string latitude, string longitude, string dateTime)
{
var tzFound = false;
var isDST = false;
var tmpDateTime = new DateTimeOffset(DateTime.Now).DateTime;
if (!String.IsNullOrEmpty(dateTime))
{
try
{
// Note: Looks stupid? I need to throw away TimeZone Offset specified in dateTime string (if any).
// Funny thing is that calling DateTime.Parse(dateTime) would automatically modify DateTime for its value in a system timezone.
tmpDateTime = DateTimeOffset.Parse(dateTime).DateTime;
}
catch (Exception) { }
}
try
{
var tmzID = GetTmzIdByLocation(latitude, longitude);
DateTimeOffset result;
if (String.IsNullOrEmpty(tmzID) || tmzID.ToLower() == "uninhabited") // TimeZone is unknown, it's probably an ocean, so we would just return time offest based on Lat/Long.
{
var offset = GetRoughDateTimeOffsetByLocation(latitude, longitude);
result = new DateTimeOffset(tmpDateTime, TimeSpan.FromMinutes(offset * 60)); // This only works correctly if tmpDateTime.Kind = Unspecified, see http://goo.gl/at3Vba
} // A known TimeZone is found, we can adjust for DST using Noda Time calls below.
else
{
tzFound = true;
// This was provided by Jon Skeet
var localDateTime = LocalDateTime.FromDateTime(tmpDateTime); // See Noda Time docs at http://goo.gl/XseiSa
var dateTimeZone = DateTimeZoneProviders.Tzdb[tmzID];
var zonedDateTime = localDateTime.InZoneLeniently(dateTimeZone); // See Noda Time docs at http://goo.gl/AqE8Qo
result = zonedDateTime.ToDateTimeOffset(); // BCL DateTimeOffset
isDST = zonedDateTime.IsDaylightSavingsTime();
}
return new { result = result.ToString(IncidentDateFormat), tzFound, isDST };
}
catch (Exception ex)
{
IMAPLog.LogEvent(System.Reflection.MethodBase.GetCurrentMethod().Name, "", ex);
throw new CustomHttpException("Unable to get timezone offset.");
}
}
An extension method (provided by Matt Johnson) for determining if DST is active What is the System.TimeZoneInfo.IsDaylightSavingTime equivalent in NodaTime?
public static class NodaTimeUtil
{
// An extension method by Matt Johnson - on Stack Overflow at http://goo.gl/ymy7Wb
public static bool IsDaylightSavingsTime(this ZonedDateTime zonedDateTime)
{
var instant = zonedDateTime.ToInstant();
var zoneInterval = zonedDateTime.Zone.GetZoneInterval(instant);
return zoneInterval.Savings != Offset.Zero;
}
}

Problems with time

I coded this snippet to log the users IP and time on my website. It works but something is wrong with the time:
public static void UserLogin(string iPaddress, string uname)
{
DateTime dt = TimeZoneInfo.ConvertTimeToUtc(DateTime.Now);
string cet= dt.AddHours(1).ToString("F", new CultureInfo("en-US"));
.....
}
The website is on a server somewhere in UK and to adjust the login time to CET without going too sophisticated, I simply toughth adding the hours difference using (AddHours) but for some reason, and I do not understand why, whatsoever number I put in there "AddHours(1)" will never get added and moreover, right now that is 13:55 at my location in Italy, the time recorder by the method is 1:55 am that is 12 hours behind even if there is no hours added "AddHours(0)".
Some help to understand what is going on in this method will be appreciated. Thanks.
You can convert time between time zones in more controlled way, for example:
DateTime nowutc = DateTime.UtcNow;
var cet = TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time");
var nowcet = TimeZoneInfo.ConvertTimeFromUtc(nowutc, cet);

JSON date to asp.net DateTime is changed at runtime

I've searched around and I'm really not sure why this happens.
Most of the time my app runs in GMT from devices using GMT, but I just span a server up in Singapore, so the time is 8hrs ahead. I'm seeing some strange behaviour with DateTime objects parsed from JSON:
My app received a JSON (ISO 8601) date like this:
LastSync=2013-01-10T11:05:38.822Z
I'm using a simple .asmx web-service, that uses the built in JSON serializer for .Net 3.5, the automatically parsed DateTime object returns a date 8hrs ahead of what the JSON says it should be. Here's the function:
<WebMethod()> _
<ScriptMethod(ResponseFormat:=ResponseFormat.Json)> _
Public Function SyncFlatTable(ByVal tableName As String, ByVal LastSync As DateTime)
Return WebServiceJSON.SyncFlatTable(tableName, LastSync)
End Function
As you can see the LastSync as DateTime argument's value is 8hrs ahead:
The weird thing is if I return Now(), the JSON output from the web service is:
newLastSend=/Date(1357817197087)/
Which using a timestamp to date online converter is no-longer 8hrs ahead.
Is this IIS's fault? I can't see any other culture settings everything else is neutral, why would it change the date? How do I stop it, or do I have to take what I'm given and adjust the date to an invariant culture date?
I got this problem as well, I ended up using the sting type to pass in/out the date info.
It seems that calling .toJSON on any date object, when it's converted to a string representation it is done so using a local date. I needed to adjust this to UTC so that when it's converted it does so with what the date should be for the server:
function removeDateUTCOffSetForServer(obj) {
if (obj) {
for (prop in obj) {
if (obj[prop] instanceof Date) {
var d = obj[prop];
var utc = new Date(d.getTime() - (d.getTimezoneOffset() * 60000));
obj[prop] = utc;
}
}
}
return obj;
}

Resources