socializer 0.1.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (291) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +11 -0
  3. data/.gitignore +29 -0
  4. data/.rubocop.yml +42 -0
  5. data/.travis.yml +13 -0
  6. data/CONTRIBUTING.md +46 -0
  7. data/Gemfile +31 -0
  8. data/README.md +91 -0
  9. data/Rakefile +38 -0
  10. data/app/assets/images/socializer/.gitkeep +0 -0
  11. data/app/assets/images/socializer/auth_buttons/facebook_128.png +0 -0
  12. data/app/assets/images/socializer/auth_buttons/facebook_256.png +0 -0
  13. data/app/assets/images/socializer/auth_buttons/facebook_32.png +0 -0
  14. data/app/assets/images/socializer/auth_buttons/facebook_64.png +0 -0
  15. data/app/assets/images/socializer/auth_buttons/google_128.png +0 -0
  16. data/app/assets/images/socializer/auth_buttons/google_256.png +0 -0
  17. data/app/assets/images/socializer/auth_buttons/google_32.png +0 -0
  18. data/app/assets/images/socializer/auth_buttons/google_64.png +0 -0
  19. data/app/assets/images/socializer/auth_buttons/linkedin_128.png +0 -0
  20. data/app/assets/images/socializer/auth_buttons/linkedin_256.png +0 -0
  21. data/app/assets/images/socializer/auth_buttons/linkedin_32.png +0 -0
  22. data/app/assets/images/socializer/auth_buttons/linkedin_64.png +0 -0
  23. data/app/assets/images/socializer/auth_buttons/twitter_128.png +0 -0
  24. data/app/assets/images/socializer/auth_buttons/twitter_256.png +0 -0
  25. data/app/assets/images/socializer/auth_buttons/twitter_32.png +0 -0
  26. data/app/assets/images/socializer/auth_buttons/twitter_64.png +0 -0
  27. data/app/assets/images/socializer/auth_buttons/yahoo_128.png +0 -0
  28. data/app/assets/images/socializer/auth_buttons/yahoo_256.png +0 -0
  29. data/app/assets/images/socializer/auth_buttons/yahoo_32.png +0 -0
  30. data/app/assets/images/socializer/auth_buttons/yahoo_64.png +0 -0
  31. data/app/assets/images/socializer/close.png +0 -0
  32. data/app/assets/images/socializer/icons/Bell.png +0 -0
  33. data/app/assets/images/socializer/icons/Edit.png +0 -0
  34. data/app/assets/images/socializer/icons/Home.png +0 -0
  35. data/app/assets/images/socializer/icons/Power.png +0 -0
  36. data/app/assets/images/socializer/icons/Safe.png +0 -0
  37. data/app/assets/images/socializer/icons/User.png +0 -0
  38. data/app/assets/images/socializer/icons/Users.png +0 -0
  39. data/app/assets/images/socializer/icons/Web.png +0 -0
  40. data/app/assets/images/socializer/loading.gif +0 -0
  41. data/app/assets/images/socializer/next.png +0 -0
  42. data/app/assets/images/socializer/pause.png +0 -0
  43. data/app/assets/images/socializer/play.png +0 -0
  44. data/app/assets/images/socializer/previous.png +0 -0
  45. data/app/assets/javascripts/socializer/activities.js.coffee +47 -0
  46. data/app/assets/javascripts/socializer/application.js +24 -0
  47. data/app/assets/javascripts/socializer/circles.js.coffee +33 -0
  48. data/app/assets/javascripts/socializer/jquery.qtip.min.js +7 -0
  49. data/app/assets/javascripts/socializer/jquery.tokeninput.js +862 -0
  50. data/app/assets/javascripts/socializer/notes.js.coffee +38 -0
  51. data/app/assets/javascripts/socializer/people.js.coffee +7 -0
  52. data/app/assets/javascripts/socializer/shares.js.coffee +8 -0
  53. data/app/assets/stylesheets/socializer/activities.css +84 -0
  54. data/app/assets/stylesheets/socializer/application.css +409 -0
  55. data/app/assets/stylesheets/socializer/authentications.css +4 -0
  56. data/app/assets/stylesheets/socializer/circles.css +74 -0
  57. data/app/assets/stylesheets/socializer/comments.css +4 -0
  58. data/app/assets/stylesheets/socializer/groups.css +61 -0
  59. data/app/assets/stylesheets/socializer/jquery.qtip.min.css +2 -0
  60. data/app/assets/stylesheets/socializer/likes.css +4 -0
  61. data/app/assets/stylesheets/socializer/memberships.css +4 -0
  62. data/app/assets/stylesheets/socializer/notes.css +21 -0
  63. data/app/assets/stylesheets/socializer/notifications.css +46 -0
  64. data/app/assets/stylesheets/socializer/pages.css +4 -0
  65. data/app/assets/stylesheets/socializer/persons.css +25 -0
  66. data/app/assets/stylesheets/socializer/sessions.css +4 -0
  67. data/app/assets/stylesheets/socializer/shares.css.scss +3 -0
  68. data/app/assets/stylesheets/socializer/ties.css +4 -0
  69. data/app/assets/stylesheets/socializer/token-input.css +183 -0
  70. data/app/controllers/socializer/activities_controller.rb +84 -0
  71. data/app/controllers/socializer/application_controller.rb +37 -0
  72. data/app/controllers/socializer/audiences_controller.rb +30 -0
  73. data/app/controllers/socializer/authentications_controller.rb +13 -0
  74. data/app/controllers/socializer/circles_controller.rb +54 -0
  75. data/app/controllers/socializer/comments_controller.rb +37 -0
  76. data/app/controllers/socializer/groups_controller.rb +70 -0
  77. data/app/controllers/socializer/likes_controller.rb +50 -0
  78. data/app/controllers/socializer/memberships_controller.rb +46 -0
  79. data/app/controllers/socializer/notes_controller.rb +43 -0
  80. data/app/controllers/socializer/notifications_controller.rb +29 -0
  81. data/app/controllers/socializer/pages_controller.rb +7 -0
  82. data/app/controllers/socializer/people_controller.rb +37 -0
  83. data/app/controllers/socializer/person_addresses_controller.rb +27 -0
  84. data/app/controllers/socializer/person_contributions_controller.rb +27 -0
  85. data/app/controllers/socializer/person_educations_controller.rb +27 -0
  86. data/app/controllers/socializer/person_employments_controller.rb +27 -0
  87. data/app/controllers/socializer/person_links_controller.rb +27 -0
  88. data/app/controllers/socializer/person_phones_controller.rb +27 -0
  89. data/app/controllers/socializer/person_places_controller.rb +27 -0
  90. data/app/controllers/socializer/person_profiles_controller.rb +27 -0
  91. data/app/controllers/socializer/sessions_controller.rb +37 -0
  92. data/app/controllers/socializer/shares_controller.rb +54 -0
  93. data/app/controllers/socializer/ties_controller.rb +16 -0
  94. data/app/helpers/socializer/application_helper.rb +22 -0
  95. data/app/models/concerns/socializer/object_type_base.rb +58 -0
  96. data/app/models/socializer/activity.rb +162 -0
  97. data/app/models/socializer/activity_field.rb +10 -0
  98. data/app/models/socializer/activity_object.rb +118 -0
  99. data/app/models/socializer/audience.rb +19 -0
  100. data/app/models/socializer/authentication.rb +20 -0
  101. data/app/models/socializer/circle.rb +32 -0
  102. data/app/models/socializer/comment.rb +13 -0
  103. data/app/models/socializer/group.rb +100 -0
  104. data/app/models/socializer/group_category.rb +11 -0
  105. data/app/models/socializer/group_link.rb +12 -0
  106. data/app/models/socializer/identity.rb +9 -0
  107. data/app/models/socializer/membership.rb +24 -0
  108. data/app/models/socializer/note.rb +13 -0
  109. data/app/models/socializer/notification.rb +16 -0
  110. data/app/models/socializer/person.rb +129 -0
  111. data/app/models/socializer/person_address.rb +12 -0
  112. data/app/models/socializer/person_contribution.rb +12 -0
  113. data/app/models/socializer/person_education.rb +8 -0
  114. data/app/models/socializer/person_employment.rb +8 -0
  115. data/app/models/socializer/person_link.rb +12 -0
  116. data/app/models/socializer/person_phone.rb +16 -0
  117. data/app/models/socializer/person_place.rb +11 -0
  118. data/app/models/socializer/person_profile.rb +12 -0
  119. data/app/models/socializer/tie.rb +12 -0
  120. data/app/models/socializer/verb.rb +9 -0
  121. data/app/views/layouts/socializer/_header.html.erb +11 -0
  122. data/app/views/layouts/socializer/application.html.erb +60 -0
  123. data/app/views/socializer/activities/_activity.html.erb +23 -0
  124. data/app/views/socializer/activities/_activity_bottom.html.erb +55 -0
  125. data/app/views/socializer/activities/_activity_content.html.erb +19 -0
  126. data/app/views/socializer/activities/_activity_top.html.erb +22 -0
  127. data/app/views/socializer/activities/_stream_card.html.erb +6 -0
  128. data/app/views/socializer/activities/_stream_list.html.erb +16 -0
  129. data/app/views/socializer/activities/audience.html.erb +19 -0
  130. data/app/views/socializer/activities/destroy.js.erb +3 -0
  131. data/app/views/socializer/activities/edit.html.erb +0 -0
  132. data/app/views/socializer/activities/index.html.erb +15 -0
  133. data/app/views/socializer/authentications/_form.html.erb +0 -0
  134. data/app/views/socializer/authentications/_menu.html.erb +5 -0
  135. data/app/views/socializer/authentications/index.html.erb +8 -0
  136. data/app/views/socializer/authentications/new.html.erb +8 -0
  137. data/app/views/socializer/circles/_card.html.erb +7 -0
  138. data/app/views/socializer/circles/_circles.html.erb +6 -0
  139. data/app/views/socializer/circles/_form.html.erb +6 -0
  140. data/app/views/socializer/circles/_menu.html.erb +7 -0
  141. data/app/views/socializer/circles/contact_of.html.erb +7 -0
  142. data/app/views/socializer/circles/contacts.html.erb +7 -0
  143. data/app/views/socializer/circles/edit.html.erb +1 -0
  144. data/app/views/socializer/circles/find_people.html.erb +7 -0
  145. data/app/views/socializer/circles/index.html.erb +6 -0
  146. data/app/views/socializer/circles/new.html.erb +1 -0
  147. data/app/views/socializer/circles/show.html.erb +10 -0
  148. data/app/views/socializer/comments/_form.html.erb +8 -0
  149. data/app/views/socializer/comments/edit.html.erb +1 -0
  150. data/app/views/socializer/comments/new.html.erb +1 -0
  151. data/app/views/socializer/groups/_card.html.erb +6 -0
  152. data/app/views/socializer/groups/_form.html.erb +6 -0
  153. data/app/views/socializer/groups/_menu.html.erb +10 -0
  154. data/app/views/socializer/groups/edit.html.erb +1 -0
  155. data/app/views/socializer/groups/index.html.erb +0 -0
  156. data/app/views/socializer/groups/joinable.html.erb +16 -0
  157. data/app/views/socializer/groups/memberships.html.erb +19 -0
  158. data/app/views/socializer/groups/new.html.erb +1 -0
  159. data/app/views/socializer/groups/ownerships.html.erb +20 -0
  160. data/app/views/socializer/groups/pending_invites.html.erb +20 -0
  161. data/app/views/socializer/groups/public.html.erb +16 -0
  162. data/app/views/socializer/groups/restricted.html.erb +16 -0
  163. data/app/views/socializer/groups/show.html.erb +29 -0
  164. data/app/views/socializer/likes/create.js.erb +2 -0
  165. data/app/views/socializer/likes/destroy.js.erb +2 -0
  166. data/app/views/socializer/likes/index.html.erb +5 -0
  167. data/app/views/socializer/notes/_form.html.erb +7 -0
  168. data/app/views/socializer/notes/create.js.erb +10 -0
  169. data/app/views/socializer/notes/destroy.js.erb +3 -0
  170. data/app/views/socializer/notes/edit.html.erb +1 -0
  171. data/app/views/socializer/notes/new.html.erb +2 -0
  172. data/app/views/socializer/notifications/index.html.erb +35 -0
  173. data/app/views/socializer/pages/index.html.erb +2 -0
  174. data/app/views/socializer/people/_card.html.erb +15 -0
  175. data/app/views/socializer/people/_form.html.erb +30 -0
  176. data/app/views/socializer/people/_login.html.erb +14 -0
  177. data/app/views/socializer/people/_menu.html.erb +9 -0
  178. data/app/views/socializer/people/edit.html.erb +2 -0
  179. data/app/views/socializer/people/index.html.erb +5 -0
  180. data/app/views/socializer/people/likes.html.erb +6 -0
  181. data/app/views/socializer/people/message.html.erb +5 -0
  182. data/app/views/socializer/people/show.html.erb +122 -0
  183. data/app/views/socializer/person_addresses/_form.html.erb +12 -0
  184. data/app/views/socializer/person_contributions/_form.html.erb +7 -0
  185. data/app/views/socializer/person_educations/_form.html.erb +10 -0
  186. data/app/views/socializer/person_employments/_form.html.erb +10 -0
  187. data/app/views/socializer/person_links/_form.html.erb +6 -0
  188. data/app/views/socializer/person_phones/_form.html.erb +6 -0
  189. data/app/views/socializer/person_places/_form.html.erb +6 -0
  190. data/app/views/socializer/person_profiles/_form.html.erb +6 -0
  191. data/app/views/socializer/shares/_form.html.erb +19 -0
  192. data/app/views/socializer/shares/new.html.erb +1 -0
  193. data/config.ru +4 -0
  194. data/config/cucumber.yml +8 -0
  195. data/config/initializers/inflections.rb +3 -0
  196. data/config/locales/en.yml +108 -0
  197. data/config/locales/fr.yml +329 -0
  198. data/config/rails_best_practices.yml +41 -0
  199. data/config/routes.rb +71 -0
  200. data/db/migrate/20110804175740_create_socializer_activity_objects.rb +14 -0
  201. data/db/migrate/20110804180557_create_socializer_people.rb +31 -0
  202. data/db/migrate/20110804184415_create_socializer_notes.rb +12 -0
  203. data/db/migrate/20110804192211_create_socializer_authentications.rb +12 -0
  204. data/db/migrate/20110805085417_create_socializer_circles.rb +14 -0
  205. data/db/migrate/20110805090617_create_socializer_activities.rb +17 -0
  206. data/db/migrate/20110805092635_create_socializer_audiences.rb +14 -0
  207. data/db/migrate/20110805094846_create_socializer_comments.rb +12 -0
  208. data/db/migrate/20110805121454_create_socializer_groups.rb +19 -0
  209. data/db/migrate/20110805121543_create_socializer_memberships.rb +14 -0
  210. data/db/migrate/20110805125606_create_socializer_ties.rb +13 -0
  211. data/db/migrate/20111207234435_create_socializer_identities.rb +12 -0
  212. data/db/migrate/20130524000429_create_socializer_verbs.rb +10 -0
  213. data/db/migrate/20130528143831_create_socializer_activity_fields.rb +10 -0
  214. data/db/migrate/20140128235250_create_socializer_notifications.rb +11 -0
  215. data/db/migrate/20140131065531_create_socializer_person_employments.rb +15 -0
  216. data/db/migrate/20140131065733_create_socializer_person_educations.rb +15 -0
  217. data/db/migrate/20140131065836_create_socializer_person_places.rb +11 -0
  218. data/db/migrate/20140131070051_create_socializer_person_contributions.rb +12 -0
  219. data/db/migrate/20140131070232_create_socializer_person_links.rb +11 -0
  220. data/db/migrate/20140131070259_create_socializer_person_profiles.rb +11 -0
  221. data/db/migrate/20140131070417_create_socializer_person_phones.rb +12 -0
  222. data/db/migrate/20140131070611_create_socializer_person_addresses.rb +17 -0
  223. data/db/migrate/20140131070839_create_socializer_group_links.rb +11 -0
  224. data/db/migrate/20140131070951_create_socializer_group_categories.rb +10 -0
  225. data/features/support/capybara.rb +14 -0
  226. data/features/support/env.rb +57 -0
  227. data/features/support/factory_girl.rb +1 -0
  228. data/lib/socializer.rb +4 -0
  229. data/lib/socializer/engine.rb +27 -0
  230. data/lib/socializer/version.rb +3 -0
  231. data/lib/tasks/cucumber.rake +65 -0
  232. data/lib/tasks/socializer_tasks.rake +4 -0
  233. data/script/cucumber +10 -0
  234. data/socializer.gemspec +49 -0
  235. data/spec/controllers/socializer/likes_controller_spec.rb +29 -0
  236. data/spec/controllers/socializer/shares_controller_spec.rb +22 -0
  237. data/spec/factories/socializer_activities.rb +11 -0
  238. data/spec/factories/socializer_activity_fields.rb +8 -0
  239. data/spec/factories/socializer_activity_objects.rb +7 -0
  240. data/spec/factories/socializer_audiences.rb +9 -0
  241. data/spec/factories/socializer_authentications.rb +6 -0
  242. data/spec/factories/socializer_circles.rb +9 -0
  243. data/spec/factories/socializer_comments.rb +6 -0
  244. data/spec/factories/socializer_group_categories.rb +8 -0
  245. data/spec/factories/socializer_group_links.rb +9 -0
  246. data/spec/factories/socializer_groups.rb +9 -0
  247. data/spec/factories/socializer_identities.rb +10 -0
  248. data/spec/factories/socializer_memberships.rb +6 -0
  249. data/spec/factories/socializer_notes.rb +7 -0
  250. data/spec/factories/socializer_notifications.rb +10 -0
  251. data/spec/factories/socializer_people.rb +7 -0
  252. data/spec/factories/socializer_person_addresses.rb +8 -0
  253. data/spec/factories/socializer_person_contributions.rb +9 -0
  254. data/spec/factories/socializer_person_educations.rb +7 -0
  255. data/spec/factories/socializer_person_employments.rb +7 -0
  256. data/spec/factories/socializer_person_links.rb +9 -0
  257. data/spec/factories/socializer_person_phones.rb +9 -0
  258. data/spec/factories/socializer_person_places.rb +8 -0
  259. data/spec/factories/socializer_person_profiles.rb +9 -0
  260. data/spec/factories/socializer_ties.rb +6 -0
  261. data/spec/factories/socializer_verbs.rb +7 -0
  262. data/spec/inflector_spec.rb +19 -0
  263. data/spec/models/socializer/activity_field_spec.rb +25 -0
  264. data/spec/models/socializer/activity_object_spec.rb +118 -0
  265. data/spec/models/socializer/activity_spec.rb +16 -0
  266. data/spec/models/socializer/audience_spec.rb +32 -0
  267. data/spec/models/socializer/authentication_spec.rb +29 -0
  268. data/spec/models/socializer/circle_spec.rb +53 -0
  269. data/spec/models/socializer/comment_spec.rb +19 -0
  270. data/spec/models/socializer/group_category_spec.rb +23 -0
  271. data/spec/models/socializer/group_link_spec.rb +25 -0
  272. data/spec/models/socializer/group_spec.rb +218 -0
  273. data/spec/models/socializer/identity_spec.rb +32 -0
  274. data/spec/models/socializer/membership_spec.rb +68 -0
  275. data/spec/models/socializer/note_spec.rb +19 -0
  276. data/spec/models/socializer/notification_spec.rb +28 -0
  277. data/spec/models/socializer/person_address_spec.rb +27 -0
  278. data/spec/models/socializer/person_contribution_spec.rb +27 -0
  279. data/spec/models/socializer/person_education_spec.rb +25 -0
  280. data/spec/models/socializer/person_employment_spec.rb +25 -0
  281. data/spec/models/socializer/person_link_spec.rb +26 -0
  282. data/spec/models/socializer/person_phone_spec.rb +28 -0
  283. data/spec/models/socializer/person_place_spec.rb +25 -0
  284. data/spec/models/socializer/person_profile_spec.rb +26 -0
  285. data/spec/models/socializer/person_spec.rb +105 -0
  286. data/spec/models/socializer/tie_spec.rb +24 -0
  287. data/spec/models/socializer/verb_spec.rb +24 -0
  288. data/spec/spec_helper.rb +84 -0
  289. data/vendor/assets/javascripts/moment/langs.js +5841 -0
  290. data/vendor/assets/javascripts/moment/moment.js +2400 -0
  291. metadata +754 -0
@@ -0,0 +1,2400 @@
1
+ //! moment.js
2
+ //! version : 2.5.1
3
+ //! authors : Tim Wood, Iskren Chernev, Moment.js contributors
4
+ //! license : MIT
5
+ //! momentjs.com
6
+
7
+ (function (undefined) {
8
+
9
+ /************************************
10
+ Constants
11
+ ************************************/
12
+
13
+ var moment,
14
+ VERSION = "2.5.1",
15
+ global = this,
16
+ round = Math.round,
17
+ i,
18
+
19
+ YEAR = 0,
20
+ MONTH = 1,
21
+ DATE = 2,
22
+ HOUR = 3,
23
+ MINUTE = 4,
24
+ SECOND = 5,
25
+ MILLISECOND = 6,
26
+
27
+ // internal storage for language config files
28
+ languages = {},
29
+
30
+ // moment internal properties
31
+ momentProperties = {
32
+ _isAMomentObject: null,
33
+ _i : null,
34
+ _f : null,
35
+ _l : null,
36
+ _strict : null,
37
+ _isUTC : null,
38
+ _offset : null, // optional. Combine with _isUTC
39
+ _pf : null,
40
+ _lang : null // optional
41
+ },
42
+
43
+ // check for nodeJS
44
+ hasModule = (typeof module !== 'undefined' && module.exports && typeof require !== 'undefined'),
45
+
46
+ // ASP.NET json date format regex
47
+ aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
48
+ aspNetTimeSpanJsonRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,
49
+
50
+ // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
51
+ // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
52
+ isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,
53
+
54
+ // format tokens
55
+ formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g,
56
+ localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,
57
+
58
+ // parsing token regexes
59
+ parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99
60
+ parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999
61
+ parseTokenOneToFourDigits = /\d{1,4}/, // 0 - 9999
62
+ parseTokenOneToSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999
63
+ parseTokenDigits = /\d+/, // nonzero number of digits
64
+ 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.
65
+ parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z
66
+ parseTokenT = /T/i, // T (ISO separator)
67
+ parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123
68
+
69
+ //strict parsing regexes
70
+ parseTokenOneDigit = /\d/, // 0 - 9
71
+ parseTokenTwoDigits = /\d\d/, // 00 - 99
72
+ parseTokenThreeDigits = /\d{3}/, // 000 - 999
73
+ parseTokenFourDigits = /\d{4}/, // 0000 - 9999
74
+ parseTokenSixDigits = /[+-]?\d{6}/, // -999,999 - 999,999
75
+ parseTokenSignedNumber = /[+-]?\d+/, // -inf - inf
76
+
77
+ // iso 8601 regex
78
+ // 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 or +00)
79
+ isoRegex = /^\s*(?:[+-]\d{6}|\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)?|\s*Z)?)?$/,
80
+
81
+ isoFormat = 'YYYY-MM-DDTHH:mm:ssZ',
82
+
83
+ isoDates = [
84
+ ['YYYYYY-MM-DD', /[+-]\d{6}-\d{2}-\d{2}/],
85
+ ['YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/],
86
+ ['GGGG-[W]WW-E', /\d{4}-W\d{2}-\d/],
87
+ ['GGGG-[W]WW', /\d{4}-W\d{2}/],
88
+ ['YYYY-DDD', /\d{4}-\d{3}/]
89
+ ],
90
+
91
+ // iso time formats and regexes
92
+ isoTimes = [
93
+ ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d{1,3}/],
94
+ ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/],
95
+ ['HH:mm', /(T| )\d\d:\d\d/],
96
+ ['HH', /(T| )\d\d/]
97
+ ],
98
+
99
+ // timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"]
100
+ parseTimezoneChunker = /([\+\-]|\d\d)/gi,
101
+
102
+ // getter and setter names
103
+ proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'),
104
+ unitMillisecondFactors = {
105
+ 'Milliseconds' : 1,
106
+ 'Seconds' : 1e3,
107
+ 'Minutes' : 6e4,
108
+ 'Hours' : 36e5,
109
+ 'Days' : 864e5,
110
+ 'Months' : 2592e6,
111
+ 'Years' : 31536e6
112
+ },
113
+
114
+ unitAliases = {
115
+ ms : 'millisecond',
116
+ s : 'second',
117
+ m : 'minute',
118
+ h : 'hour',
119
+ d : 'day',
120
+ D : 'date',
121
+ w : 'week',
122
+ W : 'isoWeek',
123
+ M : 'month',
124
+ y : 'year',
125
+ DDD : 'dayOfYear',
126
+ e : 'weekday',
127
+ E : 'isoWeekday',
128
+ gg: 'weekYear',
129
+ GG: 'isoWeekYear'
130
+ },
131
+
132
+ camelFunctions = {
133
+ dayofyear : 'dayOfYear',
134
+ isoweekday : 'isoWeekday',
135
+ isoweek : 'isoWeek',
136
+ weekyear : 'weekYear',
137
+ isoweekyear : 'isoWeekYear'
138
+ },
139
+
140
+ // format function strings
141
+ formatFunctions = {},
142
+
143
+ // tokens to ordinalize and pad
144
+ ordinalizeTokens = 'DDD w W M D d'.split(' '),
145
+ paddedTokens = 'M D H h m s w W'.split(' '),
146
+
147
+ formatTokenFunctions = {
148
+ M : function () {
149
+ return this.month() + 1;
150
+ },
151
+ MMM : function (format) {
152
+ return this.lang().monthsShort(this, format);
153
+ },
154
+ MMMM : function (format) {
155
+ return this.lang().months(this, format);
156
+ },
157
+ D : function () {
158
+ return this.date();
159
+ },
160
+ DDD : function () {
161
+ return this.dayOfYear();
162
+ },
163
+ d : function () {
164
+ return this.day();
165
+ },
166
+ dd : function (format) {
167
+ return this.lang().weekdaysMin(this, format);
168
+ },
169
+ ddd : function (format) {
170
+ return this.lang().weekdaysShort(this, format);
171
+ },
172
+ dddd : function (format) {
173
+ return this.lang().weekdays(this, format);
174
+ },
175
+ w : function () {
176
+ return this.week();
177
+ },
178
+ W : function () {
179
+ return this.isoWeek();
180
+ },
181
+ YY : function () {
182
+ return leftZeroFill(this.year() % 100, 2);
183
+ },
184
+ YYYY : function () {
185
+ return leftZeroFill(this.year(), 4);
186
+ },
187
+ YYYYY : function () {
188
+ return leftZeroFill(this.year(), 5);
189
+ },
190
+ YYYYYY : function () {
191
+ var y = this.year(), sign = y >= 0 ? '+' : '-';
192
+ return sign + leftZeroFill(Math.abs(y), 6);
193
+ },
194
+ gg : function () {
195
+ return leftZeroFill(this.weekYear() % 100, 2);
196
+ },
197
+ gggg : function () {
198
+ return leftZeroFill(this.weekYear(), 4);
199
+ },
200
+ ggggg : function () {
201
+ return leftZeroFill(this.weekYear(), 5);
202
+ },
203
+ GG : function () {
204
+ return leftZeroFill(this.isoWeekYear() % 100, 2);
205
+ },
206
+ GGGG : function () {
207
+ return leftZeroFill(this.isoWeekYear(), 4);
208
+ },
209
+ GGGGG : function () {
210
+ return leftZeroFill(this.isoWeekYear(), 5);
211
+ },
212
+ e : function () {
213
+ return this.weekday();
214
+ },
215
+ E : function () {
216
+ return this.isoWeekday();
217
+ },
218
+ a : function () {
219
+ return this.lang().meridiem(this.hours(), this.minutes(), true);
220
+ },
221
+ A : function () {
222
+ return this.lang().meridiem(this.hours(), this.minutes(), false);
223
+ },
224
+ H : function () {
225
+ return this.hours();
226
+ },
227
+ h : function () {
228
+ return this.hours() % 12 || 12;
229
+ },
230
+ m : function () {
231
+ return this.minutes();
232
+ },
233
+ s : function () {
234
+ return this.seconds();
235
+ },
236
+ S : function () {
237
+ return toInt(this.milliseconds() / 100);
238
+ },
239
+ SS : function () {
240
+ return leftZeroFill(toInt(this.milliseconds() / 10), 2);
241
+ },
242
+ SSS : function () {
243
+ return leftZeroFill(this.milliseconds(), 3);
244
+ },
245
+ SSSS : function () {
246
+ return leftZeroFill(this.milliseconds(), 3);
247
+ },
248
+ Z : function () {
249
+ var a = -this.zone(),
250
+ b = "+";
251
+ if (a < 0) {
252
+ a = -a;
253
+ b = "-";
254
+ }
255
+ return b + leftZeroFill(toInt(a / 60), 2) + ":" + leftZeroFill(toInt(a) % 60, 2);
256
+ },
257
+ ZZ : function () {
258
+ var a = -this.zone(),
259
+ b = "+";
260
+ if (a < 0) {
261
+ a = -a;
262
+ b = "-";
263
+ }
264
+ return b + leftZeroFill(toInt(a / 60), 2) + leftZeroFill(toInt(a) % 60, 2);
265
+ },
266
+ z : function () {
267
+ return this.zoneAbbr();
268
+ },
269
+ zz : function () {
270
+ return this.zoneName();
271
+ },
272
+ X : function () {
273
+ return this.unix();
274
+ },
275
+ Q : function () {
276
+ return this.quarter();
277
+ }
278
+ },
279
+
280
+ lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin'];
281
+
282
+ function defaultParsingFlags() {
283
+ // We need to deep clone this object, and es5 standard is not very
284
+ // helpful.
285
+ return {
286
+ empty : false,
287
+ unusedTokens : [],
288
+ unusedInput : [],
289
+ overflow : -2,
290
+ charsLeftOver : 0,
291
+ nullInput : false,
292
+ invalidMonth : null,
293
+ invalidFormat : false,
294
+ userInvalidated : false,
295
+ iso: false
296
+ };
297
+ }
298
+
299
+ function padToken(func, count) {
300
+ return function (a) {
301
+ return leftZeroFill(func.call(this, a), count);
302
+ };
303
+ }
304
+ function ordinalizeToken(func, period) {
305
+ return function (a) {
306
+ return this.lang().ordinal(func.call(this, a), period);
307
+ };
308
+ }
309
+
310
+ while (ordinalizeTokens.length) {
311
+ i = ordinalizeTokens.pop();
312
+ formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i);
313
+ }
314
+ while (paddedTokens.length) {
315
+ i = paddedTokens.pop();
316
+ formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2);
317
+ }
318
+ formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3);
319
+
320
+
321
+ /************************************
322
+ Constructors
323
+ ************************************/
324
+
325
+ function Language() {
326
+
327
+ }
328
+
329
+ // Moment prototype object
330
+ function Moment(config) {
331
+ checkOverflow(config);
332
+ extend(this, config);
333
+ }
334
+
335
+ // Duration Constructor
336
+ function Duration(duration) {
337
+ var normalizedInput = normalizeObjectUnits(duration),
338
+ years = normalizedInput.year || 0,
339
+ months = normalizedInput.month || 0,
340
+ weeks = normalizedInput.week || 0,
341
+ days = normalizedInput.day || 0,
342
+ hours = normalizedInput.hour || 0,
343
+ minutes = normalizedInput.minute || 0,
344
+ seconds = normalizedInput.second || 0,
345
+ milliseconds = normalizedInput.millisecond || 0;
346
+
347
+ // representation for dateAddRemove
348
+ this._milliseconds = +milliseconds +
349
+ seconds * 1e3 + // 1000
350
+ minutes * 6e4 + // 1000 * 60
351
+ hours * 36e5; // 1000 * 60 * 60
352
+ // Because of dateAddRemove treats 24 hours as different from a
353
+ // day when working around DST, we need to store them separately
354
+ this._days = +days +
355
+ weeks * 7;
356
+ // It is impossible translate months into days without knowing
357
+ // which months you are are talking about, so we have to store
358
+ // it separately.
359
+ this._months = +months +
360
+ years * 12;
361
+
362
+ this._data = {};
363
+
364
+ this._bubble();
365
+ }
366
+
367
+ /************************************
368
+ Helpers
369
+ ************************************/
370
+
371
+
372
+ function extend(a, b) {
373
+ for (var i in b) {
374
+ if (b.hasOwnProperty(i)) {
375
+ a[i] = b[i];
376
+ }
377
+ }
378
+
379
+ if (b.hasOwnProperty("toString")) {
380
+ a.toString = b.toString;
381
+ }
382
+
383
+ if (b.hasOwnProperty("valueOf")) {
384
+ a.valueOf = b.valueOf;
385
+ }
386
+
387
+ return a;
388
+ }
389
+
390
+ function cloneMoment(m) {
391
+ var result = {}, i;
392
+ for (i in m) {
393
+ if (m.hasOwnProperty(i) && momentProperties.hasOwnProperty(i)) {
394
+ result[i] = m[i];
395
+ }
396
+ }
397
+
398
+ return result;
399
+ }
400
+
401
+ function absRound(number) {
402
+ if (number < 0) {
403
+ return Math.ceil(number);
404
+ } else {
405
+ return Math.floor(number);
406
+ }
407
+ }
408
+
409
+ // left zero fill a number
410
+ // see http://jsperf.com/left-zero-filling for performance comparison
411
+ function leftZeroFill(number, targetLength, forceSign) {
412
+ var output = '' + Math.abs(number),
413
+ sign = number >= 0;
414
+
415
+ while (output.length < targetLength) {
416
+ output = '0' + output;
417
+ }
418
+ return (sign ? (forceSign ? '+' : '') : '-') + output;
419
+ }
420
+
421
+ // helper function for _.addTime and _.subtractTime
422
+ function addOrSubtractDurationFromMoment(mom, duration, isAdding, ignoreUpdateOffset) {
423
+ var milliseconds = duration._milliseconds,
424
+ days = duration._days,
425
+ months = duration._months,
426
+ minutes,
427
+ hours;
428
+
429
+ if (milliseconds) {
430
+ mom._d.setTime(+mom._d + milliseconds * isAdding);
431
+ }
432
+ // store the minutes and hours so we can restore them
433
+ if (days || months) {
434
+ minutes = mom.minute();
435
+ hours = mom.hour();
436
+ }
437
+ if (days) {
438
+ mom.date(mom.date() + days * isAdding);
439
+ }
440
+ if (months) {
441
+ mom.month(mom.month() + months * isAdding);
442
+ }
443
+ if (milliseconds && !ignoreUpdateOffset) {
444
+ moment.updateOffset(mom);
445
+ }
446
+ // restore the minutes and hours after possibly changing dst
447
+ if (days || months) {
448
+ mom.minute(minutes);
449
+ mom.hour(hours);
450
+ }
451
+ }
452
+
453
+ // check if is an array
454
+ function isArray(input) {
455
+ return Object.prototype.toString.call(input) === '[object Array]';
456
+ }
457
+
458
+ function isDate(input) {
459
+ return Object.prototype.toString.call(input) === '[object Date]' ||
460
+ input instanceof Date;
461
+ }
462
+
463
+ // compare two arrays, return the number of differences
464
+ function compareArrays(array1, array2, dontConvert) {
465
+ var len = Math.min(array1.length, array2.length),
466
+ lengthDiff = Math.abs(array1.length - array2.length),
467
+ diffs = 0,
468
+ i;
469
+ for (i = 0; i < len; i++) {
470
+ if ((dontConvert && array1[i] !== array2[i]) ||
471
+ (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
472
+ diffs++;
473
+ }
474
+ }
475
+ return diffs + lengthDiff;
476
+ }
477
+
478
+ function normalizeUnits(units) {
479
+ if (units) {
480
+ var lowered = units.toLowerCase().replace(/(.)s$/, '$1');
481
+ units = unitAliases[units] || camelFunctions[lowered] || lowered;
482
+ }
483
+ return units;
484
+ }
485
+
486
+ function normalizeObjectUnits(inputObject) {
487
+ var normalizedInput = {},
488
+ normalizedProp,
489
+ prop;
490
+
491
+ for (prop in inputObject) {
492
+ if (inputObject.hasOwnProperty(prop)) {
493
+ normalizedProp = normalizeUnits(prop);
494
+ if (normalizedProp) {
495
+ normalizedInput[normalizedProp] = inputObject[prop];
496
+ }
497
+ }
498
+ }
499
+
500
+ return normalizedInput;
501
+ }
502
+
503
+ function makeList(field) {
504
+ var count, setter;
505
+
506
+ if (field.indexOf('week') === 0) {
507
+ count = 7;
508
+ setter = 'day';
509
+ }
510
+ else if (field.indexOf('month') === 0) {
511
+ count = 12;
512
+ setter = 'month';
513
+ }
514
+ else {
515
+ return;
516
+ }
517
+
518
+ moment[field] = function (format, index) {
519
+ var i, getter,
520
+ method = moment.fn._lang[field],
521
+ results = [];
522
+
523
+ if (typeof format === 'number') {
524
+ index = format;
525
+ format = undefined;
526
+ }
527
+
528
+ getter = function (i) {
529
+ var m = moment().utc().set(setter, i);
530
+ return method.call(moment.fn._lang, m, format || '');
531
+ };
532
+
533
+ if (index != null) {
534
+ return getter(index);
535
+ }
536
+ else {
537
+ for (i = 0; i < count; i++) {
538
+ results.push(getter(i));
539
+ }
540
+ return results;
541
+ }
542
+ };
543
+ }
544
+
545
+ function toInt(argumentForCoercion) {
546
+ var coercedNumber = +argumentForCoercion,
547
+ value = 0;
548
+
549
+ if (coercedNumber !== 0 && isFinite(coercedNumber)) {
550
+ if (coercedNumber >= 0) {
551
+ value = Math.floor(coercedNumber);
552
+ } else {
553
+ value = Math.ceil(coercedNumber);
554
+ }
555
+ }
556
+
557
+ return value;
558
+ }
559
+
560
+ function daysInMonth(year, month) {
561
+ return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
562
+ }
563
+
564
+ function daysInYear(year) {
565
+ return isLeapYear(year) ? 366 : 365;
566
+ }
567
+
568
+ function isLeapYear(year) {
569
+ return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
570
+ }
571
+
572
+ function checkOverflow(m) {
573
+ var overflow;
574
+ if (m._a && m._pf.overflow === -2) {
575
+ overflow =
576
+ m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH :
577
+ m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE :
578
+ m._a[HOUR] < 0 || m._a[HOUR] > 23 ? HOUR :
579
+ m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE :
580
+ m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND :
581
+ m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND :
582
+ -1;
583
+
584
+ if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
585
+ overflow = DATE;
586
+ }
587
+
588
+ m._pf.overflow = overflow;
589
+ }
590
+ }
591
+
592
+ function isValid(m) {
593
+ if (m._isValid == null) {
594
+ m._isValid = !isNaN(m._d.getTime()) &&
595
+ m._pf.overflow < 0 &&
596
+ !m._pf.empty &&
597
+ !m._pf.invalidMonth &&
598
+ !m._pf.nullInput &&
599
+ !m._pf.invalidFormat &&
600
+ !m._pf.userInvalidated;
601
+
602
+ if (m._strict) {
603
+ m._isValid = m._isValid &&
604
+ m._pf.charsLeftOver === 0 &&
605
+ m._pf.unusedTokens.length === 0;
606
+ }
607
+ }
608
+ return m._isValid;
609
+ }
610
+
611
+ function normalizeLanguage(key) {
612
+ return key ? key.toLowerCase().replace('_', '-') : key;
613
+ }
614
+
615
+ // Return a moment from input, that is local/utc/zone equivalent to model.
616
+ function makeAs(input, model) {
617
+ return model._isUTC ? moment(input).zone(model._offset || 0) :
618
+ moment(input).local();
619
+ }
620
+
621
+ /************************************
622
+ Languages
623
+ ************************************/
624
+
625
+
626
+ extend(Language.prototype, {
627
+
628
+ set : function (config) {
629
+ var prop, i;
630
+ for (i in config) {
631
+ prop = config[i];
632
+ if (typeof prop === 'function') {
633
+ this[i] = prop;
634
+ } else {
635
+ this['_' + i] = prop;
636
+ }
637
+ }
638
+ },
639
+
640
+ _months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
641
+ months : function (m) {
642
+ return this._months[m.month()];
643
+ },
644
+
645
+ _monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
646
+ monthsShort : function (m) {
647
+ return this._monthsShort[m.month()];
648
+ },
649
+
650
+ monthsParse : function (monthName) {
651
+ var i, mom, regex;
652
+
653
+ if (!this._monthsParse) {
654
+ this._monthsParse = [];
655
+ }
656
+
657
+ for (i = 0; i < 12; i++) {
658
+ // make the regex if we don't have it already
659
+ if (!this._monthsParse[i]) {
660
+ mom = moment.utc([2000, i]);
661
+ regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
662
+ this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
663
+ }
664
+ // test the regex
665
+ if (this._monthsParse[i].test(monthName)) {
666
+ return i;
667
+ }
668
+ }
669
+ },
670
+
671
+ _weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
672
+ weekdays : function (m) {
673
+ return this._weekdays[m.day()];
674
+ },
675
+
676
+ _weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
677
+ weekdaysShort : function (m) {
678
+ return this._weekdaysShort[m.day()];
679
+ },
680
+
681
+ _weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
682
+ weekdaysMin : function (m) {
683
+ return this._weekdaysMin[m.day()];
684
+ },
685
+
686
+ weekdaysParse : function (weekdayName) {
687
+ var i, mom, regex;
688
+
689
+ if (!this._weekdaysParse) {
690
+ this._weekdaysParse = [];
691
+ }
692
+
693
+ for (i = 0; i < 7; i++) {
694
+ // make the regex if we don't have it already
695
+ if (!this._weekdaysParse[i]) {
696
+ mom = moment([2000, 1]).day(i);
697
+ regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
698
+ this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
699
+ }
700
+ // test the regex
701
+ if (this._weekdaysParse[i].test(weekdayName)) {
702
+ return i;
703
+ }
704
+ }
705
+ },
706
+
707
+ _longDateFormat : {
708
+ LT : "h:mm A",
709
+ L : "MM/DD/YYYY",
710
+ LL : "MMMM D YYYY",
711
+ LLL : "MMMM D YYYY LT",
712
+ LLLL : "dddd, MMMM D YYYY LT"
713
+ },
714
+ longDateFormat : function (key) {
715
+ var output = this._longDateFormat[key];
716
+ if (!output && this._longDateFormat[key.toUpperCase()]) {
717
+ output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) {
718
+ return val.slice(1);
719
+ });
720
+ this._longDateFormat[key] = output;
721
+ }
722
+ return output;
723
+ },
724
+
725
+ isPM : function (input) {
726
+ // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
727
+ // Using charAt should be more compatible.
728
+ return ((input + '').toLowerCase().charAt(0) === 'p');
729
+ },
730
+
731
+ _meridiemParse : /[ap]\.?m?\.?/i,
732
+ meridiem : function (hours, minutes, isLower) {
733
+ if (hours > 11) {
734
+ return isLower ? 'pm' : 'PM';
735
+ } else {
736
+ return isLower ? 'am' : 'AM';
737
+ }
738
+ },
739
+
740
+ _calendar : {
741
+ sameDay : '[Today at] LT',
742
+ nextDay : '[Tomorrow at] LT',
743
+ nextWeek : 'dddd [at] LT',
744
+ lastDay : '[Yesterday at] LT',
745
+ lastWeek : '[Last] dddd [at] LT',
746
+ sameElse : 'L'
747
+ },
748
+ calendar : function (key, mom) {
749
+ var output = this._calendar[key];
750
+ return typeof output === 'function' ? output.apply(mom) : output;
751
+ },
752
+
753
+ _relativeTime : {
754
+ future : "in %s",
755
+ past : "%s ago",
756
+ s : "a few seconds",
757
+ m : "a minute",
758
+ mm : "%d minutes",
759
+ h : "an hour",
760
+ hh : "%d hours",
761
+ d : "a day",
762
+ dd : "%d days",
763
+ M : "a month",
764
+ MM : "%d months",
765
+ y : "a year",
766
+ yy : "%d years"
767
+ },
768
+ relativeTime : function (number, withoutSuffix, string, isFuture) {
769
+ var output = this._relativeTime[string];
770
+ return (typeof output === 'function') ?
771
+ output(number, withoutSuffix, string, isFuture) :
772
+ output.replace(/%d/i, number);
773
+ },
774
+ pastFuture : function (diff, output) {
775
+ var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
776
+ return typeof format === 'function' ? format(output) : format.replace(/%s/i, output);
777
+ },
778
+
779
+ ordinal : function (number) {
780
+ return this._ordinal.replace("%d", number);
781
+ },
782
+ _ordinal : "%d",
783
+
784
+ preparse : function (string) {
785
+ return string;
786
+ },
787
+
788
+ postformat : function (string) {
789
+ return string;
790
+ },
791
+
792
+ week : function (mom) {
793
+ return weekOfYear(mom, this._week.dow, this._week.doy).week;
794
+ },
795
+
796
+ _week : {
797
+ dow : 0, // Sunday is the first day of the week.
798
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
799
+ },
800
+
801
+ _invalidDate: 'Invalid date',
802
+ invalidDate: function () {
803
+ return this._invalidDate;
804
+ }
805
+ });
806
+
807
+ // Loads a language definition into the `languages` cache. The function
808
+ // takes a key and optionally values. If not in the browser and no values
809
+ // are provided, it will load the language file module. As a convenience,
810
+ // this function also returns the language values.
811
+ function loadLang(key, values) {
812
+ values.abbr = key;
813
+ if (!languages[key]) {
814
+ languages[key] = new Language();
815
+ }
816
+ languages[key].set(values);
817
+ return languages[key];
818
+ }
819
+
820
+ // Remove a language from the `languages` cache. Mostly useful in tests.
821
+ function unloadLang(key) {
822
+ delete languages[key];
823
+ }
824
+
825
+ // Determines which language definition to use and returns it.
826
+ //
827
+ // With no parameters, it will return the global language. If you
828
+ // pass in a language key, such as 'en', it will return the
829
+ // definition for 'en', so long as 'en' has already been loaded using
830
+ // moment.lang.
831
+ function getLangDefinition(key) {
832
+ var i = 0, j, lang, next, split,
833
+ get = function (k) {
834
+ if (!languages[k] && hasModule) {
835
+ try {
836
+ require('./lang/' + k);
837
+ } catch (e) { }
838
+ }
839
+ return languages[k];
840
+ };
841
+
842
+ if (!key) {
843
+ return moment.fn._lang;
844
+ }
845
+
846
+ if (!isArray(key)) {
847
+ //short-circuit everything else
848
+ lang = get(key);
849
+ if (lang) {
850
+ return lang;
851
+ }
852
+ key = [key];
853
+ }
854
+
855
+ //pick the language from the array
856
+ //try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
857
+ //substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
858
+ while (i < key.length) {
859
+ split = normalizeLanguage(key[i]).split('-');
860
+ j = split.length;
861
+ next = normalizeLanguage(key[i + 1]);
862
+ next = next ? next.split('-') : null;
863
+ while (j > 0) {
864
+ lang = get(split.slice(0, j).join('-'));
865
+ if (lang) {
866
+ return lang;
867
+ }
868
+ if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
869
+ //the next array item is better than a shallower substring of this one
870
+ break;
871
+ }
872
+ j--;
873
+ }
874
+ i++;
875
+ }
876
+ return moment.fn._lang;
877
+ }
878
+
879
+ /************************************
880
+ Formatting
881
+ ************************************/
882
+
883
+
884
+ function removeFormattingTokens(input) {
885
+ if (input.match(/\[[\s\S]/)) {
886
+ return input.replace(/^\[|\]$/g, "");
887
+ }
888
+ return input.replace(/\\/g, "");
889
+ }
890
+
891
+ function makeFormatFunction(format) {
892
+ var array = format.match(formattingTokens), i, length;
893
+
894
+ for (i = 0, length = array.length; i < length; i++) {
895
+ if (formatTokenFunctions[array[i]]) {
896
+ array[i] = formatTokenFunctions[array[i]];
897
+ } else {
898
+ array[i] = removeFormattingTokens(array[i]);
899
+ }
900
+ }
901
+
902
+ return function (mom) {
903
+ var output = "";
904
+ for (i = 0; i < length; i++) {
905
+ output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
906
+ }
907
+ return output;
908
+ };
909
+ }
910
+
911
+ // format date using native date object
912
+ function formatMoment(m, format) {
913
+
914
+ if (!m.isValid()) {
915
+ return m.lang().invalidDate();
916
+ }
917
+
918
+ format = expandFormat(format, m.lang());
919
+
920
+ if (!formatFunctions[format]) {
921
+ formatFunctions[format] = makeFormatFunction(format);
922
+ }
923
+
924
+ return formatFunctions[format](m);
925
+ }
926
+
927
+ function expandFormat(format, lang) {
928
+ var i = 5;
929
+
930
+ function replaceLongDateFormatTokens(input) {
931
+ return lang.longDateFormat(input) || input;
932
+ }
933
+
934
+ localFormattingTokens.lastIndex = 0;
935
+ while (i >= 0 && localFormattingTokens.test(format)) {
936
+ format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
937
+ localFormattingTokens.lastIndex = 0;
938
+ i -= 1;
939
+ }
940
+
941
+ return format;
942
+ }
943
+
944
+
945
+ /************************************
946
+ Parsing
947
+ ************************************/
948
+
949
+
950
+ // get the regex to find the next token
951
+ function getParseRegexForToken(token, config) {
952
+ var a, strict = config._strict;
953
+ switch (token) {
954
+ case 'DDDD':
955
+ return parseTokenThreeDigits;
956
+ case 'YYYY':
957
+ case 'GGGG':
958
+ case 'gggg':
959
+ return strict ? parseTokenFourDigits : parseTokenOneToFourDigits;
960
+ case 'Y':
961
+ case 'G':
962
+ case 'g':
963
+ return parseTokenSignedNumber;
964
+ case 'YYYYYY':
965
+ case 'YYYYY':
966
+ case 'GGGGG':
967
+ case 'ggggg':
968
+ return strict ? parseTokenSixDigits : parseTokenOneToSixDigits;
969
+ case 'S':
970
+ if (strict) { return parseTokenOneDigit; }
971
+ /* falls through */
972
+ case 'SS':
973
+ if (strict) { return parseTokenTwoDigits; }
974
+ /* falls through */
975
+ case 'SSS':
976
+ if (strict) { return parseTokenThreeDigits; }
977
+ /* falls through */
978
+ case 'DDD':
979
+ return parseTokenOneToThreeDigits;
980
+ case 'MMM':
981
+ case 'MMMM':
982
+ case 'dd':
983
+ case 'ddd':
984
+ case 'dddd':
985
+ return parseTokenWord;
986
+ case 'a':
987
+ case 'A':
988
+ return getLangDefinition(config._l)._meridiemParse;
989
+ case 'X':
990
+ return parseTokenTimestampMs;
991
+ case 'Z':
992
+ case 'ZZ':
993
+ return parseTokenTimezone;
994
+ case 'T':
995
+ return parseTokenT;
996
+ case 'SSSS':
997
+ return parseTokenDigits;
998
+ case 'MM':
999
+ case 'DD':
1000
+ case 'YY':
1001
+ case 'GG':
1002
+ case 'gg':
1003
+ case 'HH':
1004
+ case 'hh':
1005
+ case 'mm':
1006
+ case 'ss':
1007
+ case 'ww':
1008
+ case 'WW':
1009
+ return strict ? parseTokenTwoDigits : parseTokenOneOrTwoDigits;
1010
+ case 'M':
1011
+ case 'D':
1012
+ case 'd':
1013
+ case 'H':
1014
+ case 'h':
1015
+ case 'm':
1016
+ case 's':
1017
+ case 'w':
1018
+ case 'W':
1019
+ case 'e':
1020
+ case 'E':
1021
+ return parseTokenOneOrTwoDigits;
1022
+ default :
1023
+ a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), "i"));
1024
+ return a;
1025
+ }
1026
+ }
1027
+
1028
+ function timezoneMinutesFromString(string) {
1029
+ string = string || "";
1030
+ var possibleTzMatches = (string.match(parseTokenTimezone) || []),
1031
+ tzChunk = possibleTzMatches[possibleTzMatches.length - 1] || [],
1032
+ parts = (tzChunk + '').match(parseTimezoneChunker) || ['-', 0, 0],
1033
+ minutes = +(parts[1] * 60) + toInt(parts[2]);
1034
+
1035
+ return parts[0] === '+' ? -minutes : minutes;
1036
+ }
1037
+
1038
+ // function to convert string input to date
1039
+ function addTimeToArrayFromToken(token, input, config) {
1040
+ var a, datePartArray = config._a;
1041
+
1042
+ switch (token) {
1043
+ // MONTH
1044
+ case 'M' : // fall through to MM
1045
+ case 'MM' :
1046
+ if (input != null) {
1047
+ datePartArray[MONTH] = toInt(input) - 1;
1048
+ }
1049
+ break;
1050
+ case 'MMM' : // fall through to MMMM
1051
+ case 'MMMM' :
1052
+ a = getLangDefinition(config._l).monthsParse(input);
1053
+ // if we didn't find a month name, mark the date as invalid.
1054
+ if (a != null) {
1055
+ datePartArray[MONTH] = a;
1056
+ } else {
1057
+ config._pf.invalidMonth = input;
1058
+ }
1059
+ break;
1060
+ // DAY OF MONTH
1061
+ case 'D' : // fall through to DD
1062
+ case 'DD' :
1063
+ if (input != null) {
1064
+ datePartArray[DATE] = toInt(input);
1065
+ }
1066
+ break;
1067
+ // DAY OF YEAR
1068
+ case 'DDD' : // fall through to DDDD
1069
+ case 'DDDD' :
1070
+ if (input != null) {
1071
+ config._dayOfYear = toInt(input);
1072
+ }
1073
+
1074
+ break;
1075
+ // YEAR
1076
+ case 'YY' :
1077
+ datePartArray[YEAR] = toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
1078
+ break;
1079
+ case 'YYYY' :
1080
+ case 'YYYYY' :
1081
+ case 'YYYYYY' :
1082
+ datePartArray[YEAR] = toInt(input);
1083
+ break;
1084
+ // AM / PM
1085
+ case 'a' : // fall through to A
1086
+ case 'A' :
1087
+ config._isPm = getLangDefinition(config._l).isPM(input);
1088
+ break;
1089
+ // 24 HOUR
1090
+ case 'H' : // fall through to hh
1091
+ case 'HH' : // fall through to hh
1092
+ case 'h' : // fall through to hh
1093
+ case 'hh' :
1094
+ datePartArray[HOUR] = toInt(input);
1095
+ break;
1096
+ // MINUTE
1097
+ case 'm' : // fall through to mm
1098
+ case 'mm' :
1099
+ datePartArray[MINUTE] = toInt(input);
1100
+ break;
1101
+ // SECOND
1102
+ case 's' : // fall through to ss
1103
+ case 'ss' :
1104
+ datePartArray[SECOND] = toInt(input);
1105
+ break;
1106
+ // MILLISECOND
1107
+ case 'S' :
1108
+ case 'SS' :
1109
+ case 'SSS' :
1110
+ case 'SSSS' :
1111
+ datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000);
1112
+ break;
1113
+ // UNIX TIMESTAMP WITH MS
1114
+ case 'X':
1115
+ config._d = new Date(parseFloat(input) * 1000);
1116
+ break;
1117
+ // TIMEZONE
1118
+ case 'Z' : // fall through to ZZ
1119
+ case 'ZZ' :
1120
+ config._useUTC = true;
1121
+ config._tzm = timezoneMinutesFromString(input);
1122
+ break;
1123
+ case 'w':
1124
+ case 'ww':
1125
+ case 'W':
1126
+ case 'WW':
1127
+ case 'd':
1128
+ case 'dd':
1129
+ case 'ddd':
1130
+ case 'dddd':
1131
+ case 'e':
1132
+ case 'E':
1133
+ token = token.substr(0, 1);
1134
+ /* falls through */
1135
+ case 'gg':
1136
+ case 'gggg':
1137
+ case 'GG':
1138
+ case 'GGGG':
1139
+ case 'GGGGG':
1140
+ token = token.substr(0, 2);
1141
+ if (input) {
1142
+ config._w = config._w || {};
1143
+ config._w[token] = input;
1144
+ }
1145
+ break;
1146
+ }
1147
+ }
1148
+
1149
+ // convert an array to a date.
1150
+ // the array should mirror the parameters below
1151
+ // note: all values past the year are optional and will default to the lowest possible value.
1152
+ // [year, month, day , hour, minute, second, millisecond]
1153
+ function dateFromConfig(config) {
1154
+ var i, date, input = [], currentDate,
1155
+ yearToUse, fixYear, w, temp, lang, weekday, week;
1156
+
1157
+ if (config._d) {
1158
+ return;
1159
+ }
1160
+
1161
+ currentDate = currentDateArray(config);
1162
+
1163
+ //compute day of the year from weeks and weekdays
1164
+ if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
1165
+ fixYear = function (val) {
1166
+ var int_val = parseInt(val, 10);
1167
+ return val ?
1168
+ (val.length < 3 ? (int_val > 68 ? 1900 + int_val : 2000 + int_val) : int_val) :
1169
+ (config._a[YEAR] == null ? moment().weekYear() : config._a[YEAR]);
1170
+ };
1171
+
1172
+ w = config._w;
1173
+ if (w.GG != null || w.W != null || w.E != null) {
1174
+ temp = dayOfYearFromWeeks(fixYear(w.GG), w.W || 1, w.E, 4, 1);
1175
+ }
1176
+ else {
1177
+ lang = getLangDefinition(config._l);
1178
+ weekday = w.d != null ? parseWeekday(w.d, lang) :
1179
+ (w.e != null ? parseInt(w.e, 10) + lang._week.dow : 0);
1180
+
1181
+ week = parseInt(w.w, 10) || 1;
1182
+
1183
+ //if we're parsing 'd', then the low day numbers may be next week
1184
+ if (w.d != null && weekday < lang._week.dow) {
1185
+ week++;
1186
+ }
1187
+
1188
+ temp = dayOfYearFromWeeks(fixYear(w.gg), week, weekday, lang._week.doy, lang._week.dow);
1189
+ }
1190
+
1191
+ config._a[YEAR] = temp.year;
1192
+ config._dayOfYear = temp.dayOfYear;
1193
+ }
1194
+
1195
+ //if the day of the year is set, figure out what it is
1196
+ if (config._dayOfYear) {
1197
+ yearToUse = config._a[YEAR] == null ? currentDate[YEAR] : config._a[YEAR];
1198
+
1199
+ if (config._dayOfYear > daysInYear(yearToUse)) {
1200
+ config._pf._overflowDayOfYear = true;
1201
+ }
1202
+
1203
+ date = makeUTCDate(yearToUse, 0, config._dayOfYear);
1204
+ config._a[MONTH] = date.getUTCMonth();
1205
+ config._a[DATE] = date.getUTCDate();
1206
+ }
1207
+
1208
+ // Default to current date.
1209
+ // * if no year, month, day of month are given, default to today
1210
+ // * if day of month is given, default month and year
1211
+ // * if month is given, default only year
1212
+ // * if year is given, don't default anything
1213
+ for (i = 0; i < 3 && config._a[i] == null; ++i) {
1214
+ config._a[i] = input[i] = currentDate[i];
1215
+ }
1216
+
1217
+ // Zero out whatever was not defaulted, including time
1218
+ for (; i < 7; i++) {
1219
+ config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
1220
+ }
1221
+
1222
+ // add the offsets to the time to be parsed so that we can have a clean array for checking isValid
1223
+ input[HOUR] += toInt((config._tzm || 0) / 60);
1224
+ input[MINUTE] += toInt((config._tzm || 0) % 60);
1225
+
1226
+ config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input);
1227
+ }
1228
+
1229
+ function dateFromObject(config) {
1230
+ var normalizedInput;
1231
+
1232
+ if (config._d) {
1233
+ return;
1234
+ }
1235
+
1236
+ normalizedInput = normalizeObjectUnits(config._i);
1237
+ config._a = [
1238
+ normalizedInput.year,
1239
+ normalizedInput.month,
1240
+ normalizedInput.day,
1241
+ normalizedInput.hour,
1242
+ normalizedInput.minute,
1243
+ normalizedInput.second,
1244
+ normalizedInput.millisecond
1245
+ ];
1246
+
1247
+ dateFromConfig(config);
1248
+ }
1249
+
1250
+ function currentDateArray(config) {
1251
+ var now = new Date();
1252
+ if (config._useUTC) {
1253
+ return [
1254
+ now.getUTCFullYear(),
1255
+ now.getUTCMonth(),
1256
+ now.getUTCDate()
1257
+ ];
1258
+ } else {
1259
+ return [now.getFullYear(), now.getMonth(), now.getDate()];
1260
+ }
1261
+ }
1262
+
1263
+ // date from string and format string
1264
+ function makeDateFromStringAndFormat(config) {
1265
+
1266
+ config._a = [];
1267
+ config._pf.empty = true;
1268
+
1269
+ // This array is used to make a Date, either with `new Date` or `Date.UTC`
1270
+ var lang = getLangDefinition(config._l),
1271
+ string = '' + config._i,
1272
+ i, parsedInput, tokens, token, skipped,
1273
+ stringLength = string.length,
1274
+ totalParsedInputLength = 0;
1275
+
1276
+ tokens = expandFormat(config._f, lang).match(formattingTokens) || [];
1277
+
1278
+ for (i = 0; i < tokens.length; i++) {
1279
+ token = tokens[i];
1280
+ parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
1281
+ if (parsedInput) {
1282
+ skipped = string.substr(0, string.indexOf(parsedInput));
1283
+ if (skipped.length > 0) {
1284
+ config._pf.unusedInput.push(skipped);
1285
+ }
1286
+ string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
1287
+ totalParsedInputLength += parsedInput.length;
1288
+ }
1289
+ // don't parse if it's not a known token
1290
+ if (formatTokenFunctions[token]) {
1291
+ if (parsedInput) {
1292
+ config._pf.empty = false;
1293
+ }
1294
+ else {
1295
+ config._pf.unusedTokens.push(token);
1296
+ }
1297
+ addTimeToArrayFromToken(token, parsedInput, config);
1298
+ }
1299
+ else if (config._strict && !parsedInput) {
1300
+ config._pf.unusedTokens.push(token);
1301
+ }
1302
+ }
1303
+
1304
+ // add remaining unparsed input length to the string
1305
+ config._pf.charsLeftOver = stringLength - totalParsedInputLength;
1306
+ if (string.length > 0) {
1307
+ config._pf.unusedInput.push(string);
1308
+ }
1309
+
1310
+ // handle am pm
1311
+ if (config._isPm && config._a[HOUR] < 12) {
1312
+ config._a[HOUR] += 12;
1313
+ }
1314
+ // if is 12 am, change hours to 0
1315
+ if (config._isPm === false && config._a[HOUR] === 12) {
1316
+ config._a[HOUR] = 0;
1317
+ }
1318
+
1319
+ dateFromConfig(config);
1320
+ checkOverflow(config);
1321
+ }
1322
+
1323
+ function unescapeFormat(s) {
1324
+ return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
1325
+ return p1 || p2 || p3 || p4;
1326
+ });
1327
+ }
1328
+
1329
+ // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
1330
+ function regexpEscape(s) {
1331
+ return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
1332
+ }
1333
+
1334
+ // date from string and array of format strings
1335
+ function makeDateFromStringAndArray(config) {
1336
+ var tempConfig,
1337
+ bestMoment,
1338
+
1339
+ scoreToBeat,
1340
+ i,
1341
+ currentScore;
1342
+
1343
+ if (config._f.length === 0) {
1344
+ config._pf.invalidFormat = true;
1345
+ config._d = new Date(NaN);
1346
+ return;
1347
+ }
1348
+
1349
+ for (i = 0; i < config._f.length; i++) {
1350
+ currentScore = 0;
1351
+ tempConfig = extend({}, config);
1352
+ tempConfig._pf = defaultParsingFlags();
1353
+ tempConfig._f = config._f[i];
1354
+ makeDateFromStringAndFormat(tempConfig);
1355
+
1356
+ if (!isValid(tempConfig)) {
1357
+ continue;
1358
+ }
1359
+
1360
+ // if there is any input that was not parsed add a penalty for that format
1361
+ currentScore += tempConfig._pf.charsLeftOver;
1362
+
1363
+ //or tokens
1364
+ currentScore += tempConfig._pf.unusedTokens.length * 10;
1365
+
1366
+ tempConfig._pf.score = currentScore;
1367
+
1368
+ if (scoreToBeat == null || currentScore < scoreToBeat) {
1369
+ scoreToBeat = currentScore;
1370
+ bestMoment = tempConfig;
1371
+ }
1372
+ }
1373
+
1374
+ extend(config, bestMoment || tempConfig);
1375
+ }
1376
+
1377
+ // date from iso format
1378
+ function makeDateFromString(config) {
1379
+ var i, l,
1380
+ string = config._i,
1381
+ match = isoRegex.exec(string);
1382
+
1383
+ if (match) {
1384
+ config._pf.iso = true;
1385
+ for (i = 0, l = isoDates.length; i < l; i++) {
1386
+ if (isoDates[i][1].exec(string)) {
1387
+ // match[5] should be "T" or undefined
1388
+ config._f = isoDates[i][0] + (match[6] || " ");
1389
+ break;
1390
+ }
1391
+ }
1392
+ for (i = 0, l = isoTimes.length; i < l; i++) {
1393
+ if (isoTimes[i][1].exec(string)) {
1394
+ config._f += isoTimes[i][0];
1395
+ break;
1396
+ }
1397
+ }
1398
+ if (string.match(parseTokenTimezone)) {
1399
+ config._f += "Z";
1400
+ }
1401
+ makeDateFromStringAndFormat(config);
1402
+ }
1403
+ else {
1404
+ config._d = new Date(string);
1405
+ }
1406
+ }
1407
+
1408
+ function makeDateFromInput(config) {
1409
+ var input = config._i,
1410
+ matched = aspNetJsonRegex.exec(input);
1411
+
1412
+ if (input === undefined) {
1413
+ config._d = new Date();
1414
+ } else if (matched) {
1415
+ config._d = new Date(+matched[1]);
1416
+ } else if (typeof input === 'string') {
1417
+ makeDateFromString(config);
1418
+ } else if (isArray(input)) {
1419
+ config._a = input.slice(0);
1420
+ dateFromConfig(config);
1421
+ } else if (isDate(input)) {
1422
+ config._d = new Date(+input);
1423
+ } else if (typeof(input) === 'object') {
1424
+ dateFromObject(config);
1425
+ } else {
1426
+ config._d = new Date(input);
1427
+ }
1428
+ }
1429
+
1430
+ function makeDate(y, m, d, h, M, s, ms) {
1431
+ //can't just apply() to create a date:
1432
+ //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
1433
+ var date = new Date(y, m, d, h, M, s, ms);
1434
+
1435
+ //the date constructor doesn't accept years < 1970
1436
+ if (y < 1970) {
1437
+ date.setFullYear(y);
1438
+ }
1439
+ return date;
1440
+ }
1441
+
1442
+ function makeUTCDate(y) {
1443
+ var date = new Date(Date.UTC.apply(null, arguments));
1444
+ if (y < 1970) {
1445
+ date.setUTCFullYear(y);
1446
+ }
1447
+ return date;
1448
+ }
1449
+
1450
+ function parseWeekday(input, language) {
1451
+ if (typeof input === 'string') {
1452
+ if (!isNaN(input)) {
1453
+ input = parseInt(input, 10);
1454
+ }
1455
+ else {
1456
+ input = language.weekdaysParse(input);
1457
+ if (typeof input !== 'number') {
1458
+ return null;
1459
+ }
1460
+ }
1461
+ }
1462
+ return input;
1463
+ }
1464
+
1465
+ /************************************
1466
+ Relative Time
1467
+ ************************************/
1468
+
1469
+
1470
+ // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
1471
+ function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) {
1472
+ return lang.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
1473
+ }
1474
+
1475
+ function relativeTime(milliseconds, withoutSuffix, lang) {
1476
+ var seconds = round(Math.abs(milliseconds) / 1000),
1477
+ minutes = round(seconds / 60),
1478
+ hours = round(minutes / 60),
1479
+ days = round(hours / 24),
1480
+ years = round(days / 365),
1481
+ args = seconds < 45 && ['s', seconds] ||
1482
+ minutes === 1 && ['m'] ||
1483
+ minutes < 45 && ['mm', minutes] ||
1484
+ hours === 1 && ['h'] ||
1485
+ hours < 22 && ['hh', hours] ||
1486
+ days === 1 && ['d'] ||
1487
+ days <= 25 && ['dd', days] ||
1488
+ days <= 45 && ['M'] ||
1489
+ days < 345 && ['MM', round(days / 30)] ||
1490
+ years === 1 && ['y'] || ['yy', years];
1491
+ args[2] = withoutSuffix;
1492
+ args[3] = milliseconds > 0;
1493
+ args[4] = lang;
1494
+ return substituteTimeAgo.apply({}, args);
1495
+ }
1496
+
1497
+
1498
+ /************************************
1499
+ Week of Year
1500
+ ************************************/
1501
+
1502
+
1503
+ // firstDayOfWeek 0 = sun, 6 = sat
1504
+ // the day of the week that starts the week
1505
+ // (usually sunday or monday)
1506
+ // firstDayOfWeekOfYear 0 = sun, 6 = sat
1507
+ // the first week is the week that contains the first
1508
+ // of this day of the week
1509
+ // (eg. ISO weeks use thursday (4))
1510
+ function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) {
1511
+ var end = firstDayOfWeekOfYear - firstDayOfWeek,
1512
+ daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(),
1513
+ adjustedMoment;
1514
+
1515
+
1516
+ if (daysToDayOfWeek > end) {
1517
+ daysToDayOfWeek -= 7;
1518
+ }
1519
+
1520
+ if (daysToDayOfWeek < end - 7) {
1521
+ daysToDayOfWeek += 7;
1522
+ }
1523
+
1524
+ adjustedMoment = moment(mom).add('d', daysToDayOfWeek);
1525
+ return {
1526
+ week: Math.ceil(adjustedMoment.dayOfYear() / 7),
1527
+ year: adjustedMoment.year()
1528
+ };
1529
+ }
1530
+
1531
+ //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
1532
+ function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) {
1533
+ var d = makeUTCDate(year, 0, 1).getUTCDay(), daysToAdd, dayOfYear;
1534
+
1535
+ weekday = weekday != null ? weekday : firstDayOfWeek;
1536
+ daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0);
1537
+ dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1;
1538
+
1539
+ return {
1540
+ year: dayOfYear > 0 ? year : year - 1,
1541
+ dayOfYear: dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear
1542
+ };
1543
+ }
1544
+
1545
+ /************************************
1546
+ Top Level Functions
1547
+ ************************************/
1548
+
1549
+ function makeMoment(config) {
1550
+ var input = config._i,
1551
+ format = config._f;
1552
+
1553
+ if (input === null) {
1554
+ return moment.invalid({nullInput: true});
1555
+ }
1556
+
1557
+ if (typeof input === 'string') {
1558
+ config._i = input = getLangDefinition().preparse(input);
1559
+ }
1560
+
1561
+ if (moment.isMoment(input)) {
1562
+ config = cloneMoment(input);
1563
+
1564
+ config._d = new Date(+input._d);
1565
+ } else if (format) {
1566
+ if (isArray(format)) {
1567
+ makeDateFromStringAndArray(config);
1568
+ } else {
1569
+ makeDateFromStringAndFormat(config);
1570
+ }
1571
+ } else {
1572
+ makeDateFromInput(config);
1573
+ }
1574
+
1575
+ return new Moment(config);
1576
+ }
1577
+
1578
+ moment = function (input, format, lang, strict) {
1579
+ var c;
1580
+
1581
+ if (typeof(lang) === "boolean") {
1582
+ strict = lang;
1583
+ lang = undefined;
1584
+ }
1585
+ // object construction must be done this way.
1586
+ // https://github.com/moment/moment/issues/1423
1587
+ c = {};
1588
+ c._isAMomentObject = true;
1589
+ c._i = input;
1590
+ c._f = format;
1591
+ c._l = lang;
1592
+ c._strict = strict;
1593
+ c._isUTC = false;
1594
+ c._pf = defaultParsingFlags();
1595
+
1596
+ return makeMoment(c);
1597
+ };
1598
+
1599
+ // creating with utc
1600
+ moment.utc = function (input, format, lang, strict) {
1601
+ var c;
1602
+
1603
+ if (typeof(lang) === "boolean") {
1604
+ strict = lang;
1605
+ lang = undefined;
1606
+ }
1607
+ // object construction must be done this way.
1608
+ // https://github.com/moment/moment/issues/1423
1609
+ c = {};
1610
+ c._isAMomentObject = true;
1611
+ c._useUTC = true;
1612
+ c._isUTC = true;
1613
+ c._l = lang;
1614
+ c._i = input;
1615
+ c._f = format;
1616
+ c._strict = strict;
1617
+ c._pf = defaultParsingFlags();
1618
+
1619
+ return makeMoment(c).utc();
1620
+ };
1621
+
1622
+ // creating with unix timestamp (in seconds)
1623
+ moment.unix = function (input) {
1624
+ return moment(input * 1000);
1625
+ };
1626
+
1627
+ // duration
1628
+ moment.duration = function (input, key) {
1629
+ var duration = input,
1630
+ // matching against regexp is expensive, do it on demand
1631
+ match = null,
1632
+ sign,
1633
+ ret,
1634
+ parseIso;
1635
+
1636
+ if (moment.isDuration(input)) {
1637
+ duration = {
1638
+ ms: input._milliseconds,
1639
+ d: input._days,
1640
+ M: input._months
1641
+ };
1642
+ } else if (typeof input === 'number') {
1643
+ duration = {};
1644
+ if (key) {
1645
+ duration[key] = input;
1646
+ } else {
1647
+ duration.milliseconds = input;
1648
+ }
1649
+ } else if (!!(match = aspNetTimeSpanJsonRegex.exec(input))) {
1650
+ sign = (match[1] === "-") ? -1 : 1;
1651
+ duration = {
1652
+ y: 0,
1653
+ d: toInt(match[DATE]) * sign,
1654
+ h: toInt(match[HOUR]) * sign,
1655
+ m: toInt(match[MINUTE]) * sign,
1656
+ s: toInt(match[SECOND]) * sign,
1657
+ ms: toInt(match[MILLISECOND]) * sign
1658
+ };
1659
+ } else if (!!(match = isoDurationRegex.exec(input))) {
1660
+ sign = (match[1] === "-") ? -1 : 1;
1661
+ parseIso = function (inp) {
1662
+ // We'd normally use ~~inp for this, but unfortunately it also
1663
+ // converts floats to ints.
1664
+ // inp may be undefined, so careful calling replace on it.
1665
+ var res = inp && parseFloat(inp.replace(',', '.'));
1666
+ // apply sign while we're at it
1667
+ return (isNaN(res) ? 0 : res) * sign;
1668
+ };
1669
+ duration = {
1670
+ y: parseIso(match[2]),
1671
+ M: parseIso(match[3]),
1672
+ d: parseIso(match[4]),
1673
+ h: parseIso(match[5]),
1674
+ m: parseIso(match[6]),
1675
+ s: parseIso(match[7]),
1676
+ w: parseIso(match[8])
1677
+ };
1678
+ }
1679
+
1680
+ ret = new Duration(duration);
1681
+
1682
+ if (moment.isDuration(input) && input.hasOwnProperty('_lang')) {
1683
+ ret._lang = input._lang;
1684
+ }
1685
+
1686
+ return ret;
1687
+ };
1688
+
1689
+ // version number
1690
+ moment.version = VERSION;
1691
+
1692
+ // default format
1693
+ moment.defaultFormat = isoFormat;
1694
+
1695
+ // This function will be called whenever a moment is mutated.
1696
+ // It is intended to keep the offset in sync with the timezone.
1697
+ moment.updateOffset = function () {};
1698
+
1699
+ // This function will load languages and then set the global language. If
1700
+ // no arguments are passed in, it will simply return the current global
1701
+ // language key.
1702
+ moment.lang = function (key, values) {
1703
+ var r;
1704
+ if (!key) {
1705
+ return moment.fn._lang._abbr;
1706
+ }
1707
+ if (values) {
1708
+ loadLang(normalizeLanguage(key), values);
1709
+ } else if (values === null) {
1710
+ unloadLang(key);
1711
+ key = 'en';
1712
+ } else if (!languages[key]) {
1713
+ getLangDefinition(key);
1714
+ }
1715
+ r = moment.duration.fn._lang = moment.fn._lang = getLangDefinition(key);
1716
+ return r._abbr;
1717
+ };
1718
+
1719
+ // returns language data
1720
+ moment.langData = function (key) {
1721
+ if (key && key._lang && key._lang._abbr) {
1722
+ key = key._lang._abbr;
1723
+ }
1724
+ return getLangDefinition(key);
1725
+ };
1726
+
1727
+ // compare moment object
1728
+ moment.isMoment = function (obj) {
1729
+ return obj instanceof Moment ||
1730
+ (obj != null && obj.hasOwnProperty('_isAMomentObject'));
1731
+ };
1732
+
1733
+ // for typechecking Duration objects
1734
+ moment.isDuration = function (obj) {
1735
+ return obj instanceof Duration;
1736
+ };
1737
+
1738
+ for (i = lists.length - 1; i >= 0; --i) {
1739
+ makeList(lists[i]);
1740
+ }
1741
+
1742
+ moment.normalizeUnits = function (units) {
1743
+ return normalizeUnits(units);
1744
+ };
1745
+
1746
+ moment.invalid = function (flags) {
1747
+ var m = moment.utc(NaN);
1748
+ if (flags != null) {
1749
+ extend(m._pf, flags);
1750
+ }
1751
+ else {
1752
+ m._pf.userInvalidated = true;
1753
+ }
1754
+
1755
+ return m;
1756
+ };
1757
+
1758
+ moment.parseZone = function () {
1759
+ return moment.apply(null, arguments).parseZone();
1760
+ };
1761
+
1762
+ /************************************
1763
+ Moment Prototype
1764
+ ************************************/
1765
+
1766
+
1767
+ extend(moment.fn = Moment.prototype, {
1768
+
1769
+ clone : function () {
1770
+ return moment(this);
1771
+ },
1772
+
1773
+ valueOf : function () {
1774
+ return +this._d + ((this._offset || 0) * 60000);
1775
+ },
1776
+
1777
+ unix : function () {
1778
+ return Math.floor(+this / 1000);
1779
+ },
1780
+
1781
+ toString : function () {
1782
+ return this.clone().lang('en').format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ");
1783
+ },
1784
+
1785
+ toDate : function () {
1786
+ return this._offset ? new Date(+this) : this._d;
1787
+ },
1788
+
1789
+ toISOString : function () {
1790
+ var m = moment(this).utc();
1791
+ if (0 < m.year() && m.year() <= 9999) {
1792
+ return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
1793
+ } else {
1794
+ return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
1795
+ }
1796
+ },
1797
+
1798
+ toArray : function () {
1799
+ var m = this;
1800
+ return [
1801
+ m.year(),
1802
+ m.month(),
1803
+ m.date(),
1804
+ m.hours(),
1805
+ m.minutes(),
1806
+ m.seconds(),
1807
+ m.milliseconds()
1808
+ ];
1809
+ },
1810
+
1811
+ isValid : function () {
1812
+ return isValid(this);
1813
+ },
1814
+
1815
+ isDSTShifted : function () {
1816
+
1817
+ if (this._a) {
1818
+ return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0;
1819
+ }
1820
+
1821
+ return false;
1822
+ },
1823
+
1824
+ parsingFlags : function () {
1825
+ return extend({}, this._pf);
1826
+ },
1827
+
1828
+ invalidAt: function () {
1829
+ return this._pf.overflow;
1830
+ },
1831
+
1832
+ utc : function () {
1833
+ return this.zone(0);
1834
+ },
1835
+
1836
+ local : function () {
1837
+ this.zone(0);
1838
+ this._isUTC = false;
1839
+ return this;
1840
+ },
1841
+
1842
+ format : function (inputString) {
1843
+ var output = formatMoment(this, inputString || moment.defaultFormat);
1844
+ return this.lang().postformat(output);
1845
+ },
1846
+
1847
+ add : function (input, val) {
1848
+ var dur;
1849
+ // switch args to support add('s', 1) and add(1, 's')
1850
+ if (typeof input === 'string') {
1851
+ dur = moment.duration(+val, input);
1852
+ } else {
1853
+ dur = moment.duration(input, val);
1854
+ }
1855
+ addOrSubtractDurationFromMoment(this, dur, 1);
1856
+ return this;
1857
+ },
1858
+
1859
+ subtract : function (input, val) {
1860
+ var dur;
1861
+ // switch args to support subtract('s', 1) and subtract(1, 's')
1862
+ if (typeof input === 'string') {
1863
+ dur = moment.duration(+val, input);
1864
+ } else {
1865
+ dur = moment.duration(input, val);
1866
+ }
1867
+ addOrSubtractDurationFromMoment(this, dur, -1);
1868
+ return this;
1869
+ },
1870
+
1871
+ diff : function (input, units, asFloat) {
1872
+ var that = makeAs(input, this),
1873
+ zoneDiff = (this.zone() - that.zone()) * 6e4,
1874
+ diff, output;
1875
+
1876
+ units = normalizeUnits(units);
1877
+
1878
+ if (units === 'year' || units === 'month') {
1879
+ // average number of days in the months in the given dates
1880
+ diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2
1881
+ // difference in months
1882
+ output = ((this.year() - that.year()) * 12) + (this.month() - that.month());
1883
+ // adjust by taking difference in days, average number of days
1884
+ // and dst in the given months.
1885
+ output += ((this - moment(this).startOf('month')) -
1886
+ (that - moment(that).startOf('month'))) / diff;
1887
+ // same as above but with zones, to negate all dst
1888
+ output -= ((this.zone() - moment(this).startOf('month').zone()) -
1889
+ (that.zone() - moment(that).startOf('month').zone())) * 6e4 / diff;
1890
+ if (units === 'year') {
1891
+ output = output / 12;
1892
+ }
1893
+ } else {
1894
+ diff = (this - that);
1895
+ output = units === 'second' ? diff / 1e3 : // 1000
1896
+ units === 'minute' ? diff / 6e4 : // 1000 * 60
1897
+ units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60
1898
+ units === 'day' ? (diff - zoneDiff) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
1899
+ units === 'week' ? (diff - zoneDiff) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
1900
+ diff;
1901
+ }
1902
+ return asFloat ? output : absRound(output);
1903
+ },
1904
+
1905
+ from : function (time, withoutSuffix) {
1906
+ return moment.duration(this.diff(time)).lang(this.lang()._abbr).humanize(!withoutSuffix);
1907
+ },
1908
+
1909
+ fromNow : function (withoutSuffix) {
1910
+ return this.from(moment(), withoutSuffix);
1911
+ },
1912
+
1913
+ calendar : function () {
1914
+ // We want to compare the start of today, vs this.
1915
+ // Getting start-of-today depends on whether we're zone'd or not.
1916
+ var sod = makeAs(moment(), this).startOf('day'),
1917
+ diff = this.diff(sod, 'days', true),
1918
+ format = diff < -6 ? 'sameElse' :
1919
+ diff < -1 ? 'lastWeek' :
1920
+ diff < 0 ? 'lastDay' :
1921
+ diff < 1 ? 'sameDay' :
1922
+ diff < 2 ? 'nextDay' :
1923
+ diff < 7 ? 'nextWeek' : 'sameElse';
1924
+ return this.format(this.lang().calendar(format, this));
1925
+ },
1926
+
1927
+ isLeapYear : function () {
1928
+ return isLeapYear(this.year());
1929
+ },
1930
+
1931
+ isDST : function () {
1932
+ return (this.zone() < this.clone().month(0).zone() ||
1933
+ this.zone() < this.clone().month(5).zone());
1934
+ },
1935
+
1936
+ day : function (input) {
1937
+ var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
1938
+ if (input != null) {
1939
+ input = parseWeekday(input, this.lang());
1940
+ return this.add({ d : input - day });
1941
+ } else {
1942
+ return day;
1943
+ }
1944
+ },
1945
+
1946
+ month : function (input) {
1947
+ var utc = this._isUTC ? 'UTC' : '',
1948
+ dayOfMonth;
1949
+
1950
+ if (input != null) {
1951
+ if (typeof input === 'string') {
1952
+ input = this.lang().monthsParse(input);
1953
+ if (typeof input !== 'number') {
1954
+ return this;
1955
+ }
1956
+ }
1957
+
1958
+ dayOfMonth = this.date();
1959
+ this.date(1);
1960
+ this._d['set' + utc + 'Month'](input);
1961
+ this.date(Math.min(dayOfMonth, this.daysInMonth()));
1962
+
1963
+ moment.updateOffset(this);
1964
+ return this;
1965
+ } else {
1966
+ return this._d['get' + utc + 'Month']();
1967
+ }
1968
+ },
1969
+
1970
+ startOf: function (units) {
1971
+ units = normalizeUnits(units);
1972
+ // the following switch intentionally omits break keywords
1973
+ // to utilize falling through the cases.
1974
+ switch (units) {
1975
+ case 'year':
1976
+ this.month(0);
1977
+ /* falls through */
1978
+ case 'month':
1979
+ this.date(1);
1980
+ /* falls through */
1981
+ case 'week':
1982
+ case 'isoWeek':
1983
+ case 'day':
1984
+ this.hours(0);
1985
+ /* falls through */
1986
+ case 'hour':
1987
+ this.minutes(0);
1988
+ /* falls through */
1989
+ case 'minute':
1990
+ this.seconds(0);
1991
+ /* falls through */
1992
+ case 'second':
1993
+ this.milliseconds(0);
1994
+ /* falls through */
1995
+ }
1996
+
1997
+ // weeks are a special case
1998
+ if (units === 'week') {
1999
+ this.weekday(0);
2000
+ } else if (units === 'isoWeek') {
2001
+ this.isoWeekday(1);
2002
+ }
2003
+
2004
+ return this;
2005
+ },
2006
+
2007
+ endOf: function (units) {
2008
+ units = normalizeUnits(units);
2009
+ return this.startOf(units).add((units === 'isoWeek' ? 'week' : units), 1).subtract('ms', 1);
2010
+ },
2011
+
2012
+ isAfter: function (input, units) {
2013
+ units = typeof units !== 'undefined' ? units : 'millisecond';
2014
+ return +this.clone().startOf(units) > +moment(input).startOf(units);
2015
+ },
2016
+
2017
+ isBefore: function (input, units) {
2018
+ units = typeof units !== 'undefined' ? units : 'millisecond';
2019
+ return +this.clone().startOf(units) < +moment(input).startOf(units);
2020
+ },
2021
+
2022
+ isSame: function (input, units) {
2023
+ units = units || 'ms';
2024
+ return +this.clone().startOf(units) === +makeAs(input, this).startOf(units);
2025
+ },
2026
+
2027
+ min: function (other) {
2028
+ other = moment.apply(null, arguments);
2029
+ return other < this ? this : other;
2030
+ },
2031
+
2032
+ max: function (other) {
2033
+ other = moment.apply(null, arguments);
2034
+ return other > this ? this : other;
2035
+ },
2036
+
2037
+ zone : function (input) {
2038
+ var offset = this._offset || 0;
2039
+ if (input != null) {
2040
+ if (typeof input === "string") {
2041
+ input = timezoneMinutesFromString(input);
2042
+ }
2043
+ if (Math.abs(input) < 16) {
2044
+ input = input * 60;
2045
+ }
2046
+ this._offset = input;
2047
+ this._isUTC = true;
2048
+ if (offset !== input) {
2049
+ addOrSubtractDurationFromMoment(this, moment.duration(offset - input, 'm'), 1, true);
2050
+ }
2051
+ } else {
2052
+ return this._isUTC ? offset : this._d.getTimezoneOffset();
2053
+ }
2054
+ return this;
2055
+ },
2056
+
2057
+ zoneAbbr : function () {
2058
+ return this._isUTC ? "UTC" : "";
2059
+ },
2060
+
2061
+ zoneName : function () {
2062
+ return this._isUTC ? "Coordinated Universal Time" : "";
2063
+ },
2064
+
2065
+ parseZone : function () {
2066
+ if (this._tzm) {
2067
+ this.zone(this._tzm);
2068
+ } else if (typeof this._i === 'string') {
2069
+ this.zone(this._i);
2070
+ }
2071
+ return this;
2072
+ },
2073
+
2074
+ hasAlignedHourOffset : function (input) {
2075
+ if (!input) {
2076
+ input = 0;
2077
+ }
2078
+ else {
2079
+ input = moment(input).zone();
2080
+ }
2081
+
2082
+ return (this.zone() - input) % 60 === 0;
2083
+ },
2084
+
2085
+ daysInMonth : function () {
2086
+ return daysInMonth(this.year(), this.month());
2087
+ },
2088
+
2089
+ dayOfYear : function (input) {
2090
+ var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1;
2091
+ return input == null ? dayOfYear : this.add("d", (input - dayOfYear));
2092
+ },
2093
+
2094
+ quarter : function () {
2095
+ return Math.ceil((this.month() + 1.0) / 3.0);
2096
+ },
2097
+
2098
+ weekYear : function (input) {
2099
+ var year = weekOfYear(this, this.lang()._week.dow, this.lang()._week.doy).year;
2100
+ return input == null ? year : this.add("y", (input - year));
2101
+ },
2102
+
2103
+ isoWeekYear : function (input) {
2104
+ var year = weekOfYear(this, 1, 4).year;
2105
+ return input == null ? year : this.add("y", (input - year));
2106
+ },
2107
+
2108
+ week : function (input) {
2109
+ var week = this.lang().week(this);
2110
+ return input == null ? week : this.add("d", (input - week) * 7);
2111
+ },
2112
+
2113
+ isoWeek : function (input) {
2114
+ var week = weekOfYear(this, 1, 4).week;
2115
+ return input == null ? week : this.add("d", (input - week) * 7);
2116
+ },
2117
+
2118
+ weekday : function (input) {
2119
+ var weekday = (this.day() + 7 - this.lang()._week.dow) % 7;
2120
+ return input == null ? weekday : this.add("d", input - weekday);
2121
+ },
2122
+
2123
+ isoWeekday : function (input) {
2124
+ // behaves the same as moment#day except
2125
+ // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
2126
+ // as a setter, sunday should belong to the previous week.
2127
+ return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7);
2128
+ },
2129
+
2130
+ get : function (units) {
2131
+ units = normalizeUnits(units);
2132
+ return this[units]();
2133
+ },
2134
+
2135
+ set : function (units, value) {
2136
+ units = normalizeUnits(units);
2137
+ if (typeof this[units] === 'function') {
2138
+ this[units](value);
2139
+ }
2140
+ return this;
2141
+ },
2142
+
2143
+ // If passed a language key, it will set the language for this
2144
+ // instance. Otherwise, it will return the language configuration
2145
+ // variables for this instance.
2146
+ lang : function (key) {
2147
+ if (key === undefined) {
2148
+ return this._lang;
2149
+ } else {
2150
+ this._lang = getLangDefinition(key);
2151
+ return this;
2152
+ }
2153
+ }
2154
+ });
2155
+
2156
+ // helper for adding shortcuts
2157
+ function makeGetterAndSetter(name, key) {
2158
+ moment.fn[name] = moment.fn[name + 's'] = function (input) {
2159
+ var utc = this._isUTC ? 'UTC' : '';
2160
+ if (input != null) {
2161
+ this._d['set' + utc + key](input);
2162
+ moment.updateOffset(this);
2163
+ return this;
2164
+ } else {
2165
+ return this._d['get' + utc + key]();
2166
+ }
2167
+ };
2168
+ }
2169
+
2170
+ // loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds)
2171
+ for (i = 0; i < proxyGettersAndSetters.length; i ++) {
2172
+ makeGetterAndSetter(proxyGettersAndSetters[i].toLowerCase().replace(/s$/, ''), proxyGettersAndSetters[i]);
2173
+ }
2174
+
2175
+ // add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear')
2176
+ makeGetterAndSetter('year', 'FullYear');
2177
+
2178
+ // add plural methods
2179
+ moment.fn.days = moment.fn.day;
2180
+ moment.fn.months = moment.fn.month;
2181
+ moment.fn.weeks = moment.fn.week;
2182
+ moment.fn.isoWeeks = moment.fn.isoWeek;
2183
+
2184
+ // add aliased format methods
2185
+ moment.fn.toJSON = moment.fn.toISOString;
2186
+
2187
+ /************************************
2188
+ Duration Prototype
2189
+ ************************************/
2190
+
2191
+
2192
+ extend(moment.duration.fn = Duration.prototype, {
2193
+
2194
+ _bubble : function () {
2195
+ var milliseconds = this._milliseconds,
2196
+ days = this._days,
2197
+ months = this._months,
2198
+ data = this._data,
2199
+ seconds, minutes, hours, years;
2200
+
2201
+ // The following code bubbles up values, see the tests for
2202
+ // examples of what that means.
2203
+ data.milliseconds = milliseconds % 1000;
2204
+
2205
+ seconds = absRound(milliseconds / 1000);
2206
+ data.seconds = seconds % 60;
2207
+
2208
+ minutes = absRound(seconds / 60);
2209
+ data.minutes = minutes % 60;
2210
+
2211
+ hours = absRound(minutes / 60);
2212
+ data.hours = hours % 24;
2213
+
2214
+ days += absRound(hours / 24);
2215
+ data.days = days % 30;
2216
+
2217
+ months += absRound(days / 30);
2218
+ data.months = months % 12;
2219
+
2220
+ years = absRound(months / 12);
2221
+ data.years = years;
2222
+ },
2223
+
2224
+ weeks : function () {
2225
+ return absRound(this.days() / 7);
2226
+ },
2227
+
2228
+ valueOf : function () {
2229
+ return this._milliseconds +
2230
+ this._days * 864e5 +
2231
+ (this._months % 12) * 2592e6 +
2232
+ toInt(this._months / 12) * 31536e6;
2233
+ },
2234
+
2235
+ humanize : function (withSuffix) {
2236
+ var difference = +this,
2237
+ output = relativeTime(difference, !withSuffix, this.lang());
2238
+
2239
+ if (withSuffix) {
2240
+ output = this.lang().pastFuture(difference, output);
2241
+ }
2242
+
2243
+ return this.lang().postformat(output);
2244
+ },
2245
+
2246
+ add : function (input, val) {
2247
+ // supports only 2.0-style add(1, 's') or add(moment)
2248
+ var dur = moment.duration(input, val);
2249
+
2250
+ this._milliseconds += dur._milliseconds;
2251
+ this._days += dur._days;
2252
+ this._months += dur._months;
2253
+
2254
+ this._bubble();
2255
+
2256
+ return this;
2257
+ },
2258
+
2259
+ subtract : function (input, val) {
2260
+ var dur = moment.duration(input, val);
2261
+
2262
+ this._milliseconds -= dur._milliseconds;
2263
+ this._days -= dur._days;
2264
+ this._months -= dur._months;
2265
+
2266
+ this._bubble();
2267
+
2268
+ return this;
2269
+ },
2270
+
2271
+ get : function (units) {
2272
+ units = normalizeUnits(units);
2273
+ return this[units.toLowerCase() + 's']();
2274
+ },
2275
+
2276
+ as : function (units) {
2277
+ units = normalizeUnits(units);
2278
+ return this['as' + units.charAt(0).toUpperCase() + units.slice(1) + 's']();
2279
+ },
2280
+
2281
+ lang : moment.fn.lang,
2282
+
2283
+ toIsoString : function () {
2284
+ // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
2285
+ var years = Math.abs(this.years()),
2286
+ months = Math.abs(this.months()),
2287
+ days = Math.abs(this.days()),
2288
+ hours = Math.abs(this.hours()),
2289
+ minutes = Math.abs(this.minutes()),
2290
+ seconds = Math.abs(this.seconds() + this.milliseconds() / 1000);
2291
+
2292
+ if (!this.asSeconds()) {
2293
+ // this is the same as C#'s (Noda) and python (isodate)...
2294
+ // but not other JS (goog.date)
2295
+ return 'P0D';
2296
+ }
2297
+
2298
+ return (this.asSeconds() < 0 ? '-' : '') +
2299
+ 'P' +
2300
+ (years ? years + 'Y' : '') +
2301
+ (months ? months + 'M' : '') +
2302
+ (days ? days + 'D' : '') +
2303
+ ((hours || minutes || seconds) ? 'T' : '') +
2304
+ (hours ? hours + 'H' : '') +
2305
+ (minutes ? minutes + 'M' : '') +
2306
+ (seconds ? seconds + 'S' : '');
2307
+ }
2308
+ });
2309
+
2310
+ function makeDurationGetter(name) {
2311
+ moment.duration.fn[name] = function () {
2312
+ return this._data[name];
2313
+ };
2314
+ }
2315
+
2316
+ function makeDurationAsGetter(name, factor) {
2317
+ moment.duration.fn['as' + name] = function () {
2318
+ return +this / factor;
2319
+ };
2320
+ }
2321
+
2322
+ for (i in unitMillisecondFactors) {
2323
+ if (unitMillisecondFactors.hasOwnProperty(i)) {
2324
+ makeDurationAsGetter(i, unitMillisecondFactors[i]);
2325
+ makeDurationGetter(i.toLowerCase());
2326
+ }
2327
+ }
2328
+
2329
+ makeDurationAsGetter('Weeks', 6048e5);
2330
+ moment.duration.fn.asMonths = function () {
2331
+ return (+this - this.years() * 31536e6) / 2592e6 + this.years() * 12;
2332
+ };
2333
+
2334
+
2335
+ /************************************
2336
+ Default Lang
2337
+ ************************************/
2338
+
2339
+
2340
+ // Set default language, other languages will inherit from English.
2341
+ moment.lang('en', {
2342
+ ordinal : function (number) {
2343
+ var b = number % 10,
2344
+ output = (toInt(number % 100 / 10) === 1) ? 'th' :
2345
+ (b === 1) ? 'st' :
2346
+ (b === 2) ? 'nd' :
2347
+ (b === 3) ? 'rd' : 'th';
2348
+ return number + output;
2349
+ }
2350
+ });
2351
+
2352
+ /* EMBED_LANGUAGES */
2353
+
2354
+ /************************************
2355
+ Exposing Moment
2356
+ ************************************/
2357
+
2358
+ function makeGlobal(deprecate) {
2359
+ var warned = false, local_moment = moment;
2360
+ /*global ender:false */
2361
+ if (typeof ender !== 'undefined') {
2362
+ return;
2363
+ }
2364
+ // here, `this` means `window` in the browser, or `global` on the server
2365
+ // add `moment` as a global object via a string identifier,
2366
+ // for Closure Compiler "advanced" mode
2367
+ if (deprecate) {
2368
+ global.moment = function () {
2369
+ if (!warned && console && console.warn) {
2370
+ warned = true;
2371
+ console.warn(
2372
+ "Accessing Moment through the global scope is " +
2373
+ "deprecated, and will be removed in an upcoming " +
2374
+ "release.");
2375
+ }
2376
+ return local_moment.apply(null, arguments);
2377
+ };
2378
+ extend(global.moment, local_moment);
2379
+ } else {
2380
+ global['moment'] = moment;
2381
+ }
2382
+ }
2383
+
2384
+ // CommonJS module is defined
2385
+ if (hasModule) {
2386
+ module.exports = moment;
2387
+ makeGlobal(true);
2388
+ } else if (typeof define === "function" && define.amd) {
2389
+ define("moment", function (require, exports, module) {
2390
+ if (module.config && module.config() && module.config().noGlobal !== true) {
2391
+ // If user provided noGlobal, he is aware of global
2392
+ makeGlobal(module.config().noGlobal === undefined);
2393
+ }
2394
+
2395
+ return moment;
2396
+ });
2397
+ } else {
2398
+ makeGlobal();
2399
+ }
2400
+ }).call(this);