Skip to content

Commit c14126f

Browse files
committed
Merge discvr-25.3 to develop
2 parents 96a29bb + fe5a56c commit c14126f

File tree

4 files changed

+47
-64
lines changed

4 files changed

+47
-64
lines changed

LDK/resources/web/LDK/ConvertUtils.js

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,30 @@ LDK.ConvertUtils = new function(){
2020
var result = null,
2121
parsedDate;
2222

23+
if (value instanceof Date) {
24+
return value;
25+
}
26+
2327
useStrict = Ext4.isDefined(useStrict) ? useStrict : false;
2428

2529
if (Ext4.Date.formatContainsHourInfo(format)) {
2630
// if parse format contains hour information, no DST adjustment is necessary
2731
result = Ext4.Date.parse(value, format, useStrict);
2832
} else {
29-
// set time to 12 noon, then clear the time
30-
parsedDate = Ext4.Date.parse(value + ' ' + 12, format + ' ' + 'H', useStrict);
33+
// The core of the parsing problem comes from JS Date.parse() treating ISO 8601 short differently from other date formats:
34+
// https://www.w3.org/TR/NOTE-datetime
35+
// Example:
36+
// new Date('2024-01-01')
37+
// Sun Dec 31 2023 16:00:00 GMT-0800 (Pacific Standard Time)
38+
// new Date('1/1/2024')
39+
// Mon Jan 01 2024 00:00:00 GMT-0800 (Pacific Standard Time)
40+
41+
// Therefore special case this format and append the browser's time zone:
42+
if (format === 'c' && value.length === 10) {
43+
format = 'Y-m-d';
44+
}
45+
46+
parsedDate = Ext4.Date.parse(value, format, useStrict);
3147
if (parsedDate) {
3248
result = Ext4.Date.clearTime(parsedDate);
3349
}
@@ -58,9 +74,22 @@ LDK.ConvertUtils = new function(){
5874
formats.push(format);
5975
formats = formats.concat(DATEFORMATS);
6076

77+
// See 'c' format: https://docs.sencha.com/extjs/4.2.1/#!/api/Ext.Date
78+
// And http://www.w3.org/TR/NOTE-datetime
79+
// The issue is that this treats any date beginning with YYYY-MM-DD as ISO8601,
80+
// and assumes GMT as the date/time. In general, we want the string '2024-01-01' to be treated as the browser's timezone.
81+
// Therefore push this to the lowest priority, which will allow other formats to preferentially parse date-only values
82+
if (format !== 'c' && formats.indexOf('c') > -1) {
83+
formats = Ext4.Array.remove(formats, 'c')
84+
formats.push('c')
85+
}
86+
6187
var val;
62-
for (var i=0; i < formats.length && !val; ++i) {
88+
for (var i=0; i < formats.length; ++i) {
6389
val = safeParseDate(value, formats[i]);
90+
if (val) {
91+
break;
92+
}
6493
}
6594

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

78107
Ext4.Array.forEach(results.metaData.fields, function(field){
79-
if (field.jsonType == 'date'){
108+
if (field.jsonType === 'date'){
80109
Ext4.Array.forEach(results.rows, function(row){
81110
if (row[field.name]){
82111
row[field.name] = LDK.ConvertUtils.parseDate(row[field.name]);

LDK/resources/web/LDK/StoreUtils.js

Lines changed: 10 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -115,15 +115,19 @@ LDK.StoreUtils = new function(){
115115

116116
var fields = store.model.getFields();
117117
Ext4.each(fields, function(field){
118+
var extType = field.extType || LABKEY.ext4.Util.EXT_TYPE_MAP[field.jsonType];
119+
118120
var val;
119121
if (!Ext4.isEmpty(data[field.name])){
120122
val = data[field.name];
121-
var type = Ext4.data.Types[field.extType];
123+
var type = Ext4.data.Types[extType];
122124
if (type && type.convert){
123-
if (field.extType == LABKEY.ext4.Util.EXT_TYPE_MAP.date)
125+
if (extType === LABKEY.ext4.Util.EXT_TYPE_MAP.date) {
124126
val = LDK.ConvertUtils.parseDate(val);
125-
else
127+
}
128+
else {
126129
val = type.convert(val);
130+
}
127131
}
128132

129133
model.set(field.name, val);
@@ -193,59 +197,6 @@ LDK.StoreUtils = new function(){
193197
return map;
194198
},
195199

196-
/**
197-
* Parses a string into a date, normalizing for the current timezone. Date.parse()
198-
* will make different timezone assumptions, depending on date format. For example,
199-
* 2010-02-04 is assumed to be GMT, while 2/4/2010 is assume to match the local machine.
200-
* This method tries to infer the date format, and if an ISO date is provided, it will convert the
201-
* date object to the current timezone.
202-
* @param val
203-
*/
204-
normalizeDateString: function(val){
205-
if (!val || Ext4.isDate(val)){
206-
return val;
207-
}
208-
else if (Ext4.isNumber(val)){
209-
return new Date(val);
210-
}
211-
212-
else if (Ext4.isString(val)) {
213-
//try to guess format:
214-
var date;
215-
//ISO dates are assumed to be GMT, so we convert to local time, letting Ext normalize timezone
216-
if (Ext4.Date.parse(val, Date.patterns.ISO8601Long)){
217-
date = Ext4.Date.parse(val, Date.patterns.ISO8601Long);
218-
}
219-
else if (Ext4.Date.parse(val, Date.patterns.ISO8601Short)){
220-
date = Ext4.Date.parse(val, Date.patterns.ISO8601Short);
221-
}
222-
else if (val.indexOf('Z') != -1)
223-
{
224-
var parsed = Date.parse(val);
225-
if (parsed)
226-
date = new Date(parsed);
227-
}
228-
else {
229-
//with non ISO dates, browsers seem to accept tacking the timezone to the end
230-
var parsed = Date.parse(val + ' ' + Ext4.Date.getTimezone(new Date()));
231-
if (parsed)
232-
date = new Date(parsed);
233-
}
234-
235-
if (date){
236-
var mills = Date.parse(Ext4.Date.format(date, 'm/d/Y H:i'));
237-
if (!mills == date.getTime()){
238-
console.error('Date doesn\'t match: ' + val + '/' + date.toString());
239-
return null;
240-
}
241-
else {
242-
return date;
243-
}
244-
}
245-
}
246-
return val;
247-
},
248-
249200
sortStoreByFieldNames: function(store, fieldNames){
250201
var fields = [];
251202
Ext4.each(fieldNames, function(fn){
@@ -262,7 +213,7 @@ LDK.StoreUtils = new function(){
262213
/**
263214
* 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
264215
* metadata to sort on the displayValue, instead of rawValue for lookup columns, which is usually what the user expects.
265-
* @param {array} fieldList An ordered array of field metadata objects.
216+
* @param {array} fields An ordered array of field metadata objects.
266217
* @returns {function} The sorter function that can be passed to the sort() method of an Ext.data.Store.
267218
*/
268219
getStoreSortFn: function(fields){
@@ -298,12 +249,12 @@ LDK.StoreUtils = new function(){
298249
var rec1;
299250
var rec2;
300251
rec1 = store.findExact(item.valueField, a.get(item.term));
301-
if(rec1 != -1){
252+
if(rec1 !== -1){
302253
rec1 = store.getAt(rec1);
303254
val1 = rec1.get(item.displayField) || '';
304255
}
305256
rec2 = store.findExact(item.valueField, b.get(item.term));
306-
if(rec2 != -1){
257+
if(rec2 !== -1){
307258
rec2 = store.getAt(rec2);
308259
val2 = rec2.get(item.displayField) || '';
309260
}

LDK/test/src/org/labkey/test/tests/external/labModules/LabModulesTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,9 @@ private void dateParseTest() throws ParseException
304304
String dateFormat3 = "MM/dd/yy";
305305
checkDate("02/20/11", dateFormat3);
306306
checkDate("3/5/99", dateFormat3);
307+
308+
String clientFormattedString = (String)executeScript("return Ext4.Date.format(LDK.ConvertUtils.parseDate('2024-01-01', 'c'), 'Y-m-d');");
309+
assertEquals("Incorrect date parsing", clientFormattedString, "2024-01-01");
307310
}
308311

309312
private void checkDate(String dateStr, String javaFormatStr) throws ParseException

laboratory/resources/web/laboratory/panel/AssayTemplatePanel.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ Ext4.define('Laboratory.panel.AssayTemplatePanel', {
112112
fields.push(col.editor.dataIndex || col.editor.name);
113113
}
114114

115-
if (col.dataIndex == 'category'){
115+
if (col.dataIndex === 'category'){
116116
categoryCol = col;
117117
}
118118
}, this);

0 commit comments

Comments
 (0)