src/backgrid_modules/formatters/datetime.js   A
last analyzed

Complexity

Total Complexity 29
Complexity/F 7.25

Size

Lines of Code 147
Function Count 4

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 0
c 2
b 0
f 0
nc 2097152
dl 0
loc 147
rs 10
wmc 29
mnd 3
bc 12
fnc 4
bpm 3
cpm 7.25
noi 20

4 Functions

Rating   Name   Duplication   Size   Complexity  
A _.extend.toRaw 0 3 1
F _.extend._convert 0 53 22
A datetime.js ➔ DatetimeFormatter 0 7 3
A _.extend.fromRaw 0 4 3
1
import _ from 'underscore';
0 ignored issues
show
introduced by
Definition for rule 'keyword-spacing' was not found
Loading history...
2
import {
3
  lpad
4
} from '../core.js';
5
import {
6
  CellFormatter
7
} from './cell.js';
8
/**
9
   Formatter to converts between various datetime formats.
10
11
   This class only understands ISO-8601 formatted datetime strings and UNIX
12
   offset (number of milliseconds since UNIX Epoch). See
13
   Backgrid.Extension.MomentFormatter if you need a much more flexible datetime
14
   formatter.
15
16
   @class Backgrid.DatetimeFormatter
17
   @extends Backgrid.CellFormatter
18
   @constructor
19
   @throws {Error} If both `includeDate` and `includeTime` are false.
20
*/
21
var DatetimeFormatter = function (options) {
22
  _.extend(this, this.defaults, options || {});
23
24
  if (!this.includeDate && !this.includeTime) {
25
    throw new Error("Either includeDate or includeTime must be true");
26
  }
27
};
28
DatetimeFormatter.prototype = new CellFormatter();
29
_.extend(DatetimeFormatter.prototype, {
30
31
  /**
32
     @member Backgrid.DatetimeFormatter
33
34
     @cfg {Object} options
35
36
     @cfg {boolean} [options.includeDate=true] Whether the values include the
37
     date part.
38
39
     @cfg {boolean} [options.includeTime=true] Whether the values include the
40
     time part.
41
42
     @cfg {boolean} [options.includeMilli=false] If `includeTime` is true,
43
     whether to include the millisecond part, if it exists.
44
   */
45
  defaults: {
46
    includeDate: true,
47
    includeTime: true,
48
    includeMilli: false
49
  },
50
51
  DATE_RE: /^([+\-]?\d{4})-(\d{2})-(\d{2})$/,
52
  TIME_RE: /^(\d{2}):(\d{2}):(\d{2})(\.(\d{3}))?$/,
53
  ISO_SPLITTER_RE: /T|Z| +/,
54
55
  _convert: function (data, validate) {
56
    if ((data + '').trim() === '') return null;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
57
58
    var date, time = null;
0 ignored issues
show
Unused Code introduced by
The assignment to time seems to be never used. If you intend to free memory here, this is not necessary since the variable leaves the scope anyway.
Loading history...
59
    if (_.isNumber(data)) {
60
      var jsDate = new Date(data);
61
      date = lpad(jsDate.getUTCFullYear(), 4, 0) + '-' + lpad(jsDate.getUTCMonth() + 1, 2, 0) + '-' + lpad(jsDate.getUTCDate(), 2, 0);
62
      time = lpad(jsDate.getUTCHours(), 2, 0) + ':' + lpad(jsDate.getUTCMinutes(), 2, 0) + ':' + lpad(jsDate.getUTCSeconds(), 2, 0);
63
    } else {
64
      data = data.trim();
65
      var parts = data.split(this.ISO_SPLITTER_RE) || [];
66
      date = this.DATE_RE.test(parts[0]) ? parts[0] : '';
67
      time = date && parts[1] ? parts[1] : this.TIME_RE.test(parts[0]) ? parts[0] : '';
0 ignored issues
show
introduced by
Do not nest ternary expressions
Loading history...
68
    }
69
70
    var YYYYMMDD = this.DATE_RE.exec(date) || [];
71
    var HHmmssSSS = this.TIME_RE.exec(time) || [];
72
73
    if (validate) {
74
      if (this.includeDate && _.isUndefined(YYYYMMDD[0])) return;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
75
      if (this.includeTime && _.isUndefined(HHmmssSSS[0])) return;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
76
      if (!this.includeDate && date) return;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
77
      if (!this.includeTime && time) return;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
78
    }
79
80
    var jsDate = new Date(Date.UTC(YYYYMMDD[1] * 1 || 0,
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable jsDate already seems to be declared on line 60. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
introduced by
"jsDate" is already defined
Loading history...
81
      YYYYMMDD[2] * 1 - 1 || 0,
82
      YYYYMMDD[3] * 1 || 0,
83
      HHmmssSSS[1] * 1 || null,
84
      HHmmssSSS[2] * 1 || null,
85
      HHmmssSSS[3] * 1 || null,
86
      HHmmssSSS[5] * 1 || null));
87
88
    var result = '';
89
90
    if (this.includeDate) {
91
      result = lpad(jsDate.getUTCFullYear(), 4, 0) + '-' + lpad(jsDate.getUTCMonth() + 1, 2, 0) + '-' + lpad(jsDate.getUTCDate(), 2, 0);
92
    }
93
94
    if (this.includeTime) {
95
      result = result + (this.includeDate ? 'T' : '') + lpad(jsDate.getUTCHours(), 2, 0) + ':' + lpad(jsDate.getUTCMinutes(), 2, 0) + ':' + lpad(jsDate.getUTCSeconds(), 2, 0);
0 ignored issues
show
Coding Style introduced by
This line exceeds the maximum configured line length of 150.
Loading history...
96
97
      if (this.includeMilli) {
98
        result = result + '.' + lpad(jsDate.getUTCMilliseconds(), 3, 0);
99
      }
100
    }
101
102
    if (this.includeDate && this.includeTime) {
103
      result += "Z";
104
    }
105
106
    return result;
107
  },
108
109
  /**
110
     Converts an ISO-8601 formatted datetime string to a datetime string, date
111
     string or a time string. The timezone is ignored if supplied.
112
113
     @member Backgrid.DatetimeFormatter
114
     @param {string} rawData
115
     @param {Backbone.Model} model Used for more complicated formatting
116
     @return {string|null|undefined} ISO-8601 string in UTC. Null and undefined
117
     values are returned as is.
118
  */
119
  fromRaw: function (rawData, model) {
0 ignored issues
show
Unused Code introduced by
The parameter model is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
120
    if (_.isNull(rawData) || _.isUndefined(rawData)) return '';
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
121
    return this._convert(rawData);
122
  },
123
124
  /**
125
     Converts an ISO-8601 formatted datetime string to a datetime string, date
126
     string or a time string. The timezone is ignored if supplied. This method
127
     parses the input values exactly the same way as
128
     Backgrid.Extension.MomentFormatter#fromRaw(), in addition to doing some
129
     sanity checks.
130
131
     @member Backgrid.DatetimeFormatter
132
     @param {string} formattedData
133
     @param {Backbone.Model} model Used for more complicated formatting
134
     @return {string|undefined} ISO-8601 string in UTC. Undefined if a date is
135
     found when `includeDate` is false, or a time is found when `includeTime` is
136
     false, or if `includeDate` is true and a date is not found, or if
137
     `includeTime` is true and a time is not found.
138
  */
139
  toRaw: function (formattedData, model) {
0 ignored issues
show
Unused Code introduced by
The parameter model is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
140
    return this._convert(formattedData, true);
141
  }
142
143
});
144
145
export {
146
  DatetimeFormatter
147
};
148