chiropractor 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +46 -0
- data/Rakefile +22 -0
- data/chiropractor.gemspec +24 -0
- data/lib/chiropractor.rb +11 -0
- data/lib/chiropractor/engine.rb +6 -0
- data/lib/chiropractor/version.rb +3 -0
- data/vendor/assets/javascripts/chiropractor/Backbone.ModelBinder.js +482 -0
- data/vendor/assets/javascripts/chiropractor/accounting.js +412 -0
- data/vendor/assets/javascripts/chiropractor/backbone-relational.js +1687 -0
- data/vendor/assets/javascripts/chiropractor/backbone.jst.js +7 -0
- data/vendor/assets/javascripts/chiropractor/backbone.layoutRegion.coffee +75 -0
- data/vendor/assets/javascripts/chiropractor/index.js +13 -0
- data/vendor/assets/javascripts/chiropractor/moment.js +1213 -0
- data/vendor/assets/javascripts/chiropractor/underscore.inflection.js +176 -0
- data/vendor/assets/javascripts/chiropractor/underscore.string.js +613 -0
- metadata +133 -0
@@ -0,0 +1,75 @@
|
|
1
|
+
class Backbone.Marionette.Outlet extends Backbone.Events
|
2
|
+
|
3
|
+
constructor: (options = {}) ->
|
4
|
+
_.extend(this, options)
|
5
|
+
|
6
|
+
@currentView = null
|
7
|
+
throw "must specify el" unless @el.length
|
8
|
+
@$el = @el
|
9
|
+
this
|
10
|
+
|
11
|
+
show: (view) ->
|
12
|
+
view.render()
|
13
|
+
@attach(view, false)
|
14
|
+
|
15
|
+
make: (tagName) ->
|
16
|
+
jQuery(document.createElement(tagName))
|
17
|
+
|
18
|
+
|
19
|
+
attach: (view, reTriggerRender = true) ->
|
20
|
+
# need to replace this with an empty element so that we keep our place
|
21
|
+
placeholder = @make("div")
|
22
|
+
|
23
|
+
# ok, so do the replacing here
|
24
|
+
@$el.replaceWith(placeholder)
|
25
|
+
|
26
|
+
# be nice and neat, the view if there was one
|
27
|
+
@currentView?.close()
|
28
|
+
|
29
|
+
# yay, a new view
|
30
|
+
@currentView = view
|
31
|
+
return unless view
|
32
|
+
|
33
|
+
# questionable, this needs more thought but I'm leaving it in
|
34
|
+
# basically, there's no clear lifecycle defined so until there is
|
35
|
+
# this needs to be here
|
36
|
+
view.trigger("render") if reTriggerRender
|
37
|
+
|
38
|
+
# now that we've made sure it's had all the time it needs to
|
39
|
+
# render and all that, replace the placeholder
|
40
|
+
placeholder.replaceWith(view.el)
|
41
|
+
@$el = view.$el
|
42
|
+
|
43
|
+
# now do the callbacks
|
44
|
+
view.onShow() if _.isFunction(view.onShow)
|
45
|
+
view.trigger("show")
|
46
|
+
|
47
|
+
close: ->
|
48
|
+
placeHolder = @make("div")
|
49
|
+
@$el.replaceWith(placeHolder)
|
50
|
+
@$el = placeHolder
|
51
|
+
|
52
|
+
if @currentView && _.isFunction(@currentView.close)
|
53
|
+
@currentView.close()
|
54
|
+
|
55
|
+
|
56
|
+
class Backbone.Marionette.LayoutRegion extends Backbone.Marionette.Layout
|
57
|
+
constructor: (options = {}) ->
|
58
|
+
super(options)
|
59
|
+
@bindTo(this, "render", @initializeOutlets, this)
|
60
|
+
|
61
|
+
initializeOutlets: ->
|
62
|
+
return unless @outlets
|
63
|
+
|
64
|
+
@outletBindings = @outlets
|
65
|
+
@outlets = {}
|
66
|
+
|
67
|
+
_(@outletBindings).each (selector, name) =>
|
68
|
+
@outlets[name] = new Backbone.Marionette.Outlet(el: @$(selector))
|
69
|
+
|
70
|
+
close: () ->
|
71
|
+
_(@outlets).each (outlet, name) ->
|
72
|
+
outlet.close()
|
73
|
+
|
74
|
+
super()
|
75
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
//= require jquery
|
2
|
+
//= require jquery_ujs
|
3
|
+
//= require underscore
|
4
|
+
//= require ./underscore.string
|
5
|
+
//= require ./underscore.inflection
|
6
|
+
//= require backbone
|
7
|
+
//= require backbone.marionette
|
8
|
+
//= require ./Backbone.ModelBinder
|
9
|
+
//= require ./backbone-relational
|
10
|
+
//= require ./backbone.layoutRegion
|
11
|
+
//= require ./backbone.jst
|
12
|
+
//= require ./moment
|
13
|
+
//= require ./accounting
|
@@ -0,0 +1,1213 @@
|
|
1
|
+
// moment.js
|
2
|
+
// version : 1.7.2
|
3
|
+
// author : Tim Wood
|
4
|
+
// license : MIT
|
5
|
+
// momentjs.com
|
6
|
+
|
7
|
+
(function (undefined) {
|
8
|
+
|
9
|
+
/************************************
|
10
|
+
Constants
|
11
|
+
************************************/
|
12
|
+
|
13
|
+
var moment,
|
14
|
+
VERSION = "1.7.2",
|
15
|
+
round = Math.round, i,
|
16
|
+
// internal storage for language config files
|
17
|
+
languages = {},
|
18
|
+
currentLanguage = 'en',
|
19
|
+
|
20
|
+
// check for nodeJS
|
21
|
+
hasModule = (typeof module !== 'undefined' && module.exports),
|
22
|
+
|
23
|
+
// Parameters to check for on the lang config. This list of properties
|
24
|
+
// will be inherited from English if not provided in a language
|
25
|
+
// definition. monthsParse is also a lang config property, but it
|
26
|
+
// cannot be inherited and as such cannot be enumerated here.
|
27
|
+
langConfigProperties = 'months|monthsShort|weekdays|weekdaysShort|weekdaysMin|longDateFormat|calendar|relativeTime|ordinal|meridiem'.split('|'),
|
28
|
+
|
29
|
+
// ASP.NET json date format regex
|
30
|
+
aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
|
31
|
+
|
32
|
+
// format tokens
|
33
|
+
formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|zz?|ZZ?|.)/g,
|
34
|
+
localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?)/g,
|
35
|
+
|
36
|
+
// parsing tokens
|
37
|
+
parseMultipleFormatChunker = /([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi,
|
38
|
+
|
39
|
+
// parsing token regexes
|
40
|
+
parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99
|
41
|
+
parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999
|
42
|
+
parseTokenThreeDigits = /\d{3}/, // 000 - 999
|
43
|
+
parseTokenFourDigits = /\d{1,4}/, // 0 - 9999
|
44
|
+
parseTokenWord = /[0-9a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+/i, // any word characters or numbers
|
45
|
+
parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/i, // +00:00 -00:00 +0000 -0000 or Z
|
46
|
+
parseTokenT = /T/i, // T (ISO seperator)
|
47
|
+
|
48
|
+
// preliminary iso regex
|
49
|
+
// 0000-00-00 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000
|
50
|
+
isoRegex = /^\s*\d{4}-\d\d-\d\d(T(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,
|
51
|
+
isoFormat = 'YYYY-MM-DDTHH:mm:ssZ',
|
52
|
+
|
53
|
+
// iso time formats and regexes
|
54
|
+
isoTimes = [
|
55
|
+
['HH:mm:ss.S', /T\d\d:\d\d:\d\d\.\d{1,3}/],
|
56
|
+
['HH:mm:ss', /T\d\d:\d\d:\d\d/],
|
57
|
+
['HH:mm', /T\d\d:\d\d/],
|
58
|
+
['HH', /T\d\d/]
|
59
|
+
],
|
60
|
+
|
61
|
+
// timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"]
|
62
|
+
parseTimezoneChunker = /([\+\-]|\d\d)/gi,
|
63
|
+
|
64
|
+
// getter and setter names
|
65
|
+
proxyGettersAndSetters = 'Month|Date|Hours|Minutes|Seconds|Milliseconds'.split('|'),
|
66
|
+
unitMillisecondFactors = {
|
67
|
+
'Milliseconds' : 1,
|
68
|
+
'Seconds' : 1e3,
|
69
|
+
'Minutes' : 6e4,
|
70
|
+
'Hours' : 36e5,
|
71
|
+
'Days' : 864e5,
|
72
|
+
'Months' : 2592e6,
|
73
|
+
'Years' : 31536e6
|
74
|
+
},
|
75
|
+
|
76
|
+
// format function strings
|
77
|
+
formatFunctions = {},
|
78
|
+
|
79
|
+
// tokens to ordinalize and pad
|
80
|
+
ordinalizeTokens = 'DDD w M D d'.split(' '),
|
81
|
+
paddedTokens = 'M D H h m s w'.split(' '),
|
82
|
+
|
83
|
+
/*
|
84
|
+
* moment.fn.format uses new Function() to create an inlined formatting function.
|
85
|
+
* Results are a 3x speed boost
|
86
|
+
* http://jsperf.com/momentjs-cached-format-functions
|
87
|
+
*
|
88
|
+
* These strings are appended into a function using replaceFormatTokens and makeFormatFunction
|
89
|
+
*/
|
90
|
+
formatTokenFunctions = {
|
91
|
+
// a = placeholder
|
92
|
+
// b = placeholder
|
93
|
+
// t = the current moment being formatted
|
94
|
+
// v = getValueAtKey function
|
95
|
+
// o = language.ordinal function
|
96
|
+
// p = leftZeroFill function
|
97
|
+
// m = language.meridiem value or function
|
98
|
+
M : function () {
|
99
|
+
return this.month() + 1;
|
100
|
+
},
|
101
|
+
MMM : function (format) {
|
102
|
+
return getValueFromArray("monthsShort", this.month(), this, format);
|
103
|
+
},
|
104
|
+
MMMM : function (format) {
|
105
|
+
return getValueFromArray("months", this.month(), this, format);
|
106
|
+
},
|
107
|
+
D : function () {
|
108
|
+
return this.date();
|
109
|
+
},
|
110
|
+
DDD : function () {
|
111
|
+
var a = new Date(this.year(), this.month(), this.date()),
|
112
|
+
b = new Date(this.year(), 0, 1);
|
113
|
+
return ~~(((a - b) / 864e5) + 1.5);
|
114
|
+
},
|
115
|
+
d : function () {
|
116
|
+
return this.day();
|
117
|
+
},
|
118
|
+
dd : function (format) {
|
119
|
+
return getValueFromArray("weekdaysMin", this.day(), this, format);
|
120
|
+
},
|
121
|
+
ddd : function (format) {
|
122
|
+
return getValueFromArray("weekdaysShort", this.day(), this, format);
|
123
|
+
},
|
124
|
+
dddd : function (format) {
|
125
|
+
return getValueFromArray("weekdays", this.day(), this, format);
|
126
|
+
},
|
127
|
+
w : function () {
|
128
|
+
var a = new Date(this.year(), this.month(), this.date() - this.day() + 5),
|
129
|
+
b = new Date(a.getFullYear(), 0, 4);
|
130
|
+
return ~~((a - b) / 864e5 / 7 + 1.5);
|
131
|
+
},
|
132
|
+
YY : function () {
|
133
|
+
return leftZeroFill(this.year() % 100, 2);
|
134
|
+
},
|
135
|
+
YYYY : function () {
|
136
|
+
return leftZeroFill(this.year(), 4);
|
137
|
+
},
|
138
|
+
a : function () {
|
139
|
+
return this.lang().meridiem(this.hours(), this.minutes(), true);
|
140
|
+
},
|
141
|
+
A : function () {
|
142
|
+
return this.lang().meridiem(this.hours(), this.minutes(), false);
|
143
|
+
},
|
144
|
+
H : function () {
|
145
|
+
return this.hours();
|
146
|
+
},
|
147
|
+
h : function () {
|
148
|
+
return this.hours() % 12 || 12;
|
149
|
+
},
|
150
|
+
m : function () {
|
151
|
+
return this.minutes();
|
152
|
+
},
|
153
|
+
s : function () {
|
154
|
+
return this.seconds();
|
155
|
+
},
|
156
|
+
S : function () {
|
157
|
+
return ~~(this.milliseconds() / 100);
|
158
|
+
},
|
159
|
+
SS : function () {
|
160
|
+
return leftZeroFill(~~(this.milliseconds() / 10), 2);
|
161
|
+
},
|
162
|
+
SSS : function () {
|
163
|
+
return leftZeroFill(this.milliseconds(), 3);
|
164
|
+
},
|
165
|
+
Z : function () {
|
166
|
+
var a = -this.zone(),
|
167
|
+
b = "+";
|
168
|
+
if (a < 0) {
|
169
|
+
a = -a;
|
170
|
+
b = "-";
|
171
|
+
}
|
172
|
+
return b + leftZeroFill(~~(a / 60), 2) + ":" + leftZeroFill(~~a % 60, 2);
|
173
|
+
},
|
174
|
+
ZZ : function () {
|
175
|
+
var a = -this.zone(),
|
176
|
+
b = "+";
|
177
|
+
if (a < 0) {
|
178
|
+
a = -a;
|
179
|
+
b = "-";
|
180
|
+
}
|
181
|
+
return b + leftZeroFill(~~(10 * a / 6), 4);
|
182
|
+
}
|
183
|
+
};
|
184
|
+
|
185
|
+
function getValueFromArray(key, index, m, format) {
|
186
|
+
var lang = m.lang();
|
187
|
+
return lang[key].call ? lang[key](m, format) : lang[key][index];
|
188
|
+
}
|
189
|
+
|
190
|
+
function padToken(func, count) {
|
191
|
+
return function (a) {
|
192
|
+
return leftZeroFill(func.call(this, a), count);
|
193
|
+
};
|
194
|
+
}
|
195
|
+
function ordinalizeToken(func) {
|
196
|
+
return function (a) {
|
197
|
+
var b = func.call(this, a);
|
198
|
+
return b + this.lang().ordinal(b);
|
199
|
+
};
|
200
|
+
}
|
201
|
+
|
202
|
+
while (ordinalizeTokens.length) {
|
203
|
+
i = ordinalizeTokens.pop();
|
204
|
+
formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i]);
|
205
|
+
}
|
206
|
+
while (paddedTokens.length) {
|
207
|
+
i = paddedTokens.pop();
|
208
|
+
formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2);
|
209
|
+
}
|
210
|
+
formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3);
|
211
|
+
|
212
|
+
|
213
|
+
/************************************
|
214
|
+
Constructors
|
215
|
+
************************************/
|
216
|
+
|
217
|
+
|
218
|
+
// Moment prototype object
|
219
|
+
function Moment(date, isUTC, lang) {
|
220
|
+
this._d = date;
|
221
|
+
this._isUTC = !!isUTC;
|
222
|
+
this._a = date._a || null;
|
223
|
+
this._lang = lang || false;
|
224
|
+
}
|
225
|
+
|
226
|
+
// Duration Constructor
|
227
|
+
function Duration(duration) {
|
228
|
+
var data = this._data = {},
|
229
|
+
years = duration.years || duration.y || 0,
|
230
|
+
months = duration.months || duration.M || 0,
|
231
|
+
weeks = duration.weeks || duration.w || 0,
|
232
|
+
days = duration.days || duration.d || 0,
|
233
|
+
hours = duration.hours || duration.h || 0,
|
234
|
+
minutes = duration.minutes || duration.m || 0,
|
235
|
+
seconds = duration.seconds || duration.s || 0,
|
236
|
+
milliseconds = duration.milliseconds || duration.ms || 0;
|
237
|
+
|
238
|
+
// representation for dateAddRemove
|
239
|
+
this._milliseconds = milliseconds +
|
240
|
+
seconds * 1e3 + // 1000
|
241
|
+
minutes * 6e4 + // 1000 * 60
|
242
|
+
hours * 36e5; // 1000 * 60 * 60
|
243
|
+
// Because of dateAddRemove treats 24 hours as different from a
|
244
|
+
// day when working around DST, we need to store them separately
|
245
|
+
this._days = days +
|
246
|
+
weeks * 7;
|
247
|
+
// It is impossible translate months into days without knowing
|
248
|
+
// which months you are are talking about, so we have to store
|
249
|
+
// it separately.
|
250
|
+
this._months = months +
|
251
|
+
years * 12;
|
252
|
+
|
253
|
+
// The following code bubbles up values, see the tests for
|
254
|
+
// examples of what that means.
|
255
|
+
data.milliseconds = milliseconds % 1000;
|
256
|
+
seconds += absRound(milliseconds / 1000);
|
257
|
+
|
258
|
+
data.seconds = seconds % 60;
|
259
|
+
minutes += absRound(seconds / 60);
|
260
|
+
|
261
|
+
data.minutes = minutes % 60;
|
262
|
+
hours += absRound(minutes / 60);
|
263
|
+
|
264
|
+
data.hours = hours % 24;
|
265
|
+
days += absRound(hours / 24);
|
266
|
+
|
267
|
+
days += weeks * 7;
|
268
|
+
data.days = days % 30;
|
269
|
+
|
270
|
+
months += absRound(days / 30);
|
271
|
+
|
272
|
+
data.months = months % 12;
|
273
|
+
years += absRound(months / 12);
|
274
|
+
|
275
|
+
data.years = years;
|
276
|
+
|
277
|
+
this._lang = false;
|
278
|
+
}
|
279
|
+
|
280
|
+
|
281
|
+
/************************************
|
282
|
+
Helpers
|
283
|
+
************************************/
|
284
|
+
|
285
|
+
|
286
|
+
function absRound(number) {
|
287
|
+
if (number < 0) {
|
288
|
+
return Math.ceil(number);
|
289
|
+
} else {
|
290
|
+
return Math.floor(number);
|
291
|
+
}
|
292
|
+
}
|
293
|
+
|
294
|
+
// left zero fill a number
|
295
|
+
// see http://jsperf.com/left-zero-filling for performance comparison
|
296
|
+
function leftZeroFill(number, targetLength) {
|
297
|
+
var output = number + '';
|
298
|
+
while (output.length < targetLength) {
|
299
|
+
output = '0' + output;
|
300
|
+
}
|
301
|
+
return output;
|
302
|
+
}
|
303
|
+
|
304
|
+
// helper function for _.addTime and _.subtractTime
|
305
|
+
function addOrSubtractDurationFromMoment(mom, duration, isAdding) {
|
306
|
+
var ms = duration._milliseconds,
|
307
|
+
d = duration._days,
|
308
|
+
M = duration._months,
|
309
|
+
currentDate;
|
310
|
+
|
311
|
+
if (ms) {
|
312
|
+
mom._d.setTime(+mom + ms * isAdding);
|
313
|
+
}
|
314
|
+
if (d) {
|
315
|
+
mom.date(mom.date() + d * isAdding);
|
316
|
+
}
|
317
|
+
if (M) {
|
318
|
+
currentDate = mom.date();
|
319
|
+
mom.date(1)
|
320
|
+
.month(mom.month() + M * isAdding)
|
321
|
+
.date(Math.min(currentDate, mom.daysInMonth()));
|
322
|
+
}
|
323
|
+
}
|
324
|
+
|
325
|
+
// check if is an array
|
326
|
+
function isArray(input) {
|
327
|
+
return Object.prototype.toString.call(input) === '[object Array]';
|
328
|
+
}
|
329
|
+
|
330
|
+
// compare two arrays, return the number of differences
|
331
|
+
function compareArrays(array1, array2) {
|
332
|
+
var len = Math.min(array1.length, array2.length),
|
333
|
+
lengthDiff = Math.abs(array1.length - array2.length),
|
334
|
+
diffs = 0,
|
335
|
+
i;
|
336
|
+
for (i = 0; i < len; i++) {
|
337
|
+
if (~~array1[i] !== ~~array2[i]) {
|
338
|
+
diffs++;
|
339
|
+
}
|
340
|
+
}
|
341
|
+
return diffs + lengthDiff;
|
342
|
+
}
|
343
|
+
|
344
|
+
// convert an array to a date.
|
345
|
+
// the array should mirror the parameters below
|
346
|
+
// note: all values past the year are optional and will default to the lowest possible value.
|
347
|
+
// [year, month, day , hour, minute, second, millisecond]
|
348
|
+
function dateFromArray(input, asUTC, hoursOffset, minutesOffset) {
|
349
|
+
var i, date, forValid = [];
|
350
|
+
for (i = 0; i < 7; i++) {
|
351
|
+
forValid[i] = input[i] = (input[i] == null) ? (i === 2 ? 1 : 0) : input[i];
|
352
|
+
}
|
353
|
+
// we store whether we used utc or not in the input array
|
354
|
+
input[7] = forValid[7] = asUTC;
|
355
|
+
// if the parser flagged the input as invalid, we pass the value along
|
356
|
+
if (input[8] != null) {
|
357
|
+
forValid[8] = input[8];
|
358
|
+
}
|
359
|
+
// add the offsets to the time to be parsed so that we can have a clean array
|
360
|
+
// for checking isValid
|
361
|
+
input[3] += hoursOffset || 0;
|
362
|
+
input[4] += minutesOffset || 0;
|
363
|
+
date = new Date(0);
|
364
|
+
if (asUTC) {
|
365
|
+
date.setUTCFullYear(input[0], input[1], input[2]);
|
366
|
+
date.setUTCHours(input[3], input[4], input[5], input[6]);
|
367
|
+
} else {
|
368
|
+
date.setFullYear(input[0], input[1], input[2]);
|
369
|
+
date.setHours(input[3], input[4], input[5], input[6]);
|
370
|
+
}
|
371
|
+
date._a = forValid;
|
372
|
+
return date;
|
373
|
+
}
|
374
|
+
|
375
|
+
// Loads a language definition into the `languages` cache. The function
|
376
|
+
// takes a key and optionally values. If not in the browser and no values
|
377
|
+
// are provided, it will load the language file module. As a convenience,
|
378
|
+
// this function also returns the language values.
|
379
|
+
function loadLang(key, values) {
|
380
|
+
var i, m,
|
381
|
+
parse = [];
|
382
|
+
|
383
|
+
if (!values && hasModule) {
|
384
|
+
values = require('./lang/' + key);
|
385
|
+
}
|
386
|
+
|
387
|
+
for (i = 0; i < langConfigProperties.length; i++) {
|
388
|
+
// If a language definition does not provide a value, inherit
|
389
|
+
// from English
|
390
|
+
values[langConfigProperties[i]] = values[langConfigProperties[i]] ||
|
391
|
+
languages.en[langConfigProperties[i]];
|
392
|
+
}
|
393
|
+
|
394
|
+
for (i = 0; i < 12; i++) {
|
395
|
+
m = moment([2000, i]);
|
396
|
+
parse[i] = new RegExp('^' + (values.months[i] || values.months(m, '')) +
|
397
|
+
'|^' + (values.monthsShort[i] || values.monthsShort(m, '')).replace('.', ''), 'i');
|
398
|
+
}
|
399
|
+
values.monthsParse = values.monthsParse || parse;
|
400
|
+
|
401
|
+
languages[key] = values;
|
402
|
+
|
403
|
+
return values;
|
404
|
+
}
|
405
|
+
|
406
|
+
// Determines which language definition to use and returns it.
|
407
|
+
//
|
408
|
+
// With no parameters, it will return the global language. If you
|
409
|
+
// pass in a language key, such as 'en', it will return the
|
410
|
+
// definition for 'en', so long as 'en' has already been loaded using
|
411
|
+
// moment.lang. If you pass in a moment or duration instance, it
|
412
|
+
// will decide the language based on that, or default to the global
|
413
|
+
// language.
|
414
|
+
function getLangDefinition(m) {
|
415
|
+
var langKey = (typeof m === 'string') && m ||
|
416
|
+
m && m._lang ||
|
417
|
+
null;
|
418
|
+
|
419
|
+
return langKey ? (languages[langKey] || loadLang(langKey)) : moment;
|
420
|
+
}
|
421
|
+
|
422
|
+
|
423
|
+
/************************************
|
424
|
+
Formatting
|
425
|
+
************************************/
|
426
|
+
|
427
|
+
|
428
|
+
function removeFormattingTokens(input) {
|
429
|
+
if (input.match(/\[.*\]/)) {
|
430
|
+
return input.replace(/^\[|\]$/g, "");
|
431
|
+
}
|
432
|
+
return input.replace(/\\/g, "");
|
433
|
+
}
|
434
|
+
|
435
|
+
function makeFormatFunction(format) {
|
436
|
+
var array = format.match(formattingTokens), i, length;
|
437
|
+
|
438
|
+
for (i = 0, length = array.length; i < length; i++) {
|
439
|
+
if (formatTokenFunctions[array[i]]) {
|
440
|
+
array[i] = formatTokenFunctions[array[i]];
|
441
|
+
} else {
|
442
|
+
array[i] = removeFormattingTokens(array[i]);
|
443
|
+
}
|
444
|
+
}
|
445
|
+
|
446
|
+
return function (mom) {
|
447
|
+
var output = "";
|
448
|
+
for (i = 0; i < length; i++) {
|
449
|
+
output += typeof array[i].call === 'function' ? array[i].call(mom, format) : array[i];
|
450
|
+
}
|
451
|
+
return output;
|
452
|
+
};
|
453
|
+
}
|
454
|
+
|
455
|
+
// format date using native date object
|
456
|
+
function formatMoment(m, format) {
|
457
|
+
var i = 5;
|
458
|
+
|
459
|
+
function replaceLongDateFormatTokens(input) {
|
460
|
+
return m.lang().longDateFormat[input] || input;
|
461
|
+
}
|
462
|
+
|
463
|
+
while (i-- && localFormattingTokens.test(format)) {
|
464
|
+
format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
|
465
|
+
}
|
466
|
+
|
467
|
+
if (!formatFunctions[format]) {
|
468
|
+
formatFunctions[format] = makeFormatFunction(format);
|
469
|
+
}
|
470
|
+
|
471
|
+
return formatFunctions[format](m);
|
472
|
+
}
|
473
|
+
|
474
|
+
|
475
|
+
/************************************
|
476
|
+
Parsing
|
477
|
+
************************************/
|
478
|
+
|
479
|
+
|
480
|
+
// get the regex to find the next token
|
481
|
+
function getParseRegexForToken(token) {
|
482
|
+
switch (token) {
|
483
|
+
case 'DDDD':
|
484
|
+
return parseTokenThreeDigits;
|
485
|
+
case 'YYYY':
|
486
|
+
return parseTokenFourDigits;
|
487
|
+
case 'S':
|
488
|
+
case 'SS':
|
489
|
+
case 'SSS':
|
490
|
+
case 'DDD':
|
491
|
+
return parseTokenOneToThreeDigits;
|
492
|
+
case 'MMM':
|
493
|
+
case 'MMMM':
|
494
|
+
case 'dd':
|
495
|
+
case 'ddd':
|
496
|
+
case 'dddd':
|
497
|
+
case 'a':
|
498
|
+
case 'A':
|
499
|
+
return parseTokenWord;
|
500
|
+
case 'Z':
|
501
|
+
case 'ZZ':
|
502
|
+
return parseTokenTimezone;
|
503
|
+
case 'T':
|
504
|
+
return parseTokenT;
|
505
|
+
case 'MM':
|
506
|
+
case 'DD':
|
507
|
+
case 'YY':
|
508
|
+
case 'HH':
|
509
|
+
case 'hh':
|
510
|
+
case 'mm':
|
511
|
+
case 'ss':
|
512
|
+
case 'M':
|
513
|
+
case 'D':
|
514
|
+
case 'd':
|
515
|
+
case 'H':
|
516
|
+
case 'h':
|
517
|
+
case 'm':
|
518
|
+
case 's':
|
519
|
+
return parseTokenOneOrTwoDigits;
|
520
|
+
default :
|
521
|
+
return new RegExp(token.replace('\\', ''));
|
522
|
+
}
|
523
|
+
}
|
524
|
+
|
525
|
+
// function to convert string input to date
|
526
|
+
function addTimeToArrayFromToken(token, input, datePartArray, config) {
|
527
|
+
var a, b;
|
528
|
+
|
529
|
+
switch (token) {
|
530
|
+
// MONTH
|
531
|
+
case 'M' : // fall through to MM
|
532
|
+
case 'MM' :
|
533
|
+
datePartArray[1] = (input == null) ? 0 : ~~input - 1;
|
534
|
+
break;
|
535
|
+
case 'MMM' : // fall through to MMMM
|
536
|
+
case 'MMMM' :
|
537
|
+
for (a = 0; a < 12; a++) {
|
538
|
+
if (getLangDefinition().monthsParse[a].test(input)) {
|
539
|
+
datePartArray[1] = a;
|
540
|
+
b = true;
|
541
|
+
break;
|
542
|
+
}
|
543
|
+
}
|
544
|
+
// if we didn't find a month name, mark the date as invalid.
|
545
|
+
if (!b) {
|
546
|
+
datePartArray[8] = false;
|
547
|
+
}
|
548
|
+
break;
|
549
|
+
// DAY OF MONTH
|
550
|
+
case 'D' : // fall through to DDDD
|
551
|
+
case 'DD' : // fall through to DDDD
|
552
|
+
case 'DDD' : // fall through to DDDD
|
553
|
+
case 'DDDD' :
|
554
|
+
if (input != null) {
|
555
|
+
datePartArray[2] = ~~input;
|
556
|
+
}
|
557
|
+
break;
|
558
|
+
// YEAR
|
559
|
+
case 'YY' :
|
560
|
+
datePartArray[0] = ~~input + (~~input > 70 ? 1900 : 2000);
|
561
|
+
break;
|
562
|
+
case 'YYYY' :
|
563
|
+
datePartArray[0] = ~~Math.abs(input);
|
564
|
+
break;
|
565
|
+
// AM / PM
|
566
|
+
case 'a' : // fall through to A
|
567
|
+
case 'A' :
|
568
|
+
config.isPm = ((input + '').toLowerCase() === 'pm');
|
569
|
+
break;
|
570
|
+
// 24 HOUR
|
571
|
+
case 'H' : // fall through to hh
|
572
|
+
case 'HH' : // fall through to hh
|
573
|
+
case 'h' : // fall through to hh
|
574
|
+
case 'hh' :
|
575
|
+
datePartArray[3] = ~~input;
|
576
|
+
break;
|
577
|
+
// MINUTE
|
578
|
+
case 'm' : // fall through to mm
|
579
|
+
case 'mm' :
|
580
|
+
datePartArray[4] = ~~input;
|
581
|
+
break;
|
582
|
+
// SECOND
|
583
|
+
case 's' : // fall through to ss
|
584
|
+
case 'ss' :
|
585
|
+
datePartArray[5] = ~~input;
|
586
|
+
break;
|
587
|
+
// MILLISECOND
|
588
|
+
case 'S' :
|
589
|
+
case 'SS' :
|
590
|
+
case 'SSS' :
|
591
|
+
datePartArray[6] = ~~ (('0.' + input) * 1000);
|
592
|
+
break;
|
593
|
+
// TIMEZONE
|
594
|
+
case 'Z' : // fall through to ZZ
|
595
|
+
case 'ZZ' :
|
596
|
+
config.isUTC = true;
|
597
|
+
a = (input + '').match(parseTimezoneChunker);
|
598
|
+
if (a && a[1]) {
|
599
|
+
config.tzh = ~~a[1];
|
600
|
+
}
|
601
|
+
if (a && a[2]) {
|
602
|
+
config.tzm = ~~a[2];
|
603
|
+
}
|
604
|
+
// reverse offsets
|
605
|
+
if (a && a[0] === '+') {
|
606
|
+
config.tzh = -config.tzh;
|
607
|
+
config.tzm = -config.tzm;
|
608
|
+
}
|
609
|
+
break;
|
610
|
+
}
|
611
|
+
|
612
|
+
// if the input is null, the date is not valid
|
613
|
+
if (input == null) {
|
614
|
+
datePartArray[8] = false;
|
615
|
+
}
|
616
|
+
}
|
617
|
+
|
618
|
+
// date from string and format string
|
619
|
+
function makeDateFromStringAndFormat(string, format) {
|
620
|
+
// This array is used to make a Date, either with `new Date` or `Date.UTC`
|
621
|
+
// We store some additional data on the array for validation
|
622
|
+
// datePartArray[7] is true if the Date was created with `Date.UTC` and false if created with `new Date`
|
623
|
+
// datePartArray[8] is false if the Date is invalid, and undefined if the validity is unknown.
|
624
|
+
var datePartArray = [0, 0, 1, 0, 0, 0, 0],
|
625
|
+
config = {
|
626
|
+
tzh : 0, // timezone hour offset
|
627
|
+
tzm : 0 // timezone minute offset
|
628
|
+
},
|
629
|
+
tokens = format.match(formattingTokens),
|
630
|
+
i, parsedInput;
|
631
|
+
|
632
|
+
for (i = 0; i < tokens.length; i++) {
|
633
|
+
parsedInput = (getParseRegexForToken(tokens[i]).exec(string) || [])[0];
|
634
|
+
if (parsedInput) {
|
635
|
+
string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
|
636
|
+
}
|
637
|
+
// don't parse if its not a known token
|
638
|
+
if (formatTokenFunctions[tokens[i]]) {
|
639
|
+
addTimeToArrayFromToken(tokens[i], parsedInput, datePartArray, config);
|
640
|
+
}
|
641
|
+
}
|
642
|
+
// handle am pm
|
643
|
+
if (config.isPm && datePartArray[3] < 12) {
|
644
|
+
datePartArray[3] += 12;
|
645
|
+
}
|
646
|
+
// if is 12 am, change hours to 0
|
647
|
+
if (config.isPm === false && datePartArray[3] === 12) {
|
648
|
+
datePartArray[3] = 0;
|
649
|
+
}
|
650
|
+
// return
|
651
|
+
return dateFromArray(datePartArray, config.isUTC, config.tzh, config.tzm);
|
652
|
+
}
|
653
|
+
|
654
|
+
// date from string and array of format strings
|
655
|
+
function makeDateFromStringAndArray(string, formats) {
|
656
|
+
var output,
|
657
|
+
inputParts = string.match(parseMultipleFormatChunker) || [],
|
658
|
+
formattedInputParts,
|
659
|
+
scoreToBeat = 99,
|
660
|
+
i,
|
661
|
+
currentDate,
|
662
|
+
currentScore;
|
663
|
+
for (i = 0; i < formats.length; i++) {
|
664
|
+
currentDate = makeDateFromStringAndFormat(string, formats[i]);
|
665
|
+
formattedInputParts = formatMoment(new Moment(currentDate), formats[i]).match(parseMultipleFormatChunker) || [];
|
666
|
+
currentScore = compareArrays(inputParts, formattedInputParts);
|
667
|
+
if (currentScore < scoreToBeat) {
|
668
|
+
scoreToBeat = currentScore;
|
669
|
+
output = currentDate;
|
670
|
+
}
|
671
|
+
}
|
672
|
+
return output;
|
673
|
+
}
|
674
|
+
|
675
|
+
// date from iso format
|
676
|
+
function makeDateFromString(string) {
|
677
|
+
var format = 'YYYY-MM-DDT',
|
678
|
+
i;
|
679
|
+
if (isoRegex.exec(string)) {
|
680
|
+
for (i = 0; i < 4; i++) {
|
681
|
+
if (isoTimes[i][1].exec(string)) {
|
682
|
+
format += isoTimes[i][0];
|
683
|
+
break;
|
684
|
+
}
|
685
|
+
}
|
686
|
+
return parseTokenTimezone.exec(string) ?
|
687
|
+
makeDateFromStringAndFormat(string, format + ' Z') :
|
688
|
+
makeDateFromStringAndFormat(string, format);
|
689
|
+
}
|
690
|
+
return new Date(string);
|
691
|
+
}
|
692
|
+
|
693
|
+
|
694
|
+
/************************************
|
695
|
+
Relative Time
|
696
|
+
************************************/
|
697
|
+
|
698
|
+
|
699
|
+
// helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
|
700
|
+
function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) {
|
701
|
+
var rt = lang.relativeTime[string];
|
702
|
+
return (typeof rt === 'function') ?
|
703
|
+
rt(number || 1, !!withoutSuffix, string, isFuture) :
|
704
|
+
rt.replace(/%d/i, number || 1);
|
705
|
+
}
|
706
|
+
|
707
|
+
function relativeTime(milliseconds, withoutSuffix, lang) {
|
708
|
+
var seconds = round(Math.abs(milliseconds) / 1000),
|
709
|
+
minutes = round(seconds / 60),
|
710
|
+
hours = round(minutes / 60),
|
711
|
+
days = round(hours / 24),
|
712
|
+
years = round(days / 365),
|
713
|
+
args = seconds < 45 && ['s', seconds] ||
|
714
|
+
minutes === 1 && ['m'] ||
|
715
|
+
minutes < 45 && ['mm', minutes] ||
|
716
|
+
hours === 1 && ['h'] ||
|
717
|
+
hours < 22 && ['hh', hours] ||
|
718
|
+
days === 1 && ['d'] ||
|
719
|
+
days <= 25 && ['dd', days] ||
|
720
|
+
days <= 45 && ['M'] ||
|
721
|
+
days < 345 && ['MM', round(days / 30)] ||
|
722
|
+
years === 1 && ['y'] || ['yy', years];
|
723
|
+
args[2] = withoutSuffix;
|
724
|
+
args[3] = milliseconds > 0;
|
725
|
+
args[4] = lang;
|
726
|
+
return substituteTimeAgo.apply({}, args);
|
727
|
+
}
|
728
|
+
|
729
|
+
|
730
|
+
/************************************
|
731
|
+
Top Level Functions
|
732
|
+
************************************/
|
733
|
+
|
734
|
+
|
735
|
+
moment = function (input, format) {
|
736
|
+
if (input === null || input === '') {
|
737
|
+
return null;
|
738
|
+
}
|
739
|
+
var date,
|
740
|
+
matched;
|
741
|
+
// parse Moment object
|
742
|
+
if (moment.isMoment(input)) {
|
743
|
+
return new Moment(new Date(+input._d), input._isUTC, input._lang);
|
744
|
+
// parse string and format
|
745
|
+
} else if (format) {
|
746
|
+
if (isArray(format)) {
|
747
|
+
date = makeDateFromStringAndArray(input, format);
|
748
|
+
} else {
|
749
|
+
date = makeDateFromStringAndFormat(input, format);
|
750
|
+
}
|
751
|
+
// evaluate it as a JSON-encoded date
|
752
|
+
} else {
|
753
|
+
matched = aspNetJsonRegex.exec(input);
|
754
|
+
date = input === undefined ? new Date() :
|
755
|
+
matched ? new Date(+matched[1]) :
|
756
|
+
input instanceof Date ? input :
|
757
|
+
isArray(input) ? dateFromArray(input) :
|
758
|
+
typeof input === 'string' ? makeDateFromString(input) :
|
759
|
+
new Date(input);
|
760
|
+
}
|
761
|
+
|
762
|
+
return new Moment(date);
|
763
|
+
};
|
764
|
+
|
765
|
+
// creating with utc
|
766
|
+
moment.utc = function (input, format) {
|
767
|
+
if (isArray(input)) {
|
768
|
+
return new Moment(dateFromArray(input, true), true);
|
769
|
+
}
|
770
|
+
// if we don't have a timezone, we need to add one to trigger parsing into utc
|
771
|
+
if (typeof input === 'string' && !parseTokenTimezone.exec(input)) {
|
772
|
+
input += ' +0000';
|
773
|
+
if (format) {
|
774
|
+
format += ' Z';
|
775
|
+
}
|
776
|
+
}
|
777
|
+
return moment(input, format).utc();
|
778
|
+
};
|
779
|
+
|
780
|
+
// creating with unix timestamp (in seconds)
|
781
|
+
moment.unix = function (input) {
|
782
|
+
return moment(input * 1000);
|
783
|
+
};
|
784
|
+
|
785
|
+
// duration
|
786
|
+
moment.duration = function (input, key) {
|
787
|
+
var isDuration = moment.isDuration(input),
|
788
|
+
isNumber = (typeof input === 'number'),
|
789
|
+
duration = (isDuration ? input._data : (isNumber ? {} : input)),
|
790
|
+
ret;
|
791
|
+
|
792
|
+
if (isNumber) {
|
793
|
+
if (key) {
|
794
|
+
duration[key] = input;
|
795
|
+
} else {
|
796
|
+
duration.milliseconds = input;
|
797
|
+
}
|
798
|
+
}
|
799
|
+
|
800
|
+
ret = new Duration(duration);
|
801
|
+
|
802
|
+
if (isDuration) {
|
803
|
+
ret._lang = input._lang;
|
804
|
+
}
|
805
|
+
|
806
|
+
return ret;
|
807
|
+
};
|
808
|
+
|
809
|
+
// humanizeDuration
|
810
|
+
// This method is deprecated in favor of the new Duration object. Please
|
811
|
+
// see the moment.duration method.
|
812
|
+
moment.humanizeDuration = function (num, type, withSuffix) {
|
813
|
+
return moment.duration(num, type === true ? null : type).humanize(type === true ? true : withSuffix);
|
814
|
+
};
|
815
|
+
|
816
|
+
// version number
|
817
|
+
moment.version = VERSION;
|
818
|
+
|
819
|
+
// default format
|
820
|
+
moment.defaultFormat = isoFormat;
|
821
|
+
|
822
|
+
// This function will load languages and then set the global language. If
|
823
|
+
// no arguments are passed in, it will simply return the current global
|
824
|
+
// language key.
|
825
|
+
moment.lang = function (key, values) {
|
826
|
+
var i;
|
827
|
+
|
828
|
+
if (!key) {
|
829
|
+
return currentLanguage;
|
830
|
+
}
|
831
|
+
if (values || !languages[key]) {
|
832
|
+
loadLang(key, values);
|
833
|
+
}
|
834
|
+
if (languages[key]) {
|
835
|
+
// deprecated, to get the language definition variables, use the
|
836
|
+
// moment.fn.lang method or the getLangDefinition function.
|
837
|
+
for (i = 0; i < langConfigProperties.length; i++) {
|
838
|
+
moment[langConfigProperties[i]] = languages[key][langConfigProperties[i]];
|
839
|
+
}
|
840
|
+
moment.monthsParse = languages[key].monthsParse;
|
841
|
+
currentLanguage = key;
|
842
|
+
}
|
843
|
+
};
|
844
|
+
|
845
|
+
// returns language data
|
846
|
+
moment.langData = getLangDefinition;
|
847
|
+
|
848
|
+
// compare moment object
|
849
|
+
moment.isMoment = function (obj) {
|
850
|
+
return obj instanceof Moment;
|
851
|
+
};
|
852
|
+
|
853
|
+
// for typechecking Duration objects
|
854
|
+
moment.isDuration = function (obj) {
|
855
|
+
return obj instanceof Duration;
|
856
|
+
};
|
857
|
+
|
858
|
+
// Set default language, other languages will inherit from English.
|
859
|
+
moment.lang('en', {
|
860
|
+
months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
|
861
|
+
monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
|
862
|
+
weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
|
863
|
+
weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
|
864
|
+
weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
|
865
|
+
longDateFormat : {
|
866
|
+
LT : "h:mm A",
|
867
|
+
L : "MM/DD/YYYY",
|
868
|
+
LL : "MMMM D YYYY",
|
869
|
+
LLL : "MMMM D YYYY LT",
|
870
|
+
LLLL : "dddd, MMMM D YYYY LT"
|
871
|
+
},
|
872
|
+
meridiem : function (hours, minutes, isLower) {
|
873
|
+
if (hours > 11) {
|
874
|
+
return isLower ? 'pm' : 'PM';
|
875
|
+
} else {
|
876
|
+
return isLower ? 'am' : 'AM';
|
877
|
+
}
|
878
|
+
},
|
879
|
+
calendar : {
|
880
|
+
sameDay : '[Today at] LT',
|
881
|
+
nextDay : '[Tomorrow at] LT',
|
882
|
+
nextWeek : 'dddd [at] LT',
|
883
|
+
lastDay : '[Yesterday at] LT',
|
884
|
+
lastWeek : '[last] dddd [at] LT',
|
885
|
+
sameElse : 'L'
|
886
|
+
},
|
887
|
+
relativeTime : {
|
888
|
+
future : "in %s",
|
889
|
+
past : "%s ago",
|
890
|
+
s : "a few seconds",
|
891
|
+
m : "a minute",
|
892
|
+
mm : "%d minutes",
|
893
|
+
h : "an hour",
|
894
|
+
hh : "%d hours",
|
895
|
+
d : "a day",
|
896
|
+
dd : "%d days",
|
897
|
+
M : "a month",
|
898
|
+
MM : "%d months",
|
899
|
+
y : "a year",
|
900
|
+
yy : "%d years"
|
901
|
+
},
|
902
|
+
ordinal : function (number) {
|
903
|
+
var b = number % 10;
|
904
|
+
return (~~ (number % 100 / 10) === 1) ? 'th' :
|
905
|
+
(b === 1) ? 'st' :
|
906
|
+
(b === 2) ? 'nd' :
|
907
|
+
(b === 3) ? 'rd' : 'th';
|
908
|
+
}
|
909
|
+
});
|
910
|
+
|
911
|
+
|
912
|
+
/************************************
|
913
|
+
Moment Prototype
|
914
|
+
************************************/
|
915
|
+
|
916
|
+
|
917
|
+
moment.fn = Moment.prototype = {
|
918
|
+
|
919
|
+
clone : function () {
|
920
|
+
return moment(this);
|
921
|
+
},
|
922
|
+
|
923
|
+
valueOf : function () {
|
924
|
+
return +this._d;
|
925
|
+
},
|
926
|
+
|
927
|
+
unix : function () {
|
928
|
+
return Math.floor(+this._d / 1000);
|
929
|
+
},
|
930
|
+
|
931
|
+
toString : function () {
|
932
|
+
return this._d.toString();
|
933
|
+
},
|
934
|
+
|
935
|
+
toDate : function () {
|
936
|
+
return this._d;
|
937
|
+
},
|
938
|
+
|
939
|
+
toArray : function () {
|
940
|
+
var m = this;
|
941
|
+
return [
|
942
|
+
m.year(),
|
943
|
+
m.month(),
|
944
|
+
m.date(),
|
945
|
+
m.hours(),
|
946
|
+
m.minutes(),
|
947
|
+
m.seconds(),
|
948
|
+
m.milliseconds(),
|
949
|
+
!!this._isUTC
|
950
|
+
];
|
951
|
+
},
|
952
|
+
|
953
|
+
isValid : function () {
|
954
|
+
if (this._a) {
|
955
|
+
// if the parser finds that the input is invalid, it sets
|
956
|
+
// the eighth item in the input array to false.
|
957
|
+
if (this._a[8] != null) {
|
958
|
+
return !!this._a[8];
|
959
|
+
}
|
960
|
+
return !compareArrays(this._a, (this._a[7] ? moment.utc(this._a) : moment(this._a)).toArray());
|
961
|
+
}
|
962
|
+
return !isNaN(this._d.getTime());
|
963
|
+
},
|
964
|
+
|
965
|
+
utc : function () {
|
966
|
+
this._isUTC = true;
|
967
|
+
return this;
|
968
|
+
},
|
969
|
+
|
970
|
+
local : function () {
|
971
|
+
this._isUTC = false;
|
972
|
+
return this;
|
973
|
+
},
|
974
|
+
|
975
|
+
format : function (inputString) {
|
976
|
+
return formatMoment(this, inputString ? inputString : moment.defaultFormat);
|
977
|
+
},
|
978
|
+
|
979
|
+
add : function (input, val) {
|
980
|
+
var dur = val ? moment.duration(+val, input) : moment.duration(input);
|
981
|
+
addOrSubtractDurationFromMoment(this, dur, 1);
|
982
|
+
return this;
|
983
|
+
},
|
984
|
+
|
985
|
+
subtract : function (input, val) {
|
986
|
+
var dur = val ? moment.duration(+val, input) : moment.duration(input);
|
987
|
+
addOrSubtractDurationFromMoment(this, dur, -1);
|
988
|
+
return this;
|
989
|
+
},
|
990
|
+
|
991
|
+
diff : function (input, val, asFloat) {
|
992
|
+
var inputMoment = this._isUTC ? moment(input).utc() : moment(input).local(),
|
993
|
+
zoneDiff = (this.zone() - inputMoment.zone()) * 6e4,
|
994
|
+
diff = this._d - inputMoment._d - zoneDiff,
|
995
|
+
year = this.year() - inputMoment.year(),
|
996
|
+
month = this.month() - inputMoment.month(),
|
997
|
+
date = this.date() - inputMoment.date(),
|
998
|
+
output;
|
999
|
+
if (val === 'months') {
|
1000
|
+
output = year * 12 + month + date / 30;
|
1001
|
+
} else if (val === 'years') {
|
1002
|
+
output = year + (month + date / 30) / 12;
|
1003
|
+
} else {
|
1004
|
+
output = val === 'seconds' ? diff / 1e3 : // 1000
|
1005
|
+
val === 'minutes' ? diff / 6e4 : // 1000 * 60
|
1006
|
+
val === 'hours' ? diff / 36e5 : // 1000 * 60 * 60
|
1007
|
+
val === 'days' ? diff / 864e5 : // 1000 * 60 * 60 * 24
|
1008
|
+
val === 'weeks' ? diff / 6048e5 : // 1000 * 60 * 60 * 24 * 7
|
1009
|
+
diff;
|
1010
|
+
}
|
1011
|
+
return asFloat ? output : round(output);
|
1012
|
+
},
|
1013
|
+
|
1014
|
+
from : function (time, withoutSuffix) {
|
1015
|
+
return moment.duration(this.diff(time)).lang(this._lang).humanize(!withoutSuffix);
|
1016
|
+
},
|
1017
|
+
|
1018
|
+
fromNow : function (withoutSuffix) {
|
1019
|
+
return this.from(moment(), withoutSuffix);
|
1020
|
+
},
|
1021
|
+
|
1022
|
+
calendar : function () {
|
1023
|
+
var diff = this.diff(moment().sod(), 'days', true),
|
1024
|
+
calendar = this.lang().calendar,
|
1025
|
+
allElse = calendar.sameElse,
|
1026
|
+
format = diff < -6 ? allElse :
|
1027
|
+
diff < -1 ? calendar.lastWeek :
|
1028
|
+
diff < 0 ? calendar.lastDay :
|
1029
|
+
diff < 1 ? calendar.sameDay :
|
1030
|
+
diff < 2 ? calendar.nextDay :
|
1031
|
+
diff < 7 ? calendar.nextWeek : allElse;
|
1032
|
+
return this.format(typeof format === 'function' ? format.apply(this) : format);
|
1033
|
+
},
|
1034
|
+
|
1035
|
+
isLeapYear : function () {
|
1036
|
+
var year = this.year();
|
1037
|
+
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
|
1038
|
+
},
|
1039
|
+
|
1040
|
+
isDST : function () {
|
1041
|
+
return (this.zone() < moment([this.year()]).zone() ||
|
1042
|
+
this.zone() < moment([this.year(), 5]).zone());
|
1043
|
+
},
|
1044
|
+
|
1045
|
+
day : function (input) {
|
1046
|
+
var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
|
1047
|
+
return input == null ? day :
|
1048
|
+
this.add({ d : input - day });
|
1049
|
+
},
|
1050
|
+
|
1051
|
+
startOf: function (val) {
|
1052
|
+
// the following switch intentionally omits break keywords
|
1053
|
+
// to utilize falling through the cases.
|
1054
|
+
switch (val.replace(/s$/, '')) {
|
1055
|
+
case 'year':
|
1056
|
+
this.month(0);
|
1057
|
+
/* falls through */
|
1058
|
+
case 'month':
|
1059
|
+
this.date(1);
|
1060
|
+
/* falls through */
|
1061
|
+
case 'day':
|
1062
|
+
this.hours(0);
|
1063
|
+
/* falls through */
|
1064
|
+
case 'hour':
|
1065
|
+
this.minutes(0);
|
1066
|
+
/* falls through */
|
1067
|
+
case 'minute':
|
1068
|
+
this.seconds(0);
|
1069
|
+
/* falls through */
|
1070
|
+
case 'second':
|
1071
|
+
this.milliseconds(0);
|
1072
|
+
/* falls through */
|
1073
|
+
}
|
1074
|
+
return this;
|
1075
|
+
},
|
1076
|
+
|
1077
|
+
endOf: function (val) {
|
1078
|
+
return this.startOf(val).add(val.replace(/s?$/, 's'), 1).subtract('ms', 1);
|
1079
|
+
},
|
1080
|
+
|
1081
|
+
sod: function () {
|
1082
|
+
return this.clone().startOf('day');
|
1083
|
+
},
|
1084
|
+
|
1085
|
+
eod: function () {
|
1086
|
+
// end of day = start of day plus 1 day, minus 1 millisecond
|
1087
|
+
return this.clone().endOf('day');
|
1088
|
+
},
|
1089
|
+
|
1090
|
+
zone : function () {
|
1091
|
+
return this._isUTC ? 0 : this._d.getTimezoneOffset();
|
1092
|
+
},
|
1093
|
+
|
1094
|
+
daysInMonth : function () {
|
1095
|
+
return moment.utc([this.year(), this.month() + 1, 0]).date();
|
1096
|
+
},
|
1097
|
+
|
1098
|
+
// If passed a language key, it will set the language for this
|
1099
|
+
// instance. Otherwise, it will return the language configuration
|
1100
|
+
// variables for this instance.
|
1101
|
+
lang : function (lang) {
|
1102
|
+
if (lang === undefined) {
|
1103
|
+
return getLangDefinition(this);
|
1104
|
+
} else {
|
1105
|
+
this._lang = lang;
|
1106
|
+
return this;
|
1107
|
+
}
|
1108
|
+
}
|
1109
|
+
};
|
1110
|
+
|
1111
|
+
// helper for adding shortcuts
|
1112
|
+
function makeGetterAndSetter(name, key) {
|
1113
|
+
moment.fn[name] = function (input) {
|
1114
|
+
var utc = this._isUTC ? 'UTC' : '';
|
1115
|
+
if (input != null) {
|
1116
|
+
this._d['set' + utc + key](input);
|
1117
|
+
return this;
|
1118
|
+
} else {
|
1119
|
+
return this._d['get' + utc + key]();
|
1120
|
+
}
|
1121
|
+
};
|
1122
|
+
}
|
1123
|
+
|
1124
|
+
// loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds)
|
1125
|
+
for (i = 0; i < proxyGettersAndSetters.length; i ++) {
|
1126
|
+
makeGetterAndSetter(proxyGettersAndSetters[i].toLowerCase(), proxyGettersAndSetters[i]);
|
1127
|
+
}
|
1128
|
+
|
1129
|
+
// add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear')
|
1130
|
+
makeGetterAndSetter('year', 'FullYear');
|
1131
|
+
|
1132
|
+
|
1133
|
+
/************************************
|
1134
|
+
Duration Prototype
|
1135
|
+
************************************/
|
1136
|
+
|
1137
|
+
|
1138
|
+
moment.duration.fn = Duration.prototype = {
|
1139
|
+
weeks : function () {
|
1140
|
+
return absRound(this.days() / 7);
|
1141
|
+
},
|
1142
|
+
|
1143
|
+
valueOf : function () {
|
1144
|
+
return this._milliseconds +
|
1145
|
+
this._days * 864e5 +
|
1146
|
+
this._months * 2592e6;
|
1147
|
+
},
|
1148
|
+
|
1149
|
+
humanize : function (withSuffix) {
|
1150
|
+
var difference = +this,
|
1151
|
+
rel = this.lang().relativeTime,
|
1152
|
+
output = relativeTime(difference, !withSuffix, this.lang()),
|
1153
|
+
fromNow = difference <= 0 ? rel.past : rel.future;
|
1154
|
+
|
1155
|
+
if (withSuffix) {
|
1156
|
+
if (typeof fromNow === 'function') {
|
1157
|
+
output = fromNow(output);
|
1158
|
+
} else {
|
1159
|
+
output = fromNow.replace(/%s/i, output);
|
1160
|
+
}
|
1161
|
+
}
|
1162
|
+
|
1163
|
+
return output;
|
1164
|
+
},
|
1165
|
+
|
1166
|
+
lang : moment.fn.lang
|
1167
|
+
};
|
1168
|
+
|
1169
|
+
function makeDurationGetter(name) {
|
1170
|
+
moment.duration.fn[name] = function () {
|
1171
|
+
return this._data[name];
|
1172
|
+
};
|
1173
|
+
}
|
1174
|
+
|
1175
|
+
function makeDurationAsGetter(name, factor) {
|
1176
|
+
moment.duration.fn['as' + name] = function () {
|
1177
|
+
return +this / factor;
|
1178
|
+
};
|
1179
|
+
}
|
1180
|
+
|
1181
|
+
for (i in unitMillisecondFactors) {
|
1182
|
+
if (unitMillisecondFactors.hasOwnProperty(i)) {
|
1183
|
+
makeDurationAsGetter(i, unitMillisecondFactors[i]);
|
1184
|
+
makeDurationGetter(i.toLowerCase());
|
1185
|
+
}
|
1186
|
+
}
|
1187
|
+
|
1188
|
+
makeDurationAsGetter('Weeks', 6048e5);
|
1189
|
+
|
1190
|
+
|
1191
|
+
/************************************
|
1192
|
+
Exposing Moment
|
1193
|
+
************************************/
|
1194
|
+
|
1195
|
+
|
1196
|
+
// CommonJS module is defined
|
1197
|
+
if (hasModule) {
|
1198
|
+
module.exports = moment;
|
1199
|
+
}
|
1200
|
+
/*global ender:false */
|
1201
|
+
if (typeof ender === 'undefined') {
|
1202
|
+
// here, `this` means `window` in the browser, or `global` on the server
|
1203
|
+
// add `moment` as a global object via a string identifier,
|
1204
|
+
// for Closure Compiler "advanced" mode
|
1205
|
+
this['moment'] = moment;
|
1206
|
+
}
|
1207
|
+
/*global define:false */
|
1208
|
+
if (typeof define === "function" && define.amd) {
|
1209
|
+
define("moment", [], function () {
|
1210
|
+
return moment;
|
1211
|
+
});
|
1212
|
+
}
|
1213
|
+
}).call(this);
|