splitting things

master
tykayn 2 years ago committed by Baptiste Lemoine
parent 0d268afaf9
commit 3620d7c081
  1. 2
      .idea/sqldialects.xml
  2. 20
      config.ts
  3. 6
      from_wiki_osm.ts
  4. 165
      index.js
  5. 135
      index.ts
  6. BIN
      node_modules/.cache/esm/.data.blob
  7. 1
      node_modules/.cache/esm/.data.json
  8. 13
      node_modules/.cache/esm/3ef83326c93bb5f0.js
  9. 165
      node_modules/.cache/esm/4a214f036c2197a3.js
  10. 20
      node_modules/.cache/esm/8bd6d8bafed72c02.js
  11. 23
      node_modules/esm/LICENSE
  12. 137
      node_modules/esm/README.md
  13. 1
      node_modules/esm/esm.js
  14. 1
      node_modules/esm/esm/loader.js
  15. 1
      node_modules/esm/index.js
  16. BIN
      node_modules/esm/node_modules/.cache/esm/.data.blob
  17. 1
      node_modules/esm/node_modules/.cache/esm/.data.json
  18. 71
      node_modules/esm/package.json
  19. 970
      node_modules/moment/CHANGELOG.md
  20. 22
      node_modules/moment/LICENSE
  21. 55
      node_modules/moment/README.md
  22. 71
      node_modules/moment/dist/locale/af.js
  23. 156
      node_modules/moment/dist/locale/ar-dz.js
  24. 54
      node_modules/moment/dist/locale/ar-kw.js
  25. 171
      node_modules/moment/dist/locale/ar-ly.js
  26. 55
      node_modules/moment/dist/locale/ar-ma.js
  27. 104
      node_modules/moment/dist/locale/ar-sa.js
  28. 54
      node_modules/moment/dist/locale/ar-tn.js
  29. 189
      node_modules/moment/dist/locale/ar.js
  30. 101
      node_modules/moment/dist/locale/az.js
  31. 141
      node_modules/moment/dist/locale/be.js
  32. 87
      node_modules/moment/dist/locale/bg.js
  33. 52
      node_modules/moment/dist/locale/bm.js
  34. 128
      node_modules/moment/dist/locale/bn-bd.js
  35. 118
      node_modules/moment/dist/locale/bn.js
  36. 122
      node_modules/moment/dist/locale/bo.js
  37. 165
      node_modules/moment/dist/locale/br.js
  38. 149
      node_modules/moment/dist/locale/bs.js
  39. 97
      node_modules/moment/dist/locale/ca.js
  40. 171
      node_modules/moment/dist/locale/cs.js
  41. 62
      node_modules/moment/dist/locale/cv.js
  42. 97
      node_modules/moment/dist/locale/cy.js
  43. 53
      node_modules/moment/dist/locale/da.js
  44. 79
      node_modules/moment/dist/locale/de-at.js
  45. 78
      node_modules/moment/dist/locale/de-ch.js
  46. 78
      node_modules/moment/dist/locale/de.js
  47. 90
      node_modules/moment/dist/locale/dv.js
  48. 104
      node_modules/moment/dist/locale/el.js
  49. 68
      node_modules/moment/dist/locale/en-au.js
  50. 64
      node_modules/moment/dist/locale/en-ca.js
  51. 68
      node_modules/moment/dist/locale/en-gb.js
  52. 68
      node_modules/moment/dist/locale/en-ie.js
  53. 64
      node_modules/moment/dist/locale/en-il.js
  54. 68
      node_modules/moment/dist/locale/en-in.js
  55. 68
      node_modules/moment/dist/locale/en-nz.js
  56. 68
      node_modules/moment/dist/locale/en-sg.js
  57. 68
      node_modules/moment/dist/locale/eo.js
  58. 104
      node_modules/moment/dist/locale/es-do.js
  59. 106
      node_modules/moment/dist/locale/es-mx.js
  60. 106
      node_modules/moment/dist/locale/es-us.js
  61. 106
      node_modules/moment/dist/locale/es.js
  62. 78
      node_modules/moment/dist/locale/et.js
  63. 63
      node_modules/moment/dist/locale/eu.js
  64. 110
      node_modules/moment/dist/locale/fa.js
  65. 121
      node_modules/moment/dist/locale/fi.js
  66. 58
      node_modules/moment/dist/locale/fil.js
  67. 56
      node_modules/moment/dist/locale/fo.js
  68. 69
      node_modules/moment/dist/locale/fr-ca.js
  69. 73
      node_modules/moment/dist/locale/fr-ch.js
  70. 104
      node_modules/moment/dist/locale/fr.js
  71. 77
      node_modules/moment/dist/locale/fy.js
  72. 95
      node_modules/moment/dist/locale/ga.js
  73. 95
      node_modules/moment/dist/locale/gd.js
  74. 74
      node_modules/moment/dist/locale/gl.js
  75. 124
      node_modules/moment/dist/locale/gom-deva.js
  76. 124
      node_modules/moment/dist/locale/gom-latn.js
  77. 121
      node_modules/moment/dist/locale/gu.js
  78. 94
      node_modules/moment/dist/locale/he.js
  79. 164
      node_modules/moment/dist/locale/hi.js
  80. 154
      node_modules/moment/dist/locale/hr.js
  81. 118
      node_modules/moment/dist/locale/hu.js
  82. 92
      node_modules/moment/dist/locale/hy-am.js
  83. 76
      node_modules/moment/dist/locale/id.js
  84. 139
      node_modules/moment/dist/locale/is.js
  85. 64
      node_modules/moment/dist/locale/it-ch.js
  86. 106
      node_modules/moment/dist/locale/it.js
  87. 148
      node_modules/moment/dist/locale/ja.js
  88. 76
      node_modules/moment/dist/locale/jv.js
  89. 92
      node_modules/moment/dist/locale/ka.js
  90. 82
      node_modules/moment/dist/locale/kk.js
  91. 102
      node_modules/moment/dist/locale/km.js
  92. 123
      node_modules/moment/dist/locale/kn.js
  93. 75
      node_modules/moment/dist/locale/ko.js
  94. 118
      node_modules/moment/dist/locale/ku.js
  95. 84
      node_modules/moment/dist/locale/ky.js
  96. 135
      node_modules/moment/dist/locale/lb.js
  97. 65
      node_modules/moment/dist/locale/lo.js
  98. 123
      node_modules/moment/dist/locale/lt.js
  99. 93
      node_modules/moment/dist/locale/lv.js
  100. 118
      node_modules/moment/dist/locale/me.js
  101. Some files were not shown because too many files have changed in this diff Show More

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SqlDialectMappings">
<file url="file://$PROJECT_DIR$/index.ts" dialect="GenericSQL" />
<file url="file://$PROJECT_DIR$/index.js" dialect="GenericSQL" />
<file url="PROJECT" dialect="PostgreSQL" />
</component>
</project>

@ -0,0 +1,20 @@
const parserConfig = {
// sources of data
rss_feed_url: "https://www.agendadulibre.org/events.rss?tag=openstreetmap",
// https://osmcal.org/static/api.html api doc
// see also https://wiki.openstreetmap.org/wiki/Template:Calendar
osmcal_url: "https://osmcal.org/api/v2/events/", // outputs json of coming events from https://osmcal.org/
// mobilizon instance
feeder_mobilizon_user_id: "3", // organizer_actor_id pour rattacher les nouveaux évènements à un utilisateur. 3 est le premier admin créé.
mobilizon_public_url: "https://mobilizon.openstreetmap.fr", // url publique de l'instance mobilizon pour créer les url d'évènements
// database of mobilizon
db_name: "mobilizon_dev",
db_user: "mobilizon",
db_pass: "mobilizon",
// other configs
askAgendaDuLibre: false, // should we fetch the Agenda du libre feed ?
askOsmCal: false,
runAddQueriesToMobilizon: false,
debug: false,
};
export default parserConfig;

@ -1,6 +0,0 @@
// take events on wiki page of events https://wiki.openstreetmap.org/wiki/Template:Calendar
// take events from https://osmcal.org/
// https://osmcal.org/static/api.html api doc

@ -0,0 +1,165 @@
// @author tykayn contact@cipherbliss.com www.cipherbliss.com
// imports
import utils from './utils.ts';
import parserConfig from './config.ts';
import { v4 as uuidv4 } from 'uuid';
import { htmlEscape } from 'escape-goat';
import Parser from 'rss-parser';
import { Client } from 'pg';
let parser = new Parser();
// @ts-ignore
console.log(' ==============================================='.blue);
// @ts-ignore
console.log(' ==== Rss Feeder for mobilizon - by tykayn ===='.blue);
// @ts-ignore
console.log(' ==============================================='.blue);
if (parserConfig.debug) {
// @ts-ignore
console.log('configMobilizon'.blue, config);
}
let localMobilizonEventsByTitle = [];
// trouver si un évènement existe déjà par son titre
// TODO à affiner au delà du titre
const doesThisEventAlreadyExistInLocalEvents = (rssEvent) => {
const eventAlreadyExists =
-1 !== localMobilizonEventsByTitle.indexOf(rssEvent.title);
if (!eventAlreadyExists) {
if (parserConfig.debug) {
console.log('ajouter l event ', htmlEscape(rssEvent.title));
}
addEventQuery(rssEvent);
}
};
let createEventQueries = '';
let counterOfEventsToAdd = 0;
const addEventQuery = (rssEvent) => {
if (!createEventQueries) {
createEventQueries =
'INSERT INTO events(title, description, organizer_actor_id,inserted_at,updated_at, uuid, url, status, category, options,participants_stats, begins_on, ends_on) VALUES ';
}
if (counterOfEventsToAdd) {
createEventQueries += ` , `;
}
let title = '\'' + htmlEscape(rssEvent.title) + '\'';
let content = '\'' + htmlEscape(rssEvent.content) + '\'';
let uuid = uuidv4();
let uuidString = '\'' + uuid + '\'';
let eventUrl = '\'' + parserConfig.mobilizon_public_url + '/events/' + uuid + '\'';
let begins_on = '\'' + uuid + '\'';
let ends_on = '\'' + utils.convertRssDate(rssEvent.date) + '\'';
let baseOptions =
'{"offers": [], "program": null, "attendees": [], "show_end_time": true, "show_start_time": true, "comment_moderation": "allow_all", "anonymous_participation": true, "participation_condition": [], "show_participation_price": false, "maximum_attendee_capacity": 0, "remaining_attendee_capacity": 0, "hide_organizer_when_group_event": false, "show_remaining_attendee_capacity": false}';
let baseStats =
'{"creator": 1, "rejected": 0, "moderator": 0, "participant": 0, "not_approved": 0, "administrator": 0, "not_confirmed": 0}';
// TODO complete with date conversion
// begins_on , ends_on expecting date format like this: "2020-12-17 23:00:00"
createEventQueries += `( ${title}, ${content}, ${parserConfig.feeder_mobilizon_user_id}, 'now()','now()', ${uuidString}, ${eventUrl}, 'confirmed' , 'meeting', ${baseOptions}, ${baseStats} )`;
counterOfEventsToAdd++;
};
const runCreationQuery = async () => {
createEventQueries = createEventQueries + ';';
if (createEventQueries) {
console.log(' ');
console.log(' ⚙ ');
console.log(' ');
console.log(' createEventQueries');
console.log(createEventQueries);
const res = await client.query(createEventQueries);
console.log('res', res);
return res;
}
};
const client = new Client({
host : 'localhost',
user : parserConfig.db_user,
password: parserConfig.db_pass,
database: parserConfig.db_name,
});
(async () => {
console.log('⌛ interroger la BDD mobilizon postgresql');
await client.connect();
console.log('✅ OK connecté à postgresql');
console.log(' ');
const res = await client.query('SELECT * from events');
console.log('💾 évènements enregistrés dans mobilizon : ', res.rows.length); // Hello world!
res.rows.forEach((item) => {
localMobilizonEventsByTitle.push(item.title);
console.log(' 🟢 ', item.begins_on, item.ends_on, item.title, item.url);
});
if (parserConfig.askAgendaDuLibre) {
// @ts-ignore
console.log(' ===================================================='.blue);
// @ts-ignore
console.log(' ==== demander à l\'agenda du libre son flux RSS ===='.blue);
// @ts-ignore
console.log(' ===================================================='.blue);
console.log('⌛ lecture du flux rss : ' + parserConfig.rss_feed_url);
let feed = await parser.parseURL(parserConfig.rss_feed_url);
console.log('✅ flux rss obtenu');
console.log(feed.title);
console.log('⚙ interprétation des évènements');
console.log(
'⌛ trouver les évènements qui ne font pas partie de la BDD mobilizon postgresql',
);
feed.items.forEach((rssEvent) => {
console.log(rssEvent.title);
// console.log('item', item)
doesThisEventAlreadyExistInLocalEvents(rssEvent);
});
}
if (parserConfig.askOsmCal) {
// @ts-ignore
console.log(' ===================================================='.blue);
// @ts-ignore
console.log(' ==== demander à l\'agenda du libre son flux RSS ===='.blue);
// @ts-ignore
console.log(' ===================================================='.blue);
}
if (parserConfig.runAddQueriesToMobilizon) {
// @ts-ignore
console.log('➕ rajouter les évènements manquants à la base mobilizon'.blue);
await runCreationQuery();
// @ts-ignore
console.log(' ---------- '.green);
// @ts-ignore
console.log(counterOfEventsToAdd, ' évènements ajoutés '.green);
// @ts-ignore
console.log(' ---------- '.green);
// @ts-ignore
console.log('✅ ça c\'est fait '.green);
}
await client.end();
})();
exports = () => {
console.log('hey ho', this);
};

@ -1,135 +0,0 @@
// @author tykayn contact@cipherbliss.com www.cipherbliss.com
// imports
var fs = require("fs");
let Parser = require("rss-parser");
let parser = new Parser();
const { Client } = require("pg");
var colors = require("colors");
const { v4: uuidv4 } = require("uuid");
// configuration of the parser
const config = {
rss_feed_url: "https://www.agendadulibre.org/events.rss?tag=openstreetmap",
feeder_mobilizon_user_id: "3", // organizer_actor_id pour rattacher les nouveaux évènements à un utilisateur. 3 est le premier admin créé.
mobilizon_public_url: "https://mobilizon.openstreetmap.fr", // url publique de l'instance mobilizon pour créer les url d'évènements
db_name: "mobilizon_dev",
db_user: "mobilizon",
db_pass: "mobilizon",
};
console.log(" ===============================================".blue);
console.log(" ==== Rss Feeder for mobilizon - by tykayn ====".blue);
console.log(" ===============================================".blue);
console.log("configMobilizon".blue, config);
let localMobilizonEventsByTitle = [];
// trouver si un évènement existe déjà par son titre
// TODO à affiner au delà du titre
const doesThisEventAlreadyExistInLocalEvents = (rssEvent) => {
const eventAlreadyExists =
-1 !== localMobilizonEventsByTitle.indexOf(rssEvent.title);
if (!eventAlreadyExists) {
console.log("ajouter l event ", htmlEscape(rssEvent.title));
// console.log(" ", escape(rssEvent.content ));
addEventQuery(rssEvent);
}
};
let createEventQueries = "";
let counterOfEventsToAdd = 0;
const { htmlEscape } = require("escape-goat");
const addEventQuery = (rssEvent) => {
if (!createEventQueries) {
createEventQueries =
"INSERT INTO events(title, description, organizer_actor_id,inserted_at,updated_at, uuid, url, status, category, options,participants_stats) VALUES ";
}
if (counterOfEventsToAdd) {
createEventQueries += ` , `;
}
let title = "'" + htmlEscape(rssEvent.title) + "'";
let content = "'" + htmlEscape(rssEvent.content) + "'";
let uuid = uuidv4();
let uuidString = "'" + uuid + "'";
let eventUrl = "'" + config.mobilizon_public_url + "/events/" + uuid + "'";
let baseOptions =
'{"offers": [], "program": null, "attendees": [], "show_end_time": true, "show_start_time": true, "comment_moderation": "allow_all", "anonymous_participation": true, "participation_condition": [], "show_participation_price": false, "maximum_attendee_capacity": 0, "remaining_attendee_capacity": 0, "hide_organizer_when_group_event": false, "show_remaining_attendee_capacity": false}';
let baseStats =
'{"creator": 1, "rejected": 0, "moderator": 0, "participant": 0, "not_approved": 0, "administrator": 0, "not_confirmed": 0}';
// TODO complete with date conversion
// begins_on , ends_on expecting date format like this: "2020-12-17 23:00:00"
createEventQueries += `( ${title}, ${content}, ${config.feeder_mobilizon_user_id}, 'now()','now()', ${uuidString}, ${eventUrl}, 'confirmed' , 'meeting', ${baseOptions}, ${baseStats} )`;
counterOfEventsToAdd++;
};
const runCreationQuery = async () => {
createEventQueries = createEventQueries + ";";
if (createEventQueries) {
console.log(" ");
console.log(" ⚙ ");
console.log(" ");
console.log(" createEventQueries");
console.log(createEventQueries);
const res = await client.query(createEventQueries);
console.log("res", res);
return res;
}
};
const client = new Client({
host: "localhost",
user: config.db_user,
password: config.db_pass,
database: config.db_name,
});
(async () => {
console.log("⌛ interroger la BDD mobilizon postgresql");
await client.connect();
console.log("✅ OK connecté à postgresql");
console.log(" ");
const res = await client.query("SELECT * from events");
console.log("💾 évènements enregistrés dans mobilizon : ", res.rows.length); // Hello world!
res.rows.forEach((item) => {
localMobilizonEventsByTitle.push(item.title);
console.log(" 🟢 ", item.begins_on, item.ends_on, item.title, item.url);
});
console.log("⌛ lecture du flux rss : " + config.rss_feed_url);
let feed = await parser.parseURL(config.rss_feed_url);
console.log("✅ flux rss obtenu");
console.log(feed.title);
console.log("⚙ interprétation des évènements");
console.log(
"⌛ trouver les évènements qui ne font pas partie de la BDD mobilizon postgresql"
);
feed.items.forEach((rssEvent) => {
console.log(rssEvent.title);
// console.log('item', item)
doesThisEventAlreadyExistInLocalEvents(rssEvent);
});
// @ts-ignore
console.log("➕ rajouter les évènements manquants à la base mobilizon".blue);
await runCreationQuery();
// @ts-ignore
console.log(" ---------- ".green);
// @ts-ignore
console.log(counterOfEventsToAdd, " évènements ajoutés ".green);
// @ts-ignore
console.log(" ---------- ".green);
// @ts-ignore
console.log("✅ ça c'est fait ".green);
await client.end();
})();

BIN
node_modules/.cache/esm/.data.blob generated vendored

Binary file not shown.

@ -0,0 +1 @@
{"meta":{"4a214f0323c5b60c.js":[0,7840,17,1609701952657,2,null,null,"../../../index.js",-1,469],"3ef83326c93bb5f0.js":[7840,9632,4,1609702268191,2,null,null,"../../../utils.ts",0,35],"4a214f036c2197a3.js":[9632,18832,17,1609702305847,2,null,null,"../../../index.js",0,472],"8bd6d8bafed72c02.js":[18832,20912,4,1609702292217,2,null,null,"../../../config.ts",0,35],"4ea918b634e7ddee.js":[20912,79016],"cfe8e44034e7ddee.js":[79016,82488],"b4a6e37534e7ddee.js":[82488,83856],"1e05fd5334e7ddee.js":[83856,85064],"bf10b4f234e7ddee.js":[85064,86400],"8f40bea234e7ddee.js":[86400,87512],"7e09912634e7ddee.js":[87512,88504],"2674ff5934e7ddee.js":[88504,89592],"8998963e34e7ddee.js":[89592,91136],"502bd04b34e7ddee.js":[91136,92256],"66c70c9d34e7ddee.js":[92256,93352],"8f1bb44f34e7ddee.js":[93352,94544],"434e4b9234e7ddee.js":[94544,95640],"cda6849f34e7ddee.js":[95640,96744],"e3420b7d34e7ddee.js":[96744,97648],"8b712e7434e7ddee.js":[97648,98768],"2053138034e7ddee.js":[98768,99896],"c582ecc634e7ddee.js":[99896,100672],"0bac123734e7ddee.js":[100672,103384],"1c7694f234e7ddee.js":[103384,105408],"5faa8dc034e7ddee.js":[105408,107848],"97c0385c34e7ddee.js":[107848,109936],"36df28f334e7ddee.js":[109936,112432],"eb69a67234e7ddee.js":[112432,114360],"5cfbe43834e7ddee.js":[114360,116592],"49f59e8a34e7ddee.js":[116592,127104],"d51c7bf134e7ddee.js":[127104,129496],"8a2f4c9c34e7ddee.js":[129496,131024],"10f0948334e7ddee.js":[131024,132976],"05b6411534e7ddee.js":[132976,149592],"e63a0d4134e7ddee.js":[149592,151264],"665d971034e7ddee.js":[151264,157112],"506d4c4234e7ddee.js":[157112,158936],"bc5923d134e7ddee.js":[158936,164960],"06f7b82c34e7ddee.js":[164960,166944],"c8b25ccd34e7ddee.js":[166944,172904],"1f5433a534e7ddee.js":[172904,174784],"e5bd35c434e7ddee.js":[174784,178496],"8e4a9ef134e7ddee.js":[178496,180376],"82c6418834e7ddee.js":[180376,182840],"0f45284634e7ddee.js":[182840,185816],"a46ec2ab34e7ddee.js":[185816,187880],"581626d034e7ddee.js":[187880,192080],"91804a3134e7ddee.js":[192080,194152],"6ab8978a34e7ddee.js":[194152,203800],"f875f50734e7ddee.js":[203800,208160],"93569bf434e7ddee.js":[208160,210208],"e76687d634e7ddee.js":[210208,213264],"112ad7a934e7ddee.js":[213264,215568],"d7317d4034e7ddee.js":[215568,217624],"20cf856b34e7ddee.js":[217624,218808],"4b5cde3834e7ddee.js":[218808,229632],"3d32dce434e7ddee.js":[229632,234216],"54a236fc34e7ddee.js":[234216,237776],"0284fc9e1e0f713c.js":[237776,255568],"a8f15fcc34e7ddee.js":[255568,256704],"b0a2f5d334e7ddee.js":[256704,258456],"135aeb1534e7ddee.js":[258456,260976],"3aed101f34e7ddee.js":[260976,263320],"67a658bc34e7ddee.js":[263320,267520],"92b7bd0d34e7ddee.js":[267520,270280],"51a1bfca34e7ddee.js":[270280,271432],"8b76f93b34e7ddee.js":[271432,273432],"e5dbf4c734e7ddee.js":[273432,275008],"75cfb7f334e7ddee.js":[275008,280240],"3850b3a734e7ddee.js":[280240,282168],"b771994234e7ddee.js":[282168,284344],"8785e88234e7ddee.js":[284344,285920],"7ce9446134e7ddee.js":[285920,288984],"0551020634e7ddee.js":[288984,290800],"4cbe626c34e7ddee.js":[290800,291856],"bbae285f34e7ddee.js":[291856,293416],"920f6c777d217eb1.js":[293416,296328],"6f58dc5534e7ddee.js":[296328,297232],"0cc3bc0992c47e23.js":[297232,298064],"a474b7b434e7ddee.js":[298064,300208],"972b86bf4a371210.js":[300208,301072],"cd8930bc34e7ddee.js":[301072,303704],"0eafaf3234e7ddee.js":[303704,305240],"0caa99b934e7ddee.js":[305240,306320],"d29740ff34e7ddee.js":[306320,309800],"f693a2a834e7ddee.js":[309800,311320],"00f4096434e7ddee.js":[311320,313000],"66e222ca34e7ddee.js":[313000,321208],"b6f27b6b34e7ddee.js":[321208,322016],"4618d65334e7ddee.js":[322016,323848],"47ec677034e7ddee.js":[323848,325232],"a6a949ec34e7ddee.js":[325232,326368],"3a7392a334e7ddee.js":[326368,328880],"a5de0d2834e7ddee.js":[328880,329864],"b4cc734134e7ddee.js":[329864,337112],"d3dc197e6408243f.js":[337112,337928],"6457305334e7ddee.js":[337928,340112],"2681d3c834e7ddee.js":[340112,342384],"4527f91e34e7ddee.js":[342384,343544],"af5182ed34e7ddee.js":[343544,344920],"357b6f0e34e7ddee.js":[344920,346728],"89a48c1c34e7ddee.js":[346728,348000],"e0279dc834e7ddee.js":[348000,349752],"787a006e34e7ddee.js":[349752,350704],"ebf2880534e7ddee.js":[350704,353416],"c8e1dfdc34e7ddee.js":[353416,355064],"4390ae1534e7ddee.js":[355064,358664],"8d2da48134e7ddee.js":[358664,359872],"5f16e98b34e7ddee.js":[359872,364960],"4fbbd02934e7ddee.js":[364960,368968],"f0b51d8e34e7ddee.js":[368968,370816],"06b5860134e7ddee.js":[370816,374312],"52a3a93334e7ddee.js":[374312,376224],"d8594d5534e7ddee.js":[376224,379760]},"version":"3.2.25"}

@ -0,0 +1,13 @@
_c93.x([["default",()=>_c93.o]]);const moment = require("moment");
const utils = {
convertRssDate: (rssDate) => {
let converted = moment(rssDate).format('L');// in js format like 2021-03-12T19:00:00Z
console.log('converted', converted)
// like 2021-01-03 15:31:02.918940
return converted
}
}
_c93.d(utils);

@ -0,0 +1,165 @@
let utils,parserConfig,uuidv4,htmlEscape,Parser,Client;_6c2.w("./utils.ts",[["default",["utils"],function(v){utils=v}]]);_6c2.w("./config.ts",[["default",["parserConfig"],function(v){parserConfig=v}]]);_6c2.w("uuid",[["v4",["uuidv4"],function(v){uuidv4=v}]]);_6c2.w("escape-goat",[["htmlEscape",["htmlEscape"],function(v){htmlEscape=v}]]);_6c2.w("rss-parser",[["default",["Parser"],function(v){Parser=v}]]);_6c2.w("pg",[["Client",["Client"],function(v){Client=v}]]);// @author tykayn contact@cipherbliss.com www.cipherbliss.com
// imports
let parser = new Parser();
// @ts-ignore
_6c2.g.console.log(' ==============================================='.blue);
// @ts-ignore
_6c2.g.console.log(' ==== Rss Feeder for mobilizon - by tykayn ===='.blue);
// @ts-ignore
_6c2.g.console.log(' ==============================================='.blue);
if (parserConfig.debug) {
// @ts-ignore
_6c2.g.console.log('configMobilizon'.blue, config);
}
let localMobilizonEventsByTitle = [];
// trouver si un évènement existe déjà par son titre
// TODO à affiner au delà du titre
const doesThisEventAlreadyExistInLocalEvents = (rssEvent) => {
const eventAlreadyExists =
-1 !== localMobilizonEventsByTitle.indexOf(rssEvent.title);
if (!eventAlreadyExists) {
if (parserConfig.debug) {
_6c2.g.console.log('ajouter l event ', htmlEscape(rssEvent.title));
}
addEventQuery(rssEvent);
}
};
let createEventQueries = '';
let counterOfEventsToAdd = 0;
const addEventQuery = (rssEvent) => {
if (!createEventQueries) {
createEventQueries =
'INSERT INTO events(title, description, organizer_actor_id,inserted_at,updated_at, uuid, url, status, category, options,participants_stats, begins_on, ends_on) VALUES ';
}
if (counterOfEventsToAdd) {
createEventQueries += ` , `;
}
let title = '\'' + htmlEscape(rssEvent.title) + '\'';
let content = '\'' + htmlEscape(rssEvent.content) + '\'';
let uuid = uuidv4();
let uuidString = '\'' + uuid + '\'';
let eventUrl = '\'' + parserConfig.mobilizon_public_url + '/events/' + uuid + '\'';
let begins_on = '\'' + uuid + '\'';
let ends_on = '\'' + utils.convertRssDate(rssEvent.date) + '\'';
let baseOptions =
'{"offers": [], "program": null, "attendees": [], "show_end_time": true, "show_start_time": true, "comment_moderation": "allow_all", "anonymous_participation": true, "participation_condition": [], "show_participation_price": false, "maximum_attendee_capacity": 0, "remaining_attendee_capacity": 0, "hide_organizer_when_group_event": false, "show_remaining_attendee_capacity": false}';
let baseStats =
'{"creator": 1, "rejected": 0, "moderator": 0, "participant": 0, "not_approved": 0, "administrator": 0, "not_confirmed": 0}';
// TODO complete with date conversion
// begins_on , ends_on expecting date format like this: "2020-12-17 23:00:00"
createEventQueries += `( ${title}, ${content}, ${parserConfig.feeder_mobilizon_user_id}, 'now()','now()', ${uuidString}, ${eventUrl}, 'confirmed' , 'meeting', ${baseOptions}, ${baseStats} )`;
counterOfEventsToAdd++;
};
const runCreationQuery = async () => {
createEventQueries = createEventQueries + ';';
if (createEventQueries) {
console.log(' ');
console.log(' ⚙ ');
console.log(' ');
console.log(' createEventQueries');
_6c2.g.console.log(createEventQueries);
const res = await client.query(createEventQueries);
_6c2.g.console.log('res', res);
return res;
}
};
const client = new Client({
host : 'localhost',
user : parserConfig.db_user,
password: parserConfig.db_pass,
database: parserConfig.db_name,
});
(async () => {
console.log('⌛ interroger la BDD mobilizon postgresql');
await client.connect();
console.log('✅ OK connecté à postgresql');
console.log(' ');
const res = await client.query('SELECT * from events');
_6c2.g.console.log('💾 évènements enregistrés dans mobilizon : ', res.rows.length); // Hello world!
res.rows.forEach((item) => {
localMobilizonEventsByTitle.push(item.title);
_6c2.g.console.log(' 🟢 ', item.begins_on, item.ends_on, item.title, item.url);
});
if (parserConfig.askAgendaDuLibre) {
// @ts-ignore
_6c2.g.console.log(' ===================================================='.blue);
// @ts-ignore
_6c2.g.console.log(' ==== demander à l\'agenda du libre son flux RSS ===='.blue);
// @ts-ignore
_6c2.g.console.log(' ===================================================='.blue);
_6c2.g.console.log('⌛ lecture du flux rss : ' + parserConfig.rss_feed_url);
let feed = await parser.parseURL(parserConfig.rss_feed_url);
console.log('✅ flux rss obtenu');
_6c2.g.console.log(feed.title);
console.log('⚙ interprétation des évènements');
console.log(
'⌛ trouver les évènements qui ne font pas partie de la BDD mobilizon postgresql',
);
feed.items.forEach((rssEvent) => {
_6c2.g.console.log(rssEvent.title);
// console.log('item', item)
doesThisEventAlreadyExistInLocalEvents(rssEvent);
});
}
if (parserConfig.askOsmCal) {
// @ts-ignore
_6c2.g.console.log(' ===================================================='.blue);
// @ts-ignore
_6c2.g.console.log(' ==== demander à l\'agenda du libre son flux RSS ===='.blue);
// @ts-ignore
_6c2.g.console.log(' ===================================================='.blue);
}
if (parserConfig.runAddQueriesToMobilizon) {
// @ts-ignore
_6c2.g.console.log('➕ rajouter les évènements manquants à la base mobilizon'.blue);
await runCreationQuery();
// @ts-ignore
_6c2.g.console.log(' ---------- '.green);
// @ts-ignore
_6c2.g.console.log(counterOfEventsToAdd, ' évènements ajoutés '.green);
// @ts-ignore
_6c2.g.console.log(' ---------- '.green);
// @ts-ignore
_6c2.g.console.log('✅ ça c\'est fait '.green);
}
await client.end();
})();
exports = () => {
_6c2.g.console.log('hey ho', this);
};

@ -0,0 +1,20 @@
_fed.x([["default",()=>_fed.o]]); const parserConfig = {
// sources of data
rss_feed_url: "https://www.agendadulibre.org/events.rss?tag=openstreetmap",
// https://osmcal.org/static/api.html api doc
// see also https://wiki.openstreetmap.org/wiki/Template:Calendar
osmcal_url: "https://osmcal.org/api/v2/events/", // outputs json of coming events from https://osmcal.org/
// mobilizon instance
feeder_mobilizon_user_id: "3", // organizer_actor_id pour rattacher les nouveaux évènements à un utilisateur. 3 est le premier admin créé.
mobilizon_public_url: "https://mobilizon.openstreetmap.fr", // url publique de l'instance mobilizon pour créer les url d'évènements
// database of mobilizon
db_name: "mobilizon_dev",
db_user: "mobilizon",
db_pass: "mobilizon",
// other configs
askAgendaDuLibre: false, // should we fetch the Agenda du libre feed ?
askOsmCal: false,
runAddQueriesToMobilizon: false,
debug: false,
};
_fed.d(parserConfig);

23
node_modules/esm/LICENSE generated vendored

@ -0,0 +1,23 @@
The MIT License (MIT)
Copyright esm contributors
Based on reify, copyright Ben Newman <https://github.com/benjamn/reify>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

137
node_modules/esm/README.md generated vendored

@ -0,0 +1,137 @@
# esm
The brilliantly simple, babel-less, bundle-less ECMAScript module loader.
> `esm` is the world’s most advanced ECMAScript module loader.
This fast, production ready, zero dependency loader is all you need to support
ECMAScript modules in Node 6+. See the release [post](https://medium.com/web-on-the-edge/tomorrows-es-modules-today-c53d29ac448c)
and [video](https://www.youtube.com/watch?v=JcZ-FzfDq8A#t=5) for details!
Install
---
* __New projects__
Run `npm init esm` or `yarn create esm`.
:bulb: Use the `-y` flag to answer “yes” to all prompts.
* __Existing projects__
Run `npm i esm` or `yarn add esm`.
Getting started
---
There are two ways to enable `esm`.
1. Enable `esm` for packages:
Use `esm` to load the main ES module and export it as CommonJS.
__index.js__
```js
// Set options as a parameter, environment variable, or rc file.
require = require("esm")(module/*, options*/)
module.exports = require("./main.js")
```
__main.js__
```js
// ESM syntax is supported.
export {}
```
:bulb: These files are automagically created with `npm init esm` or `yarn create esm`.
2. Enable `esm` for local runs:
```shell
node -r esm main.js
```
:bulb: Omit the filename to enable `esm` in the REPL.
Features
---
:clap: By default, :100: percent CJS interoperability is enabled so you can get stuff done.<br>
:lock: `.mjs` files are limited to basic functionality without support for `esm` options.
Out of the box `esm` just works, no configuration necessary, and supports:
* Passing all applicable [test262](https://github.com/tc39/test262) compliance tests
* [`import`](https://ponyfoo.com/articles/es6-modules-in-depth#import)/[`export`](https://ponyfoo.com/articles/es6-modules-in-depth#export)
* [`import.meta`](https://github.com/tc39/proposal-import-meta)
* [Dynamic `import`](https://github.com/tc39/proposal-dynamic-import)
* [Live bindings](https://ponyfoo.com/articles/es6-modules-in-depth#bindings-not-values)
* [File URI scheme](https://en.wikipedia.org/wiki/File_URI_scheme)
* Node `stdin`, [`--eval`](https://nodejs.org/api/cli.html#cli_e_eval_script), [`--print`](https://nodejs.org/api/cli.html#cli_p_print_script) flags
* Node [`--check`](https://nodejs.org/api/cli.html#cli_c_check) flag _(Node 10+)_
Options
---
Specify options with one of the following:
* `"esm"` field in `package.json`
* CJS/ESM in an `.esmrc.js`, `.esmrc.cjs`, or `.esmrc.mjs` file
* [JSON6](https://github.com/d3x0r/json6) in an `.esmrc` or `.esmrc.json` file
* JSON6 or file path in the `ESM_OPTIONS` environment variable
* `ESM_DISABLE_CACHE` environment variable
<table><tr><td colspan=2><code>{</code><tr><td valign=top><code>"cjs":true</code><td><p>A boolean or object for toggling CJS features in ESM.<details><summary>Features</summary><table><tr><td colspan=2><code>{</code><tr><td valign=top><code>"cache":true</code><td><p>A boolean for storing ES modules in <code>require.cache</code>.<tr><td valign=top><code>"esModule":true</code><td><p>A boolean for <code>__esModule</code> interoperability.<tr><td valign=top><code>"extensions":true</code><td><p>A boolean for respecting <code>require.extensions</code> in ESM.<tr><td valign=top><code>"mutableNamespace":true</code><td><p>A boolean for mutable <a href=https://ponyfoo.com/articles/es6-modules-in-depth#import-all-the-things>namespace objects</a>.<tr><td valign=top><code>"namedExports":true</code><td><p>A boolean for <a href=https://ponyfoo.com/articles/es6-modules-in-depth#importing-named-exports>importing named exports</a> of CJS modules.<tr><td valign=top><code>"paths":true</code><td><p>A boolean for following CJS <a href=https://github.com/nodejs/node-eps/blob/master/002-es-modules.md#432-removal-of-non-local-dependencies>path rules</a> in ESM.<tr><td valign=top><code>"vars":true</code><td><p>A boolean for <code>__dirname</code>, <code>__filename</code>, and <code>require</code> in ESM.<tr><td valign=top><code>"dedefault":false</code><td><p>A boolean for requiring ES modules without the dangling <code>require().default</code>.<tr><td valign=top><code>"topLevelReturn":false</code><td><p>A boolean for top-level <code>return</code> support.<tr><td colspan=2><code>}</code></table></details><tr><td valign=top><code>"mainFields":["main"]</code><td><p>An array of fields checked when importing a package.<tr><td valign=top><code>"mode":"auto"</code><td><p>A string mode:<ul><li><code>"auto"</code> detect files with <code>import</code>, <code>import.meta</code>, <code>export</code>,<br><a href=https://github.com/tc39/proposal-modules-pragma><code>"use module"</code></a>, or <code>.mjs</code> as ESM.<li><code>"all"</code> files besides those with <code>"use script"</code> or <code>.cjs</code> are treated as ESM.<li><code>"strict"</code> to treat <strong>only</strong> <code>.mjs</code> files as ESM.</ul><tr><td valign=top><code>"await":false</code><td><p>A boolean for <a href=https://github.com/tc39/proposal-top-level-await>top-level <code>await</code></a> in modules without ESM exports. <em>(Node 10+)</em><tr><td valign=top><code>"force":false</code><td><p>A boolean to apply these options to all module loads.<tr><td valign=top><code>"wasm":false</code><td><p>A boolean for <a href=https://nodejs.org/api/globals.html#globals_webassembly>WebAssembly</a> module support. <em>(Node 8+)</em><tr><td colspan=2><code>}</code></table>
DevOpts
---
<table><tr><td colspan=2><code>{</code><tr><td valign=top><code>"cache":true</code><td><p>A boolean for toggling cache creation or a cache directory path.<tr><td valign=top><code>"sourceMap":false</code><td><p>A boolean for including inline source maps.<tr><td colspan=2><code>}</code></table>
Tips
---
### Bundling
* For bundlers like [`browserify`](http://browserify.org/)+[`esmify`](https://github.com/mattdesl/esmify),
[`parcel-bundler`](https://parceljs.org/), and [`webpack`](https://webpack.js.org/)
add a `"module"` field to `package.json` pointing to the main ES module.
```json
"main": "index.js",
"module": "main.js"
```
:bulb: This is automagically done with `npm init esm` or `yarn create esm`.
### Extensions
* Enable `esm` for [`wallaby.js`](https://wallabyjs.com/) following their
[integration example](https://wallabyjs.com/docs/integration/node.html#es-modules).
### Loading
* Load `esm` before loaders/monitors like
[`@babel/register`](https://babeljs.io/docs/en/next/babel-register.html),
[`newrelic`](https://github.com/newrelic/node-newrelic),
[`sqreen`](https://docs.sqreen.io/sqreen-for-nodejs/getting-started-2/), and
[`ts-node`](https://github.com/TypeStrong/ts-node#programmatic).
* Load `esm` for [`jasmine`](https://jasmine.github.io/) using the
[`"helpers"`](https://jasmine.github.io/setup/nodejs.html#configuration)
field in `jasmine.json`:
```json
"helpers": [
"node_modules/esm"
]
```
* Load `esm` with “node-args" options of:<br>
- [`pm2`](https://pm2.io/doc/en/runtime/reference/pm2-cli/#pm2-flags): `--node-args="-r esm"`
* Load `esm` with “require” options of
[`ava`](https://github.com/avajs/ava/blob/master/docs/recipes/es-modules.md),
[`mocha`](https://mochajs.org/#-require-module-r-module),
[`nodemon`](https://nodemon.io/),
[`nyc`](https://github.com/istanbuljs/nyc#require-additional-modules),
[`qunit`](https://github.com/qunitjs/qunit/releases/tag/2.6.0),
[`tape`](https://github.com/substack/tape#preloading-modules), and
[`webpack`](https://webpack.js.org/api/cli/#config-options).
:bulb: Builtin `require` cannot sideload `.mjs` files. However, `.js` files
can be sideloaded or `.mjs` files may be loaded with dynamic `import`.

1
node_modules/esm/esm.js generated vendored

@ -0,0 +1 @@
const e=(function(){return this||Function("return this")()})(),{apply:t,defineProperty:n}=Reflect,{freeze:r}=Object,{hasOwnProperty:l}=Object.prototype,o=Symbol.for,{type:i,versions:u}=process,{filename:a,id:s,parent:c}=module,_=x(u,"electron"),p=_&&"renderer"===i;let d="";"string"==typeof s&&s.startsWith("internal/")&&(d=q("internal/esm/loader"));const f=require("module"),{Script:m}=require("vm"),{createCachedData:y,runInNewContext:h,runInThisContext:b}=m.prototype,{sep:g}=require("path"),{readFileSync:v}=require("fs"),w=new f(s);function q(e){let t;try{const{internalBinding:n}=require("internal/bootstrap/loaders"),r=n("natives");x(r,e)&&(t=r[e])}catch(e){}return"string"==typeof t?t:""}function x(e,n){return null!=e&&t(l,e,[n])}function D(){return M(require,w,T),w.exports}function O(e,t){return D()(e,t)}function j(e,t){try{return v(e,t)}catch(e){}return null}let C,F;w.filename=a,w.parent=c;let I="",S="";""!==d?(S=d,F={__proto__:null,filename:"esm.js"}):(I=__dirname+g+"node_modules"+g+".cache"+g+"esm",C=j(I+g+".data.blob"),S=j(__dirname+g+"esm"+g+"loader.js","utf8"),null===C&&(C=void 0),null===S&&(S=""),F={__proto__:null,cachedData:C,filename:a,produceCachedData:"function"!=typeof y});const k=new m("const __global__ = this;(function (require, module, __shared__) { "+S+"\n});",F);let M,T;if(M=p?t(b,k,[{__proto__:null,filename:a}]):t(h,k,[{__proto__:null,global:e},{__proto__:null,filename:a}]),T=D(),""!==I){const{dir:e}=T.package;let t=e.get(I);if(void 0===t){let n=C;void 0===n&&(n=null),t={buffer:C,compile:new Map([["esm",{circular:0,code:null,codeWithTDZ:null,filename:null,firstAwaitOutsideFunction:null,firstReturnOutsideFunction:null,mtime:-1,scriptData:n,sourceType:1,transforms:0,yieldIndex:-1}]]),meta:new Map},e.set(I,t)}const{pendingScripts:n}=T;let r=n.get(I);void 0===r&&(r=new Map,n.set(I,r)),r.set("esm",k)}n(O,T.symbol.package,{__proto__:null,value:!0}),n(O,T.customInspectKey,{__proto__:null,value:()=>"esm enabled"}),n(O,o("esm:package"),{__proto__:null,value:!0}),r(O),module.exports=O;

1
node_modules/esm/esm/loader.js generated vendored

File diff suppressed because one or more lines are too long

1
node_modules/esm/index.js generated vendored

@ -0,0 +1 @@
"use strict";module.exports=require("./esm.js");

Binary file not shown.

@ -0,0 +1 @@
{"meta":{"esm":[0,552384]},"version":"3.2.25"}

71
node_modules/esm/package.json generated vendored

@ -0,0 +1,71 @@
{
"_from": "esm",
"_id": "esm@3.2.25",
"_inBundle": false,
"_integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==",
"_location": "/esm",
"_phantomChildren": {},
"_requested": {
"type": "tag",
"registry": true,
"raw": "esm",
"name": "esm",
"escapedName": "esm",
"rawSpec": "",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz",
"_shasum": "342c18c29d56157688ba5ce31f8431fbb795cc10",
"_spec": "esm",
"_where": "/var/www/html/feeder-mobilizon-rss",
"author": {
"name": "John-David Dalton",
"email": "john.david.dalton@gmail.com"
},
"bugs": {
"url": "https://github.com/standard-things/esm/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "Tomorrow's ECMAScript modules today!",
"engines": {
"node": ">=6"
},
"files": [
"index.js",
"esm.js",
"esm/loader.js"
],
"homepage": "https://github.com/standard-things/esm#readme",
"husky": {
"hooks": {
"precommit": "npm run lint"
}
},
"keywords": [
"commonjs",
"ecmascript",
"export",
"import",
"modules",
"node",
"require"
],
"license": "MIT",
"main": "esm.js",
"name": "esm",
"repository": {
"type": "git",
"url": "git+https://github.com/standard-things/esm.git"
},
"runkitExample": "require = require(\"esm\")(module)\nrequire(\"lodash-es\")",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"version": "3.2.25"
}

970
node_modules/moment/CHANGELOG.md generated vendored

@ -0,0 +1,970 @@
Changelog
=========
### 2.29.1 [See full changelog](https://gist.github.com/marwahaha/cc478ba01a1292ab4bd4e861d164d99b)
* Release Oct 6, 2020
Updated deprecation message, bugfix in hi locale
### 2.29.0 [See full changelog](https://gist.github.com/marwahaha/b0111718641a6461800066549957ec14)
* Release Sept 22, 2020
New locales (es-mx, bn-bd).
Minor bugfixes and locale improvements.
More tests.
Moment is in maintenance mode. Read more at this link:
https://momentjs.com/docs/#/-project-status/
### 2.28.0 [See full changelog](https://gist.github.com/marwahaha/028fd6c2b2470b2804857cfd63c0e94f)
* Release Sept 13, 2020
Fix bug where .format() modifies original instance, and locale updates
### 2.27.0 [See full changelog](https://gist.github.com/marwahaha/5100c9c2f42019067b1f6cefc333daa7)
* Release June 18, 2020
Added Turkmen locale, other locale improvements, slight TypeScript fixes
### 2.26.0 [See full changelog](https://gist.github.com/marwahaha/0725c40740560854a849b096ea7b7590)
* Release May 19, 2020
TypeScript fixes and many locale improvements
### 2.25.3
* Release May 4, 2020
Remove package.json module property. It looks like webpack behaves differently
for modules loaded via module vs jsnext:main.
### 2.25.2
* Release May 4, 2020
This release includes ES Module bundled moment, separate from it's source code
under dist/ folder. This might alleviate issues with finding the `./locale
subfolder for loading locales. This might also mean now webpack will bundle all
locales automatically, unless told otherwise.
### 2.25.1
* Release May 1, 2020
This is a quick patch release to address some of the issues raised after
releasing 2.25.0.
* [2e268635](https://github.com/moment/moment/commit/2e268635) [misc] Revert #5269 due to webpack warning
* [226799e1](https://github.com/moment/moment/commit/226799e1) [locale] fil: Fix metadata comment
* [a83a521](https://github.com/moment/moment/commit/a83a521) [bugfix] Fix typeoff usages
* [e324334](https://github.com/moment/moment/commit/e324334) [pkg] Add ts3.1-typings in npm package
* [28cc23e](https://github.com/moment/moment/commit/28cc23e) [misc] Remove deleted generated locale en-SG
### 2.25.0 [See full changelog](https://gist.github.com/ichernev/6148e64df2427e455b10ce6a18de1a65)
* Release May 1, 2020
* [#4611](https://github.com/moment/moment/issues/4611) [022dc038](https://github.com/moment/moment/commit/022dc038) [feature] Support for strict string parsing, fixes [#2469](https://github.com/moment/moment/issues/2469)
* [#4599](https://github.com/moment/moment/issues/4599) [4b615b9d](https://github.com/moment/moment/commit/4b615b9d) [feature] Add support for eras in en and jp
* [#4296](https://github.com/moment/moment/issues/4296) [757d4ff8](https://github.com/moment/moment/commit/757d4ff8) [feature] Accept custom relative thresholds in duration.humanize
* 18 bigfixes
* 36 locale fixes
* 5 new locales (oc-lnc, zh-mo, en-in, gom-deva, fil)
### 2.24.0 [See full changelog](https://gist.github.com/marwahaha/12366fe45bee328f33acf125d4cd540e)
* Release Jan 21, 2019
* [#4338](https://github.com/moment/moment/pull/4338) [bugfix] Fix startOf/endOf DST issues while boosting performance
* [#4553](https://github.com/moment/moment/pull/4553) [feature] Add localeSort param to Locale weekday methods
* [#4887](https://github.com/moment/moment/pull/4887) [bugfix] Make Duration#as work with quarters
* 3 new locales (it-ch, ga, en-SG)
* Lots of locale improvements
### 2.23.0 [See full changelog](https://gist.github.com/marwahaha/eadb7ac11b761290399a576f8b2419a5)
* Release Dec 12, 2018
* [#4863](https://github.com/moment/moment/pull/4863) [new locale] added Kurdish language (ku)
* [#4417](https://github.com/moment/moment/pull/4417) [bugfix] isBetween should return false for invalid dates
* [#4700](https://github.com/moment/moment/pull/4700) [bugfix] Fix [#4698](https://github.com/moment/moment/pull/4698): Use ISO WeekYear for HTML5_FMT.WEEK
* [#4563](https://github.com/moment/moment/pull/4563) [feature] Fix [#4518](https://github.com/moment/moment/pull/4518): Add support to add/subtract ISO weeks
* other locale changes, build process changes, typos
### 2.22.2 [See full changelog](https://gist.github.com/marwahaha/4d992c13c2dbc0f59d4d8acae1dc6d3a)
* Release May 31, 2018
* [#4564](https://github.com/moment/moment/pull/4564) [bugfix] Avoid using trim()
* [#4453](https://github.com/moment/moment/pull/4453) [bugfix] Treat periods as periods, not regex-anything period, for weekday parsing in strict mode.
* Minor locale improvements (pa-in, be, az)
### 2.22.1 [See full changelog](https://gist.github.com/marwahaha/ff2cd13d0eda08afb7a237b10aae558c)
* Release Apr 14, 2018
* [#4495](https://github.com/moment/moment/pull/4495) [bugfix] Added HTML5_FMT to moment.d.ts
* Minor locale improvements
* QUnit upgrade and coveralls reporting
### 2.22.0 [See full changelog](https://gist.github.com/marwahaha/ae895025dac3f0641fa9ec2e36d282bb)
* Release Mar 30, 2018
* [#4423](https://github.com/moment/moment/pull/4423) [new locale] Added Mongolian locale mn
* Various locale improvements
* Minor misc changes
### 2.21.0 [See full changelog](https://gist.github.com/marwahaha/80d19ef882b71df1948df7865efdd40e)
* Release Mar 2, 2018
* [#4391](https://github.com/moment/moment/pull/4391) [bugfix] Fix [#4390](https://github.com/moment/moment/pull/4390): use offset properly in toISOString
* [#4310](https://github.com/moment/moment/pull/4310) [bugfix] Fix [#3883](https://github.com/moment/moment/pull/3883) lazy load parentLocale in defineLocale, fallback to global if missing
* [#4085](https://github.com/moment/moment/pull/4085) [misc] Print console warning when setting non-existent locales
* [#4371](https://github.com/moment/moment/pull/4371) [misc] fix deprecated rollup options
* New locales: ug-cn, en-il, tg
* Various locale improvements
### 2.20.1 [See changelog](https://gist.github.com/marwahaha/d72c1cb22076373be889b16272cbd187)
* Release Dec 18, 2017
* [#4359](https://github.com/moment/moment/pull/4359) [locale] Fix Arabic locale for months (again)
* [#4357](https://github.com/moment/moment/pull/4357) [misc] Add optional parameter keepOffset to toISOString
### 2.20.0 [See full changelog](https://gist.github.com/marwahaha/e0d4135fbf8bb75fa85c4aa2bddc5031)
* Release Dec 16, 2017
* [#4312](https://github.com/moment/moment/pull/4312) [bugfix] Fix [#4251](https://github.com/moment/moment/pull/4251): Avoid RFC2822 in utc() test
* [#4240](https://github.com/moment/moment/pull/4240) [bugfix] Fix incorrect strict parsing with full-width parentheses
* [#4341](https://github.com/moment/moment/pull/4341) [feature] Prevent toISOString converting to UTC (issue [#1751](https://github.com/moment/moment/pull/1751))
* [#4154](https://github.com/moment/moment/pull/4154) [feature] add format constants to support output to HTML5 input type formats (see [#3928](https://github.com/moment/moment/pull/3928))
* [#4143](https://github.com/moment/moment/pull/4143) [new locale] mt: Maltese language
* [#4183](https://github.com/moment/moment/pull/4183) [locale] Relative seconds i18n
* Various other locale improvements
### 2.19.4 [See changelog](https://gist.github.com/marwahaha/d3b7b0ddf4bdae512244f16e8cc59efb)
* Release Dec 10, 2017
* [#4332](https://github.com/moment/moment/pull/4332) [bugfix] Fix weekday verification for UTC and offset days (fixes [#4227](https://github.com/moment/moment/pull/4227))
* [#4336](https://github.com/moment/moment/pull/4336) [bugfix] Fix [#4334](https://github.com/moment/moment/pull/4334): Remove unused function call argument
* [#4246](https://github.com/moment/moment/pull/4246) [misc] Add 'ss' relative time key to typescript definition
### 2.19.3 [See changelog](https://gist.github.com/marwahaha/3654006bc0c2e522451c08d12c0bfabf)
* Release Nov 29, 2017
* [#4326](https://github.com/moment/moment/pull/4326) [bugfix] Fix for ReDOS vulnerability (see [#4163](https://github.com/moment/moment/issues/4163))
* [#4289](https://github.com/moment/moment/pull/4289) [misc] Fix spelling and formatting for U.S. for es-us
### 2.19.2 [See changelog (it's the same >:D)](https://gist.github.com/ichernev/76b1a3f33d3a8ff9665ce434a45221d0)
* Release Nov 11, 2017
* [#4255](https://github.com/moment/moment/pull/4255) [bugfix] Fix year setter for random days in a leap year, fixes [#4238](https://github.com/moment/moment/issues/4238)
* [#4242](https://github.com/moment/moment/pull/4242) [bugfix] updateLocale now tries to load parent, fixes [#3626](https://github.com/moment/moment/issues/3626)
### 2.19.1
* Release Oct 11, 2017
Make react native and webpack both work
* #4225 #4226 #4232
### 2.19.0 [See full changelog](https://gist.github.com/ichernev/5f3f4eb02761b4f765a0cccf02cec603)
* Release Oct 10, 2017
## Fix React Native 0.49+ crash
* [#4213](https://github.com/moment/moment/pull/4213) [critical] Rename dynamic
require to avoid React Native crash
* [#4214](https://github.com/moment/moment/pull/4214) [fixup] Move require
rename inside try/catch, fixes
[#4213](https://github.com/moment/moment/issues/4213)
## Features
* [#3735](https://github.com/moment/moment/pull/3735) [feature] Ignore NaN values in setters
* [#4106](https://github.com/moment/moment/pull/4106) [fixup] Drop isNumeric utility fn, fixes [#3735](https://github.com/moment/moment/issues/3735)
* [#4080](https://github.com/moment/moment/pull/4080) [feature] Implement a clone method for durations, fixes [#4078](https://github.com/moment/moment/issues/4078)
* [#4215](https://github.com/moment/moment/pull/4215) [misc] TS: Add duration.clone(), for [#4080](https://github.com/moment/moment/issues/4080)
## Packaging
* [#4003](https://github.com/moment/moment/pull/4003) [pkg] bower: Remove tests from package
* [#3904](https://github.com/moment/moment/pull/3904) [pkg] jsnext:main -> module in package.json
* [#4060](https://github.com/moment/moment/pull/4060) [pkg] Account for new rollup interface
Bugfixes, new locales, locale fixes etc...
### 2.18.1
* Release Mar 22, 2017
* [#3853](https://github.com/moment/moment/pull/3853) [misc] Fix invalid whitespace character causing inability to parse
moment.js
### 2.18.0 [See full changelog](https://gist.github.com/ichernev/78920c5a1e419fb28c6e4546d1b7235c)
* Release Mar 18, 2017
## Features
* [#3708](https://github.com/moment/moment/pull/3708) [feature] RFC2822 parsing
* [#3611](https://github.com/moment/moment/pull/3611) [feature] Durations gain validity
* [#3738](https://github.com/moment/moment/pull/3738) [feature] Enable relative time for multiple seconds, request [#2558](https://github.com/moment/moment/issues/2558)
* [#3766](https://github.com/moment/moment/pull/3766) [feature] Add support for k and kk format parsing
## Bugfixes
* [#3643](https://github.com/moment/moment/pull/3643) [bugfix] Fixes [#3520](https://github.com/moment/moment/issues/3520), parseZone incorrectly handled minutes under 16
* [#3710](https://github.com/moment/moment/pull/3710) [bugfix] Fixes [#3632](https://github.com/moment/moment/issues/3632), toISOString returns null for invalid date
* [#3787](https://github.com/moment/moment/pull/3787) [bugfix] Fixes [#3717](https://github.com/moment/moment/issues/3717), ensure day-of-year is non-zero
* [#3780](https://github.com/moment/moment/pull/3780) [bugfix] Fixes [#3765](https://github.com/moment/moment/issues/3765): Ensure year 0 is formatted with YYYY
* [#3806](https://github.com/moment/moment/pull/3806) [bugfix] Fixes [#3805](https://github.com/moment/moment/issues/3805), fix locale month getters for standalone/format cases
7 new locales, many locale improvements and some misc changes
### 2.17.1 [Also available here](https://gist.github.com/ichernev/f38280b2b29c4932914a6d3a4e50bfb2)
* Release Dec 03, 2016
* [#3638](https://github.com/moment/moment/pull/3638) [misc] TS: Make typescript definitions work with 1.x
* [#3628](https://github.com/moment/moment/pull/3628) [misc] Adds "sign CLA" link to `CONTRIBUTING.md`
* [#3640](https://github.com/moment/moment/pull/3640) [misc] Fix locale issues
### 2.17.0 [Also available here](https://gist.github.com/ichernev/ed58f76fb95205eeac653d719972b90c)
* Release Nov 22, 2016
* [#3435](https://github.com/moment/moment/pull/3435) [new locale] yo: Yoruba (Nigeria) locale
* [#3595](https://github.com/moment/moment/pull/3595) [bugfix] Fix accidental reference to global "value" variable
* [#3506](https://github.com/moment/moment/pull/3506) [bugfix] Fix invalid moments returning valid dates to method calls
* [#3563](https://github.com/moment/moment/pull/3563) [locale] ca: Change future relative time
* [#3504](https://github.com/moment/moment/pull/3504) [tests] Fixes [#3463](https://github.com/moment/moment/issues/3463), parseZone not handling Z correctly (tests only)
* [#3591](https://github.com/moment/moment/pull/3591) [misc] typescript: update typescript to 2.0.8, add strictNullChecks=true
* [#3597](https://github.com/moment/moment/pull/3597) [misc] Fixed capitalization in nuget spec
### 2.16.0 [See full changelog](https://gist.github.com/ichernev/17bffc1005a032cb1a8ac4c1558b4994)
* Release Nov 9, 2016
## Features
* [#3530](https://github.com/moment/moment/pull/3530) [feature] Check whether input is date before checking if format is array
* [#3515](https://github.com/moment/moment/pull/3515) [feature] Fix [#2300](https://github.com/moment/moment/issues/2300): Default to current week.
## Bugfixes
* [#3546](https://github.com/moment/moment/pull/3546) [bugfix] Implement lazy-loading of child locales with missing prents
* [#3523](https://github.com/moment/moment/pull/3523) [bugfix] parseZone should handle UTC
* [#3502](https://github.com/moment/moment/pull/3502) [bugfix] Fix [#3500](https://github.com/moment/moment/issues/3500): ISO 8601 parsing should match the full string, not the beginning of the string.
* [#3581](https://github.com/moment/moment/pull/3581) [bugfix] Fix parseZone, redo [#3504](https://github.com/moment/moment/issues/3504), fix [#3463](https://github.com/moment/moment/issues/3463)
## New Locales
* [#3416](https://github.com/moment/moment/pull/3416) [new locale] nl-be: Dutch (Belgium) locale
* [#3393](https://github.com/moment/moment/pull/3393) [new locale] ar-dz: Arabic (Algeria) locale
* [#3342](https://github.com/moment/moment/pull/3342) [new locale] tet: Tetun Dili (East Timor) locale
And more locale, build and typescript improvements
### 2.15.2
* Release Oct 23, 2016
* [#3525](https://github.com/moment/moment/pull/3525) Speedup month standalone/format regexes **(IMPORTANT)**
* [#3466](https://github.com/moment/moment/pull/3466) Fix typo of Javanese
### 2.15.1
* Release Sept 20, 2016
* [#3438](https://github.com/moment/moment/pull/3438) Fix locale autoload, revert [#3344](https://github.com/moment/moment/pull/3344)
### 2.15.0 [See full changelog](https://gist.github.com/ichernev/10e1c5bf647545c72ca30e9628a09ed3)
- Release Sept 12, 2016
## New Locales
* [#3255](https://github.com/moment/moment/pull/3255) [new locale] mi: Maori language
* [#3267](https://github.com/moment/moment/pull/3267) [new locale] ar-ly: Arabic (Libya) locale
* [#3333](https://github.com/moment/moment/pull/3333) [new locale] zh-hk: Chinese (Hong Kong) locale
## Bugfixes
* [#3276](https://github.com/moment/moment/pull/3276) [bugfix] duration: parser: Support ms durations in .NET syntax
* [#3312](https://github.com/moment/moment/pull/3312) [bugfix] locales: Enable locale-data getters without moment (fixes [#3284](https://github.com/moment/moment/issues/3284))
* [#3381](https://github.com/moment/moment/pull/3381) [bugfix] parsing: Fix parseZone without timezone in string, fixes [#3083](https://github.com/moment/moment/issues/3083)
* [#3383](https://github.com/moment/moment/pull/3383) [bugfix] toJSON: Fix isValid so that toJSON works after a moment is frozen
* [#3427](https://github.com/moment/moment/pull/3427) [bugfix] ie8: Fix IE8 (regression in 2.14.x)
## Packaging
* [#3299](https://github.com/moment/moment/pull/3299) [pkg] npm: Do not include .npmignore in npm package
* [#3273](https://github.com/moment/moment/pull/3273) [pkg] jspm: Include moment.d.ts file in package
* [#3344](https://github.com/moment/moment/pull/3344) [pkg] exports: use module.require for nodejs
Also some locale and typescript improvements
### 2.14.1
- Release July 20, 2016
* [#3280](https://github.com/moment/moment/pull/3280) Fix typescript definitions
### 2.14.0 [See full changelog](https://gist.github.com/ichernev/812e79ac36a7829a22598fe964bfc18a)
- Release July 20, 2016
## New Features
* [#3233](https://github.com/moment/moment/pull/3233) Introduce month.isFormat for format/standalone discovery
* [#2848](https://github.com/moment/moment/pull/2848) Allow user to get/set the rounding method used when calculating relative time
* [#3112](https://github.com/moment/moment/pull/3112) optimize configFromStringAndFormat
* [#3147](https://github.com/moment/moment/pull/3147) Call calendar format function with moment context
* [#3160](https://github.com/moment/moment/pull/3160) deprecate isDSTShifted
* [#3175](https://github.com/moment/moment/pull/3175) make moment calendar extensible with ad-hoc options
* [#3191](https://github.com/moment/moment/pull/3191) toDate returns a copy of the internal date object
* [#3192](https://github.com/moment/moment/pull/3192) Adding support for rollup import.
* [#3238](https://github.com/moment/moment/pull/3238) Handle empty object and empty array for creation as now
* [#3082](https://github.com/moment/moment/pull/3082) Use relative AMD moment dependency
## Bugfixes
* [#3241](https://github.com/moment/moment/pull/3241) Escape all 24 mixed pieces, not only first 12 in computeMonthsParse
* [#3008](https://github.com/moment/moment/pull/3008) Object setter orders sets based on size of unit
* [#3177](https://github.com/moment/moment/pull/3177) Bug Fix [#2704](https://github.com/moment/moment/pull/2704) - isoWeekday(String) inconsistent with isoWeekday(Number)
* [#3230](https://github.com/moment/moment/pull/3230) fix passing date with format string to ignore format string
* [#3232](https://github.com/moment/moment/pull/3232) Fix negative 0 in certain diff cases
* [#3235](https://github.com/moment/moment/pull/3235) Use proper locale inheritance for the base locale, fixes [#3137](https://github.com/moment/moment/pull/3137)
Plus es-do locale and locale bugfixes
### 2.13.0 [See full changelog](https://gist.github.com/ichernev/0132fcf5b61f7fc140b0bb0090480d49)
- Release April 18, 2016
## Enhancements:
* [#2982](https://github.com/moment/moment/pull/2982) Add 'date' as alias to 'day' for startOf() and endOf().
* [#2955](https://github.com/moment/moment/pull/2955) Add parsing negative components in durations when ISO 8601
* [#2991](https://github.com/moment/moment/pull/2991) isBetween support for both open and closed intervals
* [#3105](https://github.com/moment/moment/pull/3105) Add localeSorted argument to weekday listers
* [#3102](https://github.com/moment/moment/pull/3102) Add k and kk formatting tokens
## Bugfixes
* [#3109](https://github.com/moment/moment/pull/3109) Fix [#1756](https://github.com/moment/moment/issues/1756) Resolved thread-safe issue on server side.
* [#3078](https://github.com/moment/moment/pull/3078) Fix parsing for months/weekdays with weird characters
* [#3098](https://github.com/moment/moment/pull/3098) Use Z suffix when in UTC mode ([#3020](https://github.com/moment/moment/issues/3020))
* [#2995](https://github.com/moment/moment/pull/2995) Fix floating point rounding errors in durations
* [#3059](https://github.com/moment/moment/pull/3059) fix bug where diff returns -0 in month-related diffs
* [#3045](https://github.com/moment/moment/pull/3045) Fix mistaking any input for 'a' token
* [#2877](https://github.com/moment/moment/pull/2877) Use explicit .valueOf() calls instead of coercion
* [#3036](https://github.com/moment/moment/pull/3036) Year setter should keep time when DST changes
Plus 3 new locales and locale fixes.
### 2.12.0 [See full changelog](https://gist.github.com/ichernev/6e5bfdf8d6522fc4ac73)
- Release March 7, 2016
## Enhancements:
* [#2932](https://github.com/moment/moment/pull/2932) List loaded locales
* [#2818](https://github.com/moment/moment/pull/2818) Parse ISO-8061 duration containing both day and week values
* [#2774](https://github.com/moment/moment/pull/2774) Implement locale inheritance and locale updating
## Bugfixes:
* [#2970](https://github.com/moment/moment/pull/2970) change add subtract to handle decimal values by rounding
* [#2887](https://github.com/moment/moment/pull/2887) Fix toJSON casting of invalid moment
* [#2897](https://github.com/moment/moment/pull/2897) parse string arguments for month() correctly, closes #2884
* [#2946](https://github.com/moment/moment/pull/2946) Fix usage suggestions for min and max
## New locales:
* [#2917](https://github.com/moment/moment/pull/2917) Locale Punjabi(Gurmukhi) India format conversion
And more
### 2.11.2 (Fix ReDoS attack vector)
- Release February 7, 2016
* [#2939](https://github.com/moment/moment/pull/2939) use full-string match to speed up aspnet regex match
### 2.11.1 [See full changelog](https://gist.github.com/ichernev/8ec3ee25b749b4cff3c2)
- Release January 9, 2016
## Bugfixes:
* [#2881](https://github.com/moment/moment/pull/2881) Revert "Merge pull request #2746 from mbad0la:develop" Sep->Sept
* [#2868](https://github.com/moment/moment/pull/2868) Add format and parse token Y, so it actually works
* [#2865](https://github.com/moment/moment/pull/2865) Use typeof checks for undefined for global variables
* [#2858](https://github.com/moment/moment/pull/2858) Fix Date mocking regression introduced in 2.11.0
* [#2864](https://github.com/moment/moment/pull/2864) Include changelog in npm release
* [#2830](https://github.com/moment/moment/pull/2830) dep: add grunt-cli
* [#2869](https://github.com/moment/moment/pull/2869) Fix months parsing for some locales
### 2.11.0 [See full changelog](https://gist.github.com/ichernev/6594bc29719dde6b2f66)
- Release January 4, 2016
* [#2624](https://github.com/moment/moment/pull/2624) Proper handling of invalid moments
* [#2634](https://github.com/moment/moment/pull/2634) Fix strict month parsing issue in cs,ru,sk
* [#2735](https://github.com/moment/moment/pull/2735) Reset the locale back to 'en' after defining all locales in min/locales.js
* [#2702](https://github.com/moment/moment/pull/2702) Week rework
* [#2746](https://github.com/moment/moment/pull/2746) Changed September Abbreviation to "Sept" in locale-specific english
files and default locale file
* [#2646](https://github.com/moment/moment/pull/2646) Fix [#2645](https://github.com/moment/moment/pull/2645) - invalid dates pre-1970
* [#2641](https://github.com/moment/moment/pull/2641) Implement basic format and comma as ms separator in ISO 8601
* [#2665](https://github.com/moment/moment/pull/2665) Implement stricter weekday parsing
* [#2700](https://github.com/moment/moment/pull/2700) Add [Hh]mm and [Hh]mmss formatting tokens, so you can parse 123 with
hmm for example
* [#2565](https://github.com/moment/moment/pull/2565) [#2835](https://github.com/moment/moment/pull/2835) Expose arguments used for moment creation with creationData
(fix [#2443](https://github.com/moment/moment/pull/2443))
* [#2648](https://github.com/moment/moment/pull/2648) fix issue [#2640](https://github.com/moment/moment/pull/2640): support instanceof operator
* [#2709](https://github.com/moment/moment/pull/2709) Add isSameOrAfter and isSameOrBefore comparison methods
* [#2721](https://github.com/moment/moment/pull/2721) Fix moment creation from object with strings values
* [#2740](https://github.com/moment/moment/pull/2740) Enable 'd hh:mm:ss.sss' format for durations
* [#2766](https://github.com/moment/moment/pull/2766) [#2833](https://github.com/moment/moment/pull/2833) Alternate Clock Source Support
### 2.10.6
- Release July 28, 2015
[#2515](https://github.com/moment/moment/pull/2515) Fix regression introduced
in `2.10.5` related to `moment.ISO_8601` parsing.
### 2.10.5 [See full changelog](https://gist.github.com/ichernev/6ec13ac7efc396da44b2)
- Release July 26, 2015
Important changes:
* [#2357](https://github.com/moment/moment/pull/2357) Improve unit bubbling for ISO dates
this fixes day to year conversions to work around end-of-year (~365 days). As
a side effect 365 days is 11 months and 30 days, and 366 days is one year.
* [#2438](https://github.com/moment/moment/pull/2438) Fix inconsistent moment.min and moment.max results
Return invalid result if any of the inputs is invalid
* [#2494](https://github.com/moment/moment/pull/2494) Fix two digit year parsing with YYYY format
This brings the benefits of YY to YYYY
* [#2368](https://github.com/moment/moment/pull/2368) perf: use faster form of copying dates, across the board improvement
### 2.10.3 [See full changelog](https://gist.github.com/ichernev/f264b9bed5b00f8b1b7f)
- Release May 13, 2015
* add `moment.fn.to` and `moment.fn.toNow` (similar to `from` and `fromNow`)
* new locales (Sinhalese (si), Montenegrin (me), Javanese (ja))
* performance improvements
### 2.10.2
- Release April 9, 2015
* fixed moment-with-locales in browser env caused by esperanto change
### 2.10.1
* regression: Add moment.duration.fn back
### 2.10.0
Ported code to es6 modules.
### 2.9.0 [See full changelog](https://gist.github.com/ichernev/0c9a9b49951111a27ce7)
- Release January 8, 2015
languages:
* [2104](https://github.com/moment/moment/issues/2104) Frisian (fy) language file with unit test
* [2097](https://github.com/moment/moment/issues/2097) add ar-tn locale
deprecations:
* [2074](https://github.com/moment/moment/issues/2074) Implement `moment.fn.utcOffset`, deprecate `moment.fn.zone`
features:
* [2088](https://github.com/moment/moment/issues/2088) add moment.fn.isBetween
* [2054](https://github.com/moment/moment/issues/2054) Call updateOffset when creating moment (needed for default timezone in
moment-timezone)
* [1893](https://github.com/moment/moment/issues/1893) Add moment.isDate method
* [1825](https://github.com/moment/moment/issues/1825) Implement toJSON function on Duration
* [1809](https://github.com/moment/moment/issues/1809) Allowing moment.set() to accept a hash of units
* [2128](https://github.com/moment/moment/issues/2128) Add firstDayOfWeek, firstDayOfYear locale getters
* [2131](https://github.com/moment/moment/issues/2131) Add quarter diff support