Adding date.format to make date strings customisable to fit your locale
[KiwiIRC.git] / client / src / helpers / utils.js
CommitLineData
2dd6a025
D
1/*jslint devel: true, browser: true, continue: true, sloppy: true, forin: true, plusplus: true, maxerr: 50, indent: 4, nomen: true, regexp: true*/
2/*globals $, front, gateway, Utilityview */
3
2dd6a025
D
4
5
2dd6a025
D
6/**
7* Generate a random string of given length
8* @param {Number} string_length The length of the random string
9* @returns {String} The random string
10*/
11function randomString(string_length) {
12 var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz",
13 randomstring = '',
14 i,
15 rnum;
16 for (i = 0; i < string_length; i++) {
17 rnum = Math.floor(Math.random() * chars.length);
18 randomstring += chars.substring(rnum, rnum + 1);
19 }
20 return randomstring;
21}
22
23/**
24* String.trim shim
25*/
26if (typeof String.prototype.trim === 'undefined') {
27 String.prototype.trim = function () {
28 return this.replace(/^\s+|\s+$/g, "");
29 };
30}
31
32/**
33* String.lpad shim
34* @param {Number} length The length of padding
35* @param {String} characher The character to pad with
36* @returns {String} The padded string
37*/
38if (typeof String.prototype.lpad === 'undefined') {
39 String.prototype.lpad = function (length, character) {
40 var padding = "",
41 i;
42 for (i = 0; i < length; i++) {
43 padding += character;
44 }
45 return (padding + this).slice(-length);
46 };
47}
48
49
50/**
51* Convert seconds into hours:minutes:seconds
52* @param {Number} secs The number of seconds to converts
53* @returns {Object} An object representing the hours/minutes/second conversion of secs
54*/
55function secondsToTime(secs) {
56 var hours, minutes, seconds, divisor_for_minutes, divisor_for_seconds, obj;
57 hours = Math.floor(secs / (60 * 60));
58
59 divisor_for_minutes = secs % (60 * 60);
60 minutes = Math.floor(divisor_for_minutes / 60);
61
62 divisor_for_seconds = divisor_for_minutes % 60;
63 seconds = Math.ceil(divisor_for_seconds);
64
65 obj = {
66 "h": hours,
67 "m": minutes,
68 "s": seconds
69 };
70 return obj;
71}
72
73
64c6bcb4
D
74/* Command input Alias + re-writing */
75function InputPreProcessor () {
76 this.recursive_depth = 3;
77
78 this.aliases = {};
79 this.vars = {version: 1};
80
81 // Current recursive depth
82 var depth = 0;
83
84
85 // Takes an array of words to process!
86 this.processInput = function (input) {
87 var words = input || [],
88 alias = this.aliases[words[0]],
89 alias_len,
90 current_alias_word = '',
91 compiled = [];
92
93 // If an alias wasn't found, return the original input
94 if (!alias) return input;
95
96 // Split the alias up into useable words
97 alias = alias.split(' ');
98 alias_len = alias.length;
99
100 // Iterate over each word and pop them into the final compiled array.
101 // Any $ words are processed with the result ending into the compiled array.
102 for (var i=0; i<alias_len; i++) {
103 current_alias_word = alias[i];
104
105 // Non $ word
106 if (current_alias_word[0] !== '$') {
107 compiled.push(current_alias_word);
108 continue;
109 }
110
111 // Refering to an input word ($N)
112 if (!isNaN(current_alias_word[1])) {
113 var num = current_alias_word.match(/\$(\d+)(\+)?(\d+)?/);
114
115 // Did we find anything or does the word it refers to non-existant?
116 if (!num || !words[num[1]]) continue;
64bdb2ff 117
64c6bcb4
D
118 if (num[2] === '+' && num[3]) {
119 // Add X number of words
120 compiled = compiled.concat(words.slice(parseInt(num[1], 10), parseInt(num[1], 10) + parseInt(num[3], 10)));
121 } else if (num[2] === '+') {
122 // Add the remaining of the words
123 compiled = compiled.concat(words.slice(parseInt(num[1], 10)));
124 } else {
125 // Add a single word
126 compiled.push(words[parseInt(num[1], 10)]);
127 }
128
129 continue;
130 }
131
132
133 // Refering to a variable
134 if (typeof this.vars[current_alias_word.substr(1)] !== 'undefined') {
135
136 // Get the variable
137 compiled.push(this.vars[current_alias_word.substr(1)]);
138
139 continue;
140 }
141
142 }
143
144 return compiled;
145 };
146
147
148 this.process = function (input) {
149 input = input || '';
150
151 var words = input.split(' ');
152
153 depth++;
154 if (depth >= this.recursive_depth) {
155 depth--;
156 return input;
157 }
158
159 if (this.aliases[words[0]]) {
160 words = this.processInput(words);
64bdb2ff 161
64c6bcb4
D
162 if (this.aliases[words[0]]) {
163 words = this.process(words.join(' ')).split(' ');
164 }
165
166 }
167
168 depth--;
169 return words.join(' ');
170 };
171}
172
173
1167a85d
D
174/**
175 * Convert HSL to RGB formatted colour
176 */
177function hsl2rgb(h, s, l) {
178 var m1, m2, hue;
179 var r, g, b
180 s /=100;
181 l /= 100;
182 if (s == 0)
183 r = g = b = (l * 255);
184 else {
185 function HueToRgb(m1, m2, hue) {
186 var v;
187 if (hue < 0)
188 hue += 1;
189 else if (hue > 1)
190 hue -= 1;
191
192 if (6 * hue < 1)
193 v = m1 + (m2 - m1) * hue * 6;
194 else if (2 * hue < 1)
195 v = m2;
196 else if (3 * hue < 2)
197 v = m1 + (m2 - m1) * (2/3 - hue) * 6;
198 else
199 v = m1;
200
201 return 255 * v;
202 }
203 if (l <= 0.5)
204 m2 = l * (s + 1);
205 else
206 m2 = l + s - l * s;
207 m1 = l * 2 - m2;
208 hue = h / 360;
209 r = HueToRgb(m1, m2, hue + 1/3);
210 g = HueToRgb(m1, m2, hue);
211 b = HueToRgb(m1, m2, hue - 1/3);
212 }
213 return [r,g,b];
214}
215
216
b166c1ac
D
217/**
218 * Formats a kiwi message to IRC format
219 */
220function formatToIrcMsg(message) {
221 // Format any colour codes (eg. $c4)
222 message = message.replace(/%C(\d)/ig, function(match, colour_number) {
223 return String.fromCharCode(3) + colour_number.toString();
224 });
225
226 var formatters = {
227 B: '\x02', // Bold
228 I: '\x1D', // Italics
229 U: '\x1F', // Underline
230 O: '\x0F' // Out / Clear formatting
231 };
232 message = message.replace(/%([BIUO])/ig, function(match, format_code) {
233 if (typeof formatters[format_code.toUpperCase()] !== 'undefined')
234 return formatters[format_code.toUpperCase()];
235 });
236
237 return message;
238}
239
240
2dd6a025
D
241/**
242* Formats a message. Adds bold, underline and colouring
243* @param {String} msg The message to format
244* @returns {String} The HTML formatted message
245*/
246function formatIRCMsg (msg) {
f47955d3
JA
247 "use strict";
248 var out = '',
249 currentTag = '',
250 openTags = {
251 bold: false,
252 italic: false,
253 underline: false,
254 colour: false
255 },
f47955d3
JA
256 spanFromOpen = function () {
257 var style = '',
258 colours;
643ca730 259 if (!(openTags.bold || openTags.italic || openTags.underline || openTags.colour)) {
f47955d3
JA
260 return '';
261 } else {
262 style += (openTags.bold) ? 'font-weight: bold; ' : '';
263 style += (openTags.italic) ? 'font-style: italic; ' : '';
264 style += (openTags.underline) ? 'text-decoration: underline; ' : '';
265 if (openTags.colour) {
266 colours = openTags.colour.split(',');
267 style += 'color: ' + colours[0] + ((colours[1]) ? '; background-color: ' + colours[1] + ';' : '');
268 }
9d8f8dfe 269 return '<span class="format_span" style="' + style + '">';
f47955d3
JA
270 }
271 },
2dd6a025 272 colourMatch = function (str) {
f47955d3 273 var re = /^\x03(([0-9][0-9]?)(,([0-9][0-9]?))?)/;
2dd6a025 274 return re.exec(str);
f47955d3
JA
275 },
276 hexFromNum = function (num) {
2dd6a025
D
277 switch (parseInt(num, 10)) {
278 case 0:
279 return '#FFFFFF';
280 case 1:
281 return '#000000';
282 case 2:
283 return '#000080';
284 case 3:
285 return '#008000';
286 case 4:
287 return '#FF0000';
288 case 5:
289 return '#800040';
290 case 6:
291 return '#800080';
292 case 7:
293 return '#FF8040';
294 case 8:
295 return '#FFFF00';
296 case 9:
297 return '#80FF00';
298 case 10:
299 return '#008080';
300 case 11:
301 return '#00FFFF';
302 case 12:
303 return '#0000FF';
304 case 13:
305 return '#FF55FF';
306 case 14:
307 return '#808080';
308 case 15:
309 return '#C0C0C0';
310 default:
311 return null;
312 }
f47955d3
JA
313 },
314 i = 0,
315 colours = [],
316 match;
317
318 for (i = 0; i < msg.length; i++) {
319 switch (msg[i]) {
320 case '\x02':
643ca730 321 if ((openTags.bold || openTags.italic || openTags.underline || openTags.colour)) {
f47955d3
JA
322 out += currentTag + '</span>';
323 }
324 openTags.bold = !openTags.bold;
325 currentTag = spanFromOpen();
326 break;
327 case '\x1D':
2cb3c82e 328 if ((openTags.bold || openTags.italic || openTags.underline || openTags.colour)) {
f47955d3
JA
329 out += currentTag + '</span>';
330 }
331 openTags.italic = !openTags.italic;
332 currentTag = spanFromOpen();
333 break;
334 case '\x1F':
643ca730 335 if ((openTags.bold || openTags.italic || openTags.underline || openTags.colour)) {
f47955d3
JA
336 out += currentTag + '</span>';
337 }
338 openTags.underline = !openTags.underline;
339 currentTag = spanFromOpen();
340 break;
341 case '\x03':
643ca730 342 if ((openTags.bold || openTags.italic || openTags.underline || openTags.colour)) {
f47955d3
JA
343 out += currentTag + '</span>';
344 }
345 match = colourMatch(msg.substr(i, 6));
346 if (match) {
f47955d3
JA
347 i += match[1].length;
348 // 2 & 4
349 colours[0] = hexFromNum(match[2]);
350 if (match[4]) {
351 colours[1] = hexFromNum(match[4]);
2dd6a025 352 }
f47955d3
JA
353 openTags.colour = colours.join(',');
354 } else {
355 openTags.colour = false;
356 }
357 currentTag = spanFromOpen();
358 break;
359 case '\x0F':
643ca730 360 if ((openTags.bold || openTags.italic || openTags.underline || openTags.colour)) {
f47955d3 361 out += currentTag + '</span>';
2dd6a025 362 }
f47955d3
JA
363 openTags.bold = openTags.italic = openTags.underline = openTags.colour = false;
364 break;
365 default:
643ca730 366 if ((openTags.bold || openTags.italic || openTags.underline || openTags.colour)) {
f47955d3
JA
367 currentTag += msg[i];
368 } else {
369 out += msg[i];
370 }
371 break;
2dd6a025 372 }
f47955d3 373 }
643ca730 374 if ((openTags.bold || openTags.italic || openTags.underline || openTags.colour)) {
f47955d3
JA
375 out += currentTag + '</span>';
376 }
377 return out;
2dd6a025
D
378}
379
380
51a4c383 381function formatDate (d) {
4cdfa487
CC
382 /*
383 date.format.js
384 A JavaScript date format library that uses the same method as PHP's date() function.
385
386 https://github.com/jacwright/date.format
387 */
388 Date.shortMonths = [_kiwi.global.i18n.translate('client.libs.date_format.short_months.january').fetch(),
389 _kiwi.global.i18n.translate('client.libs.date_format.short_months.february').fetch(),
390 _kiwi.global.i18n.translate('client.libs.date_format.short_months.march').fetch(),
391 _kiwi.global.i18n.translate('client.libs.date_format.short_months.april').fetch(),
392 _kiwi.global.i18n.translate('client.libs.date_format.short_months.may').fetch(),
393 _kiwi.global.i18n.translate('client.libs.date_format.short_months.june').fetch(),
394 _kiwi.global.i18n.translate('client.libs.date_format.short_months.july').fetch(),
395 _kiwi.global.i18n.translate('client.libs.date_format.short_months.august').fetch(),
396 _kiwi.global.i18n.translate('client.libs.date_format.short_months.september').fetch(),
397 _kiwi.global.i18n.translate('client.libs.date_format.short_months.october').fetch(),
398 _kiwi.global.i18n.translate('client.libs.date_format.short_months.november').fetch(),
399 _kiwi.global.i18n.translate('client.libs.date_format.short_months.december').fetch()];
400 Date.longMonths = [_kiwi.global.i18n.translate('client.libs.date_format.long_months.january').fetch(),
401 _kiwi.global.i18n.translate('client.libs.date_format.long_months.february').fetch(),
402 _kiwi.global.i18n.translate('client.libs.date_format.long_months.march').fetch(),
403 _kiwi.global.i18n.translate('client.libs.date_format.long_months.april').fetch(),
404 _kiwi.global.i18n.translate('client.libs.date_format.long_months.may').fetch(),
405 _kiwi.global.i18n.translate('client.libs.date_format.long_months.june').fetch(),
406 _kiwi.global.i18n.translate('client.libs.date_format.long_months.july').fetch(),
407 _kiwi.global.i18n.translate('client.libs.date_format.long_months.august').fetch(),
408 _kiwi.global.i18n.translate('client.libs.date_format.long_months.september').fetch(),
409 _kiwi.global.i18n.translate('client.libs.date_format.long_months.october').fetch(),
410 _kiwi.global.i18n.translate('client.libs.date_format.long_months.november').fetch(),
411 _kiwi.global.i18n.translate('client.libs.date_format.long_months.december').fetch()];
412 Date.shortDays = [_kiwi.global.i18n.translate('client.libs.date_format.short_days.monday').fetch(),
413 _kiwi.global.i18n.translate('client.libs.date_format.short_days.tuesday').fetch(),
414 _kiwi.global.i18n.translate('client.libs.date_format.short_days.wednesday').fetch(),
415 _kiwi.global.i18n.translate('client.libs.date_format.short_days.thursday').fetch(),
416 _kiwi.global.i18n.translate('client.libs.date_format.short_days.friday').fetch(),
417 _kiwi.global.i18n.translate('client.libs.date_format.short_days.saturday').fetch(),
418 _kiwi.global.i18n.translate('client.libs.date_format.short_days.sunday').fetch()];
419 Date.longDays = [_kiwi.global.i18n.translate('client.libs.date_format.long_days.monday').fetch(),
420 _kiwi.global.i18n.translate('client.libs.date_format.long_days.tuesday').fetch(),
421 _kiwi.global.i18n.translate('client.libs.date_format.long_days.wednesday').fetch(),
422 _kiwi.global.i18n.translate('client.libs.date_format.long_days.thursday').fetch(),
423 _kiwi.global.i18n.translate('client.libs.date_format.long_days.friday').fetch(),
424 _kiwi.global.i18n.translate('client.libs.date_format.long_days.saturday').fetch(),
425 _kiwi.global.i18n.translate('client.libs.date_format.long_days.sunday').fetch()];
426
427 // defining patterns
428 var replaceChars = {
429 // Day
430 d: function() { return (this.getDate() < 10 ? '0' : '') + this.getDate(); },
431 D: function() { return Date.shortDays[this.getDay()]; },
432 j: function() { return this.getDate(); },
433 l: function() { return Date.longDays[this.getDay()]; },
434 N: function() { return this.getDay() + 1; },
435 S: function() { return (this.getDate() % 10 == 1 && this.getDate() != 11 ? 'st' : (this.getDate() % 10 == 2 && this.getDate() != 12 ? 'nd' : (this.getDate() % 10 == 3 && this.getDate() != 13 ? 'rd' : 'th'))); },
436 w: function() { return this.getDay(); },
437 z: function() { var d = new Date(this.getFullYear(),0,1); return Math.ceil((this - d) / 86400000); }, // Fixed now
438 // Week
439 W: function() { var d = new Date(this.getFullYear(), 0, 1); return Math.ceil((((this - d) / 86400000) + d.getDay() + 1) / 7); }, // Fixed now
440 // Month
441 F: function() { return Date.longMonths[this.getMonth()]; },
442 m: function() { return (this.getMonth() < 9 ? '0' : '') + (this.getMonth() + 1); },
443 M: function() { return Date.shortMonths[this.getMonth()]; },
444 n: function() { return this.getMonth() + 1; },
445 t: function() { var d = new Date(); return new Date(d.getFullYear(), d.getMonth(), 0).getDate() }, // Fixed now, gets #days of date
446 // Year
447 L: function() { var year = this.getFullYear(); return (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)); }, // Fixed now
448 o: function() { var d = new Date(this.valueOf()); d.setDate(d.getDate() - ((this.getDay() + 6) % 7) + 3); return d.getFullYear();}, //Fixed now
449 Y: function() { return this.getFullYear(); },
450 y: function() { return ('' + this.getFullYear()).substr(2); },
451 // Time
452 a: function() { return this.getHours() < 12 ? 'am' : 'pm'; },
453 A: function() { return this.getHours() < 12 ? 'AM' : 'PM'; },
454 B: function() { return Math.floor((((this.getUTCHours() + 1) % 24) + this.getUTCMinutes() / 60 + this.getUTCSeconds() / 3600) * 1000 / 24); }, // Fixed now
455 g: function() { return this.getHours() % 12 || 12; },
456 G: function() { return this.getHours(); },
457 h: function() { return ((this.getHours() % 12 || 12) < 10 ? '0' : '') + (this.getHours() % 12 || 12); },
458 H: function() { return (this.getHours() < 10 ? '0' : '') + this.getHours(); },
459 i: function() { return (this.getMinutes() < 10 ? '0' : '') + this.getMinutes(); },
460 s: function() { return (this.getSeconds() < 10 ? '0' : '') + this.getSeconds(); },
461 u: function() { var m = this.getMilliseconds(); return (m < 10 ? '00' : (m < 100 ?
462 '0' : '')) + m; },
463 // Timezone
464 e: function() { return "Not Yet Supported"; },
465 I: function() {
466 var DST = null;
467 for (var i = 0; i < 12; ++i) {
468 var d = new Date(this.getFullYear(), i, 1);
469 var offset = d.getTimezoneOffset();
470
471 if (DST === null) DST = offset;
472 else if (offset < DST) { DST = offset; break; } else if (offset > DST) break;
473 }
474 return (this.getTimezoneOffset() == DST) | 0;
475 },
476 O: function() { return (-this.getTimezoneOffset() < 0 ? '-' : '+') + (Math.abs(this.getTimezoneOffset() / 60) < 10 ? '0' : '') + (Math.abs(this.getTimezoneOffset() / 60)) + '00'; },
477 P: function() { return (-this.getTimezoneOffset() < 0 ? '-' : '+') + (Math.abs(this.getTimezoneOffset() / 60) < 10 ? '0' : '') + (Math.abs(this.getTimezoneOffset() / 60)) + ':00'; }, // Fixed now
478 T: function() { var m = this.getMonth(); this.setMonth(0); var result = this.toTimeString().replace(/^.+ \(?([^\)]+)\)?$/, '$1'); this.setMonth(m); return result;},
479 Z: function() { return -this.getTimezoneOffset() * 60; },
480 // Full Date/Time
481 c: function() { return this.format("Y-m-d\\TH:i:sP"); }, // Fixed now
482 r: function() { return this.toString(); },
483 U: function() { return this.getTime() / 1000; }
484 };
485
486 // Simulates PHP's date function
487 Date.prototype.format = function(format) {
488 var date = this;
489 return format.replace(/(\\?)(.)/g, function(_, esc, chr) {
490 return (esc === '' && replaceChars[chr]) ? replaceChars[chr].call(date) : chr;
491 });
492 };
493 /* End of date.format */
494
51a4c383 495 d = d || new Date();
4cdfa487 496 return d.format(_kiwi.global.i18n.translate('client_date_format').fetch());
0260a968
JA
497}
498
499function escapeRegex (str) {
500 return str.replace(/[\[\\\^\$\.\|\?\*\+\(\)]/g, '\\$&');
501}
2eacc942
JA
502
503function emoticonFromText(str) {
504 var words_in = str.split(' '),
505 words_out = [],
506 i,
e62f5be1
D
507 pushEmoticon = function (alt, emote_name) {
508 words_out.push('<i class="emoticon ' + emote_name + '">' + alt + '</i>');
2eacc942
JA
509 };
510
511 for (i = 0; i < words_in.length; i++) {
512 switch(words_in[i]) {
513 case ':)':
e62f5be1 514 pushEmoticon(':)', 'smile');
2eacc942
JA
515 break;
516 case ':(':
e62f5be1 517 pushEmoticon(':(', 'sad');
2eacc942
JA
518 break;
519 case ':3':
e62f5be1 520 pushEmoticon(':3', 'lion');
2eacc942
JA
521 break;
522 case ';3':
e62f5be1 523 pushEmoticon(';3', 'winky_lion');
2eacc942
JA
524 break;
525 case ':s':
e62f5be1
D
526 case ':S':
527 pushEmoticon(':s', 'confused');
2eacc942
JA
528 break;
529 case ';(':
e62f5be1
D
530 case ';_;':
531 pushEmoticon(';(', 'cry');
2eacc942
JA
532 break;
533 case ';)':
e62f5be1 534 pushEmoticon(';)', 'wink');
2eacc942
JA
535 break;
536 case ';D':
e62f5be1 537 pushEmoticon(';D"', 'wink_happy');
2eacc942
JA
538 break;
539 case ':P':
e62f5be1
D
540 case ':p':
541 pushEmoticon(':P', 'tongue');
2eacc942
JA
542 break;
543 case 'xP':
e62f5be1 544 pushEmoticon('xP', 'cringe_tongue');
2eacc942
JA
545 break;
546 case ':o':
547 case ':O':
e62f5be1
D
548 case ':0':
549 pushEmoticon(':o', 'shocked');
2eacc942
JA
550 break;
551 case ':D':
e62f5be1 552 pushEmoticon(':D', 'happy');
2eacc942 553 break;
e62f5be1
D
554 case '^^':
555 case '^.^':
556 pushEmoticon('^^,', 'eyebrows');
2eacc942
JA
557 break;
558 case '&lt;3':
e62f5be1 559 pushEmoticon('<3', 'heart');
2eacc942
JA
560 break;
561 case '&gt;_&lt;':
e62f5be1
D
562 case '&gt;.&lt;':
563 pushEmoticon('>_<', 'doh');
2eacc942
JA
564 break;
565 case 'XD':
566 case 'xD':
e62f5be1 567 pushEmoticon('xD', 'big_grin');
2eacc942
JA
568 break;
569 case 'o.0':
e62f5be1
D
570 case 'o.O':
571 pushEmoticon('o.0', 'wide_eye_right');
2eacc942
JA
572 break;
573 case '0.o':
e62f5be1
D
574 case 'O.o':
575 pushEmoticon('0.o', 'wide_eye_left');
2eacc942
JA
576 break;
577 case ':\\':
578 case '=\\':
2eacc942
JA
579 case ':/':
580 case '=/':
e62f5be1 581 pushEmoticon(':\\', 'unsure');
2eacc942
JA
582 break;
583 default:
584 words_out.push(words_in[i]);
585 }
586 }
587
588 return words_out.join(' ');
589}
697a76c5
JA
590
591// Code based on http://anentropic.wordpress.com/2009/06/25/javascript-iso8601-parser-and-pretty-dates/#comment-154
592function parseISO8601(str) {
593 if (Date.prototype.toISOString) {
594 return new Date(str);
595 } else {
596 var parts = str.split('T'),
597 dateParts = parts[0].split('-'),
598 timeParts = parts[1].split('Z'),
599 timeSubParts = timeParts[0].split(':'),
600 timeSecParts = timeSubParts[2].split('.'),
601 timeHours = Number(timeSubParts[0]),
602 _date = new Date();
603
604 _date.setUTCFullYear(Number(dateParts[0]));
605 _date.setUTCDate(1);
606 _date.setUTCMonth(Number(dateParts[1])-1);
607 _date.setUTCDate(Number(dateParts[2]));
608 _date.setUTCHours(Number(timeHours));
609 _date.setUTCMinutes(Number(timeSubParts[1]));
610 _date.setUTCSeconds(Number(timeSecParts[0]));
611 if (timeSecParts[1]) {
612 _date.setUTCMilliseconds(Number(timeSecParts[1]));
613 }
614
615 return _date;
616 }
617}