momentjs-rails 2.2.1 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/news.md +3 -0
  4. data/test/dummy/log/test.log +147 -14
  5. data/test/dummy/tmp/cache/assets/D1C/680/sprockets%2F16ed4d5afdb2919596e6f8790e2116c2 +0 -0
  6. data/test/dummy/tmp/cache/assets/D35/CA0/sprockets%2F493e64bce2d302801dc01cf7cd096a58 +0 -0
  7. data/test/dummy/tmp/cache/assets/D3F/5F0/sprockets%2F4a6c53eae7c6e41a69a191578bbb6417 +0 -0
  8. data/test/dummy/tmp/cache/assets/D58/BD0/sprockets%2F4de9ddc9b725c715a54c98697b2528fe +0 -0
  9. data/test/dummy/tmp/cache/assets/D75/510/sprockets%2Fe690787ac522f47a6be024bfcc1767ee +0 -0
  10. data/test/dummy/tmp/cache/assets/E10/250/sprockets%2Fe4badb9ddfda484eb9671bf88567be61 +0 -0
  11. data/test/integration/navigation_test.rb +1 -1
  12. data/vendor/assets/javascripts/moment.js +717 -178
  13. data/vendor/assets/javascripts/moment/ar-ma.js +2 -2
  14. data/vendor/assets/javascripts/moment/ar.js +2 -2
  15. data/vendor/assets/javascripts/moment/bg.js +3 -3
  16. data/vendor/assets/javascripts/moment/br.js +2 -2
  17. data/vendor/assets/javascripts/moment/bs.js +139 -0
  18. data/vendor/assets/javascripts/moment/ca.js +2 -2
  19. data/vendor/assets/javascripts/moment/cs.js +2 -2
  20. data/vendor/assets/javascripts/moment/cv.js +2 -2
  21. data/vendor/assets/javascripts/moment/cy.js +77 -0
  22. data/vendor/assets/javascripts/moment/da.js +2 -2
  23. data/vendor/assets/javascripts/moment/de.js +2 -2
  24. data/vendor/assets/javascripts/moment/el.js +2 -2
  25. data/vendor/assets/javascripts/moment/en-au.js +62 -0
  26. data/vendor/assets/javascripts/moment/en-ca.js +2 -2
  27. data/vendor/assets/javascripts/moment/en-gb.js +2 -2
  28. data/vendor/assets/javascripts/moment/eo.js +2 -2
  29. data/vendor/assets/javascripts/moment/es.js +2 -2
  30. data/vendor/assets/javascripts/moment/et.js +2 -2
  31. data/vendor/assets/javascripts/moment/eu.js +2 -2
  32. data/vendor/assets/javascripts/moment/fa.js +2 -2
  33. data/vendor/assets/javascripts/moment/fi.js +2 -2
  34. data/vendor/assets/javascripts/moment/fo.js +56 -0
  35. data/vendor/assets/javascripts/moment/fr-ca.js +2 -2
  36. data/vendor/assets/javascripts/moment/fr.js +2 -2
  37. data/vendor/assets/javascripts/moment/gl.js +2 -2
  38. data/vendor/assets/javascripts/moment/he.js +2 -2
  39. data/vendor/assets/javascripts/moment/hi.js +2 -2
  40. data/vendor/assets/javascripts/moment/hr.js +2 -2
  41. data/vendor/assets/javascripts/moment/hu.js +4 -3
  42. data/vendor/assets/javascripts/moment/id.js +2 -2
  43. data/vendor/assets/javascripts/moment/is.js +2 -2
  44. data/vendor/assets/javascripts/moment/it.js +2 -2
  45. data/vendor/assets/javascripts/moment/ja.js +2 -2
  46. data/vendor/assets/javascripts/moment/ka.js +2 -2
  47. data/vendor/assets/javascripts/moment/ko.js +2 -2
  48. data/vendor/assets/javascripts/moment/lt.js +118 -0
  49. data/vendor/assets/javascripts/moment/lv.js +2 -2
  50. data/vendor/assets/javascripts/moment/ml.js +2 -2
  51. data/vendor/assets/javascripts/moment/mr.js +2 -2
  52. data/vendor/assets/javascripts/moment/ms-my.js +2 -2
  53. data/vendor/assets/javascripts/moment/nb.js +2 -2
  54. data/vendor/assets/javascripts/moment/ne.js +2 -2
  55. data/vendor/assets/javascripts/moment/nl.js +5 -5
  56. data/vendor/assets/javascripts/moment/nn.js +2 -2
  57. data/vendor/assets/javascripts/moment/pl.js +2 -2
  58. data/vendor/assets/javascripts/moment/pt-br.js +2 -2
  59. data/vendor/assets/javascripts/moment/pt.js +2 -2
  60. data/vendor/assets/javascripts/moment/ro.js +2 -2
  61. data/vendor/assets/javascripts/moment/ru.js +20 -5
  62. data/vendor/assets/javascripts/moment/sk.js +2 -2
  63. data/vendor/assets/javascripts/moment/sl.js +2 -2
  64. data/vendor/assets/javascripts/moment/sq.js +2 -2
  65. data/vendor/assets/javascripts/moment/sv.js +2 -2
  66. data/vendor/assets/javascripts/moment/th.js +2 -2
  67. data/vendor/assets/javascripts/moment/tl-ph.js +58 -0
  68. data/vendor/assets/javascripts/moment/tr.js +2 -2
  69. data/vendor/assets/javascripts/moment/tzm-la.js +2 -2
  70. data/vendor/assets/javascripts/moment/tzm.js +2 -2
  71. data/vendor/assets/javascripts/moment/uk.js +18 -3
  72. data/vendor/assets/javascripts/moment/uz.js +55 -0
  73. data/vendor/assets/javascripts/moment/vn.js +62 -0
  74. data/vendor/assets/javascripts/moment/zh-cn.js +43 -18
  75. data/vendor/assets/javascripts/moment/zh-tw.js +7 -6
  76. metadata +10 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e72db56d51cf7e5fe91b467a0b6bfd71734b004e
4
- data.tar.gz: e9160df8b82151849bb7f782d9cbbf1ad57d645d
3
+ metadata.gz: 05d9abfe5085c85b3c1c25276455b53af15e746e
4
+ data.tar.gz: 1b46ea4baeea50dfcc502b5a787ac80cd55f14c6
5
5
  SHA512:
6
- metadata.gz: e578afd22ba49caff9d23d185be3945645f209c57c591c328966bfa0a2c24a76810ce90fa4412080ba4f7b93b37e416cf4d832c62ca0baa0b30f0758fa21fcec
7
- data.tar.gz: 2a12778ba0838e3ee1293f49995fbaa0daeefd79514038725d26e7f6fc1e4f7b7b3a163e0f7559d9b1f49de8915a699dd754620ceed39bbd1e993b3e2d6974e6
6
+ metadata.gz: 64a99f42e2197d11b462e3cd6a2050d4123cf324f0430273fb4bb0fd212ed8ea3155b685485646e45ddcb523753e6416a87730e7ad382becc84a6300a1ac05fb
7
+ data.tar.gz: defb86b1dce99f53e50a9d1a31eba9d42c6a7a7e5d1e7b5843b2ef4928373e6053bf7a5e4319ceb08e0999cdabac6357bc39a5203fa4d23a3172f05b13440990
data/README.md CHANGED
@@ -24,7 +24,7 @@ If you want to include a localization file, also add the following directive:
24
24
 
25
25
  ## Versioning
26
26
 
27
- momentjs-rails 2.2.1 == Moment.js 2.2.1
27
+ momentjs-rails 2.4.0 == Moment.js 2.4.0
28
28
 
29
29
  Every attempt is made to mirror the currently shipping Momentum.js version number wherever possible.
30
30
  The major, minor, and patch version numbers will always represent the Momentum.js version. Should a gem
data/news.md CHANGED
@@ -1,3 +1,6 @@
1
+ ### Version 2.4.0 (2013-11-13)
2
+ - Updated to Moment.js to 2.4.0
3
+
1
4
  ### Version 2.2.1 (2013-09-19)
2
5
  - Updated to Moment.js to 2.2.1
3
6
 
@@ -1,20 +1,153 @@
1
- Started GET "/assets/moment.js" for 127.0.0.1 at 2013-09-19 11:00:54 -0400
2
- Compiled moment.js (0ms) (pid 11385)
3
- Served asset /moment.js - 200 OK (6ms)
4
- Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-09-19 11:00:54 -0400
5
- Compiled moment/fr.js (0ms) (pid 11385)
6
- Served asset /moment/fr.js - 200 OK (23ms)
7
- Started GET "/assets/moment.js" for 127.0.0.1 at 2013-09-19 11:00:54 -0400
1
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:04:06 -0400
2
+ Compiled moment.js (0ms) (pid 43125)
3
+ Served asset /moment.js - 200 OK (14ms)
4
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-03-16 16:04:06 -0400
5
+ Compiled moment/fr.js (0ms) (pid 43125)
6
+ Served asset /moment/fr.js - 200 OK (96ms)
7
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:05:04 -0400
8
+ Served asset /moment.js - 200 OK (25ms)
9
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-03-16 16:05:04 -0400
10
+ Served asset /moment/fr.js - 200 OK (2ms)
11
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:05:17 -0400
12
+ Served asset /moment.js - 200 OK (2ms)
13
+ Started GET "/assets/momentmotherfucker/fr.js" for 127.0.0.1 at 2013-03-16 16:05:17 -0400
14
+ Served asset /momentmotherfucker/fr.js - 404 Not Found (1ms)
15
+ Started GET "/assets/moments.js" for 127.0.0.1 at 2013-03-16 16:05:53 -0400
16
+ Served asset /moments.js - 404 Not Found (1ms)
17
+ Started GET "/assets/moment/rfr.js" for 127.0.0.1 at 2013-03-16 16:05:53 -0400
18
+ Served asset /moment/rfr.js - 404 Not Found (1ms)
19
+ Started GET "/assets/moments.js" for 127.0.0.1 at 2013-03-16 16:06:02 -0400
20
+ Served asset /moments.js - 404 Not Found (1ms)
21
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-03-16 16:06:02 -0400
22
+ Served asset /moment/fr.js - 200 OK (2ms)
23
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:06:22 -0400
24
+ Served asset /moment.js - 200 OK (2ms)
25
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-03-16 16:06:22 -0400
26
+ Served asset /moment/fr.js - 200 OK (1ms)
27
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:07:08 -0400
28
+ Served asset /moment.js - 200 OK (3ms)
29
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-03-16 16:07:08 -0400
30
+ Served asset /moment/fr.js - 200 OK (1ms)
31
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:08:10 -0400
32
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-03-16 16:08:10 -0400
33
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:08:17 -0400
34
+ Served asset /moment.js - 200 OK (2ms)
35
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-03-16 16:08:17 -0400
36
+ Served asset /moment/fr.js - 200 OK (1ms)
37
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:08:51 -0400
38
+ Served asset /moment.js - 200 OK (2ms)
39
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-03-16 16:08:51 -0400
40
+ Served asset /moment/fr.js - 200 OK (1ms)
41
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:08:57 -0400
42
+ Served asset /moment.js - 200 OK (2ms)
43
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-03-16 16:08:57 -0400
44
+ Served asset /moment/fr.js - 200 OK (1ms)
45
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:09:13 -0400
46
+ Served asset /moment.js - 200 OK (2ms)
47
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-03-16 16:09:13 -0400
48
+ Served asset /moment/fr.js - 200 OK (2ms)
49
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:09:49 -0400
50
+ Served asset /moment.js - 200 OK (2ms)
51
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-03-16 16:09:49 -0400
52
+ Served asset /moment/fr.js - 200 OK (1ms)
53
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:10:05 -0400
54
+ Served asset /moment.js - 200 OK (2ms)
55
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-03-16 16:10:05 -0400
56
+ Served asset /moment/fr.js - 200 OK (1ms)
57
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:11:18 -0400
58
+ Served asset /moment.js - 200 OK (2ms)
59
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-03-16 16:11:18 -0400
60
+ Served asset /moment/fr.js - 200 OK (1ms)
61
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:12:28 -0400
62
+ Served asset /moment.js - 200 OK (16ms)
63
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-03-16 16:12:28 -0400
64
+ Served asset /moment/fr.js - 200 OK (10ms)
65
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:12:47 -0400
66
+ Served asset /moment.js - 200 OK (1ms)
67
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-03-16 16:12:47 -0400
68
+ Served asset /moment/fr.js - 200 OK (11ms)
69
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:14:04 -0400
70
+ Served asset /moment.js - 200 OK (1ms)
71
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-03-16 16:14:04 -0400
72
+ Served asset /moment/fr.js - 200 OK (1ms)
73
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:15:39 -0400
74
+ Served asset /moment.js - 200 OK (1ms)
75
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-03-16 16:15:39 -0400
76
+ Served asset /moment/fr.js - 200 OK (12ms)
77
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:37:24 -0400
78
+ Served asset /moment.js - 200 OK (14ms)
79
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-03-16 16:37:24 -0400
80
+ Served asset /moment/fr.js - 200 OK (11ms)
81
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:37:32 -0400
82
+ Served asset /moment.js - 200 OK (1ms)
83
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-03-16 16:37:32 -0400
84
+ Served asset /moment/fr.js - 200 OK (12ms)
85
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:44:51 -0400
86
+ Served asset /moment.js - 200 OK (46ms)
87
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-03-16 16:44:52 -0400
88
+ Served asset /moment/fr.js - 200 OK (12ms)
89
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:44:52 -0400
90
+ Served asset /moment.js - 200 OK (0ms)
91
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:45:09 -0400
92
+ Served asset /moment.js - 200 OK (1ms)
93
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-03-16 16:45:09 -0400
94
+ Served asset /moment/fr.js - 200 OK (11ms)
95
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:45:09 -0400
96
+ Served asset /moment.js - 200 OK (0ms)
97
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:47:53 -0400
98
+ Compiled moment.js (0ms) (pid 62815)
99
+ Served asset /moment.js - 200 OK (18ms)
100
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-03-16 16:47:53 -0400
101
+ Compiled moment/fr.js (0ms) (pid 62815)
102
+ Served asset /moment/fr.js - 200 OK (18ms)
103
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:47:53 -0400
104
+ Served asset /moment.js - 200 OK (0ms)
105
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:48:16 -0400
106
+ Served asset /moment.js - 200 OK (2ms)
107
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-03-16 16:48:16 -0400
108
+ Served asset /moment/fr.js - 200 OK (1ms)
109
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:48:16 -0400
8
110
  Served asset /moment.js - 200 OK (0ms)
9
- Started GET "/assets/moment.js" for 127.0.0.1 at 2013-09-19 11:01:37 -0400
10
- Served asset /moment.js - 200 OK (11ms)
11
- Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-09-19 11:01:37 -0400
111
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:50:40 -0400
112
+ Compiled moment.js (10ms) (pid 64044)
113
+ Served asset /moment.js - 200 OK (40ms)
114
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-03-16 16:50:40 -0400
115
+ Served asset /moment/fr.js - 200 OK (2ms)
116
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:50:40 -0400
117
+ Served asset /moment.js - 200 OK (0ms)
118
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:50:53 -0400
119
+ Compiled moment.js (11ms) (pid 64218)
120
+ Served asset /moment.js - 200 OK (16ms)
121
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-03-16 16:50:53 -0400
12
122
  Served asset /moment/fr.js - 200 OK (1ms)
13
- Started GET "/assets/moment.js" for 127.0.0.1 at 2013-09-19 11:01:37 -0400
123
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-03-16 16:50:53 -0400
14
124
  Served asset /moment.js - 200 OK (0ms)
15
- Started GET "/assets/moment.js" for 127.0.0.1 at 2013-09-19 11:02:11 -0400
125
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-06-06 21:49:55 -0400
16
126
  Served asset /moment.js - 200 OK (2ms)
17
- Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-09-19 11:02:11 -0400
127
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-06-06 21:49:55 -0400
128
+ Compiled moment/fr.js (0ms) (pid 73048)
129
+ Served asset /moment/fr.js - 200 OK (28ms)
130
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-06-06 21:49:55 -0400
131
+ Served asset /moment.js - 200 OK (0ms)
132
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-07-20 10:00:25 -0400
133
+ Compiled moment.js (0ms) (pid 5373)
134
+ Served asset /moment.js - 200 OK (75ms)
135
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-07-20 10:00:25 -0400
136
+ Compiled moment/fr.js (0ms) (pid 5373)
137
+ Served asset /moment/fr.js - 200 OK (96ms)
138
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-07-20 10:00:25 -0400
139
+ Served asset /moment.js - 200 OK (0ms)
140
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-07-20 10:01:19 -0400
141
+ Served asset /moment.js - 200 OK (2ms)
142
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-07-20 10:01:19 -0400
18
143
  Served asset /moment/fr.js - 200 OK (1ms)
19
- Started GET "/assets/moment.js" for 127.0.0.1 at 2013-09-19 11:02:11 -0400
144
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-07-20 10:01:19 -0400
145
+ Served asset /moment.js - 200 OK (0ms)
146
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-11-14 20:25:32 -0500
147
+ Compiled moment.js (1ms) (pid 43502)
148
+ Served asset /moment.js - 200 OK (78ms)
149
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-11-14 20:25:32 -0500
150
+ Compiled moment/fr.js (0ms) (pid 43502)
151
+ Served asset /moment/fr.js - 200 OK (28ms)
152
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-11-14 20:25:32 -0500
20
153
  Served asset /moment.js - 200 OK (0ms)
@@ -8,7 +8,7 @@ class NavigationTest < ActionDispatch::IntegrationTest
8
8
 
9
9
  test 'momentjs response is for the expected version' do
10
10
  get 'assets/moment.js'
11
- assert_match(/VERSION = "2\.2\.1"/, @response.body)
11
+ assert_match(/VERSION = "2\.4\.0"/, @response.body)
12
12
  end
13
13
 
14
14
  test 'can access momentjs translation' do
@@ -1,5 +1,5 @@
1
1
  //! moment.js
2
- //! version : 2.2.1
2
+ //! version : 2.4.0
3
3
  //! authors : Tim Wood, Iskren Chernev, Moment.js contributors
4
4
  //! license : MIT
5
5
  //! momentjs.com
@@ -11,8 +11,18 @@
11
11
  ************************************/
12
12
 
13
13
  var moment,
14
- VERSION = "2.2.1",
15
- round = Math.round, i,
14
+ VERSION = "2.4.0",
15
+ round = Math.round,
16
+ i,
17
+
18
+ YEAR = 0,
19
+ MONTH = 1,
20
+ DATE = 2,
21
+ HOUR = 3,
22
+ MINUTE = 4,
23
+ SECOND = 5,
24
+ MILLISECOND = 6,
25
+
16
26
  // internal storage for language config files
17
27
  languages = {},
18
28
 
@@ -21,10 +31,14 @@
21
31
 
22
32
  // ASP.NET json date format regex
23
33
  aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
24
- aspNetTimeSpanJsonRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)\:(\d+)\.?(\d{3})?/,
34
+ aspNetTimeSpanJsonRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,
35
+
36
+ // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
37
+ // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
38
+ isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,
25
39
 
26
40
  // format tokens
27
- formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|SS?S?|X|zz?|ZZ?|.)/g,
41
+ formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g,
28
42
  localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,
29
43
 
30
44
  // parsing token regexes
@@ -33,19 +47,28 @@
33
47
  parseTokenThreeDigits = /\d{3}/, // 000 - 999
34
48
  parseTokenFourDigits = /\d{1,4}/, // 0 - 9999
35
49
  parseTokenSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999
50
+ parseTokenDigits = /\d+/, // nonzero number of digits
36
51
  parseTokenWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i, // any word (or two) characters or numbers including two/three word month in arabic.
37
52
  parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/i, // +00:00 -00:00 +0000 -0000 or Z
38
53
  parseTokenT = /T/i, // T (ISO seperator)
39
54
  parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123
40
55
 
41
56
  // preliminary iso regex
42
- // 0000-00-00 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000
43
- isoRegex = /^\s*\d{4}-\d\d-\d\d((T| )(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,
57
+ // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000)
58
+ isoRegex = /^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d:?\d\d|Z)?)?$/,
59
+
44
60
  isoFormat = 'YYYY-MM-DDTHH:mm:ssZ',
45
61
 
62
+ isoDates = [
63
+ 'YYYY-MM-DD',
64
+ 'GGGG-[W]WW',
65
+ 'GGGG-[W]WW-E',
66
+ 'YYYY-DDD'
67
+ ],
68
+
46
69
  // iso time formats and regexes
47
70
  isoTimes = [
48
- ['HH:mm:ss.S', /(T| )\d\d:\d\d:\d\d\.\d{1,3}/],
71
+ ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d{1,3}/],
49
72
  ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/],
50
73
  ['HH:mm', /(T| )\d\d:\d\d/],
51
74
  ['HH', /(T| )\d\d/]
@@ -72,10 +95,24 @@
72
95
  m : 'minute',
73
96
  h : 'hour',
74
97
  d : 'day',
98
+ D : 'date',
75
99
  w : 'week',
76
- W : 'isoweek',
100
+ W : 'isoWeek',
77
101
  M : 'month',
78
- y : 'year'
102
+ y : 'year',
103
+ DDD : 'dayOfYear',
104
+ e : 'weekday',
105
+ E : 'isoWeekday',
106
+ gg: 'weekYear',
107
+ GG: 'isoWeekYear'
108
+ },
109
+
110
+ camelFunctions = {
111
+ dayofyear : 'dayOfYear',
112
+ isoweekday : 'isoWeekday',
113
+ isoweek : 'isoWeek',
114
+ weekyear : 'weekYear',
115
+ isoweekyear : 'isoWeekYear'
79
116
  },
80
117
 
81
118
  // format function strings
@@ -171,14 +208,17 @@
171
208
  return this.seconds();
172
209
  },
173
210
  S : function () {
174
- return ~~(this.milliseconds() / 100);
211
+ return toInt(this.milliseconds() / 100);
175
212
  },
176
213
  SS : function () {
177
- return leftZeroFill(~~(this.milliseconds() / 10), 2);
214
+ return leftZeroFill(toInt(this.milliseconds() / 10), 2);
178
215
  },
179
216
  SSS : function () {
180
217
  return leftZeroFill(this.milliseconds(), 3);
181
218
  },
219
+ SSSS : function () {
220
+ return leftZeroFill(this.milliseconds(), 3);
221
+ },
182
222
  Z : function () {
183
223
  var a = -this.zone(),
184
224
  b = "+";
@@ -186,7 +226,7 @@
186
226
  a = -a;
187
227
  b = "-";
188
228
  }
189
- return b + leftZeroFill(~~(a / 60), 2) + ":" + leftZeroFill(~~a % 60, 2);
229
+ return b + leftZeroFill(toInt(a / 60), 2) + ":" + leftZeroFill(toInt(a) % 60, 2);
190
230
  },
191
231
  ZZ : function () {
192
232
  var a = -this.zone(),
@@ -195,7 +235,7 @@
195
235
  a = -a;
196
236
  b = "-";
197
237
  }
198
- return b + leftZeroFill(~~(10 * a / 6), 4);
238
+ return b + leftZeroFill(toInt(10 * a / 6), 4);
199
239
  },
200
240
  z : function () {
201
241
  return this.zoneAbbr();
@@ -206,7 +246,9 @@
206
246
  X : function () {
207
247
  return this.unix();
208
248
  }
209
- };
249
+ },
250
+
251
+ lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin'];
210
252
 
211
253
  function padToken(func, count) {
212
254
  return function (a) {
@@ -240,19 +282,21 @@
240
282
 
241
283
  // Moment prototype object
242
284
  function Moment(config) {
285
+ checkOverflow(config);
243
286
  extend(this, config);
244
287
  }
245
288
 
246
289
  // Duration Constructor
247
290
  function Duration(duration) {
248
- var years = duration.years || duration.year || duration.y || 0,
249
- months = duration.months || duration.month || duration.M || 0,
250
- weeks = duration.weeks || duration.week || duration.w || 0,
251
- days = duration.days || duration.day || duration.d || 0,
252
- hours = duration.hours || duration.hour || duration.h || 0,
253
- minutes = duration.minutes || duration.minute || duration.m || 0,
254
- seconds = duration.seconds || duration.second || duration.s || 0,
255
- milliseconds = duration.milliseconds || duration.millisecond || duration.ms || 0;
291
+ var normalizedInput = normalizeObjectUnits(duration),
292
+ years = normalizedInput.year || 0,
293
+ months = normalizedInput.month || 0,
294
+ weeks = normalizedInput.week || 0,
295
+ days = normalizedInput.day || 0,
296
+ hours = normalizedInput.hour || 0,
297
+ minutes = normalizedInput.minute || 0,
298
+ seconds = normalizedInput.second || 0,
299
+ milliseconds = normalizedInput.millisecond || 0;
256
300
 
257
301
  // store reference to input for deterministic cloning
258
302
  this._input = duration;
@@ -277,7 +321,6 @@
277
321
  this._bubble();
278
322
  }
279
323
 
280
-
281
324
  /************************************
282
325
  Helpers
283
326
  ************************************/
@@ -289,6 +332,15 @@
289
332
  a[i] = b[i];
290
333
  }
291
334
  }
335
+
336
+ if (b.hasOwnProperty("toString")) {
337
+ a.toString = b.toString;
338
+ }
339
+
340
+ if (b.hasOwnProperty("valueOf")) {
341
+ a.valueOf = b.valueOf;
342
+ }
343
+
292
344
  return a;
293
345
  }
294
346
 
@@ -347,14 +399,20 @@
347
399
  return Object.prototype.toString.call(input) === '[object Array]';
348
400
  }
349
401
 
402
+ function isDate(input) {
403
+ return Object.prototype.toString.call(input) === '[object Date]' ||
404
+ input instanceof Date;
405
+ }
406
+
350
407
  // compare two arrays, return the number of differences
351
- function compareArrays(array1, array2) {
408
+ function compareArrays(array1, array2, dontConvert) {
352
409
  var len = Math.min(array1.length, array2.length),
353
410
  lengthDiff = Math.abs(array1.length - array2.length),
354
411
  diffs = 0,
355
412
  i;
356
413
  for (i = 0; i < len; i++) {
357
- if (~~array1[i] !== ~~array2[i]) {
414
+ if ((dontConvert && array1[i] !== array2[i]) ||
415
+ (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
358
416
  diffs++;
359
417
  }
360
418
  }
@@ -362,9 +420,157 @@
362
420
  }
363
421
 
364
422
  function normalizeUnits(units) {
365
- return units ? unitAliases[units] || units.toLowerCase().replace(/(.)s$/, '$1') : units;
423
+ if (units) {
424
+ var lowered = units.toLowerCase().replace(/(.)s$/, '$1');
425
+ units = unitAliases[units] || camelFunctions[lowered] || lowered;
426
+ }
427
+ return units;
428
+ }
429
+
430
+ function normalizeObjectUnits(inputObject) {
431
+ var normalizedInput = {},
432
+ normalizedProp,
433
+ prop,
434
+ index;
435
+
436
+ for (prop in inputObject) {
437
+ if (inputObject.hasOwnProperty(prop)) {
438
+ normalizedProp = normalizeUnits(prop);
439
+ if (normalizedProp) {
440
+ normalizedInput[normalizedProp] = inputObject[prop];
441
+ }
442
+ }
443
+ }
444
+
445
+ return normalizedInput;
446
+ }
447
+
448
+ function makeList(field) {
449
+ var count, setter;
450
+
451
+ if (field.indexOf('week') === 0) {
452
+ count = 7;
453
+ setter = 'day';
454
+ }
455
+ else if (field.indexOf('month') === 0) {
456
+ count = 12;
457
+ setter = 'month';
458
+ }
459
+ else {
460
+ return;
461
+ }
462
+
463
+ moment[field] = function (format, index) {
464
+ var i, getter,
465
+ method = moment.fn._lang[field],
466
+ results = [];
467
+
468
+ if (typeof format === 'number') {
469
+ index = format;
470
+ format = undefined;
471
+ }
472
+
473
+ getter = function (i) {
474
+ var m = moment().utc().set(setter, i);
475
+ return method.call(moment.fn._lang, m, format || '');
476
+ };
477
+
478
+ if (index != null) {
479
+ return getter(index);
480
+ }
481
+ else {
482
+ for (i = 0; i < count; i++) {
483
+ results.push(getter(i));
484
+ }
485
+ return results;
486
+ }
487
+ };
488
+ }
489
+
490
+ function toInt(argumentForCoercion) {
491
+ var coercedNumber = +argumentForCoercion,
492
+ value = 0;
493
+
494
+ if (coercedNumber !== 0 && isFinite(coercedNumber)) {
495
+ if (coercedNumber >= 0) {
496
+ value = Math.floor(coercedNumber);
497
+ } else {
498
+ value = Math.ceil(coercedNumber);
499
+ }
500
+ }
501
+
502
+ return value;
503
+ }
504
+
505
+ function daysInMonth(year, month) {
506
+ return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
507
+ }
508
+
509
+ function daysInYear(year) {
510
+ return isLeapYear(year) ? 366 : 365;
511
+ }
512
+
513
+ function isLeapYear(year) {
514
+ return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
366
515
  }
367
516
 
517
+ function checkOverflow(m) {
518
+ var overflow;
519
+ if (m._a && m._pf.overflow === -2) {
520
+ overflow =
521
+ m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH :
522
+ m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE :
523
+ m._a[HOUR] < 0 || m._a[HOUR] > 23 ? HOUR :
524
+ m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE :
525
+ m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND :
526
+ m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND :
527
+ -1;
528
+
529
+ if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
530
+ overflow = DATE;
531
+ }
532
+
533
+ m._pf.overflow = overflow;
534
+ }
535
+ }
536
+
537
+ function initializeParsingFlags(config) {
538
+ config._pf = {
539
+ empty : false,
540
+ unusedTokens : [],
541
+ unusedInput : [],
542
+ overflow : -2,
543
+ charsLeftOver : 0,
544
+ nullInput : false,
545
+ invalidMonth : null,
546
+ invalidFormat : false,
547
+ userInvalidated : false,
548
+ iso: false
549
+ };
550
+ }
551
+
552
+ function isValid(m) {
553
+ if (m._isValid == null) {
554
+ m._isValid = !isNaN(m._d.getTime()) &&
555
+ m._pf.overflow < 0 &&
556
+ !m._pf.empty &&
557
+ !m._pf.invalidMonth &&
558
+ !m._pf.nullInput &&
559
+ !m._pf.invalidFormat &&
560
+ !m._pf.userInvalidated;
561
+
562
+ if (m._strict) {
563
+ m._isValid = m._isValid &&
564
+ m._pf.charsLeftOver === 0 &&
565
+ m._pf.unusedTokens.length === 0;
566
+ }
567
+ }
568
+ return m._isValid;
569
+ }
570
+
571
+ function normalizeLanguage(key) {
572
+ return key ? key.toLowerCase().replace('_', '-') : key;
573
+ }
368
574
 
369
575
  /************************************
370
576
  Languages
@@ -540,9 +746,15 @@
540
746
  week : function (mom) {
541
747
  return weekOfYear(mom, this._week.dow, this._week.doy).week;
542
748
  },
749
+
543
750
  _week : {
544
751
  dow : 0, // Sunday is the first day of the week.
545
752
  doy : 6 // The week that contains Jan 1st is the first week of the year.
753
+ },
754
+
755
+ _invalidDate: 'Invalid date',
756
+ invalidDate: function () {
757
+ return this._invalidDate;
546
758
  }
547
759
  });
548
760
 
@@ -571,20 +783,52 @@
571
783
  // definition for 'en', so long as 'en' has already been loaded using
572
784
  // moment.lang.
573
785
  function getLangDefinition(key) {
786
+ var i = 0, j, lang, next, split,
787
+ get = function (k) {
788
+ if (!languages[k] && hasModule) {
789
+ try {
790
+ require('./lang/' + k);
791
+ } catch (e) { }
792
+ }
793
+ return languages[k];
794
+ };
795
+
574
796
  if (!key) {
575
797
  return moment.fn._lang;
576
798
  }
577
- if (!languages[key] && hasModule) {
578
- try {
579
- require('./lang/' + key);
580
- } catch (e) {
581
- // call with no params to set to default
582
- return moment.fn._lang;
799
+
800
+ if (!isArray(key)) {
801
+ //short-circuit everything else
802
+ lang = get(key);
803
+ if (lang) {
804
+ return lang;
583
805
  }
806
+ key = [key];
584
807
  }
585
- return languages[key] || moment.fn._lang;
586
- }
587
808
 
809
+ //pick the language from the array
810
+ //try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
811
+ //substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
812
+ while (i < key.length) {
813
+ split = normalizeLanguage(key[i]).split('-');
814
+ j = split.length;
815
+ next = normalizeLanguage(key[i + 1]);
816
+ next = next ? next.split('-') : null;
817
+ while (j > 0) {
818
+ lang = get(split.slice(0, j).join('-'));
819
+ if (lang) {
820
+ return lang;
821
+ }
822
+ if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
823
+ //the next array item is better than a shallower substring of this one
824
+ break;
825
+ }
826
+ j--;
827
+ }
828
+ i++;
829
+ }
830
+ return moment.fn._lang;
831
+ }
588
832
 
589
833
  /************************************
590
834
  Formatting
@@ -592,7 +836,7 @@
592
836
 
593
837
 
594
838
  function removeFormattingTokens(input) {
595
- if (input.match(/\[.*\]/)) {
839
+ if (input.match(/\[[\s\S]/)) {
596
840
  return input.replace(/^\[|\]$/g, "");
597
841
  }
598
842
  return input.replace(/\\/g, "");
@@ -621,6 +865,10 @@
621
865
  // format date using native date object
622
866
  function formatMoment(m, format) {
623
867
 
868
+ if (!m.isValid()) {
869
+ return m.lang().invalidDate();
870
+ }
871
+
624
872
  format = expandFormat(format, m.lang());
625
873
 
626
874
  if (!formatFunctions[format]) {
@@ -637,9 +885,11 @@
637
885
  return lang.longDateFormat(input) || input;
638
886
  }
639
887
 
640
- while (i-- && (localFormattingTokens.lastIndex = 0,
641
- localFormattingTokens.test(format))) {
888
+ localFormattingTokens.lastIndex = 0;
889
+ while (i >= 0 && localFormattingTokens.test(format)) {
642
890
  format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
891
+ localFormattingTokens.lastIndex = 0;
892
+ i -= 1;
643
893
  }
644
894
 
645
895
  return format;
@@ -653,12 +903,17 @@
653
903
 
654
904
  // get the regex to find the next token
655
905
  function getParseRegexForToken(token, config) {
906
+ var a;
656
907
  switch (token) {
657
908
  case 'DDDD':
658
909
  return parseTokenThreeDigits;
659
910
  case 'YYYY':
911
+ case 'GGGG':
912
+ case 'gggg':
660
913
  return parseTokenFourDigits;
661
914
  case 'YYYYY':
915
+ case 'GGGGG':
916
+ case 'ggggg':
662
917
  return parseTokenSixDigits;
663
918
  case 'S':
664
919
  case 'SS':
@@ -681,9 +936,13 @@
681
936
  return parseTokenTimezone;
682
937
  case 'T':
683
938
  return parseTokenT;
939
+ case 'SSSS':
940
+ return parseTokenDigits;
684
941
  case 'MM':
685
942
  case 'DD':
686
943
  case 'YY':
944
+ case 'GG':
945
+ case 'gg':
687
946
  case 'HH':
688
947
  case 'hh':
689
948
  case 'mm':
@@ -695,16 +954,23 @@
695
954
  case 'h':
696
955
  case 'm':
697
956
  case 's':
957
+ case 'w':
958
+ case 'ww':
959
+ case 'W':
960
+ case 'WW':
961
+ case 'e':
962
+ case 'E':
698
963
  return parseTokenOneOrTwoDigits;
699
964
  default :
700
- return new RegExp(token.replace('\\', ''));
965
+ a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), "i"));
966
+ return a;
701
967
  }
702
968
  }
703
969
 
704
970
  function timezoneMinutesFromString(string) {
705
971
  var tzchunk = (parseTokenTimezone.exec(string) || [])[0],
706
972
  parts = (tzchunk + '').match(parseTimezoneChunker) || ['-', 0, 0],
707
- minutes = +(parts[1] * 60) + ~~parts[2];
973
+ minutes = +(parts[1] * 60) + toInt(parts[2]);
708
974
 
709
975
  return parts[0] === '+' ? -minutes : minutes;
710
976
  }
@@ -718,7 +984,7 @@
718
984
  case 'M' : // fall through to MM
719
985
  case 'MM' :
720
986
  if (input != null) {
721
- datePartArray[1] = ~~input - 1;
987
+ datePartArray[MONTH] = toInt(input) - 1;
722
988
  }
723
989
  break;
724
990
  case 'MMM' : // fall through to MMMM
@@ -726,33 +992,33 @@
726
992
  a = getLangDefinition(config._l).monthsParse(input);
727
993
  // if we didn't find a month name, mark the date as invalid.
728
994
  if (a != null) {
729
- datePartArray[1] = a;
995
+ datePartArray[MONTH] = a;
730
996
  } else {
731
- config._isValid = false;
997
+ config._pf.invalidMonth = input;
732
998
  }
733
999
  break;
734
1000
  // DAY OF MONTH
735
1001
  case 'D' : // fall through to DD
736
1002
  case 'DD' :
737
1003
  if (input != null) {
738
- datePartArray[2] = ~~input;
1004
+ datePartArray[DATE] = toInt(input);
739
1005
  }
740
1006
  break;
741
1007
  // DAY OF YEAR
742
1008
  case 'DDD' : // fall through to DDDD
743
1009
  case 'DDDD' :
744
1010
  if (input != null) {
745
- datePartArray[1] = 0;
746
- datePartArray[2] = ~~input;
1011
+ config._dayOfYear = toInt(input);
747
1012
  }
1013
+
748
1014
  break;
749
1015
  // YEAR
750
1016
  case 'YY' :
751
- datePartArray[0] = ~~input + (~~input > 68 ? 1900 : 2000);
1017
+ datePartArray[YEAR] = toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
752
1018
  break;
753
1019
  case 'YYYY' :
754
1020
  case 'YYYYY' :
755
- datePartArray[0] = ~~input;
1021
+ datePartArray[YEAR] = toInt(input);
756
1022
  break;
757
1023
  // AM / PM
758
1024
  case 'a' : // fall through to A
@@ -764,23 +1030,24 @@
764
1030
  case 'HH' : // fall through to hh
765
1031
  case 'h' : // fall through to hh
766
1032
  case 'hh' :
767
- datePartArray[3] = ~~input;
1033
+ datePartArray[HOUR] = toInt(input);
768
1034
  break;
769
1035
  // MINUTE
770
1036
  case 'm' : // fall through to mm
771
1037
  case 'mm' :
772
- datePartArray[4] = ~~input;
1038
+ datePartArray[MINUTE] = toInt(input);
773
1039
  break;
774
1040
  // SECOND
775
1041
  case 's' : // fall through to ss
776
1042
  case 'ss' :
777
- datePartArray[5] = ~~input;
1043
+ datePartArray[SECOND] = toInt(input);
778
1044
  break;
779
1045
  // MILLISECOND
780
1046
  case 'S' :
781
1047
  case 'SS' :
782
1048
  case 'SSS' :
783
- datePartArray[6] = ~~ (('0.' + input) * 1000);
1049
+ case 'SSSS' :
1050
+ datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000);
784
1051
  break;
785
1052
  // UNIX TIMESTAMP WITH MS
786
1053
  case 'X':
@@ -792,11 +1059,29 @@
792
1059
  config._useUTC = true;
793
1060
  config._tzm = timezoneMinutesFromString(input);
794
1061
  break;
795
- }
796
-
797
- // if the input is null, the date is not valid
798
- if (input == null) {
799
- config._isValid = false;
1062
+ case 'w':
1063
+ case 'ww':
1064
+ case 'W':
1065
+ case 'WW':
1066
+ case 'd':
1067
+ case 'dd':
1068
+ case 'ddd':
1069
+ case 'dddd':
1070
+ case 'e':
1071
+ case 'E':
1072
+ token = token.substr(0, 1);
1073
+ /* falls through */
1074
+ case 'gg':
1075
+ case 'gggg':
1076
+ case 'GG':
1077
+ case 'GGGG':
1078
+ case 'GGGGG':
1079
+ token = token.substr(0, 2);
1080
+ if (input) {
1081
+ config._w = config._w || {};
1082
+ config._w[token] = input;
1083
+ }
1084
+ break;
800
1085
  }
801
1086
  }
802
1087
 
@@ -804,19 +1089,65 @@
804
1089
  // the array should mirror the parameters below
805
1090
  // note: all values past the year are optional and will default to the lowest possible value.
806
1091
  // [year, month, day , hour, minute, second, millisecond]
807
- function dateFromArray(config) {
808
- var i, date, input = [], currentDate;
1092
+ function dateFromConfig(config) {
1093
+ var i, date, input = [], currentDate,
1094
+ yearToUse, fixYear, w, temp, lang, weekday, week;
809
1095
 
810
1096
  if (config._d) {
811
1097
  return;
812
1098
  }
813
1099
 
1100
+ currentDate = currentDateArray(config);
1101
+
1102
+ //compute day of the year from weeks and weekdays
1103
+ if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
1104
+ fixYear = function (val) {
1105
+ return val ?
1106
+ (val.length < 3 ? (parseInt(val, 10) > 68 ? '19' + val : '20' + val) : val) :
1107
+ (config._a[YEAR] == null ? moment().weekYear() : config._a[YEAR]);
1108
+ };
1109
+
1110
+ w = config._w;
1111
+ if (w.GG != null || w.W != null || w.E != null) {
1112
+ temp = dayOfYearFromWeeks(fixYear(w.GG), w.W || 1, w.E, 4, 1);
1113
+ }
1114
+ else {
1115
+ lang = getLangDefinition(config._l);
1116
+ weekday = w.d != null ? parseWeekday(w.d, lang) :
1117
+ (w.e != null ? parseInt(w.e, 10) + lang._week.dow : 0);
1118
+
1119
+ week = parseInt(w.w, 10) || 1;
1120
+
1121
+ //if we're parsing 'd', then the low day numbers may be next week
1122
+ if (w.d != null && weekday < lang._week.dow) {
1123
+ week++;
1124
+ }
1125
+
1126
+ temp = dayOfYearFromWeeks(fixYear(w.gg), week, weekday, lang._week.doy, lang._week.dow);
1127
+ }
1128
+
1129
+ config._a[YEAR] = temp.year;
1130
+ config._dayOfYear = temp.dayOfYear;
1131
+ }
1132
+
1133
+ //if the day of the year is set, figure out what it is
1134
+ if (config._dayOfYear) {
1135
+ yearToUse = config._a[YEAR] == null ? currentDate[YEAR] : config._a[YEAR];
1136
+
1137
+ if (config._dayOfYear > daysInYear(yearToUse)) {
1138
+ config._pf._overflowDayOfYear = true;
1139
+ }
1140
+
1141
+ date = makeUTCDate(yearToUse, 0, config._dayOfYear);
1142
+ config._a[MONTH] = date.getUTCMonth();
1143
+ config._a[DATE] = date.getUTCDate();
1144
+ }
1145
+
814
1146
  // Default to current date.
815
1147
  // * if no year, month, day of month are given, default to today
816
1148
  // * if day of month is given, default month and year
817
1149
  // * if month is given, default only year
818
1150
  // * if year is given, don't default anything
819
- currentDate = currentDateArray(config);
820
1151
  for (i = 0; i < 3 && config._a[i] == null; ++i) {
821
1152
  config._a[i] = input[i] = currentDate[i];
822
1153
  }
@@ -827,40 +1158,31 @@
827
1158
  }
828
1159
 
829
1160
  // add the offsets to the time to be parsed so that we can have a clean array for checking isValid
830
- input[3] += ~~((config._tzm || 0) / 60);
831
- input[4] += ~~((config._tzm || 0) % 60);
1161
+ input[HOUR] += toInt((config._tzm || 0) / 60);
1162
+ input[MINUTE] += toInt((config._tzm || 0) % 60);
832
1163
 
833
- date = new Date(0);
834
-
835
- if (config._useUTC) {
836
- date.setUTCFullYear(input[0], input[1], input[2]);
837
- date.setUTCHours(input[3], input[4], input[5], input[6]);
838
- } else {
839
- date.setFullYear(input[0], input[1], input[2]);
840
- date.setHours(input[3], input[4], input[5], input[6]);
841
- }
842
-
843
- config._d = date;
1164
+ config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input);
844
1165
  }
845
1166
 
846
1167
  function dateFromObject(config) {
847
- var o = config._i;
1168
+ var normalizedInput;
848
1169
 
849
1170
  if (config._d) {
850
1171
  return;
851
1172
  }
852
1173
 
1174
+ normalizedInput = normalizeObjectUnits(config._i);
853
1175
  config._a = [
854
- o.years || o.year || o.y,
855
- o.months || o.month || o.M,
856
- o.days || o.day || o.d,
857
- o.hours || o.hour || o.h,
858
- o.minutes || o.minute || o.m,
859
- o.seconds || o.second || o.s,
860
- o.milliseconds || o.millisecond || o.ms
1176
+ normalizedInput.year,
1177
+ normalizedInput.month,
1178
+ normalizedInput.day,
1179
+ normalizedInput.hour,
1180
+ normalizedInput.minute,
1181
+ normalizedInput.second,
1182
+ normalizedInput.millisecond
861
1183
  ];
862
1184
 
863
- dateFromArray(config);
1185
+ dateFromConfig(config);
864
1186
  }
865
1187
 
866
1188
  function currentDateArray(config) {
@@ -878,74 +1200,116 @@
878
1200
 
879
1201
  // date from string and format string
880
1202
  function makeDateFromStringAndFormat(config) {
1203
+
1204
+ config._a = [];
1205
+ config._pf.empty = true;
1206
+
881
1207
  // This array is used to make a Date, either with `new Date` or `Date.UTC`
882
1208
  var lang = getLangDefinition(config._l),
883
1209
  string = '' + config._i,
884
- i, parsedInput, tokens;
1210
+ i, parsedInput, tokens, token, skipped,
1211
+ stringLength = string.length,
1212
+ totalParsedInputLength = 0;
885
1213
 
886
- tokens = expandFormat(config._f, lang).match(formattingTokens);
887
-
888
- config._a = [];
1214
+ tokens = expandFormat(config._f, lang).match(formattingTokens) || [];
889
1215
 
890
1216
  for (i = 0; i < tokens.length; i++) {
891
- parsedInput = (getParseRegexForToken(tokens[i], config).exec(string) || [])[0];
1217
+ token = tokens[i];
1218
+ parsedInput = (getParseRegexForToken(token, config).exec(string) || [])[0];
892
1219
  if (parsedInput) {
1220
+ skipped = string.substr(0, string.indexOf(parsedInput));
1221
+ if (skipped.length > 0) {
1222
+ config._pf.unusedInput.push(skipped);
1223
+ }
893
1224
  string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
1225
+ totalParsedInputLength += parsedInput.length;
894
1226
  }
895
- // don't parse if its not a known token
896
- if (formatTokenFunctions[tokens[i]]) {
897
- addTimeToArrayFromToken(tokens[i], parsedInput, config);
1227
+ // don't parse if it's not a known token
1228
+ if (formatTokenFunctions[token]) {
1229
+ if (parsedInput) {
1230
+ config._pf.empty = false;
1231
+ }
1232
+ else {
1233
+ config._pf.unusedTokens.push(token);
1234
+ }
1235
+ addTimeToArrayFromToken(token, parsedInput, config);
1236
+ }
1237
+ else if (config._strict && !parsedInput) {
1238
+ config._pf.unusedTokens.push(token);
898
1239
  }
899
1240
  }
900
1241
 
901
- // add remaining unparsed input to the string
902
- if (string) {
903
- config._il = string;
1242
+ // add remaining unparsed input length to the string
1243
+ config._pf.charsLeftOver = stringLength - totalParsedInputLength;
1244
+ if (string.length > 0) {
1245
+ config._pf.unusedInput.push(string);
904
1246
  }
905
1247
 
906
1248
  // handle am pm
907
- if (config._isPm && config._a[3] < 12) {
908
- config._a[3] += 12;
1249
+ if (config._isPm && config._a[HOUR] < 12) {
1250
+ config._a[HOUR] += 12;
909
1251
  }
910
1252
  // if is 12 am, change hours to 0
911
- if (config._isPm === false && config._a[3] === 12) {
912
- config._a[3] = 0;
1253
+ if (config._isPm === false && config._a[HOUR] === 12) {
1254
+ config._a[HOUR] = 0;
913
1255
  }
914
- // return
915
- dateFromArray(config);
1256
+
1257
+ dateFromConfig(config);
1258
+ checkOverflow(config);
1259
+ }
1260
+
1261
+ function unescapeFormat(s) {
1262
+ return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
1263
+ return p1 || p2 || p3 || p4;
1264
+ });
1265
+ }
1266
+
1267
+ // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
1268
+ function regexpEscape(s) {
1269
+ return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
916
1270
  }
917
1271
 
918
1272
  // date from string and array of format strings
919
1273
  function makeDateFromStringAndArray(config) {
920
1274
  var tempConfig,
921
- tempMoment,
922
1275
  bestMoment,
923
1276
 
924
- scoreToBeat = 99,
1277
+ scoreToBeat,
925
1278
  i,
926
1279
  currentScore;
927
1280
 
1281
+ if (config._f.length === 0) {
1282
+ config._pf.invalidFormat = true;
1283
+ config._d = new Date(NaN);
1284
+ return;
1285
+ }
1286
+
928
1287
  for (i = 0; i < config._f.length; i++) {
1288
+ currentScore = 0;
929
1289
  tempConfig = extend({}, config);
1290
+ initializeParsingFlags(tempConfig);
930
1291
  tempConfig._f = config._f[i];
931
1292
  makeDateFromStringAndFormat(tempConfig);
932
- tempMoment = new Moment(tempConfig);
933
-
934
- currentScore = compareArrays(tempConfig._a, tempMoment.toArray());
935
1293
 
936
- // if there is any input that was not parsed
937
- // add a penalty for that format
938
- if (tempMoment._il) {
939
- currentScore += tempMoment._il.length;
1294
+ if (!isValid(tempConfig)) {
1295
+ continue;
940
1296
  }
941
1297
 
942
- if (currentScore < scoreToBeat) {
1298
+ // if there is any input that was not parsed add a penalty for that format
1299
+ currentScore += tempConfig._pf.charsLeftOver;
1300
+
1301
+ //or tokens
1302
+ currentScore += tempConfig._pf.unusedTokens.length * 10;
1303
+
1304
+ tempConfig._pf.score = currentScore;
1305
+
1306
+ if (scoreToBeat == null || currentScore < scoreToBeat) {
943
1307
  scoreToBeat = currentScore;
944
- bestMoment = tempMoment;
1308
+ bestMoment = tempConfig;
945
1309
  }
946
1310
  }
947
1311
 
948
- extend(config, bestMoment);
1312
+ extend(config, bestMoment || tempConfig);
949
1313
  }
950
1314
 
951
1315
  // date from iso format
@@ -955,8 +1319,14 @@
955
1319
  match = isoRegex.exec(string);
956
1320
 
957
1321
  if (match) {
958
- // match[2] should be "T" or undefined
959
- config._f = 'YYYY-MM-DD' + (match[2] || " ");
1322
+ config._pf.iso = true;
1323
+ for (i = 4; i > 0; i--) {
1324
+ if (match[i]) {
1325
+ // match[5] should be "T" or undefined
1326
+ config._f = isoDates[i - 1] + (match[6] || " ");
1327
+ break;
1328
+ }
1329
+ }
960
1330
  for (i = 0; i < 4; i++) {
961
1331
  if (isoTimes[i][1].exec(string)) {
962
1332
  config._f += isoTimes[i][0];
@@ -964,10 +1334,11 @@
964
1334
  }
965
1335
  }
966
1336
  if (parseTokenTimezone.exec(string)) {
967
- config._f += " Z";
1337
+ config._f += "Z";
968
1338
  }
969
1339
  makeDateFromStringAndFormat(config);
970
- } else {
1340
+ }
1341
+ else {
971
1342
  config._d = new Date(string);
972
1343
  }
973
1344
  }
@@ -984,8 +1355,8 @@
984
1355
  makeDateFromString(config);
985
1356
  } else if (isArray(input)) {
986
1357
  config._a = input.slice(0);
987
- dateFromArray(config);
988
- } else if (input instanceof Date) {
1358
+ dateFromConfig(config);
1359
+ } else if (isDate(input)) {
989
1360
  config._d = new Date(+input);
990
1361
  } else if (typeof(input) === 'object') {
991
1362
  dateFromObject(config);
@@ -994,6 +1365,40 @@
994
1365
  }
995
1366
  }
996
1367
 
1368
+ function makeDate(y, m, d, h, M, s, ms) {
1369
+ //can't just apply() to create a date:
1370
+ //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
1371
+ var date = new Date(y, m, d, h, M, s, ms);
1372
+
1373
+ //the date constructor doesn't accept years < 1970
1374
+ if (y < 1970) {
1375
+ date.setFullYear(y);
1376
+ }
1377
+ return date;
1378
+ }
1379
+
1380
+ function makeUTCDate(y) {
1381
+ var date = new Date(Date.UTC.apply(null, arguments));
1382
+ if (y < 1970) {
1383
+ date.setUTCFullYear(y);
1384
+ }
1385
+ return date;
1386
+ }
1387
+
1388
+ function parseWeekday(input, language) {
1389
+ if (typeof input === 'string') {
1390
+ if (!isNaN(input)) {
1391
+ input = parseInt(input, 10);
1392
+ }
1393
+ else {
1394
+ input = language.weekdaysParse(input);
1395
+ if (typeof input !== 'number') {
1396
+ return null;
1397
+ }
1398
+ }
1399
+ }
1400
+ return input;
1401
+ }
997
1402
 
998
1403
  /************************************
999
1404
  Relative Time
@@ -1061,6 +1466,20 @@
1061
1466
  };
1062
1467
  }
1063
1468
 
1469
+ //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
1470
+ function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) {
1471
+ var d = new Date(Date.UTC(year, 0)).getUTCDay(),
1472
+ daysToAdd, dayOfYear;
1473
+
1474
+ weekday = weekday != null ? weekday : firstDayOfWeek;
1475
+ daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0);
1476
+ dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1;
1477
+
1478
+ return {
1479
+ year: dayOfYear > 0 ? year : year - 1,
1480
+ dayOfYear: dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear
1481
+ };
1482
+ }
1064
1483
 
1065
1484
  /************************************
1066
1485
  Top Level Functions
@@ -1070,8 +1489,12 @@
1070
1489
  var input = config._i,
1071
1490
  format = config._f;
1072
1491
 
1073
- if (input === null || input === '') {
1074
- return null;
1492
+ if (typeof config._pf === 'undefined') {
1493
+ initializeParsingFlags(config);
1494
+ }
1495
+
1496
+ if (input === null) {
1497
+ return moment.invalid({nullInput: true});
1075
1498
  }
1076
1499
 
1077
1500
  if (typeof input === 'string') {
@@ -1080,6 +1503,7 @@
1080
1503
 
1081
1504
  if (moment.isMoment(input)) {
1082
1505
  config = extend({}, input);
1506
+
1083
1507
  config._d = new Date(+input._d);
1084
1508
  } else if (format) {
1085
1509
  if (isArray(format)) {
@@ -1094,24 +1518,38 @@
1094
1518
  return new Moment(config);
1095
1519
  }
1096
1520
 
1097
- moment = function (input, format, lang) {
1521
+ moment = function (input, format, lang, strict) {
1522
+ if (typeof(lang) === "boolean") {
1523
+ strict = lang;
1524
+ lang = undefined;
1525
+ }
1098
1526
  return makeMoment({
1099
1527
  _i : input,
1100
1528
  _f : format,
1101
1529
  _l : lang,
1530
+ _strict : strict,
1102
1531
  _isUTC : false
1103
1532
  });
1104
1533
  };
1105
1534
 
1106
1535
  // creating with utc
1107
- moment.utc = function (input, format, lang) {
1108
- return makeMoment({
1536
+ moment.utc = function (input, format, lang, strict) {
1537
+ var m;
1538
+
1539
+ if (typeof(lang) === "boolean") {
1540
+ strict = lang;
1541
+ lang = undefined;
1542
+ }
1543
+ m = makeMoment({
1109
1544
  _useUTC : true,
1110
1545
  _isUTC : true,
1111
1546
  _l : lang,
1112
1547
  _i : input,
1113
- _f : format
1548
+ _f : format,
1549
+ _strict : strict
1114
1550
  }).utc();
1551
+
1552
+ return m;
1115
1553
  };
1116
1554
 
1117
1555
  // creating with unix timestamp (in seconds)
@@ -1124,9 +1562,13 @@
1124
1562
  var isDuration = moment.isDuration(input),
1125
1563
  isNumber = (typeof input === 'number'),
1126
1564
  duration = (isDuration ? input._input : (isNumber ? {} : input)),
1127
- matched = aspNetTimeSpanJsonRegex.exec(input),
1565
+ // matching against regexp is expensive, do it on demand
1566
+ match = null,
1128
1567
  sign,
1129
- ret;
1568
+ ret,
1569
+ parseIso,
1570
+ timeEmpty,
1571
+ dateTimeEmpty;
1130
1572
 
1131
1573
  if (isNumber) {
1132
1574
  if (key) {
@@ -1134,15 +1576,34 @@
1134
1576
  } else {
1135
1577
  duration.milliseconds = input;
1136
1578
  }
1137
- } else if (matched) {
1138
- sign = (matched[1] === "-") ? -1 : 1;
1579
+ } else if (!!(match = aspNetTimeSpanJsonRegex.exec(input))) {
1580
+ sign = (match[1] === "-") ? -1 : 1;
1139
1581
  duration = {
1140
1582
  y: 0,
1141
- d: ~~matched[2] * sign,
1142
- h: ~~matched[3] * sign,
1143
- m: ~~matched[4] * sign,
1144
- s: ~~matched[5] * sign,
1145
- ms: ~~matched[6] * sign
1583
+ d: toInt(match[DATE]) * sign,
1584
+ h: toInt(match[HOUR]) * sign,
1585
+ m: toInt(match[MINUTE]) * sign,
1586
+ s: toInt(match[SECOND]) * sign,
1587
+ ms: toInt(match[MILLISECOND]) * sign
1588
+ };
1589
+ } else if (!!(match = isoDurationRegex.exec(input))) {
1590
+ sign = (match[1] === "-") ? -1 : 1;
1591
+ parseIso = function (inp) {
1592
+ // We'd normally use ~~inp for this, but unfortunately it also
1593
+ // converts floats to ints.
1594
+ // inp may be undefined, so careful calling replace on it.
1595
+ var res = inp && parseFloat(inp.replace(',', '.'));
1596
+ // apply sign while we're at it
1597
+ return (isNaN(res) ? 0 : res) * sign;
1598
+ };
1599
+ duration = {
1600
+ y: parseIso(match[2]),
1601
+ M: parseIso(match[3]),
1602
+ d: parseIso(match[4]),
1603
+ h: parseIso(match[5]),
1604
+ m: parseIso(match[6]),
1605
+ s: parseIso(match[7]),
1606
+ w: parseIso(match[8])
1146
1607
  };
1147
1608
  }
1148
1609
 
@@ -1169,20 +1630,20 @@
1169
1630
  // no arguments are passed in, it will simply return the current global
1170
1631
  // language key.
1171
1632
  moment.lang = function (key, values) {
1633
+ var r;
1172
1634
  if (!key) {
1173
1635
  return moment.fn._lang._abbr;
1174
1636
  }
1175
- key = key.toLowerCase();
1176
- key = key.replace('_', '-');
1177
1637
  if (values) {
1178
- loadLang(key, values);
1638
+ loadLang(normalizeLanguage(key), values);
1179
1639
  } else if (values === null) {
1180
1640
  unloadLang(key);
1181
1641
  key = 'en';
1182
1642
  } else if (!languages[key]) {
1183
1643
  getLangDefinition(key);
1184
1644
  }
1185
- moment.duration.fn._lang = moment.fn._lang = getLangDefinition(key);
1645
+ r = moment.duration.fn._lang = moment.fn._lang = getLangDefinition(key);
1646
+ return r._abbr;
1186
1647
  };
1187
1648
 
1188
1649
  // returns language data
@@ -1203,6 +1664,29 @@
1203
1664
  return obj instanceof Duration;
1204
1665
  };
1205
1666
 
1667
+ for (i = lists.length - 1; i >= 0; --i) {
1668
+ makeList(lists[i]);
1669
+ }
1670
+
1671
+ moment.normalizeUnits = function (units) {
1672
+ return normalizeUnits(units);
1673
+ };
1674
+
1675
+ moment.invalid = function (flags) {
1676
+ var m = moment.utc(NaN);
1677
+ if (flags != null) {
1678
+ extend(m._pf, flags);
1679
+ }
1680
+ else {
1681
+ m._pf.userInvalidated = true;
1682
+ }
1683
+
1684
+ return m;
1685
+ };
1686
+
1687
+ moment.parseZone = function (input) {
1688
+ return moment(input).parseZone();
1689
+ };
1206
1690
 
1207
1691
  /************************************
1208
1692
  Moment Prototype
@@ -1224,7 +1708,7 @@
1224
1708
  },
1225
1709
 
1226
1710
  toString : function () {
1227
- return this.format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ");
1711
+ return this.clone().lang('en').format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ");
1228
1712
  },
1229
1713
 
1230
1714
  toDate : function () {
@@ -1249,22 +1733,24 @@
1249
1733
  },
1250
1734
 
1251
1735
  isValid : function () {
1252
- if (this._isValid == null) {
1253
- if (this._a) {
1254
- this._isValid = !compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray());
1255
- } else {
1256
- this._isValid = !isNaN(this._d.getTime());
1257
- }
1736
+ return isValid(this);
1737
+ },
1738
+
1739
+ isDSTShifted : function () {
1740
+
1741
+ if (this._a) {
1742
+ return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0;
1258
1743
  }
1259
- return !!this._isValid;
1744
+
1745
+ return false;
1746
+ },
1747
+
1748
+ parsingFlags : function () {
1749
+ return extend({}, this._pf);
1260
1750
  },
1261
1751
 
1262
1752
  invalidAt: function () {
1263
- var i, arr1 = this._a, arr2 = (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray();
1264
- for (i = 6; i >= 0 && arr1[i] === arr2[i]; --i) {
1265
- // empty loop body
1266
- }
1267
- return i;
1753
+ return this._pf.overflow;
1268
1754
  },
1269
1755
 
1270
1756
  utc : function () {
@@ -1360,8 +1846,7 @@
1360
1846
  },
1361
1847
 
1362
1848
  isLeapYear : function () {
1363
- var year = this.year();
1364
- return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
1849
+ return isLeapYear(this.year());
1365
1850
  },
1366
1851
 
1367
1852
  isDST : function () {
@@ -1372,12 +1857,7 @@
1372
1857
  day : function (input) {
1373
1858
  var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
1374
1859
  if (input != null) {
1375
- if (typeof input === 'string') {
1376
- input = this.lang().weekdaysParse(input);
1377
- if (typeof input !== 'number') {
1378
- return this;
1379
- }
1380
- }
1860
+ input = parseWeekday(input, this.lang());
1381
1861
  return this.add({ d : input - day });
1382
1862
  } else {
1383
1863
  return day;
@@ -1420,7 +1900,7 @@
1420
1900
  this.date(1);
1421
1901
  /* falls through */
1422
1902
  case 'week':
1423
- case 'isoweek':
1903
+ case 'isoWeek':
1424
1904
  case 'day':
1425
1905
  this.hours(0);
1426
1906
  /* falls through */
@@ -1438,7 +1918,7 @@
1438
1918
  // weeks are a special case
1439
1919
  if (units === 'week') {
1440
1920
  this.weekday(0);
1441
- } else if (units === 'isoweek') {
1921
+ } else if (units === 'isoWeek') {
1442
1922
  this.isoWeekday(1);
1443
1923
  }
1444
1924
 
@@ -1447,7 +1927,7 @@
1447
1927
 
1448
1928
  endOf: function (units) {
1449
1929
  units = normalizeUnits(units);
1450
- return this.startOf(units).add((units === 'isoweek' ? 'week' : units), 1).subtract('ms', 1);
1930
+ return this.startOf(units).add((units === 'isoWeek' ? 'week' : units), 1).subtract('ms', 1);
1451
1931
  },
1452
1932
 
1453
1933
  isAfter: function (input, units) {
@@ -1503,6 +1983,13 @@
1503
1983
  return this._isUTC ? "Coordinated Universal Time" : "";
1504
1984
  },
1505
1985
 
1986
+ parseZone : function () {
1987
+ if (typeof this._i === 'string') {
1988
+ this.zone(this._i);
1989
+ }
1990
+ return this;
1991
+ },
1992
+
1506
1993
  hasAlignedHourOffset : function (input) {
1507
1994
  if (!input) {
1508
1995
  input = 0;
@@ -1515,7 +2002,7 @@
1515
2002
  },
1516
2003
 
1517
2004
  daysInMonth : function () {
1518
- return moment.utc([this.year(), this.month() + 1, 0]).date();
2005
+ return daysInMonth(this.year(), this.month());
1519
2006
  },
1520
2007
 
1521
2008
  dayOfYear : function (input) {
@@ -1544,7 +2031,7 @@
1544
2031
  },
1545
2032
 
1546
2033
  weekday : function (input) {
1547
- var weekday = (this._d.getDay() + 7 - this.lang()._week.dow) % 7;
2034
+ var weekday = (this.day() + 7 - this.lang()._week.dow) % 7;
1548
2035
  return input == null ? weekday : this.add("d", input - weekday);
1549
2036
  },
1550
2037
 
@@ -1557,12 +2044,15 @@
1557
2044
 
1558
2045
  get : function (units) {
1559
2046
  units = normalizeUnits(units);
1560
- return this[units.toLowerCase()]();
2047
+ return this[units]();
1561
2048
  },
1562
2049
 
1563
2050
  set : function (units, value) {
1564
2051
  units = normalizeUnits(units);
1565
- this[units.toLowerCase()](value);
2052
+ if (typeof this[units] === 'function') {
2053
+ this[units](value);
2054
+ }
2055
+ return this;
1566
2056
  },
1567
2057
 
1568
2058
  // If passed a language key, it will set the language for this
@@ -1654,7 +2144,7 @@
1654
2144
  return this._milliseconds +
1655
2145
  this._days * 864e5 +
1656
2146
  (this._months % 12) * 2592e6 +
1657
- ~~(this._months / 12) * 31536e6;
2147
+ toInt(this._months / 12) * 31536e6;
1658
2148
  },
1659
2149
 
1660
2150
  humanize : function (withSuffix) {
@@ -1703,7 +2193,33 @@
1703
2193
  return this['as' + units.charAt(0).toUpperCase() + units.slice(1) + 's']();
1704
2194
  },
1705
2195
 
1706
- lang : moment.fn.lang
2196
+ lang : moment.fn.lang,
2197
+
2198
+ toIsoString : function () {
2199
+ // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
2200
+ var years = Math.abs(this.years()),
2201
+ months = Math.abs(this.months()),
2202
+ days = Math.abs(this.days()),
2203
+ hours = Math.abs(this.hours()),
2204
+ minutes = Math.abs(this.minutes()),
2205
+ seconds = Math.abs(this.seconds() + this.milliseconds() / 1000);
2206
+
2207
+ if (!this.asSeconds()) {
2208
+ // this is the same as C#'s (Noda) and python (isodate)...
2209
+ // but not other JS (goog.date)
2210
+ return 'P0D';
2211
+ }
2212
+
2213
+ return (this.asSeconds() < 0 ? '-' : '') +
2214
+ 'P' +
2215
+ (years ? years + 'Y' : '') +
2216
+ (months ? months + 'M' : '') +
2217
+ (days ? days + 'D' : '') +
2218
+ ((hours || minutes || seconds) ? 'T' : '') +
2219
+ (hours ? hours + 'H' : '') +
2220
+ (minutes ? minutes + 'M' : '') +
2221
+ (seconds ? seconds + 'S' : '');
2222
+ }
1707
2223
  });
1708
2224
 
1709
2225
  function makeDurationGetter(name) {
@@ -1740,7 +2256,7 @@
1740
2256
  moment.lang('en', {
1741
2257
  ordinal : function (number) {
1742
2258
  var b = number % 10,
1743
- output = (~~ (number % 100 / 10) === 1) ? 'th' :
2259
+ output = (toInt(number % 100 / 10) === 1) ? 'th' :
1744
2260
  (b === 1) ? 'st' :
1745
2261
  (b === 2) ? 'nd' :
1746
2262
  (b === 3) ? 'rd' : 'th';
@@ -1754,22 +2270,45 @@
1754
2270
  Exposing Moment
1755
2271
  ************************************/
1756
2272
 
1757
-
1758
- // CommonJS module is defined
1759
- if (hasModule) {
1760
- module.exports = moment;
1761
- }
1762
- /*global ender:false */
1763
- if (typeof ender === 'undefined') {
2273
+ function makeGlobal(deprecate) {
2274
+ var warned = false, local_moment = moment;
2275
+ /*global ender:false */
2276
+ if (typeof ender !== 'undefined') {
2277
+ return;
2278
+ }
1764
2279
  // here, `this` means `window` in the browser, or `global` on the server
1765
2280
  // add `moment` as a global object via a string identifier,
1766
2281
  // for Closure Compiler "advanced" mode
1767
- this['moment'] = moment;
2282
+ if (deprecate) {
2283
+ this.moment = function () {
2284
+ if (!warned && console && console.warn) {
2285
+ warned = true;
2286
+ console.warn(
2287
+ "Accessing Moment through the global scope is " +
2288
+ "deprecated, and will be removed in an upcoming " +
2289
+ "release.");
2290
+ }
2291
+ return local_moment.apply(null, arguments);
2292
+ };
2293
+ } else {
2294
+ this['moment'] = moment;
2295
+ }
1768
2296
  }
1769
- /*global define:false */
1770
- if (typeof define === "function" && define.amd) {
1771
- define("moment", [], function () {
2297
+
2298
+ // CommonJS module is defined
2299
+ if (hasModule) {
2300
+ module.exports = moment;
2301
+ makeGlobal(true);
2302
+ } else if (typeof define === "function" && define.amd) {
2303
+ define("moment", function (require, exports, module) {
2304
+ if (module.config().noGlobal !== true) {
2305
+ // If user provided noGlobal, he is aware of global
2306
+ makeGlobal(module.config().noGlobal === undefined);
2307
+ }
2308
+
1772
2309
  return moment;
1773
2310
  });
2311
+ } else {
2312
+ makeGlobal();
1774
2313
  }
1775
2314
  }).call(this);