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.)
Related
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.");
}
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.
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;
}
}
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;
}
I can't figure out how convert the datetime that wcf outputs into a datetime that ExtJs can use. I have found lots of articles about this but they are all for ExtJs 3 and I couldn't get it to work with 4.
I did find this code but I don't know how I could use it to convert everything in my JsonStore.
//this method is used to convert the MS JSON date format to the ExtJS Grid Date Column Value
function dateFormatter(dt) {
/// <summary>this method is used to convert the MS JSON date format to the ExtJS Grid Date Column Value</summary>
/// <param name="dt">Actual JSON Date Value</param>
try {
//microsoft JSON date format needs to convert into Javascript date
var newdata = dt.replace(/\/Date\((-?[0-9]+)([+-][0-9]+)?\)\//g, "new Date($1)");
newdata = eval('(' + newdata + ')');
return newdata.format('m/d/Y');
}
catch (e) {
return dt;
}
}
Unlike Ext JS 3, Ext JS 4 does not extend the native Date object. Instead it provides Ext.Date. So instead of:
date.format('m/d/Y');
you would instead use:
Ext.Date.format(date, 'm/d/Y');
Additionally using eval() is a really bad idea most of the time. This code is no exception.
And if you drop eval, the try-catch is also not needed.
Finally, a function that both parses a date and converts it to another format seems to be doing too much. Often you will want to display the same date in different formats in different parts of your app. Therefore I would rather just have a function that parses the WCF date format into JavaScript Data object. And then use convert the Date object into particular string format at the very place where it's needed.
Removing all extraneous stuff, this is what I get:
function parseWcfDate(dt) {
var milliseconds = dt.replace(/\/Date\((-?[0-9]+)([+-][0-9]+)?\)\//, "$1");
return new Date(parseInt(milliseconds, 10));
}
Anyway, all this is too much trouble... Ext JS has built-in support for parsing WCF formatted dates:
Ext.Date.parse("/Date(1234567894560)/", "MS");
Also see:
How to handle json DateTime returned from WCF Data Services (OData)
How do I format a Microsoft JSON date?
Use JSON.NET with JavaScriptDateConverter.