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);
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 am currently writing a custom function in Google App Scripts. Right now I am struggling. I defined an argument to take input from a date cell and change the format.
e.g 9/16/2010 to 09.16.2010 where a given column has the former date and the function outputs the latter.
The output is a string, but I can't seem to find any information on this specific text editing feature of javascript.
It's also worth mentioning that the date in a given column is based on a form output, I am not calling a specific short date in the code, so rather this is more string manipulation than date formatting
Any help is appreciated.
/**
*Generates a Trip Key
*
*#param DateColumn Date
*#param SchoolColumn School name
*#param LocationColumn Location
*#customfunction
*/
function GENERATEKEY(DateColumn) {
var Date = DateColumn
const dateStr = Date;
const dateArr = dateStr.split('/');
dateArr[0] = ('0' + dateArr[0]).slice(-2);
dateArr[1] = ('0' + dateArr[1]).slice(-2);
const DateEdited = dateArr.join('.');
return neWDateStr; //gives 00.00.0000
//var Key = Date SchoolColumn "#" LocationColumn
}
Date is a built-in object. It should not be used as a variable name.
While const is allowed in Google Apps Script, it's not fully supported (it doesn't work as the ECMAScript states). IMHO it's better to use var to avoid "confusions".
In Google Sheets, based in the spreadsheet settings, change values entered in supported date-time format into serial numbers and use a number format to display it as date, time, date-time or duration. When a serial number displayed as date, date-time, time or duration is passed to a custom function, Google Apps Script convert it to a Date object.
To return a date formatted use Utilities.formatDate(...) Details in https://developers.google.com/apps-script/reference/utilities/utilities#formatdatedate,-timezone,-format
Related
How to format the date in this Google Apps Script
You could simply use inbuilt TEXT function:
=TEXT(A2,"mm.dd.yyyy")
The reason your current script(as provided in one of the previous answers) doesn't work is because the argument DateColumn is not of type String. You can convert the date object to a specific string and format it accordingly or use inbuilt Utilities library.
function DOWHATTEXTDOES(dateColumn) {
return Utilities.formatDate(dateColumn, SpreadsheetApp.getActive().getSpreadsheetTimeZone(), "yyyy.MM.dd")
}
Essential Reading:
Custom function Data type
Date
You can do something like this
"02/05/2009".split('/').join('.');
Get and Set the numberFormat for the active range
Sheet.getRange().setNumberFormat("mm.dd.yyyy");
Here's a dialog and function that I use sometimes for playing around with different formats. I find it a lot easier and quicker that using the spreadsheet functions.
The top function is a dialog that reads and displays the current format for the active range and has a textbox and button for each cell in the in the active range that allows you to set the number format and see the change immediately.
function getandSetActiveRangeFormats() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
var rg=sh.getActiveRange();
var fA=rg.getNumberFormats();
var html='<style>th,td{border:1px solid black;}</style><table><tr><th>Item</th><th>A1 Notation</th><th>Number Format</th><th>Enter Format</th><th>Set Format</th></tr>';
var item=1;
var row=rg.getRow();
var col=rg.getColumn();
fA.forEach(function(r,i){
r.forEach(function(c,j){
var txt=Utilities.formatString('<input type="text" id="RC-%s-%s" />',row+i,col+j);
var btn=Utilities.formatString('<input type="button" value="Set Form" onClick="setFormat(%s,%s);" />',row+i,col+j);
html+=Utilities.formatString('<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>',item++,sh.getRange(row + i,col + j).getA1Notation(),fA[i][j],txt,btn);
});
});
html+='</table><input type="button" value="Exit" onClick="google.script.host.close();" />';
html+='<script>function setFormat(row,col){var f=document.getElementById("RC-"+row+"-"+col).value;google.script.run.setFormat(row,col,f);}</script>';
var ui=HtmlService.createHtmlOutput(Utilities.formatString(html));
SpreadsheetApp.getUi().showModelessDialog(ui, "Display Cell Formats")
}
function setFormat(row,col,format) {
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
sh.getRange(row,col).setNumberFormat(format);
}
Animation:
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);
}
}
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>
So I have been tasked with creating a jQuery slideshow from an XML file with a timing mechanism to change the images based on date. I have the slideshow working from the XML, but I am struggling with adding the date feature. I would like to be able to "turn on" and "turn off" images based on the onDate and offDate. I understand Javascript is not the best way to show things based on date, but there are limits within the current site structure that prevent server side timing. So I would like to have the ability to load up say 10 images, and then only show three based on what today's date is, and what the onDate/offDate are.
This is the logic I was thinking.... If today is < onDate .hide or if today is > offDate .hide else .show
Where I am struggling
The correct way to enter the date in the XML file.
Parsing the date from XML into something that Javascript and in turn jQuery can use to compare today's date with the date in XML and show the image accordingly.
Once the date has been established figuring out a way to show or hide the specific image based on date.
Any help would be greatly appreciated.
XML
<eq-banner>
<id>1</id>
<url>linktopage.html</url>
<img>image.jpg</img>
<dept>equipment</dept>
<onDate>12/01/2010</onDate>
<offDate>12/31/2010</offDate>
<copy>FREE Stuff</copy>
</eq-banner>
jQuery
<script>
$(document).ready(function () {
$.ajax({
type: "GET",
url: "rotationData.xml",
dataType: "xml",
success: xmlParser
});
});
function xmlParser(equipment) {
$(equipment).find('eq-banner').each(function() {
var id = $(this).attr('id');
var dept = $(this).find('dept').text();
var url = $(this).find('url').text();
var img = $(this).find('img').text();
$('<div class="'+dept+'"</div>').html('<img src="images/'+img+'" /><br />').appendTo('#apparel')
$("#equipment").cycle({
fx:"fade",
speed:100,
timeout:5000
});;
});
}
</script>
HTML
<div id="equipment">
</div>
If you trust the data quality of the XML source, specifically that the dates are all well-formed as in your sample, it's pretty easy to turn that into a JavaScript "Date" object:
var str = "12/31/2010";
var pieces = str.split('/');
var date = new Date(~~str[2], ~~str[0] - 1, ~~str[1]);
(The ~~ trick converts the strings to numbers; do that however you prefer.) Also months are numbered from zero, and hence the subtraction.
Comparing dates works perfectly well in JavaScript, or you can call the ".getTime()" method on a date to explicitly get a "milliseconds since the epoch" value to compare instead.
As to how you'd show/hide the images, I'd be inclined to conditionally add a class to elements to be hidden (or shown; whichever makes the most sense).
XML doesn't have a "correct" way of handling dates, and JavaScript can parse just about anything. However, the most JS-friendly format would be something like "October 20, 2011" with the time optionally added in "12:34:56" format. A string like that can be fed directly to the new Date() constructor and be parsed correctly regardless of location.
datestr = "October 20, 2011";
date = new Date(datestr);
To compare Date objects, just use < or > -- however, a JS Date object contains a time element which will also be compared. So if you create a new Date object for the present with var now = new Date(); and compare it to var dat = new Date("string with today's date"); you'll find that dat is less than now because dat has time 00:00:00 while now has the present time. If this is a problem, you'll have to explicitly compare Date.getDate(), Date.getMonth() and Date.getFullYear() all at once. ( http://www.w3schools.com/jsref/jsref_obj_date.asp )