petercawdron
Kilo Guru

If you've from a European country you'll know dates are horrible to work with in ServiceNow. It's not ServiceNow's fault, it's that most server software runs US date formats (mm/dd/yy) while the client/browser uses European date formats (dd/mm/yy).

I recently ran into a consultant script that tried to validate dates server-side (using GlideAjax to a Script Includes because he wanted to use the GlideDateTime API), but the validation only worked AFTER the 12th day of each month (as that was the only time the US date format would recognise dates correctly), so his routine would see 12/10 as the 10th of December but 13/10 would (correctly) be reckoned as the 13th of October. In reality, from a European perspective, these two dates are right next to each other, not two months apart.

The solution is... 

  • Don't pass dates to the server for validation.
  • Convert everything into Epoch.
  • Keep everything client side.

Here's an example of an onChange client script that warns the user if dates are in the past.

function onChange(control, oldValue, newValue, isLoading, isTemplate) {
	if (isLoading || newValue === '')
		return;
	
	var epochStart = getDateFromFormat(g_form.getValue('start_date'), g_user_date_time_format);
	var epochEnd   = getDateFromFormat(g_form.getValue('end_date'),   g_user_date_time_format);
	var epochNow   = new Date().getTime();
	
	if(epochStart > epochEnd && epochEnd !=0){
		g_form.showFieldMsg('start_date', "Your planned start date should not occur after the planned end date",'error');
	}
	
	if(epochStart < epochNow){
		g_form.showFieldMsg('start_date', "Your planned start date should not occur before now",'error');
	}
}

A similar approach can work really well with Catalog Items in the portal, for example...

//Check that dates are valid
	var starts = g_form.getValue('dateFrom');
	var ends  = g_form.getValue('dateTo');
	
	var startParts = starts.split('/');
	var endParts   = ends.split('/');
	 
	var epochStart = new Date(startParts[2] +'-'+ startParts[1] +'-'+ startParts[0] ).getTime();
	var epochEnd   = new Date(endParts[2]   +'-'+ endParts[1]   +'-'+ endParts[0]   ).getTime();
	var epochNow   = new Date().getTime();
	 
	if(epochStart > epochEnd && epochEnd !=0){
		g_form.clearMessages();
		g_form.setValue('dateTo','');
		g_form.showFieldMsg('dateTo', "You entered "+ ends +" but you cannot return an item before you've received it on " + starts,'error');
	}else if(epochStart < epochNow){
		g_form.clearMessages();
		g_form.setValue('dateFrom','');
		g_form.showFieldMsg('dateFrom', "You entered "+ starts +" but you cannot collect an item before today",'error'); 
	}else{
		g_form.clearMessages();
	}

Which gives a clear message to your users

find_real_file.png

Comments
Mark Roethof
Tera Patron
Tera Patron

Hi there,

Have you considered using no-code date validation? Just using (Catalog) UI Policies for this? There's no need to code this. See an article I wrote on this:
No Code date validations thru (Catalog) UI Policies

Also, change your showFieldMsg, that is also uses getMessage for internationalization. 

Kind regards,
Mark

---

LinkedIn
Community article list

petercawdron
Kilo Guru

Nice. Thanks.

petercawdron
Kilo Guru

Although I like this approach, I couldn't get it to work for me with relative dates (and ended up reusing the original code) 

I thought this would work if the dateFrom was on the 20th and the dateTo was before that, on say the 18th, but couldn't get it to work

find_real_file.png

Version history
Last update:
‎10-10-2019 09:51 PM
Updated by: