Hey I'm getting diffrent date after deserialization.
before the date is 30.03.2017, and after the date is 29.03.2017.
before
after
Json string (stam value):
[{"a_id":1,"auctionname":"computer","deadLine":"\/Date(1490821200000)\/"},{"a_id":2,"auctionname":"keyboard","deadLine":"\/Date(1490821200000)\/"},{"a_id":3,"auctionname":"mouse","deadLine":"\/Date(1490821200000)\/"}]
my code:
[Test]
public void GetAuctionsByJson_works()
{
Mock<IAuctionRespository> mockAuction = new Mock<IAuctionRespository>();
mockAuction.Setup(m => m.Auctions).Returns(new Auction[]
{
new Auction { a_id=1, auctionname="computer", deadLine=DateTime.Today},
new Auction { a_id=2, auctionname="keyboard", deadLine=DateTime.Today},
new Auction { a_id=3, auctionname="mouse", deadLine=DateTime.Today}
}.AsQueryable());
CustomerController controller = new CustomerController(mockAuction.Object);
var actual = controller.GetAuctionsByJson() as JsonResult;
JavaScriptSerializer serializer = new JavaScriptSerializer();
string stam = serializer.Serialize(actual.Data);
List<Auction> result = serializer.Deserialize<List<Auction>>(serializer.Serialize(actual.Data));
//List<Auction> result = ser.ReadObject(actual);// as List<Auction>; //null --> decirialized
}
There are multiple issues.
First, the format \/Date(1490821200000)\/ isn't used anymore. It was used in the early 2000s when there was no defacto standard to represen time in AJAX calls. The number is an escaped number of ticks in UTC. The defacto standard is ISO8601, 2017-03-30T00:00:00Z.
Second JavascriptSerializer isn't used anymore. It's been replaced by Json.NET even in ASP.NET Web API. I'm not sure if it understands ISO8601 or not. It isn't used anyway, except in legacy code.
Finally, DateTime.Today returns the local time. DateTime.Today in a +3 timezone is 30/3/2017 12:00:00 am but 29/3/2017 09:00:00 pmin UTC. Its .Kind property is Local. Even Json.NET would serialize this as 2017-03-30T00:00:00+03:00
To get the current date in UTC, one should use DateTime.UtcNow.Date. This has a Kind value of Utc. Json.NET will serialize this as 2017-03-30T00:00:00Z
Try changind all calls to
DateTime.Today
with
DateTime.UtcNow.Date
Related
I am getting different dates as a result while displaying it in the UI.
I am getting a de-serialised json object which contains date time in the format of
row.Date => {1/1/2021 12:00:00 AM}
the same date I was displaying in the UI like
var startDate = row.Date != null && row.Date != undefined ? moment(row.Date).format('MM/DD/YYYY') : "";
I was checking this by changing my local time zones.
I have tried with PST,CST,AT,EST,UTC-12:00 International Date Line West, UTC+14:00 Kiritimati Island.
I have tried the following scenarios to remove the offset while de-serializing the json object but still it shows the date as {1/1/2021 12:00:00 AM}
public JsonSerializerSettings SeralizerSettings = new JsonSerializerSettings() { DateTimeZoneHandling = DateTimeZoneHandling.Utc,DateParseHandling = DateParseHandling.DateTime };
or
public JsonSerializerSettings SeralizerSettings = new JsonSerializerSettings() { DateParseHandling = DateParseHandling.DateTime };
All the time the de-serialized json returning date as {1/1/2021 12:00:00 AM} but in the UI it showing as 31/12/2020 for some timezones, it shows 01/01/2021 and for some other time zones it shows 01/02/2021 based on the time zones.
How can I handle this scenario? Please help with this. I need to get in all the time zones should show as same date ie; 01/01/2021
note: in JS the value of row.Date getting as a timespan.
I wish to return a Json Result containing the datetime queried from database. The testing on my local machine is without any problem, however, after publishing to production server, all datetime show 3 hours ahead. I assume it is due to the server located in another timezone area.
Need help to solve this issue.
Data in Database (MS SQL):
StartDt: 2019-07-02 04:00:00.000
Controller.cs:
[HttpGet]
public ActionResult GetAll()
{
CalendarModel calendarModel = new CalendarModel();
var calendarEvents = from cal in db.Calendar
orderby cal.created descending
select cal;
return Json(calendarEvents, JsonRequestBehavior.AllowGet);
}
Json Result Fetched from my compuer:
[
{
//some data
"startDt": "/Date(1562054400000)/",
//some data
},
The above datetime is parsed as "2019-07-02T04:00:00.000-04:00", which is correct.
Json Result Fetched from production server (queried from same database):
[
{
//some data
"startDt": "/Date(1562065200000)/",
//some data
},
This datetime is "2019-07-02T07:00:00.000-04:00", which is wrong.
--------Update my solution-------
Thank #TommasoBertoni's answer inspired me that the key reason for this issue is due to the Unspecified DateTime Kind by default but turns to be local while Json serializing. So just need to set the DateTime Kind to UTC can solve that, but be aware that parsing the DateTime in front end also need to take it as UTC otherwise it will be considered as local by default.
Controller.cs:
[HttpGet]
public ActionResult GetAll()
{
CalendarModel calendarModel = new CalendarModel();
var calendarEvents = from cal in db.Calendar
orderby cal.created descending
select cal;
//Add this
foreach (var item in calendarEvents)
{
item.startDt = DateTime.SpecifyKind(item.startDt, DateTimeKind.Utc);
}
return Json(calendarEvents, JsonRequestBehavior.AllowGet);
}
.js
(using moment.js library)
//parse it as utc
moment.utc(startDt).format("YYYY-MM-DDTHH:mm:ss")
The problem is that ASP.NET uses a custom Microsoft JSON date format, that encodes DateTime values as /Date(ticks)/, where ticks represents milliseconds since epoch (UTC).
So November 29, 1989, 4:55:30 AM, in UTC is encoded as /Date(628318530718)/ (see here for more).
Example:
Microsoft JSON date format: /Date(1563464520158)/
ISO 8601 format: 2019-07-18T15:42:02.4592008Z
If a DateTime has an Unspecified kind, it will be assumed as Local and the value will be conveted to UTC in order to get the ticks since epoch.
This json format is still used in MVC, but not in Web API: this means that when you are in a Controller and serialize the result with Json(...) you'll get the non-ISO format, but if you're in an ApiController the default serializer is Json.NET, which supports the ISO 8601 format and won't convert the DateTime value.
So, to fix this behavior either you switch to Web APIs, or if you want to keep using the MVC controller, you can see the answers to these questions:
Setting the default JSON serializer in ASP.NET MVC
Using JSON.NET as the default JSON serializer in ASP.NET MVC 3
How to use Json.NET for JSON modelbinding in an MVC5 project
...or you could force the DateTime Kind to be Utc right before the json serialization, but I wouldn't recommend that.
class TestRepo
{
public IEnumerable<DateTime> GetDates()
{
var now = DateTime.Now;
// Use DateTime instances with different Kind
// showing that it doesn't impact the serialization format.
var utc = DateTime.SpecifyKind(new DateTime(now.Ticks), DateTimeKind.Utc);
var local = DateTime.SpecifyKind(new DateTime(now.Ticks), DateTimeKind.Local);
var unspecified = DateTime.SpecifyKind(new DateTime(now.Ticks), DateTimeKind.Unspecified);
return new DateTime[] { utc, local, unspecified };
}
}
// MVC controller
public class MVCValuesController : Controller
{
public ActionResult Index()
{
IEnumerable<DateTime> dates = new TestRepo().GetDates();
return Json(dates, JsonRequestBehavior.AllowGet);
}
}
// json result:
[
"/Date(1563465361835)/", // <-- Utc
"/Date(1563458161835)/", // <-- Local
"/Date(1563458161835)/" // <-- Unspecified
]
// Web API controller
public class ValuesController : ApiController
{
public IEnumerable<DateTime> Get()
{
IEnumerable<DateTime> dates = new TestRepo().GetDates();
return dates;
}
}
// json result:
[
"2019-07-18T15:56:03.6401158Z", // <-- Utc
"2019-07-18T15:56:03.6401158+02:00", // <-- Local
"2019-07-18T15:56:03.6401158" // <-- Unspecified
]
I am using JavaScriptSerializer for serializing DateTime, but when I deserialize it show one day less from the date it get serialize:
Here is test:
DateTime startDate=new DateTime(2012,1,20);//set the 20th of January
JavaScriptSerializer serializer=new JavaScriptSerializer();
string serializeDate= serializer.Serialize(startDate);
DateTime afterDeserialize= serializer.Deserialize<DateTime>(serializeDate);//I get 19th of Jan
Assert.Equals(startDate, afterDeserialize);
firstly I thougt it because of javascript datetime format but as I know for javascript Month is zero index 0=January, but I am getting one day less than the original date.
It's not losing a day arbitrarily, it's converting to a UTC date (or I should say using the date in a UTC date format) so when it's unserialized it you're no longer within your personal time zone. It's basically performing:
DateTime whateverDate = /* incoming date */;
long ticks = whateverDate.ToUniversalTime() // make UTC
.Subtract(new DateTime(1970, 1, 1)) // subtract UNIX Epoch
.TotalMilliseconds(); // get milliseconds since then
// push in to the "\/Date(ticks)\/" format
String value = String.Format(#"\/Date({0})\/", ticks);
However, try the following:
// or you rely on it serializing, then bring it back to your own local time
// (apply the time zone).
afterDeserialize = afterDeserialize.ToLocalTime();
You'll now have the UTC time back to your local time (with time zone applied).
To Pass your test:
DateTime startDate = new DateTime(2012,1,20);
JavaScriptSerializer serializer = new JavaScriptSerializer();
String serializeDate = serializer.Serialize(startDate);
DateTime afterDeserialize = serializer.Deserialize<DateTime>(serializeDate)
.ToLocalTime(); // Note: this is added
Assert.Equals(startDate, afterDeserialize); // pass!
I had the same problem and solved it by using
Newtonsoft.Json.JsonConvert.SerializeObject()
instead of
new System.Web.Script.Serialization.JavaScriptSerializer().Serialize().
The latter call stores your DateTime converted to some random timezone (GMT+0 seems to be hardcoded).
On deserializing JavaScriptSerializer giving me output in UTC (Universal Time) which due to change in hours change the date. As Brad Christie suggested to change DateTime to UTC it can solve the problems.
But actually there is no need to change the:
DateTime startDate = new DateTime(2012, 1, 20).ToUniversalTime();
as it is already taking it as Universal Time. So I just convert the output of deserialize to LocalTime:
DateTime afterDeserialize= serializer.Deserialize<DateTime>(serializeDate);
afterDeserialize.ToLocalTime();
it solved the issue.
We are sending JSON to an API defined by swagger that some properties are DateTime in the format yyyy-MM-ddThh:mm:ss.000Z (the milliseconds must be 3 digits or it fails validation at the endpoint) and some are Date (no time) properties.
I have seen many messages saying use the formatters like this:
var jsonSettings = new JsonSerializerSettings();
jsonSettings.DateFormatString = "yyyy-MM-ddThh:mm:ss.000Z"; //try .fffZ too
var jsonObject= Newtonsoft.Json.JsonConvert.DeserializeObject<OurSwaggerObject>(json , setting);
but this does not convert the DateTimes into the correct format, and how does C# deal with a Date only type? It always seems to serialise as DateTime.MinValue()
Here is an example:
Someone sends me json as string but the the dates and datetimes in the incorrect format to be sent to the endpoint. I was hoping that the swagger class and json deserialisation would format them but it is not.
This is the swagger generated class
public class OurSwaggerObject
{
[Newtonsoft.Json.JsonProperty("dateTimeField", Required = Newtonsoft.Json.Required.Always)]
[System.ComponentModel.DataAnnotations.Required]
[System.ComponentModel.DataAnnotations.RegularExpression(#"^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d\.\d{3}Z$")]
public DateTime dateTimeField { get; set; }
[Newtonsoft.Json.JsonProperty("dateField", Required = Newtonsoft.Json.Required.Always)]
[System.ComponentModel.DataAnnotations.Required]
[System.ComponentModel.DataAnnotations.RegularExpression(#"^\d{4}-\d\d-\d\d$")]
public DateTime dateField { get; set; }
}
So I try and coerce the json to be correct but I'm doing it wrong or something is missing
string json = #"{ 'dateTimeField': '1995-04-07T00:00:00',
'dateField': '1995-04-07T00:00:00'
}";
/* The json we need to satisfy the swagger endpoint is:
{ 'dateTimeField': '1995-04-07T00:00:00.000Z',
'dateField': '1995-04-07'
}
*/
OurSwaggerObject deserialisedIntoObject = Newtonsoft.Json.JsonConvert.DeserializeObject<OurSwaggerObject>(json);
string serialisedToString = Newtonsoft.Json.JsonConvert.SerializeObject(deserialisedIntoObject);
//serialisedToString= "{\"dateTimeField\":\"1995-04-07T00:00:00\",\"dateField\":\"1995-04-07T00:00:00\"}"
var jsonSettings = new JsonSerializerSettings();
jsonSettings.DateFormatString = "yyyy-MM-ddThh:mm:ss.fffZ"; //this won't help much for the 'date' only field!
deserialisedIntoObject = Newtonsoft.Json.JsonConvert.DeserializeObject<OurSwaggerObject>(json,jsonSettings);
serialisedToString = Newtonsoft.Json.JsonConvert.SerializeObject(deserialisedIntoObject, jsonSettings);
//serialisedToString="{\"dateTimeField\":\"1995-04-07T00:00:00\",\"dateField\":\"1995-04-07T00:00:00\"}"
As I mentioned in a comment, there is no standard date representation in JSON. The ISO8601 is the de-facto standard, ie most people started using this some years ago. ISO8601 does not require milliseconds. If the other endpoint requires them, it's violating the defacto standard.
Json.NET has been using IOS8601 since version 4.5. The current one is 10.0.3. The following code :
JsonConvert.SerializeObject(DateTime.Now)
returns
"2017-09-08T19:01:55.714942+03:00"
On my machine. Notice the timezone offset. That's also part of the standard. Z means UTC.
You can specify your own time format, provided it's the correct one. In this case, it should be yyyy-MM-ddTHH:mm:ss.fffZ. Notice the fff for milliseconds and HH for 24-hour.
The following code
var settings=new JsonSerializerSettings{DateFormatString ="yyyy-MM-ddTHH:mm:ss.fffZ"};
var json=JsonConvert.SerializeObject(DateTime.Now,settings);
returns
"2017-09-08T19:04:14.480Z"
The format string does not force a timezone translation. You can tell Json.NET to treat the time as Local or Utc through the DateTimeZoneHandling setting :
var settings=new JsonSerializerSettings{
DateFormatString ="yyyy-MM-ddTH:mm:ss.fffZ",
DateTimeZoneHandling=DateTimeZoneHandling.Utc};
var json=JsonConvert.SerializeObject(DateTime.Now,settings);
Returns :
"2017-09-08T16:08:19.290Z"
UPDATE
As Matt Johnson explains, Z is just a literal, while K generates either Z or an offset, depending on the DateTimeZoneHandling setting.
The format string yyyy-MM-ddTH:mm:ss.fffK with DateTimeZoneHandling.Utc :
var settings=new JsonSerializerSettings{
DateFormatString ="yyyy-MM-ddTH:mm:ss.fffK",
DateTimeZoneHandling=DateTimeZoneHandling.Utc};
var json=JsonConvert.SerializeObject(DateTime.Now,settings);
Will return :
2017-09-11T9:10:08.293Z
Changing to DateTimeZoneHandling.Utc will return
2017-09-11T12:15:12.862+03:00
Which, by the way is the default behaviour of Json.NET, apart from the forced millisecond precision.
Finally, .NET doesn't have a Date-only type yet. DateTime is used for both dates and date+time values. You can get the date part of a DateTime with the DateTime.Date property. You can retrieve the current date with DateTime.Today.
Time of day is represented by the Timespan type. You can extract the time of day from a DateTime value with DateTime.TimeOfDay. Timespan isn't strictly a time-of-day type as it can represent more than 24 hours.
What was that yet?
Support for explicit Date, TimeOfDay is comming through the CoreFX Lab project. This contains "experimental" features that are extremely likely to appear in the .NET Runtime like UTF8 support, Date, String, Channles. Some of these already appear as separate NuGet packages.
One can use the System.Time classes already, either by copying the code or adding them through the experimental NuGet source
Get current universaltime to json date time format and vice versa:
DateTime currentDateTime = DateTime.Now.ToUniversalTime();
var jsonDateTime = GetJSONFromUserDateTime(currentDateTime);
DateTime getDateTime = GetUserDateTimeFromJSON(jsonDateTime);
Here are both methods:
/// <summary>
/// Convert UserDateTime({9/7/2018 8:37:20 AM}) to JSON datetime(1536309440373) format
/// </summary>
/// <param name="givenDateTime"></param>
/// <returns></returns>
public static string GetJSONFromUserDateTime(DateTime givenDateTime)
{
string jsonDateTime = string.Empty;
if (givenDateTime != null)
{
JsonSerializerSettings microsoftDateFormatSettings = new JsonSerializerSettings
{
DateFormatHandling = DateFormatHandling.MicrosoftDateFormat
};
jsonDateTime = JsonConvert.SerializeObject(givenDateTime, microsoftDateFormatSettings);
jsonDateTime = jsonDateTime.Replace("\"\\/Date(", "").Replace(")\\/\"", "");
}
return jsonDateTime;
}
/// <summary>
/// Convert JSON datetime(1536309440373) to user datetime({9/7/2018 8:37:20 AM})
/// </summary>
/// <param name="jsonDateTime"></param>
/// <returns></returns>
public static dynamic GetUserDateTimeFromJSON(string jsonDateTime)
{
dynamic userDateTime = null;
if (!string.IsNullOrEmpty(jsonDateTime))
{
JsonSerializerSettings microsoftDateFormatSettings = new JsonSerializerSettings
{
DateFormatHandling = DateFormatHandling.MicrosoftDateFormat
};
userDateTime = JsonConvert.DeserializeObject("\"\\/Date(" + jsonDateTime + ")\\/\"", microsoftDateFormatSettings);
}
return userDateTime;
}
If, like Willie Esteche you wish to convert a number that is too low, you have probably got a Unix Date Time value. His solution does indeed work, but as of .Net Framework 4.6 there is an easier way to do things.
Given a value of 1500013000, first you convert this to a DateTimeOffset with the FromUnixTimeSeconds() method, then simply grab the DateTime component.
DateTime dt = DateTimeOffset.FromUnixTimeSeconds(1500013000).UtcDateTime;
Conversion back (assuming UTC) is performed like so:
long Udt = new DateTimeOffset(dt,TimeSpan.Zero).ToUnixTimeSeconds();
In my case, i using this config in vb.net, it's so easy translate to c #
settings.NullValueHandling = NullValueHandling.Ignore
settings.DateTimeZoneHandling = DateTimeZoneHandling.Local
BE = JsonConvert.DeserializeObject(Of EN_BE)(str, settings)
I get this format date from laravel API
2020-08-02T01:41:05.000000Z
and i convert to correct value same to database
2020-08-01 20:41:05
You can try this:
DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
This question already has answers here:
How to make ASP.Net MVC model binder treat incoming date as UTC?
(7 answers)
Closed 5 years ago.
I'm having trouble with DateTimes in my ASP.NET C# Web Api 2 project. I need to pass through an ISO 8601 date in my query string as follows:
api/resource?at=2016-02-14T23:30:58Z
My controller method is as follows
[HttpGet("/resource")]
public IActionResult GetResource([FromQuery]DateTime? at = null)
{
if (!at.HasValue)
{
at = DateTime.UtcNow;
}
else
{
at = DateTime.SpecifyKind(at.Value, DateTimeKind.Utc);
}
// ...
}
Notice the little hack - the date is coming in with a DateTimeKind of Local, despite being specified with the 'Z' signifying UTC. Dates should always be passed in UTC although I would ideally not like this to be a constraint. I am using NodaTime internally and only expose DateTime in the query and response models for legacy reasons.
Why are my dates parsed to a DateTimeKind of local?
How can I read my UTC dates from query strings using ASP.NET web api 2?
If you use DateTimeOffset instead of DateTime, the time-zone offset is preserved. You could then either use it directly, or convert it to a DateTime via the UtcDateTime property.
DateTimeOffset dto = DateTimeOffset.Parse("2016-02-14T23:30:58Z");
DateTime dt = dto.UtcDateTime;
[HttpGet("/resource")]
public IActionResult GetResource([FromQuery]DateTimeOffset? at = null)
{
if (!at.HasValue)
{
at = DateTimeOffset.UtcNow;
}
// ...
}