I am getting a date from my api and the format i get is "2019-04-17T15:04:28"
the date is UTC.
Should the date i get back have the Z at the end or doesn't it matter. Javascript date function will display incorrect if the Z is not there wont it?
Thanks #Esko thanks i think for me the confusion is that in .net core if you change the json serializer options in startup.cs by the following:
AddJsonOptions(opt =>{
opt.SerializerSettings.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.IsoDateFormat;
});
the tool tip in visual studio says yet it doesn't put the Z on and the documentation also doesn't show the Z (https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_DateFormatHandling.htm)
Instead i am going to try and set a different option
opt.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc;
If you know the timezone to be constant, you can always just append +0Z00 to your datestring. For example, if the server serializes time into CEST, turn "2019-04-17T15:04:28" into "2019-04-17T15:04:28+0100"
Parsing "2019-04-17T15:04:28" in new Date will parse it as if it's in your local timezone - the meaning of this string depends on what timezone it's parsed in.
Parsing "2019-04-17T15:04:28Z" will parse it in GMT - meaning that no matter what system parses it, it will always refer to the same time.
In other words, "2019-04-17T15:04:28" as a timestamp is ambiguous unless you know the timezone it was recorded in.
I had the similar problem and I found the answer
In my case the DateTime was with Kind Unspecified, in this case the JsonConvert hasn't enough information to add the Z in the end.
You have several options:
Convert it to UTC with ToUniversalTime method
If you're sure you're working with UTC you can add it to general JsonOptions like this:
JsonConvert.DefaultSettings = (() =>
{
return new JsonSerializerSettings
{
Converters = new List<JsonConverter>() {new IsoDateTimeConverter { DateTimeStyles= System.Globalization.DateTimeStyles.AssumeUniversal } }
};
});
if you just want to add the Kind=UTC to current Unspecified Date, you can always write isoConverter like this:
JsonSerializerSettings
{
Converters = new List<JsonConverter>() { new CustomIsoDateTimeConverter() }
};
Where the class will look like this:
public class CustomIsoDateTimeConverter : IsoDateTimeConverter
{
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
if (value is DateTime dateTime && dateTime.Kind == DateTimeKind.Unspecified)
value = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc);
base.WriteJson(writer, value, serializer);
}
}
Related
I can't figure out how to build a function that does this
INPUT: dateToDateFormat('16/07/2022') -> OUTPUT: DD/MM/YYYY
INPUT: dateToDateFormat('07/16/2022') -> OUTPUT: MM/DD/YYYY
The input dates will be already formatted by .toLocaleString function
Edit:
I think I was not precise enough with the output, it should literally output MM/DD/YYYY as a string, not the actual date value
A) First of all, your desired date string conversion seems to be easy (solution below) without using any package/overhead.
B) However, if you need to process it further as a JS Date Object, things become more difficult. In this case, I like to provide some useful code snippets at least which might help you depending on your usecase is or what you are aiming for.
A) CONVERSION
Seems you need a simple swap of day and month in your date string?
In this case, you do not need to install and import the overhead of a package such as date-fns, moment or day.js.
You can use the following function:
const date1 = "16/07/2022"
const date2 = "07/16/2022"
const dateToDateFormat = (date) => {
const obj = date.split(/\//);
return `${obj[1]}/${obj[0]}/${obj[2]}`;
};
console.log("New date1:", dateToDateFormat(date1))
console.log("New date2:", dateToDateFormat(date2))
B) STRING TO DATE
Are you using your date results to simply render it as string in the frontend? In this case, the following part might be less relevant.
However, in case of processing them by using a JS Date Object, you should be aware of the following. Unfortunately, you will not be able to convert all of your desired date results/formats, here in this case date strings "16/07/2022" & "07/16/2022", with native or common JS methods to JS Date Objects in an easy way due to my understanding. Check and run the following code snippet to see what I mean:
const newDate1 = '07/16/2022'
const newDate2 = '16/07/2022'
const dateFormat1 = new Date(newDate1);
const dateFormat2 = new Date(newDate2);
console.log("dateFormat1", dateFormat1);
console.log("dateFormat2", dateFormat2);
dateFormat2 with its leading 16 results in an 'invalid date'. You can receive more details about this topic in Mozilla's documentation. Furthermore, dateFormat1 can be converted to a valid date format but the result is not correct as the day is the 15th and not 16th. This is because JS works with arrays in this case and they are zero-based. This means that JavaScript starts counting from zero when it indexes an array (... without going into further details).
CHECK VALIDITY
In general, if you need to further process a date string, here "16/07/2022" or "07/16/2022", by converting it to a JS Date Object, you can in any case check if you succeed and a simple conversion with JS methods provides a valid Date format with the following function. At least you have kind of a control over the 'invalid date' problem:
const newDate1 = '07/16/2022'
const newDate2 = '16/07/2022'
const dateFormat1 = new Date(newDate1);
const dateFormat2 = new Date(newDate2);
function isDateValidFormat(date) {
return date instanceof Date && !isNaN(date);
}
console.log("JS Date Object?", isDateValidFormat(dateFormat1));
console.log("JS Date Object?", isDateValidFormat(dateFormat2));
Now, what is the benefit? You can use this function for further processing of your date format depending on what you need it for. As I said, it will not help us too much as we still can have valid date formats but with a falsy output (15th instead of 16th).
CONVERT TO DATE OBJECT BY KNOWING THE FORMAT
The following function converts any of your provided kinds of dates ("MM/DD/YYYY" or "DD/MM/YYYY") to a valid JS Date Object and - at the same time - a correct date. However, drawback is that it assumes to know what kind of input is used; "MM/DD/YYYY" or "DD/MM/YYYY". The dilemma is, that this information is crucial. For example, JS does not know if, for example, "07/12/2022" is "MM/DD/YYYY" or "DD/MM/YYYY". It would return a wrong result.
const newDate1 = "07/16/2022"
const newDate2 = "16/07/2022"
function convertToValidDateObject(date, inputFormat) {
const obj = date.split(/\//);
const obj0 = Number(obj[0])
const obj1 = Number(obj[1])
const obj2 = obj[2]
//
// CHECK INPUT FORMAT
if (inputFormat === "MM/DD/YYYY") {
return new Date(obj2, obj0-1, obj1+1);
} else if (inputFormat === "DD/MM/YYYY") {
return new Date(obj2, obj1-1, obj0+1);
} else {
return "ERROR! Check, if your input is valid!"
}
}
console.log("newDate1:", convertToValidDateObject(newDate1, "MM/DD/YYYY"))
console.log("newDate2:", convertToValidDateObject(newDate2, "DD/MM/YYYY"))
console.log("newDate2:", convertToValidDateObject(newDate2, "MM/YYYY"))
If the wrong format is provided as a second argument, an error is provided in the console. In practise I suggest you to use a try-catch block ( I tried here, but it does not work here in this stackoverflow editor).
I wish you good luck. Hope these information can help you.
I have an <input type="text"/> where the user can (try to) type in a date in whatever format/syntax (even in an invalid format).
I want to get the value of whatever the user typed in, pass it through a localized moment and then update the input with the correct format.
I'm trying to follow these guidelines in order to use a local moment
// I want to use a local instance of moment
let localLocale = moment();
// I want to set the locale to be 'fr'
localLocale.locale('fr')
// I want to set the format to be 'LL'
localLocale.format('LL')
// this is what the user typed in
let userInput = '2/3/1986'
// I want to do:
let formattedUserInput = something(userInput)
The value of formattedUserInput must be Mars 2, 1986
I'm looking for what something should be. The moment docs are so confusing there is no explanation on how to do this.
If userInput is obviously gibberish, the something() should return null or throw an error or whatever I don't mind.
I tried localLocale(userInput) but it throws a localLocale is not a function
You can use moment(String, String[]) to parse inputs in difefrent formats:
If you don't know the exact format of an input string, but know it could be one of many, you can use an array of formats.
You can use moment.ISO_8601, as shown here, to parse ISO 8601 inputs as moment(String) does.
Please note that moment(String, String[])
Starting in version 2.3.0, Moment uses some simple heuristics to determine which format to use. In order:
Prefer formats resulting in valid dates over invalid ones.
Prefer formats that parse more of the string than less and use more of the format than less, i.e. prefer stricter parsing.
Prefer formats earlier in the array than later.
One possible solution can be the following:
function something(userInput){
let m = moment(userInput, [moment.ISO_8601, 'DD/MM/YYYY', 'MM/DD/YYYY' ]);
if( !m.isValid() ){
// throw "Invalid input";
}
return m.locale('fr').format('LL');
}
['2/3/1986', 'aaa', '10-15-2017'].forEach((userInput) => {
console.log( something(userInput) );
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/locale/fr.js"></script>
The locale set is local to the moment instance you have defined. So
let localLocale = moment();
localLocale.locale('fr');
sets the local for localLocale to 'fr'. So if you want to do it locally for just this input, you'd use:
// this is what the user typed in
let userInput = '2/3/1986';
// Use a local instance of moment, using the user's input
let localLocale = moment(userInput, 'D/M/YYYY');
// Set the locale to be 'fr'
localLocale.locale('fr');
// Get the formatted string
let formattedUserInput = localLocale.format('LL');
console.log(formattedUserInput);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment-with-locales.min.js" integrity="sha256-VrmtNHAdGzjNsUNtWYG55xxE9xDTz4gF63x/prKXKH0=" crossorigin="anonymous"></script>
I cant seem to figure out what the issue is I have a manual time enter function on my website where a user can enter a time and then I store it in the db..
So my function looks like this..
createTime() {
this.startTime = moment(`${this.hour}:${this.minute} ${this.timeOfDay}`, `HH:mm a`).utc();
}
so I typed in 5:45pm
now when I console.log() the created moment I get this...
so its the right utc time but it says its in AUS TIME
then when I get the time back from the server and then try to convert it back to local time like so..
fixTime(momentObject: moment.Moment) {
return moment(momentObject).local().format('hh:mm A');
}
I get 4:45am
I can not figure out what the issue is.. how can I fix this?
fixTime(momentObject: moment.Moment) {
var testDateUtc = moment.utc(momentObject);
var localDate = moment(testDateUtc).local();
return localDate.format('hh:mm A');
}
you must Create a moment object and set the UTC flag to true on the object and Create a localized moment object converted from the original moment object and finally Return a formatted string from the localized moment
object.
See: http://momentjs.com/docs/#/manipulating/local/
I'm using DateTextBox as one of many controls in my screen. I register them in one place and then batch set values to them in loop, calling set('value', val) on each of them. All controls behave correctly, only the DateTextBox won't accept the data from server.
Initially java's Date was serialized as long (ex. 1280959200000), but when I've changed to ISO format (ex. "2010-08-04T22:00:00.000+0000") it isn't accepted either. But both are accepted date formats for new Date() constructor.
On the output I get the date value in ISO format: "2013-08-04T22:00:00.000Z" so it should be also accepted on input.
What can I do with DateTextBox to make it accept values in all formats supported by JavaScript's Date object, or one of the formats that can be returned from my server?
I think the fundamental problem is that the Javascript built-in Date object only accepts certain formats, and Dojo is relying on that built-in-behavior. At work, we have a similar issue, where lots of legacy PHP code is accustomed to passing dates around in a Mysql-derived format (ex. YYYY-MM-DD HH:MM:SS)
Our current workaround is to subclass dijit/form/DateTextBox, which also lets us impose some UI improvements. When something tries to set a value which isn't already a Date object and looks like a MySQL datetime, this code re-forms it to match ISO-8601 and passes it on through.
Dojo 1.9 code for a custom version of DateTextBox:
define([
"dojo/_base/declare",
"dojo/_base/lang",
"dojo/_base/array",
"dijit/form/DateTextBox"
], function(declare, lang, array, DateTextBox){
var clazz = declare([DateTextBox], {
_mysqlStyleExp : /^(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2})$/,
postMixInProperties: function(){ // change value string to Date object
this.inherited(arguments);
this.constraints.datePattern = "yyyy-MM-dd"; // Affects display to user
},
_convertMysqlDateToIso: function(value){
value = lang.trim(value);
var matches = this._mysqlStyleExp.exec(value);
if(matches !== null){
// Put the "T" in the middle and add fractional seconds with UTC
// timezone
// If your MySQL dates are NOT in UTC, obviously this will screw things up!
return matches[1] + "T" + matches[2] + ".000Z";
}else{
return null;
}
},
_setValueAttr : function(/*Date|String*/ value, /*Boolean?*/ priorityChange, /*String?*/ formattedValue){
/*
We want to be slightly more permissive in terms of the strings that can be set in order to support
older code... But someday it'd be nice to standardize on Date.toJSON, so warn.
*/
if(typeof(value) === "string"){
var isoDate = this._convertMysqlDateToIso(value);
if(isoDate !== null){
console.warn("Converting non-ISO date of "+value);
value = isoDate;
}
}
this.inherited(arguments);
}
});
return clazz;
});
Note that this only affects data flowing into the Dojo widget.
The docs say:
The value of this widget as a JavaScript Date object, with only
year/month/day specified.
So instead of this (which I assume you're currently doing):
new dijit.form.DateTextBox({value: "2010-08-04T22:00:00.000+0000"}, domNode);
Do this:
var myDate = new Date("2010-08-04T22:00:00.000+0000");
new dijit.form.DateTextBox({value: myDate}, domNode);
After serializing an object with DateTime field with JavaScriptSerializer, I see that the DateTime field looks like this:
EffectiveFrom: "/Date(1355496152000)/"
How can I convert this string to Javascript Date object?
UPDATE: This answer may not be appropriate in all cases. See JD's answer for an elegant solution that is likely better.
You could just "fix" the output from JavaScriptSerializer on the .Net side of things:
JavaScriptSerializer serializer = new JavaScriptSerializer();
var json = serializer.Serialize(this);
json = Regex.Replace(json,#"\""\\/Date\((-?\d+)\)\\/\""","new Date($1)");
return json;
This would change
EffectiveFrom: "/Date(1355496152000)/"
to
EffectiveFrom: new Date(1355496152000)
Which is directly consumable by Javascript
EDIT: update to accommodate negative dates
EDIT: Here is the Regex line for VB folks:
json = Regex.Replace(json, """\\/Date\((-?\d+)\)\\/""", "new Date($1)")
UPDATE 2016.11.20: With a lot more datetime handling in javascript/json behind me, I would suggest changing the regex to something as simple as
json = Regex.Replace(json,#"\""\\/Date\((-?\d+)\)\\/\""","$1");
The resulting value is valid JSON, and can be converted to a Date object on the javascript side.
It is also worth noting that moment.js (http://momentjs.com/docs/#/parsing/) handles this format happily enough.
moment("/Date(1198908717056-0700)/");
There is an answer that may help you:
Parsing Date-and-Times from JavaScript to C#
If you want to parse datetime string to datetime value with javascript you must use "new Date" like this:
var data = new Date("1355496152000");
var obj = { EffectiveFrom: "/Date(1355496152000)/" };
//parse the Date value and replace the property value with Date object:
var dateValue = parseInt(obj.EffectiveFrom.replace(/\/Date\((\d+)\)\//g, "$1"));
obj.EffectiveFrom = new Date(dateValue);
This is a bit of a hack, but the above seemed inelegant for what I'm trying to achieve, so in the object definition I'm serializing, I did this:
/// <summary>Date of the record retention event or document date.
/// </summary>
public string DateOfRetentionEvent;
[ScriptIgnore]
public DateTime RetentionEventDate
{
get
{
return _retentionEventDate;
}
set
{
_retentionEventDate = value;
DateOfRetentionEvent = value.ToShortDateString();
}
}
The point being that, at least in my use case (deserialization never happens), the JSON doesn't really care what C# is doing with the date value. Adding [ScriptIgnore] to the DateTime value and giving an alternative view for the parser to output should do the trick. It does in my case:
{
"DateToDispose": "1/1/2020",
"DateOfRetentionEvent": "10/1/2014",
"FullRetentionCode": "NR+5",
"RetentionEvent": "NR",
"RetentionPeriod": 5
}