Commit 7d4a59daf1694c1ed49facab6dad0819edb8e27f

Authored by Erdogan Furkan
2 parents 3ec6bc73 e3824d6e

Merge branch 'develop' of https://gitlab.irap.omp.eu/CDPP/AMDA_IHM into develop

js/app/controllers/PlotModule.js
... ... @@ -214,6 +214,21 @@ Ext.define('amdaDesktop.PlotModule', {
214 214 if (!this.plotResultWindowsManager.get(winResultId)) return null;
215 215 return this.plotResultWindowsManager.get(winResultId);
216 216 },
  217 +
  218 + setTimeInterval : function(timeObj){
  219 + var me = this;
  220 + var desktop = this.app.getDesktop();
  221 + var win = desktop.getWindow(this.id);
  222 + if (win) {
  223 + me.getUiContent().setTimeFromData(timeObj);
  224 + win.show();
  225 + }
  226 + else {
  227 + this.createWindow(function () {
  228 + me.getUiContent().setTimeFromData(timeObj);
  229 + });
  230 + }
  231 + },
217 232  
218 233 addParameter : function(paramNode) {
219 234 var me = this;
... ... @@ -324,6 +339,7 @@ Ext.define('amdaDesktop.PlotModule', {
324 339 downloadValues.durationHour = plotValues.durationHour;
325 340 downloadValues.durationMin = plotValues.durationMin;
326 341 downloadValues.durationSec = plotValues.durationSec;
  342 + downloadValues.durationMs = plotValues.durationMs;
327 343 if (plotValues.timeTables)
328 344 downloadValues.timeTables = plotValues.timeTables;
329 345 downloadValues.list = [];
... ...
js/app/models/AmdaTimeObject.js
... ... @@ -37,26 +37,31 @@ Ext.define('amdaModel.AmdaTimeObject', {
37 37 { name: 'folderId', type: 'string'},
38 38 { name: 'processId', type: 'string'},
39 39 { name: 'timesrc', type: 'string'/*, defaultValue: amdaModel.AmdaTimeObject.inputTimeSrc[1] /*'Interval'*/ },
40   - { name: 'startDate', type: 'date', defaultValue:Ext.Date.add(Ext.Date.clearTime(new Date()),Ext.Date.DAY,-1),
  40 + {
  41 + name: 'startDate',
  42 + type: 'date',
  43 + defaultValue:Ext.Date.add(Ext.Date.clearTime(new Date()),Ext.Date.DAY,-1),
41 44 convert: function(value,rec) {
42 45 if (!Ext.isDate(value)) {
43   - var valueString = new String(value);
44   - var date = new Date(valueString.replace(/\-/g,'\/').replace(/[T|Z]/g,' '));
  46 + var valueString = new String(value).replaceAll('\/','\-');
  47 + var date = new Date(valueString);
45 48 return date;
46 49 }
47 50 return value;
48 51 }
49 52 },
50 53 {
51   - name: 'stopDate', type: 'date', defaultValue: Ext.Date.clearTime (new Date()), persist: false,
52   - convert: function(value,rec) {
53   - if (!Ext.isDate(value)){
54   - var valueString = new String(value);
55   - var date = new Date(valueString.replace(/\-/g,'\/').replace(/[T|Z]/g,' '));
56   - return date;
  54 + name: 'stopDate',
  55 + type: 'date',
  56 + defaultValue: Ext.Date.clearTime (new Date()), persist: false,
  57 + convert: function(value,rec) {
  58 + if (!Ext.isDate(value)) {
  59 + var valueString = new String(value).replaceAll('\/','\-');
  60 + var date = new Date(valueString);
  61 + return date;
57 62 }
58 63 return value;
59   - }
  64 + }
60 65 },
61 66 {
62 67 name: 'durationDay', type: 'int',
... ... @@ -90,7 +95,15 @@ Ext.define('amdaModel.AmdaTimeObject', {
90 95  
91 96 return Ext.String.leftPad(Math.floor(diffS), 2, '0');
92 97 }
93   - },
  98 + },
  99 + {
  100 + name: 'durationMs', type: 'int',
  101 + convert: function(value, rec) {
  102 + var diffS = (rec.get('stopDate') - rec.get('startDate'))%1000;
  103 +
  104 + return Ext.String.leftPad(Math.floor(diffS), 3, '0');
  105 + }
  106 + },
94 107 { name: 'timeTables', defaultValue: null } // array of TTobject
95 108 ]
96 109 });
... ...
js/app/models/Catalog.js
... ... @@ -37,7 +37,7 @@ Ext.define('amdaModel.Catalog', {
37 37 // }
38 38 values.objName = this.get('objName');
39 39 values.objFormat = this.get('objFormat');
40   - values.folderId = this.get('folderId');
  40 + values.folderId = this.get('folderId');
41 41 values.nbIntervals = this.get('nbIntervals');
42 42 values.cacheToken = this.get('cacheToken');
43 43 values.parameters = this.get('parameters');
... ...
js/app/models/Download.js
... ... @@ -163,12 +163,13 @@ Ext.define('amdaModel.Download', {
163 163 }
164 164 });
165 165 } else {
166   - myValues.startDate = this.get('startDate');
167   - myValues.stopDate = this.get('stopDate');
  166 + myValues.startDate = Ext.Date.format(this.get('startDate'), 'Y-m-d\\TH:i:s.u');
  167 + myValues.stopDate = Ext.Date.format(this.get('stopDate'), 'Y-m-d\\TH:i:s.u');
168 168 myValues.durationDay = this.get('durationDay');
169 169 myValues.durationHour = this.get('durationHour');
170 170 myValues.durationMin = this.get('durationMin');
171 171 myValues.durationSec = this.get('durationSec');
  172 + myValues.durationMs = this.get('durationMs');
172 173 }
173 174  
174 175 // if there's at least one parameter
... ...
js/app/models/DownloadNode.js
... ... @@ -73,12 +73,13 @@ Ext.define('amdaModel.DownloadNode', {
73 73 });
74 74 }
75 75 else {
76   - myValues.startDate = obj.get('startDate');
77   - myValues.stopDate = obj.get('stopDate');
  76 + myValues.startDate = Ext.Date.format(obj.get('startDate'), 'Y-m-d\\TH:i:s.u');
  77 + myValues.stopDate = Ext.Date.format(obj.get('startDate'), 'Y-m-d\\TH:i:s.u');
78 78 myValues.durationDay = obj.get('durationDay');
79 79 myValues.durationHour = obj.get('durationHour');
80 80 myValues.durationMin = obj.get('durationMin');
81 81 myValues.durationSec = obj.get('durationSec');
  82 + myValues.durationMs = obj.get('durationMs');
82 83 }
83 84  
84 85 myValues.name = obj.get('name');
... ...
js/app/models/InteractiveNode.js
... ... @@ -476,14 +476,14 @@ Ext.define('amdaModel.InteractiveNode', {
476 476  
477 477 var startDate = new Date(startString.replace(/\-/g,'\/').replace(/[T|Z]/g,' '));
478 478 var stopDate = new Date(stopString.replace(/\-/g,'\/').replace(/[T|Z]/g,' '));
479   -
  479 +
480 480 if (stopDate - startDate > 86400000 ) {
481 481 var startTime = Ext.Date.add(stopDate, Ext.Date.DAY, -1);
482 482 // var timeObj = {start: Ext.Date.format(startTime, 'Y/m/d H:i:s'), stop: Ext.Date.format(stopDate, 'Y/m/d H:i:s')};
483   - var timeObj = {start: Ext.Date.format(startTime, 'Y/m/d'), stop: Ext.Date.format(stopDate, 'Y/m/d')};
  483 + var timeObj = {start: Ext.Date.format(startTime, 'Y/m/d H:i:s.u'), stop: Ext.Date.format(stopDate, 'Y/m/d H:i:s.u')};
484 484 }
485 485 else {
486   - var timeObj = {start: node.get('globalStart'), stop: node.get('globalStop')};
  486 + var timeObj = {start: Ext.Date.format(startTime, 'Y/m/d H:i:s.u'), stop: Ext.Date.format(stopDate, 'Y/m/d H:i:s.u')};
487 487 }
488 488 return timeObj;
489 489 },
... ...
js/app/models/PlotObjects/MultiplotRequestObject.js
... ... @@ -126,12 +126,13 @@ Ext.define('amdaPlotObj.MultiplotRequestObject', {
126 126 }
127 127 });
128 128 } else {
129   - requestValues['startDate'] = this.get('startDate');
130   - requestValues['stopDate'] = this.get('stopDate');
  129 + requestValues['startDate'] = Ext.Date.format(this.get('startDate'), 'Y-m-d\\TH:i:s.u');
  130 + requestValues['stopDate'] = Ext.Date.format(this.get('stopDate'), 'Y-m-d\\TH:i:s.u');
131 131 requestValues['durationDay'] = this.get('durationDay');
132 132 requestValues['durationHour'] = this.get('durationHour');
133 133 requestValues['durationMin'] = this.get('durationMin');
134 134 requestValues['durationSec'] = this.get('durationSec');
  135 + requestValues['durationMs'] = this.get('durationMs');
135 136 }
136 137  
137 138 requestValues['plots'] = [];
... ...
js/app/models/PlotObjects/PlotRequestObject.js
... ... @@ -288,12 +288,13 @@ Ext.define('amdaPlotObj.PlotRequestObject', {
288 288 }
289 289 });
290 290 } else {
291   - requestValues['startDate'] = this.get('startDate');
292   - requestValues['stopDate'] = this.get('stopDate');
  291 + requestValues['startDate'] = Ext.Date.format(this.get('startDate'), 'Y-m-d\\TH:i:s.u');
  292 + requestValues['stopDate'] = Ext.Date.format(this.get('stopDate'), 'Y-m-d\\TH:i:s.u');
293 293 requestValues['durationDay'] = this.get('durationDay');
294 294 requestValues['durationHour'] = this.get('durationHour');
295 295 requestValues['durationMin'] = this.get('durationMin');
296 296 requestValues['durationSec'] = this.get('durationSec');
  297 + requestValues['durationMs'] = this.get('durationMs');
297 298 }
298 299  
299 300 requestValues['page-layout-type'] = this.get('page-layout-type');
... ...
js/app/models/Search.js
... ... @@ -65,12 +65,13 @@ Ext.define('amdaModel.Search', {
65 65 }
66 66 });
67 67 } else {
68   - myValues.startDate = this.get('startDate');
69   - myValues.stopDate = this.get('stopDate');
  68 + myValues.startDate = Ext.Date.format(this.get('startDate'), 'Y-m-d\\TH:i:s.u');
  69 + myValues.stopDate = Ext.Date.format(this.get('stopDate'), 'Y-m-d\\TH:i:s.u');
70 70 myValues.durationDay = this.get('durationDay');
71 71 myValues.durationHour = this.get('durationHour');
72 72 myValues.durationMin = this.get('durationMin');
73 73 myValues.durationSec = this.get('durationSec');
  74 + myValues.durationMs = this.get('durationMs');
74 75 }
75 76  
76 77 myValues.leaf = true;
... ...
js/app/models/Statistic.js
... ... @@ -104,12 +104,13 @@ Ext.define('amdaModel.Statistic', {
104 104 });
105 105 } else
106 106 {
107   - values.startDate = this.get('startDate');
108   - values.stopDate = this.get('stopDate');
  107 + values.startDate = Ext.Date.format(this.get('startDate'), 'Y-m-d\\TH:i:s.u');
  108 + values.stopDate = Ext.Date.format(this.get('stopDate'), 'Y-m-d\\TH:i:s.u');
109 109 values.durationDay = this.get('durationDay');
110 110 values.durationHour = this.get('durationHour');
111 111 values.durationMin = this.get('durationMin');
112 112 values.durationSec = this.get('durationSec');
  113 + values.durationMs = this.get('durationMs');
113 114 }
114 115  
115 116 values.leaf = true;
... ...
js/app/models/TimeTable.js
... ... @@ -29,19 +29,15 @@ Ext.define('amdaModel.Interval', {
29 29 { name: 'start', type : 'date', defaultValue : new Date(),
30 30 convert: function(value,rec) {
31 31 if (!Ext.isDate(value)){
32   - var valueString = new String(value);
33   - var date = new Date(valueString.replace(/\-/g,'\/').replace(/[T|Z]/g,' '));
34   - return date;
  32 + return new Date(value);
35 33 }
36 34 return value;
37 35 }
38 36 },
39 37 { name: 'stop', type : 'date', defaultValue : new Date(),
40 38 convert: function(value,rec) {
41   - if (!Ext.isDate(value)){
42   - var valueString = new String(value);
43   - var date = new Date(valueString.replace(/\-/g,'\/').replace(/[T|Z]/g,' '));
44   - return date;
  39 + if (!Ext.isDate(value)){
  40 + return new Date(value);
45 41 }
46 42 return value;
47 43 }
... ...
js/app/views/CatalogUI.js
... ... @@ -179,8 +179,8 @@ Ext.define('amdaUI.CatalogUI', {
179 179 return;
180 180 }
181 181 Ext.Array.each(result.intervals, function (item, index) {
182   - starts[index] = (item.start);
183   - stops[index] = (item.stop);
  182 + starts[index] = Ext.Date.format(item.start, 'Y-m-d\\TH:i:s.u');
  183 + stops[index] = Ext.Date.format(item.start, 'Y-m-d\\TH:i:s.u');
184 184 });
185 185 if(starts.length !== 0 || stops.length !== 0) {
186 186  
... ... @@ -205,7 +205,7 @@ Ext.define('amdaUI.CatalogUI', {
205 205 var timeTabNode = Ext.create('amdaModel.TimeTableNode', {leaf: true});
206 206 ttObj.set('relatedCatalogId', catId)
207 207 creatDate = new Date(this.object.get('created'));
208   - date = Ext.Date.format(creatDate, 'Y-m-d\\TH:i:s');
  208 + date = Ext.Date.format(creatDate, 'Y-m-d\\TH:i:s.u');
209 209 descr = 'Generated by CDPP/Amda Catalog Module \n' + 'From Catalog: ' + this.object.get('name') + '\nOn: ' + date + '\n';
210 210 ttObj.set('description', descr + this.object.get('description'));
211 211 ttObj.set('contact', this.object.get('contact'));
... ... @@ -271,11 +271,10 @@ Ext.define('amdaUI.CatalogUI', {
271 271 {
272 272 name: 'start',
273 273 type: 'date',
274   - dateFormat: 'Y-m-d\\TH:i:s',
  274 + dateFormat: 'Y-m-d\\TH:i:s.u',
275 275 convert: function (value, rec) {
276 276 if (!Ext.isDate(value)) {
277   - var valueString = new String(value);
278   - return new Date(valueString.replace(/\-/g, '\/').replace(/[T|Z]/g, ' '));
  277 + return new Date(value);
279 278 }
280 279 return value;
281 280 }
... ... @@ -283,11 +282,10 @@ Ext.define('amdaUI.CatalogUI', {
283 282 {
284 283 name: 'stop',
285 284 type: 'date',
286   - dateFormat: 'Y-m-d\\TH:i:s',
  285 + dateFormat: 'Y-m-d\\TH:i:s.u',
287 286 convert: function (value, rec) {
288 287 if (!Ext.isDate(value)) {
289   - var valueString = new String(value);
290   - return new Date(valueString.replace(/\-/g, '\/').replace(/[T|Z]/g, ' '));
  288 + return new Date(value);
291 289 }
292 290 return value;
293 291 }
... ... @@ -365,40 +363,36 @@ Ext.define('amdaUI.CatalogUI', {
365 363 }
366 364 },
367 365 {
368   - xtype: 'datecolumn',
369   - text: 'Start Time',
370   - format: 'Y-m-d\\TH:i:s',
371   - sortable: true,
372   - dataIndex: 'start',
373   - width: 120,
374   - minWidth: 50,
375   - menuDisabled: false,
376   - editor: {
377   - xtype: 'datefield',
378   - allowBlank: false,
379   - hideTrigger: true,
380   - format: 'Y-m-d\\TH:i:s'
381   - },
382   - filter: {type: 'date', dateFormat: 'Y-m-d'}
  366 + header: 'Start Time', dataIndex: 'start', width: 120,
  367 + editor: {xtype: 'datefield', allowBlank: false, hideTrigger: true, format: 'Y-m-d\\TH:i:s.u'},
  368 + renderer: function (value) {
  369 + if (value != null) {
  370 + if (Ext.isDate(value)) {
  371 + return Ext.Date.format(value, 'Y-m-d\\TH:i:s.u');
  372 + } else {
  373 + return Ext.Date.format(new Date(value), 'Y-m-d\\TH:i:s.u');
  374 + }
  375 + } else {
  376 + return value;
  377 + }
  378 + }
383 379 },
384 380 {
385   - xtype: 'datecolumn',
386   - text: 'Stop Time',
387   - format: 'Y-m-d\\TH:i:s',
388   - sortable: true,
389   - dataIndex: 'stop',
390   - width: 120,
391   - minWidth: 50,
392   - menuDisabled: false,
393   - editor: {
394   - xtype: 'datefield',
395   - allowBlank: false,
396   - hideTrigger: true,
397   - format: 'Y-m-d\\TH:i:s'
398   - },
399   - filter: {type: 'date', dateFormat: 'Y-m-d'}
  381 + header: 'Stop Time', dataIndex: 'stop', width: 120,
  382 + editor: {xtype: 'datefield', allowBlank: false, hideTrigger: true, format: 'Y-m-d\\TH:i:s.u'},
  383 + renderer: function (value) {
  384 + if (value != null) {
  385 + if (Ext.isDate(value)) {
  386 + return Ext.Date.format(value, 'Y-m-d\\TH:i:s.u');
  387 + } else {
  388 + return Ext.Date.format(new Date(value), 'Y-m-d\\TH:i:s.u');
  389 + }
  390 + } else {
  391 + return value;
  392 + }
  393 + }
400 394 },
401   - {
  395 + {
402 396 xtype: 'gridcolumn',
403 397 text: 'Duration (day)',
404 398 sortable: true,
... ... @@ -506,7 +500,7 @@ Ext.define('amdaUI.CatalogUI', {
506 500 case 1: //dateTime
507 501 field = Ext.apply({}, field, {
508 502 type: 'date',
509   - dateFormat: 'Y-m-d\\TH:i:s',
  503 + dateFormat: 'Y-m-d\\TH:i:s.u',
510 504 convert: function (value, rec) {
511 505 if (!Ext.isDate(value)) {
512 506 var valueString = new String(value);
... ... @@ -523,7 +517,7 @@ Ext.define('amdaUI.CatalogUI', {
523 517 xtype: 'datefield',
524 518 allowBlank: false,
525 519 hideTrigger: true,
526   - format: 'Y-m-d\\TH:i:s'
  520 + format: 'Y-m-d\\TH:i:s.u'
527 521 },
528 522 filter: {type: 'date', dateFormat: 'Y-m-d'}
529 523 });
... ... @@ -894,7 +888,10 @@ Ext.define('amdaUI.CatalogUI', {
894 888 'isCatalog': true,
895 889 'data': {}
896 890 };
897   - obj['data'][activeColumn.dataIndex] = value;
  891 + if(activeColumn.dataIndex == "start" || activeColumn.dataIndex == "stop")
  892 + obj['data'][activeColumn.dataIndex] = Ext.Date.format(value, 'Y-m-d\\TH:i:s.u');
  893 + else
  894 + obj['data'][activeColumn.dataIndex] = value;
898 895  
899 896 //Interval is modified on the server side
900 897 me.editing = true;
... ... @@ -1065,10 +1062,10 @@ Ext.define('amdaUI.CatalogUI', {
1065 1062 items :[{
1066 1063 fieldLabel: 'Start Time',
1067 1064 name: 'surveyStart',
1068   - emptyText: 'YYYY/MM/DDThh:mm:ss',
1069   - format: 'Y-m-d\\TH:i:s',
  1065 + emptyText: 'YYYY/MM/DDThh:mm:ss.fff',
  1066 + format: 'Y-m-d\\TH:i:s.u',
1070 1067 enforceMaxLength: true,
1071   - maxLength: 19,
  1068 + maxLength: 25,
1072 1069 labelWidth: 60,
1073 1070 labelAlign: 'left',
1074 1071 listeners: {
... ... @@ -1080,11 +1077,11 @@ Ext.define('amdaUI.CatalogUI', {
1080 1077 }, {
1081 1078 fieldLabel: 'Stop Time',
1082 1079 name: 'surveyStop',
1083   - emptyText: 'YYYY/MM/DDThh:mm:ss',
1084   - format: 'Y-m-d\\TH:i:s',
  1080 + emptyText: 'YYYY/MM/DDThh:mm:ss.fff',
  1081 + format: 'Y-m-d\\TH:i:s.u',
1085 1082 labelAlign: 'left',
1086 1083 enforceMaxLength: true,
1087   - maxLength: 19,
  1084 + maxLength: 25,
1088 1085 labelWidth: 60,
1089 1086 align: 'left',
1090 1087 listeners: {
... ...
js/app/views/IntervalUI.js
... ... @@ -122,7 +122,7 @@ Ext.define('amdaUI.IntervalUI', {
122 122 // get stop value
123 123 var stop = this.getStopTime();
124 124 // if duration computable
125   - if (stop != null && start != null) {
  125 + if (Ext.isDate(start) && Ext.isDate(stop)) {
126 126 if ( stop <= start ) {
127 127 form.findField('stopDate').markInvalid('Stop Time must be after Start Time');
128 128 } else {
... ... @@ -140,6 +140,7 @@ Ext.define(&#39;amdaUI.IntervalUI&#39;, {
140 140 form.findField('durationHour').setValue(Math.floor(diff/3600000 % 24));
141 141 form.findField('durationMin').setValue(Math.floor(diff/60000 % 60));
142 142 form.findField('durationSec').setValue(Math.floor(diff/1000 % 60));
  143 + form.findField('durationMs').setValue(Math.floor(diff%1000 ));
143 144  
144 145 if (durationDays > this.durationLimit) {
145 146 form.findField('durationDay').markInvalid('Maximum interval is ' + this.durationLimit + ' days!');
... ... @@ -149,6 +150,7 @@ Ext.define(&#39;amdaUI.IntervalUI&#39;, {
149 150 form.findField('durationHour').setValue('');
150 151 form.findField('durationMin').setValue('');
151 152 form.findField('durationSec').setValue('');
  153 + form.findField('durationMs').setValue('');
152 154 }
153 155 },
154 156  
... ... @@ -158,7 +160,8 @@ Ext.define(&#39;amdaUI.IntervalUI&#39;, {
158 160 form.findField('durationDay').isValid() &&
159 161 form.findField('durationHour').isValid() &&
160 162 form.findField('durationMin').isValid() &&
161   - form.findField('durationSec').isValid()
  163 + form.findField('durationSec').isValid() &&
  164 + form.findField('durationMs').isValid()
162 165 );
163 166 },
164 167  
... ... @@ -185,7 +188,8 @@ Ext.define(&#39;amdaUI.IntervalUI&#39;, {
185 188 var h = form.findField('durationHour').getValue();
186 189 var m = form.findField('durationMin').getValue();
187 190 var s = form.findField('durationSec').getValue();
188   - var duration = (d?d:0)*86400 + (h?h:0)*3600 + (m?m:0)*60 + (s?s:0)
  191 + var ms = form.findField('durationMs').getValue();
  192 + var duration = (d?d:0)*86400 + (h?h:0)*3600 + (m?m:0)*60 + (s?s:0) + (ms?ms:0)/1000;
189 193 var stop = Ext.Date.add(start, Ext.Date.SECOND, duration);
190 194  
191 195 if (Ext.Date.isDST(stop) && !Ext.Date.isDST(start))
... ... @@ -226,12 +230,12 @@ Ext.define(&#39;amdaUI.IntervalUI&#39;, {
226 230 xtype: 'datefield',
227 231 // margin : '10 0 5 5', // (top, right, bottom, left).
228 232 name: fieldName,
229   - // width : 220,
230   - emptyText: 'YYYY/MM/DD hh:mm:ss',
231   - tip: 'Date formatted as YYYY/MM/DD hh:mm:ss',
232   - format: 'Y/m/d H:i:s',
  233 + width : 230,
  234 + emptyText: 'YYYY/MM/DD hh:mm:ss.uuu',
  235 + tip: 'Date formatted as YYYY/MM/DD hh:mm:ss.uuu',
  236 + format: 'Y/m/d H:i:s.u',
233 237 enforceMaxLength: true,
234   - maxLength: 19,
  238 + maxLength: 25,
235 239 fieldLabel: fieldText,
236 240 labelAlign: 'left',
237 241 labelWidth: 60,
... ... @@ -296,7 +300,8 @@ Ext.define(&#39;amdaUI.IntervalUI&#39;, {
296 300 { name: 'durationDay', emptyText: 'Days', tip: 'Days', maxValue: 73000, maxLength: 5, fieldLabel: 'Duration', labelWidth: 60, width: 110},
297 301 { name: 'durationHour', emptyText: 'Hrs', tip: 'Hours', maxValue: 23},
298 302 { name: 'durationMin', emptyText: 'Mins', tip: 'Minutes', maxValue: 59},
299   - { name: 'durationSec', emptyText: 'Secs', tip: 'Seconds', maxValue: 59}
  303 + { name: 'durationSec', emptyText: 'Secs', tip: 'Seconds', maxValue: 59},
  304 + { name: 'durationMs', emptyText: 'MS', tip: 'Milliseconds', maxLength: 3, maxValue: 999}
300 305 ]
301 306 };
302 307 },
... ...
js/app/views/PlotComponents/PlotExtendShiftPlug.js
... ... @@ -22,6 +22,8 @@ Ext.define(&#39;amdaPlotComp.PlotExtendShiftPlug&#39;, {
22 22 win : null,
23 23 form : null,
24 24 interactiveId : '',
  25 + actionDone :'',
  26 + durationDone: 0,
25 27  
26 28 constructor: function(config) {
27 29 Ext.apply(this, config);
... ... @@ -44,7 +46,7 @@ Ext.define(&#39;amdaPlotComp.PlotExtendShiftPlug&#39;, {
44 46 {
45 47 this.win = new Ext.Window({
46 48 id: 'plot-extendshift-win-' + this.hostCmp.ownerCt.getId(), // Plot window ID
47   - width: 230,
  49 + width: 275,
48 50 height: 120,
49 51 x: 0, y: 0,
50 52 baseCls:'x-panel',
... ... @@ -111,11 +113,23 @@ Ext.define(&#39;amdaPlotComp.PlotExtendShiftPlug&#39;, {
111 113 var durationUnitField = this.form.getForm().findField('durationUnit');
112 114 var duration = this.toSec(durationField.getValue(), durationUnitField.getValue());
113 115 if (duration) {
114   - this.hostCmp.callInteractivePlot({'action' : actionType, 'interactiveId' : this.interactiveId, 'duration' : duration});
  116 + this.durationDone = duration;
  117 + this.actionDone = actionType;
  118 + this.hostCmp.callInteractivePlot({'action' : actionType, 'interactiveId' : this.interactiveId, 'duration' : duration});
  119 + Ext.getCmp('undo-PlotExtendShiftPlug').enable();
115 120 }
116 121 else
117 122 myDesktopApp.errorMsg('No duration defined');
118 123 },
  124 + undoAction : function(){
  125 + if( this.durationDone){
  126 + this.hostCmp.callInteractivePlot({'action' : this.actionDone , 'interactiveId' : this.interactiveId, 'duration' : -this.durationDone});
  127 + Ext.getCmp('undo-PlotExtendShiftPlug').disable();
  128 + }
  129 + else
  130 + myDesktopApp.errorMsg('No duration defined');
  131 +
  132 + },
119 133  
120 134 /**
121 135 * Main form
... ... @@ -123,7 +137,7 @@ Ext.define(&#39;amdaPlotComp.PlotExtendShiftPlug&#39;, {
123 137 getFormConfig: function(){
124 138 this.form = new Ext.form.FormPanel( {
125 139 frame: true,
126   - width: 230,
  140 + width: 275,
127 141 height: 120,
128 142 layout: {
129 143 type: 'vbox',
... ... @@ -171,6 +185,7 @@ Ext.define(&#39;amdaPlotComp.PlotExtendShiftPlug&#39;, {
171 185 }
172 186 ],
173 187 buttons: [
  188 +
174 189 {
175 190 text: 'Extend/Shrink',
176 191 scope : this,
... ... @@ -178,13 +193,23 @@ Ext.define(&#39;amdaPlotComp.PlotExtendShiftPlug&#39;, {
178 193 this.executeAction('extend');
179 194 }
180 195 },
181   - '->',
  196 + '-',
182 197 {
183 198 text: 'Shift',
184 199 scope : this,
185 200 handler: function(bt,event) {
186 201 this.executeAction('shift');
187 202 }
  203 + },
  204 + '-',
  205 + {
  206 + text: 'Undo',
  207 + id:'undo-PlotExtendShiftPlug',
  208 + scope : this,
  209 + disabled : true,
  210 + handler: function(bt,event) {
  211 + this.undoAction();
  212 + }
188 213 }
189 214 ]
190 215 });
... ...
js/app/views/PlotComponents/PlotSauvaudForm.js
... ... @@ -49,7 +49,7 @@ Ext.define(&#39;amdaPlotComp.PlotSauvaudForm&#39;, {
49 49 { 'key': 0, 'value': 'dim1' },
50 50 { 'key': 1, 'value': 'dim2' },
51 51 ];
52   - const dimField = this.addStandardCombo('right_dimension', 'Right Dim', dataStore , function (name, value, oldValue) {
  52 + const dimField = this.addStandardCombo('right_dimension', 'Switch Dimension', dataStore , function (name, value, oldValue) {
53 53 if (ref.object.get('right_dim') != value) {
54 54 ref.object.set('right_dim', value);
55 55 }
... ...
js/app/views/PlotComponents/PlotTabContent.js
... ... @@ -39,6 +39,7 @@ Ext.define(&#39;amdaPlotComp.PlotTabContent&#39;, {
39 39  
40 40 setTime : function(startDate, stopDate) {
41 41 this.timeSelector.intervalSel.setInterval(startDate, stopDate);
  42 + this.timeSelector.setActiveTimeSource(amdaModel.AmdaTimeObject.inputTimeSrc[1]);
42 43  
43 44 },
44 45 getTimeSelector: function(){
... ...
js/app/views/PlotComponents/PlotZoomPlug.js
... ... @@ -193,7 +193,13 @@ Ext.define(&#39;amdaPlotComp.PlotZoomPlug&#39;, {
193 193  
194 194 this.hostCmp.panelImage.resetZoom();
195 195 },
196   -
  196 + setTimePlot : function(){
  197 + var timeObj = new Object();
  198 + timeObj.start = this.form.getForm().findField('zoom-min-time').getValue();
  199 + timeObj.stop = this.form.getForm().findField('zoom-max-time').getValue();
  200 + var plotModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.plot.id);
  201 + plotModule.setTimeInterval(timeObj);
  202 + },
197 203 /**
198 204 * Main form
199 205 */
... ... @@ -212,11 +218,11 @@ Ext.define(&#39;amdaPlotComp.PlotZoomPlug&#39;, {
212 218 items: [
213 219 {
214 220 xtype: 'datefield', name: 'zoom-min-time', fieldLabel: 'Start Time',
215   - format: 'Y-m-d\\TH:i:s'
  221 + format: 'Y/m/d H:i:s.u',
216 222 },
217 223 {
218 224 xtype: 'datefield', name: 'zoom-max-time', fieldLabel: 'Stop Time',
219   - format: 'Y-m-d\\TH:i:s'
  225 + format: 'Y/m/d H:i:s.u'
220 226 },
221 227 {
222 228 xtype: 'numberfield', name: 'zoom-min-float', fieldLabel: 'Min Value'
... ... @@ -232,6 +238,15 @@ Ext.define(&#39;amdaPlotComp.PlotZoomPlug&#39;, {
232 238 handler: function () {
233 239 this.resetMinMaxValue();
234 240 }
  241 + },
  242 + {
  243 + xtype: 'button',
  244 + width: 100,
  245 + text: 'Use interval in plot',
  246 + scope: this,
  247 + handler: function () {
  248 + this.setTimePlot();
  249 + }
235 250 }
236 251 ]
237 252 };
... ... @@ -372,7 +387,7 @@ Ext.define(&#39;amdaPlotComp.PlotZoomPlug&#39;, {
372 387  
373 388 this.form = new Ext.form.FormPanel({
374 389 frame: true,
375   - width: 250,
  390 + width: 255,
376 391 layout: {
377 392 type: 'vbox',
378 393 pack: 'start',
... ... @@ -392,8 +407,8 @@ Ext.define(&#39;amdaPlotComp.PlotZoomPlug&#39;, {
392 407 scope: this,
393 408 handler: function () {
394 409 if (this.zoomType == 'timeAxis') {
395   - var minZoom = this.form.getForm().findField('zoom-min-time').getValue();
396   - var maxZoom = this.form.getForm().findField('zoom-max-time').getValue();
  410 + var minZoom = Ext.Date.format(this.form.getForm().findField('zoom-min-time').getValue(), 'Y-m-d H:i:s.u');
  411 + var maxZoom = Ext.Date.format(this.form.getForm().findField('zoom-max-time').getValue(),'Y-m-d H:i:s.u');
397 412 }
398 413 else {
399 414 var minZoom = this.form.getForm().findField('zoom-min-float').getValue();
... ...
js/app/views/PlotTabResultUI.js
... ... @@ -520,6 +520,22 @@ Ext.define(&#39;amdaUI.PlotTabResultUI&#39;, {
520 520 this.callInteractivePlot({'action' : 'goto', 'interactiveId' : this.interactiveId, 'ttFileIndex' : ttFileIndex, 'intIndex' : ttintervalIndex});
521 521 }
522 522 },
  523 + '-',
  524 + {
  525 + text: 'Use This Time Inteval',
  526 + scope: this,
  527 + handler: function(){
  528 + var timeObj = new Object();
  529 + var startTime = new Date(this.crtContext.page.startTime*1000);
  530 + timeObj.start = Ext.Date.add(startTime, Ext.Date.MINUTE, startTime.getTimezoneOffset());
  531 +
  532 + var stopTime = new Date(this.crtContext.page.stopTime*1000);
  533 + timeObj.stop = Ext.Date.add(stopTime, Ext.Date.MINUTE, stopTime.getTimezoneOffset());
  534 +
  535 + var plotModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.plot.id);
  536 + plotModule.setTimeInterval(timeObj);
  537 + }
  538 + },
523 539 '-',
524 540 {
525 541 text: 'Go to Interval #',
... ...
js/app/views/PlotUI.js
... ... @@ -140,12 +140,9 @@ Ext.define(&#39;amdaUI.PlotUI&#39;, {
140 140 setTimeFromData : function(obj) {
141 141 if (!obj.start || !obj.stop)
142 142 return;
143   - var dateStart = new Date(obj.start.replace(/[T|Z]/g,' ').replace(/\-/g,'\/'));
144   - var dateStop = new Date(obj.stop.replace(/[T|Z]/g,' ').replace(/\-/g,'\/'));
145   -
146 143 var plotTab = this.plotTabs.getCurrentPlotTabContent();
147 144 if (plotTab)
148   - plotTab.setTime(dateStart, dateStop);
  145 + plotTab.setTime(obj.start, obj.stop);
149 146 },
150 147  
151 148 savePlotRequest : function() {
... ...
js/app/views/StatisticsUI.js
... ... @@ -177,17 +177,17 @@ Ext.define(&#39;amdaUI.StatisticsUI&#39;,
177 177  
178 178 /**
179 179 * Set Start-Stop from parameter info (Local & MyData)
180   - */
  180 +
181 181 setTimeFromData: function (obj) {
182 182 if (!obj.start || !obj.stop)
183 183 return;
184 184  
185   - var dateStart = new Date(obj.start.replace(/[T|Z]/g, ' ').replace(/\-/g, '\/'));
186   - var dateStop = new Date(obj.stop.replace(/[T|Z]/g, ' ').replace(/\-/g, '\/'));
  185 + //var dateStart = new Date(obj.start.replace(/[T|Z]/g, ' ').replace(/\-/g, '\/'));
  186 + //var dateStop = new Date(obj.stop.replace(/[T|Z]/g, ' ').replace(/\-/g, '\/'));
187 187  
188   - this.formPanel.items.items[1].getForm().setValues({startDate: dateStart, stopDate: dateStop});
189   - this.timeSelector.intervalSel.updateDuration();
190   - },
  188 + //this.formPanel.items.items[1].getForm().setValues({startDate: dateStart, stopDate: dateStop});
  189 + // this.timeSelector.intervalSel.updateDuration();
  190 + }, */
191 191  
192 192 generateCatalog: function ()
193 193 {
... ...
js/app/views/TimeSelectorUI.js
... ... @@ -61,6 +61,9 @@ Ext.define(&#39;amdaUI.TimeSelectorUI&#39;, {
61 61 getActiveTimeSource: function() {
62 62 return this.timeSrc.getActiveTab().getItemId();
63 63 },
  64 + setActiveTimeSource : function (timeSrcIndex){
  65 + this.timeSrc.setActiveTab(timeSrcIndex);
  66 + },
64 67  
65 68 isValid: function(acceptEmptyTTList = true) {
66 69 if (this.getActiveTimeSource() === amdaModel.AmdaTimeObject.inputTimeSrc[0]) {
... ...
js/app/views/TimeTableUI.js
... ... @@ -298,7 +298,7 @@ Ext.define(&#39;amdaUI.TimeTableUI&#39;, {
298 298 var catNode = Ext.create('amdaModel.CatalogNode', {leaf: true});
299 299 catObj.set('relatedTimeTableId', id);
300 300 creatDate = new Date(this.object.get('created'));
301   - date = Ext.Date.format(creatDate, 'Y-m-d\\TH:i:s');
  301 + date = Ext.Date.format(creatDate, 'Y-m-d\\TH:i:s.u');
302 302 descr = 'Generated by CDPP/Amda Time Table Module \n' + 'From Time Table: ' + this.object.get('name') + ' which was generated on: ' + date + '\n';
303 303 catObj.set('description', descr + this.object.get('description'));
304 304 var nbParam = parseInt(text);
... ... @@ -510,8 +510,8 @@ Ext.define(&#39;amdaUI.TimeTableUI&#39;, {
510 510 {type: 'numeric', dataIndex: 'durationHour'},
511 511 {type: 'numeric', dataIndex: 'durationMin'},
512 512 {type: 'numeric', dataIndex: 'durationSec'},
513   - {type: 'date', dataIndex: 'start', dateFormat: 'Y-m-d'},
514   - {type: 'date', dataIndex: 'stop', dateFormat: 'Y-m-d'}
  513 + {type: 'date', dataIndex: 'start', dateFormat: 'c'},
  514 + {type: 'date', dataIndex: 'stop', dateFormat: 'c'}
515 515 ]
516 516 };
517 517 var cellEditing = Ext.create('Ext.grid.plugin.CellEditing', {
... ... @@ -542,7 +542,7 @@ Ext.define(&#39;amdaUI.TimeTableUI&#39;, {
542 542 'isCatalog': false,
543 543 'data': {}
544 544 };
545   - obj['data'][activeColumn.dataIndex] = value;
  545 + obj['data'][activeColumn.dataIndex] = Ext.Date.format(value, 'Y-m-d\\TH:i:s.u');
546 546  
547 547 //context.grid.getSelectionModel().deselectAll();
548 548 //Interval is modified on the server side
... ... @@ -612,13 +612,13 @@ Ext.define(&#39;amdaUI.TimeTableUI&#39;, {
612 612 },
613 613 {
614 614 header: 'Start Time', dataIndex: 'start', width: 120,
615   - editor: {xtype: 'datefield', allowBlank: false, hideTrigger: true, format: 'Y-m-d\\TH:i:s'},
  615 + editor: {xtype: 'datefield', allowBlank: false, hideTrigger: true, format: 'Y-m-d\\TH:i:s.u'},
616 616 renderer: function (value) {
617 617 if (value != null) {
618 618 if (Ext.isDate(value)) {
619   - return Ext.Date.format(value, 'Y-m-d\\TH:i:s');
  619 + return Ext.Date.format(value, 'Y-m-d\\TH:i:s.u');
620 620 } else {
621   - return Ext.Date.format(new Date(value), 'Y-m-d\\TH:i:s');
  621 + return Ext.Date.format(new Date(value), 'Y-m-d\\TH:i:s.u');
622 622 }
623 623 } else {
624 624 return value;
... ... @@ -627,13 +627,13 @@ Ext.define(&#39;amdaUI.TimeTableUI&#39;, {
627 627 },
628 628 {
629 629 header: 'Stop Time', dataIndex: 'stop', width: 120,
630   - editor: {xtype: 'datefield', allowBlank: false, hideTrigger: true, format: 'Y-m-d\\TH:i:s'},
  630 + editor: {xtype: 'datefield', allowBlank: false, hideTrigger: true, format: 'Y-m-d\\TH:i:s.u'},
631 631 renderer: function (value) {
632 632 if (value != null) {
633 633 if (Ext.isDate(value)) {
634   - return Ext.Date.format(value, 'Y-m-d\\TH:i:s');
  634 + return Ext.Date.format(value, 'Y-m-d\\TH:i:s.u');
635 635 } else {
636   - return Ext.Date.format(new Date(value), 'Y-m-d\\TH:i:s');
  636 + return Ext.Date.format(new Date(value), 'Y-m-d\\TH:i:s.u');
637 637 }
638 638 } else {
639 639 return value;
... ...
php/classes/AmdaAction.php
... ... @@ -247,8 +247,8 @@ class AmdaAction
247 247 $info .= "<br/>Time Range : depending on mission selection";
248 248 else
249 249 $info .= "<br/>Time Range : undefined";
250   - $child->setAttribute('dataStart', date("Y-m-d\TH:i:s\Z", strtotime(' -1 day')));
251   - $child->setAttribute('dataStop', date("Y-m-d\TH:i:s\Z", time()));
  250 + $child->setAttribute('dataStart', date("Y-m-d\TH:i:s.u\Z", strtotime(' -1 day')));
  251 + $child->setAttribute('dataStop', date("Y-m-d\TH:i:s.u\Z", time()));
252 252 } else {
253 253 $info .= "<br/>Time Range: ".$child->getAttribute('dataStart')."-".$child->getAttribute('dataStop');
254 254 }
... ... @@ -366,7 +366,7 @@ class AmdaAction
366 366 else {
367 367 if (!empty($timeRestriction)) {
368 368 $disable = FALSE;
369   - $formattedTimeRestriction = date("Y-m-d\TH:i:s\Z",strtotime($timeRestriction)+1);
  369 + $formattedTimeRestriction = date("Y-m-d\TH:i:s.u\Z",strtotime($timeRestriction)+1);
370 370 $info .= "<br/><b>After $formattedTimeRestriction data are restricted to group ".$child->getAttribute('group')."</b>";
371 371 }
372 372 else {
... ... @@ -478,15 +478,15 @@ class AmdaAction
478 478  
479 479 if ($child->tagName == 'parameter'){
480 480 if ($child->parentNode->hasAttribute('dataStart')){
481   - $globalStart = date('Y-m-d\TH:i:s\Z', strtotime($child->parentNode->getAttribute('dataStart')));
482   - $globalStop = date('Y-m-d\TH:i:s\Z', strtotime($child->parentNode->getAttribute('dataStop')));
  481 + $globalStart = date('Y-m-d\TH:i:s.u\Z', strtotime($child->parentNode->getAttribute('dataStart')));
  482 + $globalStop = date('Y-m-d\TH:i:s.u\Z', strtotime($child->parentNode->getAttribute('dataStop')));
483 483 }
484 484 }
485 485  
486 486 if ( $child->tagName == 'component'){
487 487 if ($child->parentNode->parentNode->hasAttribute('dataStart')){
488   - $globalStart = date('Y-m-d\TH:i:s\Z', strtotime($child->parentNode->getAttribute('dataStart')));
489   - $globalStop = date('Y-m-d\TH:i:s\Z', strtotime($child->parentNode->getAttribute('dataStop')));
  488 + $globalStart = date('Y-m-d\TH:i:s.u\Z', strtotime($child->parentNode->getAttribute('dataStart')));
  489 + $globalStop = date('Y-m-d\TH:i:s.u\Z', strtotime($child->parentNode->getAttribute('dataStop')));
490 490 }
491 491 }
492 492  
... ... @@ -678,7 +678,7 @@ class AmdaAction
678 678 $result = $this->executeRequest((Object) array(
679 679 'compression' => 'none',
680 680 'fileformat' => 'internal',
681   - 'timeformat' => 'YYYY-MM-DDThh:mm:ss',
  681 + 'timeformat' => 'YYYY-MM-DDThh:mm:ss.u',
682 682 'sendToSamp' => FALSE,
683 683 'list' => array(
684 684 (Object) array(
... ...
php/classes/CatalogCacheIntervalObject.php
... ... @@ -59,7 +59,7 @@ class CatalogCacheIntervalObject extends TimeTableCacheIntervalObject
59 59 fwrite($handle,pack('d', floatval($value)));
60 60 break;
61 61 case 1: //date (timestamp)
62   - fwrite($handle,pack('L', TimeUtils::iso2stamp($value)));
  62 + fwrite($handle,pack('d', TimeUtils::iso2stamp($value)));
63 63 break;
64 64 case 2: //string
65 65 fwrite($handle,pack('L', strlen($value)));
... ... @@ -101,7 +101,7 @@ class CatalogCacheIntervalObject extends TimeTableCacheIntervalObject
101 101 $val = $res['val'];
102 102 break;
103 103 case 1: //date (timestamp)
104   - if (!$res = unpack('Lval',fread($handle,4))) {
  104 + if (!$res = unpack('dval',fread($handle,8))) {
105 105 break;
106 106 }
107 107 $val = TimeUtils::stamp2iso($res['val']);
... ...
php/classes/RequestMgr.php
... ... @@ -94,9 +94,10 @@ class RequestMgr extends AmdaObjectMgr
94 94 $time = strtotime($obj->startDate);
95 95  
96 96 $interval = $obj->durationDay*86400 +
97   - $obj->durationHour*3600 +
98   - $obj->durationMin*60 + $obj->durationSec;
  97 + $obj->durationHour*3600 +
  98 + $obj->durationMin*60 + $obj->durationSec;
99 99 $stopTime = gmdate("Y-m-d\TH:i:s", $time+$interval);
  100 + $stopTime = $stopTime.'.'.$obj->durationMs;
100 101 $obj->stopDate = $stopTime;
101 102  
102 103 return $obj;
... ...
php/classes/TimeTableCacheIntervalObject.php
... ... @@ -107,17 +107,27 @@ class TimeTableCacheIntervalObject
107 107 }
108 108  
109 109 public function writeBin($handle) {
110   - fwrite($handle,pack('L6',$this->id,$this->index,$this->start,$this->stop,$this->isNew,$this->isModified));
  110 +
  111 + fwrite($handle,pack('L2',$this->id,$this->index));
  112 + fwrite($handle,pack('d2', $this->start,$this->stop));
  113 + fwrite($handle, pack('L2', $this->isNew,$this->isModified));
111 114 }
112 115  
113 116 public function loadBin($handle) {
114   - $array = unpack('L6int',fread($handle,6*4));
115   - $this->id = $array['int1'];
116   - $this->index = $array['int2'];
117   - $this->start = $array['int3'];
118   - $this->stop = $array['int4'];
119   - $this->isNew = $array['int5'];
120   - $this->isModified = $array['int6'];
  117 +
  118 + $res = unpack('L2int',fread($handle,4*2));
  119 + $this->id = $res['int1'];
  120 + $this->index = $res['int2'];
  121 +
  122 + $res = unpack('d2d',fread($handle,8*2));
  123 + $this->start = $res['d1'];
  124 + $this->stop = $res['d2'];
  125 +
  126 +
  127 + $res = unpack('L2int',fread($handle,4*2));
  128 + $this->isNew = $res['int1'];
  129 + $this->isModified = $res['int2'];
  130 +
121 131 }
122 132  
123 133 public function dump() {
... ...
php/classes/TimeTableCacheMgr.php
... ... @@ -240,10 +240,10 @@
240 240 $index = 0;
241 241  
242 242 if (!isset($start))
243   - $start = date('Y-m-d\TH:i:s');
  243 + $start = date('Y-m-d\TH:i:s.u');
244 244  
245 245 if (!isset($stop))
246   - $stop = date('Y-m-d\TH:i:s');
  246 + $stop = date('Y-m-d\TH:i:s.u');
247 247  
248 248 $this->cache->addInterval(array('start' => $start, 'stop' => $stop), true, $index);
249 249  
... ...
php/classes/TimeTableMgr.php
... ... @@ -200,7 +200,7 @@ class TimeTableMgr extends AmdaObjectMgr
200 200 }
201 201  
202 202 $this->id = $this->setId();
203   - $this->created = date('Y-m-d\TH:i:s');
  203 + $this->created = date('Y-m-d\TH:i:s.u');
204 204 if (!$this->id) {
205 205 return ['error' => ID_CREATION_ERROR];
206 206 }
... ...
php/classes/TimeUtils.php
... ... @@ -9,13 +9,18 @@ class TimeUtils
9 9 catch (Exception $e) {
10 10 $time = new DateTime('1970-01-01T00:00:00Z');
11 11 }
12   - $stamp = $time->format('U');
  12 + $stamp = $time->format('U.u');
13 13 unset($time);
14 14 return $stamp;
15 15 }
16 16  
17 17 public static function stamp2iso($stamp) {
18   - return date('Y-m-d\TH:i:s',$stamp);
  18 + $intStamp = floor($stamp);
  19 + $intMilli = round(($stamp-$intStamp)*1000);
  20 + // c'est moche mais setTime de php ne prends pas en compte les ms
  21 + $strMilli = str_pad(strval($intMilli),3, '0', STR_PAD_LEFT);
  22 + $dateIso = date("Y-m-d\TH:i:s",$intStamp).'.'.$strMilli;
  23 + return $dateIso;
19 24 }
20 25 }
21 26  
... ...