I have a ASP.NET WEB.API 4 and a Controller returning the following json:
{ date: "2013-03-14T00:00:00" }
I parse it on the client (JavaScript):
date = new Date(json.date); // json.date being "2013-03-14T00:00:00"
Later I do a POST and in the body the date has changed format to
{ date: "2013-03-13T23:00:00.000Z" }
My guess was that some time zone stuff has been added by JavaScript or the browser?
Because of DB storing dates as int (yyyymmdd) I do the following convertion:
public static int ToInt(DateTime date)
{
return date.Year * 10000 + date.Month * 100 + date.Day;
}
The resulting int is then one day off :(
However if I do
date.ToLocalTime()
before calling the ToInt method, it looks fine.
Have I understood this correctly and is ToLocalTime() a sufficient solution or do I need to spend a day reading up on UTC dates in .NET and JavaScript?
Thanks!
In my opinion you will get better result if your controller will return date in ZULU format. So before sending use: ToUniversalTime (http://msdn.microsoft.com/en-us/library/system.datetime.touniversaltime.aspx) Than the result also will be in ZULU format, so you don't have to convert it to LocalTime
date = new Date(json.date); // json.date being "2013-03-14T00:00:00"
And what timezone is that json.date in? If there's no information about this, the JS Date constructor will assume it is the client's local timezone (and that is quite random). If you want it to be UTC, just add "Z" after your ISO-datestring:
date = new Date(json.date+"Z");
Also always use the [gs]etUTC(FullYear|Month|Date|…) methods then.
Related
I am facing an issue while parsing JSON Date Time object using moment(of course I tried many approaches suggested in Stackoverflow but nothing worked in my case).
In my application, I'm storing a DateTime value as UTC DateTime. Now when I'm displaying I need to display it according to the browser timezone. After going through many StackOverflow questions, I used "moment.js" as below
//From server, the Date object looks like /Date(1506510057813)/
//The equivalent DateTime value stored in Database is 2017-09-27 13:00:57.813
fuction DateTimeFormatter(value)
{
if (value != undefined) {
var newValue = new Date(moment.utc(value));
//But at this line, even with just moment(value) all I am getting is DateTime which is not same as UTC time.
//I don't want any time zone to get appended all I want is just 13:00:57
var newHours = newValue.getHours() - newValue.getTimezoneOffset() / 60;
var newMinutes = (newHours + '.0').split('.')[1] * 6;
newValue.setHours(newHours);
newValue.setMinutes(newMinutes);
return moment(newValue).format(applicationTableDateFormat);
}
else
return "";
}
Please let me know what I am doing wrong or is there any other way I can display time as per browser time zone.
Once you have a UTC moment, you can convert it to local.
moment.utc(value).local().format(...)
https://momentjs.com/docs/#/manipulating/local/
But it sounds like maybe your real problem is when you store the date. If you're storing it as UTC, make sure you actually convert the local value to UTC before you store it. That way when you read it, you get a predictable value that you can safely convert to any locale.
Angularjs has its own mechanism to display formatted dates on views you just needs an absolute representation of a date and it takes care of the rest. And by absolute, I mean, a Date which is settled in a timezone whether it's utc or not, you need to know what timezone you are talking about.
The date filter
It's a filter from the core module of angularjs and it accepts:
"... either as Date object, milliseconds (string or number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.sssZ and its shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is specified in the string input, the time is considered to be in the local timezone." (Angularjs date filter)
The problem
Angularjs need a proper date input in order to display it correctly, in your case you seem to have the milliseconds format (sort of, /Date(1506510057813)/), you could use that and extract the numeric part and input that on the pipe, or you can change the server to send the ISO 8601 date (a.k.a., yyyy-MM-ddTHH:mm:ss.sssZ).
For example:
let rawDate = '/Date(1506510057813)/';
let re = /\/Date\((\d+)\)\//g; // regex to extract number from the string date
let myDate = new Date(Number(re.exec()[1])) // extract the milliseconds
Or
let rawDate = '2017-09-27T11:00:57.813Z';
let myDate = new Date(rawDate)// and you don't need to do anything else
Either way you'd end up with something like this:
<span> {{ myDate | date }}</span>
I am storing a datetime value in a cookie using ASP.Net server-side C# code.
On client-side, I am reading the date and converting it to UTC using JavaScript. The code for this is as given below.
Storing date time in ASP.Net
//DateTime.Now depends on location of web server
HttpCookie cookie = new HttpCookie("xyz", DateTime.Now.ToUniversalTime().ToString());
Response.Cookies.Add(cookie);
JavaScript code to read date time sent by ASP.Net
//cDate depends on user's location
//c is value read from cookie named 'xyz'
var cDate = new Date(c);
var cDate_utc = new Date(cDate.getUTCFullYear(), cDate.getUTCMonth(), cDate.getUTCDate(), cDate.getUTCHours(), cDate.getUTCMinutes(), cDate.getUTCSeconds());
When the end user's location is different from ASP.Net web server's location, then the datetime value in the cookie will be incorrectly interpreted by JavaScript. For example, in one case the value stored in cookie was 10/31/2015 7:29:54 PM and there is no way for JavaScript to know that this is UTC which means it would be incorrectly parsed on client-side.
Question: How can I pass DateTime value from ASP.Net to JavaScript in above scenario so it interprets correctly in JavaScript no matter what the geographical locations of end user's browser and ASP.Net web server are?
UPDATE with a solution that worked
After a lot of research, I came up with the following. The bottom line is to always work in UTC so day light savings does not cause problems with the programming logic.
Pass UTC and not local date time from ASP.Net server-side to client-side via a cookie using individual components of date time. Do not pass a date time string but individual components of date time as a comma-delimited list in following format: year,month, day, hours, min, sec, milliseconds. Passing individual components rather than a date time string from ASP.Net is better since JavaScript Date constructor can behave in an erratic manner when parsing a string especially if the format of string passed is not what the constructor likes. Passing individual components also helps in cross-browser consistent behavior since the Date constructor with individual components works well across all major browsers.
On client-side, read the cookie value and instantiate a Date object that will be the local time on browser side corresponding to server-side UTC time
Now you have the server-side ASP.Net passed date time in local date time on client-side. This might work for some cases, but can cause sudden surprises on client-side when daylight savings happens, so it's best to convert this client-side date to UTC.
Pass date time in UTC to client-side from ASP.Net
DateTime utcDateTime = DateTime.Noe.ToUniversalTime();
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append(utcDateTime.Year);
sb.Append(",");
sb.Append(utcDateTime.Month - 1); //since JavaScript uses a 0 based index for month
sb.Append(",");
sb.Append(utcDateTime.Day);
sb.Append(",");
sb.Append(utcDateTime.Hour);
sb.Append(",");
sb.Append(utcDateTime.Minute);
sb.Append(",");
sb.Append(utcDateTime.Second);
sb.Append(",");
sb.Append(utcDateTime.Millisecond);
HttpCookie cookie = new HttpCookie("xyz", sb.ToString());
Response.Cookies.Add(cookie);
Get UTC date time in JavaScript for passed ASP.Net date time
var c = getCookie("xyz");//getCookie is a custom JavaScript function to read cookie value
if (c) {
var dateArray = c.split(",");
//get local date time corresponding to ASP.Net passed UTC date time
var cDate = new Date( Date.UTC(dateArray[0], dateArray[1],dateArray[2], dateArray[3], dateArray[4], dateArray[5], dateArray[6])) ;
//get UTC date time so day light savings does not cause issues in logic on client-side
cDate_utc = new Date(cDate.getUTCFullYear(), cDate.getUTCMonth(), cDate.getUTCDate(), cDate.getUTCHours(), cDate.getUTCMinutes(), cDate.getUTCSeconds());
logInfo("date from cookie in utc is " + cDate_utc);
}
Although the comments already point you in the right direction:
If you use moment.js it will by default use UTC format and even if it wasn't (for completeness sake) you can use this format to specify an offset: 2013-02-08 09:30:26.123+07:00
You call the code like this: moment(cDate, $format);
If I understand your question correctly, you want to convert the date passed in the cookie from UTC to local time.
You can use Date.prototype.getTimezoneOffset()
getTimezoneOffset returns the offset from UTC to local time in minutes.
Adjust locally by subtracting the offset minutes...
new Date(dateServer.getTime() - ((60 * 1000) * dateServer.getTimezoneOffset()))
Here's an example...
var dateJan;
var dateJul;
var dateValue;
var divLocal;
var divServer;
var timezoneOffset;
dateValue = new Date('10/31/2015 7:29:54 PM')
divServer = document.getElementById('serverUTCTime');
divLocal = document.getElementById('localTime')
divServer.innerHTML = 'from server = ' + dateValue.toString();
// Get dates for Jan & Jul
dateJan = new Date(dateValue.getFullYear(), 0, 1);
dateJul = new Date(dateValue.getFullYear(), 6, 1);
// Get timezone offset
timezoneOffset = Math.max(dateJan.getTimezoneOffset(), dateJul.getTimezoneOffset());
// Check if daylight savings
if (dateValue.getTimezoneOffset() < timezoneOffset) {
// Adjust date by Jan offset
dateValue = new Date(dateValue.getTime() - ((60 * 1000) * dateJan.getTimezoneOffset()));
} else {
// Adjust date by Jul offset
dateValue = new Date(dateValue.getTime() - ((60 * 1000) * dateJul.getTimezoneOffset()));
}
divLocal.innerHTML = 'to local = ' + dateValue.toString();
<div id="serverUTCTime"></div>
<br/>
<div id="localTime"></div>
I have tried to search for the answer already, and although I find answers that are very similar, I don't think they are exactly what I am looking for. Please forgive me if this is already answered elsewhere.
I am trying to parse an ISO date in javascript so that I can compare it to the client system date and display information depending on if the ISO date is before or after the client system date.
This was fine until I needed to support IE8 and now I am stuck.
I have created a function because I have three different dates that I need to do this to.
for example, my ISO date is: 2015-12-22T11:59 in UTC time.
but once my date is parsed, the full date is 11:59 in local time, no matter which time zone i test, it's always 11.59 in THAT time zone.
I know that the function I have created currently doesn't do anything with timezone, this is where I am stuck. I don't know what to add to get my end date to change as a reflection of the timezone of the clients machine.
any help or advice would be greatly appreciated.
I am not able to use something like moments.js because I have an upload restriction.
Jquery is available though. or plain javascript.
<script>
function setSaleContent() {
//creating a new date object that takes the clients current system time. so we can compare it to the dates stored in our array
var currentDate = new Date();
console.log(currentDate + " this is the clients date ");
//These variables actually come from an external array object, but I'm putting them in here like this for this example.
var destinations = {
freedate: "2015-12-16T11:59",
courierdate: "2015-12-22T11:59",
nextdaydate: "2015-12-23T11:59",
}
//fetch all the ISO dates from the array.
var freeDateISO = destinations["freedate"];
var courierDateISO = destinations["courierdate"];
var nextdayDateISO = destinations["nextdaydate"];
//I am creating this reusable function to split up my ISO date for the sake of IE8.. and create it into a date format that can be compared against another date. I know that this isn't doing anything with my timezone and that is where my problem lies.
function parseDate(str) {
var parts = /^(\d{4}).(\d{2}).(\d{2}).(\d{2}):(\d{2})/.exec(str);
if (parts) {
return new Date(parts[1], parts[2] - 1, parts[3], parts[4], parts[5]);
}
return new Date();
}
//I would like this date to change to reflect the time zone of the clients system time.
//currently returns the date at 11.59 regardless of timezone.
//If i was in GMT i would want it to say 11.59
//If i was in CT time I would like this to say 05.59
//If i was in Perth I would like this to say 19:59
var freeDate = parseDate(freeDateISO);
console.log(freeDate + " this is the converted date for IE")
}
window.onload = setSaleContent;
The simple solution is to append Z to the ISO date to indicate it is in UTC time, such as 2015-12-22T11:59Z.
When JavaScript parses that date as a string, it will then automatically convert the UTC date to the local time zone.
While this is simple enough with a parsing call in the form new Date(str);, it will not play nice with your parse call with numerical arguments targeting IE8 and other old browsers.
A polyfill for parsing ISO dates with timezone exists: Javascript JSON Date parse in IE7/IE8 returns NaN
This can replace your custom parseDate function after some modification to take an input string.
Alternatively, implement your own custom date manipulater to account for the local timezone using the .getTimezoneOffset() method on the newly created date, which gives the time zone offset in minutes, but you will have to come up with a method of utilising the offset such as adjusting hours and minutes, due to the limited methods of the JavaScript date object.
I am querying data using OData, url looks like http://myurl.com/api/Customer?$filter=ResDate eq DateTime'2014-03-15T12:01:55.123'.
I'm getting date/time from jquery.datepicker instead of the static date and using moment.js to convert from DD-MM-YYYY to YYYY-MM-DDTHH:mm:ss in order to pass it to web service.
function convertDateToISOdate(date){
var newDate = moment(date,'DD-MM-YYYY').format('YYYY-MM-DDTHH:mm:ss');
return newDate;
}
Date returns from the function, is 2014-03-15T00:00:00.
Problem : 2014-03-15T12:01:55.123 is not equal to 2014-03-15T00:00:00, so there's no record selected.
What I want is , just to compare the date , not include time stamp.
Note : I can not change the format date/time at server side(Web service) because it's not belongs to me.
Any idea is much appreciated.
Your first call to moment(date,'DD-M-YYYY') is stripping the time information from the incoming data. try using moment(date) (no format) instead because momentjs recognizes your incoming date format intrinsically, without having to be told which format to use, and will correctly parse the H:M:S data, too.
MomentJS date parse information
I have an MVC 3 web application for a web API, a controller emit json.
In the json result I see dates are being serialised automatically
as
{
Flag: "U"
EventId: "168ef1d4-60ca-4fa1-b03b-8c3207650347"
EventTitle: "test event 11"
DateTimeStart: "/Date(1369217469310)/"
IsCustomEvent: true
Location: null
}
in javascript I need to convert DateTimeStart in human readable format and using this code
var date = new Date(1369217469310);
alert(date);
I see the resulting data as
Wed May 22 2013 12:11:09 GMT+0200 (CEST)
This is 1 hour a head of the date stored in the application wich is 22/05/2013 11:11:09.
I would like to know where the issue could be and how to fix it:
Is it .Net serialising dates by default using CEST wich is +1 UCT, in this case how to set up UCT at 0?
Is it an issue when converting in the date using JavaScript?
Please let em know how you would fix it, thanks!
I haven't enough information to advice about the server side. Generally the source of the problem on server side may be the CultureInfo set in you application. You may consider to convert all datetimes as UTC before sending it to the browser. Check the DateTime.ToUniversalTime() method.
On client side you also are able to fix the offset between regional time and UTC. There is no build in function to do this, but it's very simple operation to perform. Check the code below.
var date = new Date();
var dateWithOffset = date.getTime() + date.getTimezoneOffset() * 60000;