tw-shift-schedule
Version:
96 lines (79 loc) • 3.01 kB
JavaScript
var moo = require('moo')
// Lexer: 利用 moo.lexer 對工作記錄進行切段,可以做出以下判斷:
// * 上班時間是否超過 12 小時?
// * 兩個上班時段間的休息時間,應該是休息時間,還是下班時間?
// * 上班後是否有至少 8 小時的休息?
//
// lexer 只負責檢查「單一工作時段是否合法」
// 多個工作時段之間的關係,例如:每週含加班工時上限 72 小時、變形工時的休假日數等,不在此檢查
// **note: 因為變形工時不會增加工作時數,單日工時上限也相同,因此 lexer 一定要通過才有可能是合法的變形工時
module.exports = function (scheduleData, opts) {
if (!opts) opts = {}
if (!opts.min_between_shift) opts.min_between_shift = 8
let lexer = moo.compile({
fullRest: /\.{1440,}/,
work: /x+/,
rest: /\.+/,
invalid: moo.error
})
// 補上最後的 newline 方便 lexer 處理
if (!scheduleData.endsWith('\n')) {
scheduleData += '\n'
}
// remove comments
scheduleData = scheduleData.replace(/#.+\n/, '')
// ignore all spaces within the scheduleData
scheduleData = scheduleData.replace(/\s/g, '')
lexer.reset(scheduleData)
let tokens = []
var token
let minuteWorked = 0
let workTokens = []
while (token = lexer.next()) {
if (token.type === 'fullRest') {
// 休息了 24 小時那就一定是前一班結束了
pushWorkTokensIfNotEmpty()
tokens.push(token)
}
if (token.type === 'rest') {
// 34 條
/*
勞工工作採輪班制者,其工作班次,每週更換一次。但經勞工同意者不在此限。
依前項更換班次時,至少應有連續十一小時之休息時間。但因工作特性或
特殊原因,經中央目的事業主管機關商請中央主管機關公告者,得變更休
息時間不少於連續八小時。
*/
// TODO: 勞資協商前是 11 小時
// 遇到超過輪班間隔底限的休息時斷,就視為前一班已經結束。
// 因為把前後兩班視成一班對雇主完全沒好處,應不會有人這樣排。
if (token.value.length >= opts.min_between_shift * 60) {
pushWorkTokensIfNotEmpty()
tokens.push(token)
} else {
workTokens.push(token)
}
}
if (token.type === 'work') {
minuteWorked += token.value.length
if (minuteWorked > 12 * 60) {
pushWorkTokensIfNotEmpty()
tokens.push({ type: 'invalid', value: token.value, offset: token.offset })
break
}
workTokens.push(token)
}
}
pushWorkTokensIfNotEmpty()
return tokens
function pushWorkTokensIfNotEmpty () {
minuteWorked = 0
if (workTokens.length > 0) {
let combinedWorkToken = { type: 'work', value: '', offset: workTokens[0].offset }
for (let t of workTokens) {
combinedWorkToken.value += t.value
}
tokens.push(combinedWorkToken)
workTokens = []
}
}
}