Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 33 additions & 4 deletions LDK/resources/web/LDK/ConvertUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,30 @@ LDK.ConvertUtils = new function(){
var result = null,
parsedDate;

if (value instanceof Date) {
return value;
}

useStrict = Ext4.isDefined(useStrict) ? useStrict : false;

if (Ext4.Date.formatContainsHourInfo(format)) {
// if parse format contains hour information, no DST adjustment is necessary
result = Ext4.Date.parse(value, format, useStrict);
} else {
// set time to 12 noon, then clear the time
parsedDate = Ext4.Date.parse(value + ' ' + 12, format + ' ' + 'H', useStrict);
// The core of the parsing problem comes from JS Date.parse() treating ISO 8601 short differently from other date formats:
// https://www.w3.org/TR/NOTE-datetime
// Example:
// new Date('2024-01-01')
// Sun Dec 31 2023 16:00:00 GMT-0800 (Pacific Standard Time)
// new Date('1/1/2024')
// Mon Jan 01 2024 00:00:00 GMT-0800 (Pacific Standard Time)

// Therefore special case this format and append the browser's time zone:
if (format === 'c' && value.length === 10) {
format = 'Y-m-d';
}

parsedDate = Ext4.Date.parse(value, format, useStrict);
if (parsedDate) {
result = Ext4.Date.clearTime(parsedDate);
}
Expand Down Expand Up @@ -58,9 +74,22 @@ LDK.ConvertUtils = new function(){
formats.push(format);
formats = formats.concat(DATEFORMATS);

// See 'c' format: https://docs.sencha.com/extjs/4.2.1/#!/api/Ext.Date
// And http://www.w3.org/TR/NOTE-datetime
// The issue is that this treats any date beginning with YYYY-MM-DD as ISO8601,
// and assumes GMT as the date/time. In general, we want the string '2024-01-01' to be treated as the browser's timezone.
// Therefore push this to the lowest priority, which will allow other formats to preferentially parse date-only values
if (format !== 'c' && formats.indexOf('c') > -1) {
formats = Ext4.Array.remove(formats, 'c')
formats.push('c')
}

var val;
for (var i=0; i < formats.length && !val; ++i) {
for (var i=0; i < formats.length; ++i) {
val = safeParseDate(value, formats[i]);
if (val) {
break;
}
}

// two digit years tend to get parsed as 1900, rather than 2000s, so we make assumptions about dates more than 90 in the past
Expand All @@ -76,7 +105,7 @@ LDK.ConvertUtils = new function(){
}

Ext4.Array.forEach(results.metaData.fields, function(field){
if (field.jsonType == 'date'){
if (field.jsonType === 'date'){
Ext4.Array.forEach(results.rows, function(row){
if (row[field.name]){
row[field.name] = LDK.ConvertUtils.parseDate(row[field.name]);
Expand Down
69 changes: 10 additions & 59 deletions LDK/resources/web/LDK/StoreUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,19 @@ LDK.StoreUtils = new function(){

var fields = store.model.getFields();
Ext4.each(fields, function(field){
var extType = field.extType || LABKEY.ext4.Util.EXT_TYPE_MAP[field.jsonType];

var val;
if (!Ext4.isEmpty(data[field.name])){
val = data[field.name];
var type = Ext4.data.Types[field.extType];
var type = Ext4.data.Types[extType];
if (type && type.convert){
if (field.extType == LABKEY.ext4.Util.EXT_TYPE_MAP.date)
if (extType === LABKEY.ext4.Util.EXT_TYPE_MAP.date) {
val = LDK.ConvertUtils.parseDate(val);
else
}
else {
val = type.convert(val);
}
}

model.set(field.name, val);
Expand Down Expand Up @@ -193,59 +197,6 @@ LDK.StoreUtils = new function(){
return map;
},

/**
* Parses a string into a date, normalizing for the current timezone. Date.parse()
* will make different timezone assumptions, depending on date format. For example,
* 2010-02-04 is assumed to be GMT, while 2/4/2010 is assume to match the local machine.
* This method tries to infer the date format, and if an ISO date is provided, it will convert the
* date object to the current timezone.
* @param val
*/
normalizeDateString: function(val){
if (!val || Ext4.isDate(val)){
return val;
}
else if (Ext4.isNumber(val)){
return new Date(val);
}

else if (Ext4.isString(val)) {
//try to guess format:
var date;
//ISO dates are assumed to be GMT, so we convert to local time, letting Ext normalize timezone
if (Ext4.Date.parse(val, Date.patterns.ISO8601Long)){
date = Ext4.Date.parse(val, Date.patterns.ISO8601Long);
}
else if (Ext4.Date.parse(val, Date.patterns.ISO8601Short)){
date = Ext4.Date.parse(val, Date.patterns.ISO8601Short);
}
else if (val.indexOf('Z') != -1)
{
var parsed = Date.parse(val);
if (parsed)
date = new Date(parsed);
}
else {
//with non ISO dates, browsers seem to accept tacking the timezone to the end
var parsed = Date.parse(val + ' ' + Ext4.Date.getTimezone(new Date()));
if (parsed)
date = new Date(parsed);
}

if (date){
var mills = Date.parse(Ext4.Date.format(date, 'm/d/Y H:i'));
if (!mills == date.getTime()){
console.error('Date doesn\'t match: ' + val + '/' + date.toString());
return null;
}
else {
return date;
}
}
}
return val;
},

sortStoreByFieldNames: function(store, fieldNames){
var fields = [];
Ext4.each(fieldNames, function(fn){
Expand All @@ -262,7 +213,7 @@ LDK.StoreUtils = new function(){
/**
* A sorter function that can be used to sort an Ext store based on one or more fields. The primary advantage is that this sorter uses the column
* metadata to sort on the displayValue, instead of rawValue for lookup columns, which is usually what the user expects.
* @param {array} fieldList An ordered array of field metadata objects.
* @param {array} fields An ordered array of field metadata objects.
* @returns {function} The sorter function that can be passed to the sort() method of an Ext.data.Store.
*/
getStoreSortFn: function(fields){
Expand Down Expand Up @@ -298,12 +249,12 @@ LDK.StoreUtils = new function(){
var rec1;
var rec2;
rec1 = store.findExact(item.valueField, a.get(item.term));
if(rec1 != -1){
if(rec1 !== -1){
rec1 = store.getAt(rec1);
val1 = rec1.get(item.displayField) || '';
}
rec2 = store.findExact(item.valueField, b.get(item.term));
if(rec2 != -1){
if(rec2 !== -1){
rec2 = store.getAt(rec2);
val2 = rec2.get(item.displayField) || '';
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,9 @@ private void dateParseTest() throws ParseException
String dateFormat3 = "MM/dd/yy";
checkDate("02/20/11", dateFormat3);
checkDate("3/5/99", dateFormat3);

String clientFormattedString = (String)executeScript("return Ext4.Date.format(LDK.ConvertUtils.parseDate('2024-01-01', 'c'), 'Y-m-d');");
assertEquals("Incorrect date parsing", clientFormattedString, "2024-01-01");
}

private void checkDate(String dateStr, String javaFormatStr) throws ParseException
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ Ext4.define('Laboratory.panel.AssayTemplatePanel', {
fields.push(col.editor.dataIndex || col.editor.name);
}

if (col.dataIndex == 'category'){
if (col.dataIndex === 'category'){
categoryCol = col;
}
}, this);
Expand Down