hkopendata
Version:
Access different Opendata API and data in Hong Kong
168 lines (157 loc) • 4.95 kB
JavaScript
// https://www.1823.gov.hk/f/upload/1229/1823_cal_dictionary.pdf
const moment = require("../../moment");
const cmn = require("../../common");
const BASE_URL = "https://www.1823.gov.hk/common/ical/{lang}.json";
const HOLIDAY = {};
const VALID = {
lang: /^(en|tc|sc)$/,
year: /^[0-9]{4}$/
};
const PARAMS = {
lang: "en",
year: moment().format("YYYY")
}
function beforeSearch() {
if (Object.keys(HOLIDAY).length === 0) {
let _holiday = cmn.GetDataJson("hk-holiday");
for (let key in _holiday) HOLIDAY[key] = _holiday[key];
}
}
function validateParameters(params) {
let result = cmn.ValidateParameters(params, VALID);
if (parseInt(params.year) < 2018 || parseInt(params.year) > parseInt(moment().format("YYYY"))) {
result.error = true;
result.message = "Invalid year. Range: 2018 - Current year."
}
if (!result.error) {
result.data = {
...params
}
}
return result;
}
function search(data, opts) {
beforeSearch();
return new Promise((resolve, reject) => {
let processed = validateParameters({
...PARAMS,
...data
}),
params;
if (processed.error) {
reject(processed);
} else {
let result = [],
complete = false;
params = processed.data;
if (!opts.update && params.year in HOLIDAY) {
for (let date in HOLIDAY[params.year]) {
if (params.lang in HOLIDAY[params.year][date]) {
result.push({
date: date,
name: HOLIDAY[params.year][date][params.lang]
});
complete = true;
}
}
}
if (!complete) {
if (typeof opts === "undefined") opts = {};
opts = {
...params,
...opts
};
cmn.APIRequest(cmn.ReplaceURL(BASE_URL, params))
.then((res) => {
resolve(processData(res, opts));
})
.catch((err) => reject(err))
} else {
resolve(result);
}
}
})
}
function processData(data, opts) {
let result = {},
updated = Boolean(opts.update),
lang = opts.lang;
data.vcalendar[0].vevent.map((item) => {
let date = moment(item.dtstart[0], "YYYYMMDD"),
year = date.format("YYYY");
if (!(year in result)) result[year] = [];
result[year].push({
date: date.format("YYYY-MM-DD"),
name: item.summary
});
})
Object.keys(result).map((year) => {
if (!(year in HOLIDAY)) {
HOLIDAY[year] = {};
updated = true;
}
result[year].map((v) => {
if (!(v.date in HOLIDAY[year])) {
HOLIDAY[year][v.date] = {};
updated = true;
}
if (!(lang in HOLIDAY[year][v.date])) {
HOLIDAY[year][v.date][lang] = v.name;
updated = true;
}
})
})
if (updated) {
if (opts.history) {
for (let year in opts.history) {
if (!(year in HOLIDAY)) HOLIDAY[year] = opts.history[year];
}
}
cmn.UpdateDataJson("hk-holiday", HOLIDAY);
}
return result;
}
function is(date, office, day) {
return new Promise((resolve, reject) => {
let d = moment(date);
if (d.isValid()) {
let year = d.format("YYYY");
date = d.format("YYYY-MM-DD");
if (typeof day === "undefined") day = 5;
if (!office && day == 7 && d.isoWeekday() == 7) { // 7: Sunday
resolve(true);
} else if (office && Array.isArray(day) && day.indexOf(d.isoWeekday()) != -1) { // day: Array of non-office day
resolve(true);
} else if (office && !Array.isArray(day) && d.isoWeekday() > day) { // day: N-days of work (start from Monday)
resolve(true);
} else if (!(year in HOLIDAY)) {
search({
year
})
.then((res) => {
resolve(res.filter(v => v.date == date).length > 0)
})
.catch((err) => reject(err))
} else {
resolve(date in HOLIDAY[year])
}
} else {
reject("Invalid date");
}
})
}
function isPublic(date) {
return is(date, false)
}
function isHoliday(date) {
return is(date, false, 7)
}
function isOffice(date, day) {
return is(date, true, day)
}
module.exports = {
search,
isPublic,
isHoliday,
isOffice
}