cronli5 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/cronli5.min.js +2 -2
- package/dist/cronli5.cjs +34 -17
- package/dist/cronli5.js +34 -17
- package/dist/lang/de.cjs +4 -2
- package/dist/lang/de.js +4 -2
- package/dist/lang/en.cjs +2 -11
- package/dist/lang/en.js +2 -11
- package/dist/lang/es.cjs +2 -11
- package/dist/lang/es.js +2 -11
- package/dist/lang/fi.cjs +4 -15
- package/dist/lang/fi.js +4 -15
- package/dist/lang/zh.cjs +2 -4
- package/dist/lang/zh.js +2 -4
- package/package.json +1 -1
- package/src/core/normalize.ts +54 -6
- package/src/lang/de/index.ts +7 -2
- package/src/lang/en/index.ts +13 -18
- package/src/lang/es/index.ts +6 -16
- package/src/lang/fi/index.ts +8 -19
- package/src/lang/zh/index.ts +10 -9
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,33 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.1.2]
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- **Non-uniform steps in the time fields now list their fires** instead of
|
|
14
|
+
reading "every N". A step is a true "every N" cadence only when it tiles the
|
|
15
|
+
field's cycle evenly — `step` divides the cycle (60 for minutes/seconds, 24 for
|
|
16
|
+
hours) **and** `start < step`; otherwise the gap at the field boundary differs.
|
|
17
|
+
`*/7 * * * *` fires at :00, :07, …, :56 — the :56→:00 gap is 4 minutes, not 7 —
|
|
18
|
+
so it now reads "at 0, 7, 14, 21, 28, 35, 42, 49, and 56 minutes past the hour"
|
|
19
|
+
rather than "every seven minutes". `7/6` and `11/6` (the step divides 60 but
|
|
20
|
+
starts past it) enumerate too. Genuine "every N" steps (`*/6`, `*/15`, `5/6`,
|
|
21
|
+
`11/12`, `*/2` hours) are unchanged. German already rendered these; English,
|
|
22
|
+
Spanish, Finnish, and Chinese now match. Date/month/weekday steps are unchanged
|
|
23
|
+
(their cycles vary — a separate follow-up).
|
|
24
|
+
- **Chinese no longer drops the start of an offset step.** `5/6` had rendered as
|
|
25
|
+
"每6分钟" — identical to `*/6`, the wrong schedule — and now enumerates its
|
|
26
|
+
fires ("每小时5、11、…、59分"), matching how Chinese already rendered offset
|
|
27
|
+
second and hour steps.
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- **German** no longer doubles the period when a sentence ends in an ordinal
|
|
32
|
+
("…am 3., 5. und 8." instead of "…8.."), and an hour list no longer takes
|
|
33
|
+
"von" ("in den Stunden 9, 11 und 13 Uhr", not "von 9, 11 und 13 Uhr"; genuine
|
|
34
|
+
"von … bis" ranges are unchanged).
|
|
35
|
+
|
|
9
36
|
## [0.1.1]
|
|
10
37
|
|
|
11
38
|
### Fixed
|
package/cronli5.min.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use strict";(()=>{var qn={SUN:0,MON:1,TUE:2,WED:3,THU:4,FRI:5,SAT:6},Vn={JAN:1,FEB:2,MAR:3,APR:4,MAY:5,JUN:6,JUL:7,AUG:8,SEP:9,OCT:10,NOV:11,DEC:12},h={second:{cyclic:!0,max:59,min:0,top:59},minute:{cyclic:!0,max:59,min:0,top:59},hour:{cyclic:!0,max:23,min:0,top:23},date:{aliases:{"?":"*"},cyclic:!0,max:31,min:1,top:31},month:{cyclic:!0,max:12,min:1,numbers:Vn,top:12},weekday:{aliases:{"?":"*",L:"6"},cyclic:!0,max:7,min:0,numbers:qn,top:6},year:{max:9999,min:1970}},k=["second","minute","hour","date","month","weekday","year"],U={"@annually":"0 0 1 1 *","@yearly":"0 0 1 1 *","@monthly":"0 0 1 * *","@weekly":"0 0 * * 0","@daily":"0 0 * * *","@midnight":"0 0 * * *","@hourly":"0 * * * *"},Q=6;function s(n,e){return(""+n).indexOf(e)!==-1}function F(n){return Array.from(new Set(n))}function I(n){return/^\d+$/.test(n)}function d(n,e){return I(n)?+n:e[n.toUpperCase()]}function an(n){return k.forEach(function(r){Jn(n[r],h[r],r)}),n}function Jn(n,e,r){typeof n!="string"&&typeof n!="number"&&sn(n,r);let t=""+n;t!=="*"&&(r==="date"&&C(t)||r==="weekday"&&w(t,e)||t.split(",").forEach(function(o){$n(o,e)||sn(o,r)}))}function C(n){if(n==="L"||n==="LW"||n==="WL")return!0;let e=/^L-(\d{1,2})$/.exec(n);if(e)return+e[1]>=1&&+e[1]<=30;let r=/^(\d{1,2})W$|^W(\d{1,2})$/.exec(n);if(r){let t=+(r[1]||r[2]);return t>=1&&t<=31}return!1}function w(n,e){if(/L$/.test(n))return v(n.slice(0,-1),e);let r=n.split("#");return r.length===2?v(r[0],e)&&/^[1-5]$/.test(r[1]):!1}function $n(n,e){return s(n,"/")?Yn(n,e):s(n,"-")?ln(n,e):v(n,e)}function Yn(n,e){let r=n.split("/");return r.length!==2||!I(r[1])||+r[1]<1?!1:r[0]==="*"||v(r[0],e)||ln(r[0],e,!0)}function ln(n,e,r){let t=n.split("-");return t.length!==2||!v(t[0],e)||!v(t[1],e)?!1:e.cyclic&&!r?!0:d(t[0],e.numbers)<=d(t[1],e.numbers)}function v(n,e){return n==="*"?!1:I(n)?+n>=e.min&&+n<=e.max:e.numbers?n.toUpperCase()in e.numbers:!1}function sn(n,e){throw new Error('`cronli5` was passed an invalid field value "'+n+'" for the '+e+" field.")}function mn(n){k.forEach(function(r){let t=h[r].aliases,i=t&&t[""+n[r]];i&&(n[r]=i)})}function fn(n){return k.forEach(function(r){let t=""+n[r];if(r==="date"&&C(t)||r==="weekday"&&w(t,h[r])){n[r]=t;return}n[r]=Bn(t,h[r])}),n}function Bn(n,e){let r=""+n;if(r==="*")return r;let t=r.split(",").map(function(o){return Zn(Kn(Gn(o,e),e),e)});return t.indexOf("*")!==-1?"*":F(t).sort(function(o,u){return cn(o,e)-cn(u,e)}).join(",")}function Gn(n,e){let r=n.split("/");if(!e.cyclic||r.length!==2||+r[1]!=1)return n;let t=r[0];return s(t,"-")?t:t==="*"||d(t,e.numbers)===e.min?"*":t+"-"+e.top}function Kn(n,e){let r=n.split("/");if(!e.cyclic||typeof e.top!="number"||r.length!==2||s(r[0],"-"))return n;let t=r[0];return(t==="*"?e.min:d(t,e.numbers))+ +r[1]<=e.top?n:t==="*"?""+e.min:t}function Zn(n,e){let r=n.split("/")[0];if(!s(r,"-"))return n;let t=r.split("-");return d(t[0],e.numbers)!==d(t[1],e.numbers)?n:t[0]}function cn(n,e){let r=n.split("/")[0].split("-")[0];return r==="*"?e.min:d(r,e.numbers)}function dn(n,e){let r=n instanceof Array;if(n===null||typeof n>"u"||n===""||r&&n.length===0)throw new Error("`cronli5` expects a non-empty cron pattern as the first argument.");if(r)return gn(n,e);if(typeof n=="object")return Xn(n);if(typeof n=="string")return _n(n,e);throw new Error("`cronli5` was passed an unexpected type.")}function gn(n,e){if(n.length>7)throw new Error("`cronli5` was passed a cron pattern with more than seven fields.");return!e.seconds&&n.length<(e.years?7:6)&&n.unshift("0"),{second:n[0]||"0",minute:n[1]||"*",hour:n[2]||"*",date:n[3]||"*",month:n[4]||"*",weekday:n[5]||"*",year:n[6]||"*"}}function Xn(n){if(!n.second&&!n.minute&&!n.hour)throw new Error("`cronli5` expects that any object being interpreted as a cron pattern have at least one of the following properties: `second`, `minute`, or `hour`");let e=typeof n.second<"u",r=typeof n.minute<"u",t=e?"*":"0",i=e||r?"*":"0";return{second:N(n.second,"0"),minute:N(n.minute,t),hour:N(n.hour,i),date:N(n.date,"*"),month:N(n.month,"*"),weekday:N(n.weekday,"*"),year:N(n.year,"*")}}function N(n,e){return typeof n>"u"?e:n}function _n(n,e){let r=ne(n).split(/\s+/);return gn(r,e)}function ne(n){let e=n.trim();if(e.charAt(0)!=="@")return n;let r=e.toLowerCase();if(Object.hasOwn(U,r))return U[r];throw new Error("`cronli5` does not recognize the macro `"+e+"`.")}function hn(n){return n!=="*"&&!s(n,",")&&!s(n,"-")&&!s(n,"/")}function q(n){return s(n,"-")&&!s(n,",")&&!s(n,"/")}function ee(n){return s(n,"/")&&!s(n,",")}function V(n){return n!=="*"&&!s(n,"-")&&!s(n,"/")}function J(n){return n!=="*"&&!q(n)&&!ee(n)}function R(n,e,r){let t=[],i=n;for(;i<=r;)t.push(i),i+=e;return t}function pn(n,e,r,t){let i=n.split("/"),o=+i[1];if(s(i[0],"-")){let m=i[0].split("-");return R(d(m[0],t),o,d(m[1],t))}let u=i[0]==="*"?e:d(i[0],t);return R(u,o,r)}function $(n,e,r){let t=[];return n.split(",").forEach(function(o){if(s(o,"/"))t.push(...pn(o,e,r));else if(s(o,"-")){let u=o.split("-");+u[0]<=+u[1]?t.push(...R(+u[0],1,+u[1])):(t.push(...R(+u[0],1,r)),t.push(...R(e,1,+u[1])))}else t.push(+o)}),F(t)}function re(n){return V(n)?n.split(",").map(Number):[0]}function te(n){if(n==="*")return[0,59];if(q(n)){let e=n.split("-");if(+e[0]<=+e[1])return[+e[0],+e[1]]}return null}function ie(n){return n==="*"?59:Math.max(...$(n,0,59))}function oe(n){if(hn(n)&&n!=="0")return+n}function ue(n,e){return n==="*"?"wildcard":e==="date"&&C(n)||e==="weekday"&&w(n,h.weekday)?"quartz":s(n,",")?"list":s(n,"/")?"step":s(n,"-")?"range":"single"}function se(n,e,r){return e==="wildcard"||e==="quartz"?null:n.split(",").map(function(i){if(s(i,"/")){let o=i.split("/");return{fires:pn(i,r.min,r.top,r.numbers),interval:+o[1],kind:"step",startToken:o[0]}}return s(i,"-")?{bounds:i.split("-"),kind:"range"}:{kind:"single",value:i}})}function yn(n){let e={},r={};k.forEach(function(u){e[u]=ue(n[u],u),r[u]=se(n[u],e[u],h[u])});let i={analyses:{clockSecond:oe(n.second),lastMinuteFire:ie(n.minute),minuteSpan:te(n.minute),segments:r},pattern:n,shapes:e};return{...i,plan:ae(i)}}function ae(n){let{analyses:e,pattern:r,shapes:t}=n;if(r.second!=="0"){let i=le(r,t,e);if(i)return i}return bn(r,t,e)||On(r,t,e)}function le(n,e,r){let t=ce(n,e);return t||(n.hour==="*"&&e.minute==="single"&&n.second!=="*"?{kind:"secondsWithinMinute",singleSecond:e.second==="single"}:e.second==="single"&&V(n.minute)&&J(n.hour)?null:{kind:"composeSeconds",rest:bn(n,e,r,!0)||On(n,e,r,!0)})}function ce(n,e){return n.minute!=="*"||n.hour!=="*"?null:n.second==="*"?{kind:"everySecond"}:e.second==="single"?{kind:"secondPastMinute"}:{kind:"standaloneSeconds"}}function bn(n,e,r,t=!1){if(e.minute==="step")return{hours:fe(n,e,r),kind:"minuteFrequency"};if(e.hour==="single"&&r.minuteSpan)return{hour:+n.hour,kind:"minuteSpanInHour",span:r.minuteSpan};let i=de(n,e);if(i)return i;let o=me(n,e);if(o)return o;if(n.hour==="*")return ge(n,e,t)}function Sn(n){let[e,r]=n.split("/"),t=e==="*"?0:+e;return e.indexOf("-")===-1&&24%+r===0&&t<+r}function me(n,e){return e.hour!=="step"?null:n.minute==="*"?Sn(n.hour)?{form:"wildcard",kind:"minuteSpanAcrossHourStep"}:{form:"wildcard",kind:"minutesAcrossHours",times:M(n.hour)}:e.minute==="range"?{form:"range",kind:"minuteSpanAcrossHourStep"}:null}function fe(n,e,r){if(e.hour==="list")return{kind:"during",times:M(n.hour)};if(e.hour==="range"){let t=n.hour.split("-");return{from:+t[0],kind:"window",last:r.lastMinuteFire,to:+t[1]}}return e.hour==="single"?{from:+n.hour,kind:"window",last:r.lastMinuteFire,to:+n.hour}:e.hour==="step"?Sn(n.hour)?{kind:"step"}:{kind:"during",times:M(n.hour)}:{kind:"none"}}function de(n,e){return J(n.hour)?n.minute==="*"?{form:"wildcard",kind:"minutesAcrossHours",times:M(n.hour)}:e.minute==="range"||e.minute==="list"&&s(n.minute,"-")&&!s(n.minute,"/")?{form:e.minute==="range"?"range":"list",kind:"minutesAcrossHours",times:M(n.hour)}:null:null}function ge(n,e,r){if(e.minute==="range")return{kind:"rangeOfMinutes"};if(e.minute==="list")return{kind:"multipleMinutes"};if(n.minute==="*")return{kind:"everyMinute"};if(n.minute!=="0"||r)return{kind:"singleMinute"}}function On(n,e,r,t=!1){let i=t&&n.minute==="0";return e.hour==="range"&&!i?he(n,e,r):e.hour==="step"&&n.minute==="0"&&!t?{kind:"hourStep"}:n.hour==="*"&&!i?{kind:"everyHour"}:pe(n,r,i)}function he(n,e,r){let t=n.hour.split("-"),i="lead";return n.minute==="*"?i="wildcard":e.minute==="range"&&(i="range"),{boundMinute:e.minute==="range"||e.minute==="list"?null:r.lastMinuteFire,from:+t[0],kind:"hourRange",last:r.lastMinuteFire,minuteForm:i,to:+t[1]}}function pe(n,e,r=!1){let t=$(n.hour,0,23),i=re(n.minute);if(!r&&t.length*i.length>Q)return{fold:i.length===1,kind:"compactClockTimes",minute:i[0]};let o=[];return t.forEach(function(m){i.forEach(function(D){o.push({hour:m,minute:D,second:e.clockSecond})})}),{kind:"clockTimes",times:o}}function M(n){let e=$(n,0,23);return e.length<=Q?{fires:e,kind:"fires"}:{kind:"segments"}}function kn(n,e){let r=dn(n,e);return mn(r),an(r),fn(r)}function Y(n){return n=""+n,n.length<2?"0"+n:n}function Nn(n,e,r){return r.short?n:e[n]||n}function B(n,{sep:e,pad:r,lean:t}){let i=r?Y(n.hour):""+n.hour;return t&&!n.minute&&!n.second?i:i+e+Y(n.minute)+(n.second?e+Y(n.second):"")}var G={gb:{am:"am",closeUp:!0,dayFirst:!0,midday:"midday",midnight:"midnight",ordinals:!1,pm:"pm",sep:".",serialComma:!1,through:" to "},us:{am:"a.m.",closeUp:!1,dayFirst:!1,midday:"noon",midnight:"midnight",ordinals:!1,pm:"p.m.",sep:":",serialComma:!0,through:" through "},house:{am:"AM",closeUp:!1,dayFirst:!1,midday:"noon",midnight:"midnight",ordinals:!0,pm:"PM",sep:":",serialComma:!0,through:" - "}};function zn(n){return typeof n=="object"&&n!==null?{...G.us,...n}:G[n==="uk"?"gb":n]||G.us}var ye=["zero","one","two","three","four","five","six","seven","eight","nine","ten"],K=["th","st","nd","rd"],g=[null,["January","Jan"],["February","Feb"],["March","Mar"],["April","Apr"],["May","May"],["June","Jun"],["July","Jul"],["August","Aug"],["September","Sep"],["October","Oct"],["November","Nov"],["December","Dec"]],y=[["Sunday","Sun"],["Monday","Mon"],["Tuesday","Tue"],["Wednesday","Wed"],["Thursday","Thu"],["Friday","Fri"],["Saturday","Sat"]],be={JAN:g[1],FEB:g[2],MAR:g[3],APR:g[4],MAY:g[5],JUN:g[6],JUL:g[7],AUG:g[8],SEP:g[9],OCT:g[10],NOV:g[11],DEC:g[12]},Se={SUN:y[0],MON:y[1],TUE:y[2],WED:y[3],THU:y[4],FRI:y[5],SAT:y[6]},Oe=[null,"first","second","third","fourth","fifth"];function ke(n){return n=n||{},{ampm:typeof n.ampm=="boolean"?n.ampm:!0,lenient:!!n.lenient,seconds:!!n.seconds,short:!!n.short,style:zn(n.dialect),years:!!n.years}}function Ne(n,e){return _e(Pn(n,n.plan,e),n,e)}function Pn(n,e,r){let t=Ve[e.kind];return t(n,e,r)}function ze(n,e,r){return"every second"+a(n,r)}function Pe(n,e,r){return H(n,r)+a(n,r)}function ve(n,e,r){let t=n.pattern.second;return c(t,r)+" "+P(t,"second")+" past the minute, every minute"+a(n,r)}function Ce(n,e,r){let t=n.pattern.minute,i=c(t,r),o=P(t,"minute");if(e.singleSecond){let u=n.pattern.second;return i+" "+o+" and "+c(u,r)+" "+P(u,"second")+" past the hour, every hour"+a(n,r)}return H(n,r)+", "+i+" "+o+" past the hour, every hour"+a(n,r)}function we(n,e,r){return H(n,r)+", "+Pn(n,e.rest,r)}function H(n,e){let r=n.pattern.second,t=n.shapes.second;if(r==="*")return"every second";if(t==="step")return Rn(n.analyses.segments.second[0],"second","minute",e);if(t==="range"){let i=r.split("-"),o=A(i,e);return"every second from "+o(i[0])+O(e)+o(i[1])+" past the minute"}return t==="single"?"at "+c(r,e)+" "+P(r,"second")+" past the minute":b(T(n.analyses.segments.second,e),"second","minute",e)}function Re(n,e,r){return"every minute"+a(n,r)}function Me(n,e,r){let t=n.pattern.minute;return c(t,r)+" "+P(t,"minute")+" past the hour, every hour"+a(n,r)}function xe(n,e,r){return L(n.pattern.minute,r)+a(n,r)}function Te(n,e,r){return b(T(n.analyses.segments.minute,r),"minute","hour",r)+a(n,r)}function Fe(n,e,r){let t=Rn(n.analyses.segments.minute[0],"minute","hour",r);return e.hours.kind==="during"?t+=" during the "+_(n,e.hours.times,!1,r)+" hours":e.hours.kind==="window"?t+=" "+wn(e.hours,r):e.hours.kind==="step"&&(t+=" "+vn(n.analyses.segments.hour[0],r)),t+a(n,r)}function Ie(n,e,r){return"every minute from "+l({hour:e.hour,minute:e.span[0]},r)+O(r)+l({hour:e.hour,minute:e.span[1]},r)+a(n,r)}function He(n,e,r){if(e.form==="wildcard")return"every minute during the "+_(n,e.times,!1,r)+" hours"+a(n,r);let t=_(n,e.times,!0,r);return(e.form==="range"?L(n.pattern.minute,r):b(T(n.analyses.segments.minute,r),"minute","hour",r))+", at "+t+a(n,r)}var Le={2:"other",3:"third",4:"fourth",6:"sixth",8:"eighth",12:"twelfth"};function vn(n,e){let r="during every "+Le[n.interval]+" hour",t=n.startToken==="*"?0:+n.startToken;return t===0?r:r+" starting at "+l({hour:t,minute:0},e)}function Ae(n,e,r){let t=n.analyses.segments.hour[0];return e.form==="wildcard"?"every minute "+vn(t,r)+a(n,r):L(n.pattern.minute,r)+", "+Mn(t,r)+a(n,r)}function L(n,e){let r=n.split("-"),t=A(r,e);return"every minute from "+t(r[0])+O(e)+t(r[1])+" past the hour"}function Ee(n,e,r){return"every hour"+a(n,r)}function We(n,e,r){let t=wn(je(e),r);return e.minuteForm==="wildcard"?"every minute "+t+a(n,r):e.minuteForm==="range"?L(n.pattern.minute,r)+", "+t+a(n,r):Cn(n,r)+" "+t+a(n,r)}function Cn(n,e){return n.pattern.minute==="0"?"every hour":b(T(n.analyses.segments.minute,e),"minute","hour",e)}function De(n,e,r){return Mn(n.analyses.segments.hour[0],r)+a(n,r)}function je(n){return{from:n.from,last:n.boundMinute??0,to:n.to}}function wn(n,e){return"from "+l({hour:n.from,minute:0},e)+O(e)+l({hour:n.to,minute:n.last},e)}function Ue(n,e,r){let t=tn(e.times),i=e.times.map(function(u){return l({hour:u.hour,minute:u.minute,second:u.second,plain:t},r)});return xn(n,r)+"at "+S(i,r)}function Qe(n,e,r){if(e.fold){if(n.analyses.segments.hour.some(function(m){return m.kind==="range"})&&!n.analyses.clockSecond)return qe(n,e,r)+a(n,r);let o={minute:e.minute,second:n.analyses.clockSecond};return xn(n,r)+"at "+nn(n,o,!0,r)}let t=b(T(n.analyses.segments.minute,r),"minute","hour",r)+", at "+nn(n,{minute:0,second:null},!0,r)+a(n,r);return n.analyses.clockSecond?H(n,r)+", "+t:t}function qe(n,e,r){let t=e.minute,i=[],o=[];n.analyses.segments.hour.forEach(function(f){f.kind==="range"?i.push("from "+l({hour:f.bounds[0],minute:0},r)+O(r)+l({hour:f.bounds[1],minute:t},r)):f.kind==="step"?o.push(...f.fires):o.push(+f.value)});let u=Cn(n,r)+" "+S(i,r);return o.length&&(u+=" and at "+S(o.map(function(f){return l({hour:f,minute:t},r)}),r)),u}var Ve={clockTimes:Ue,compactClockTimes:Qe,composeSeconds:we,everyHour:Ee,everyMinute:Re,everySecond:ze,hourRange:We,hourStep:De,minuteFrequency:Fe,minuteSpanAcrossHourStep:Ae,minuteSpanInHour:Ie,minutesAcrossHours:He,multipleMinutes:Te,rangeOfMinutes:xe,secondPastMinute:ve,secondsWithinMinute:Ce,singleMinute:Me,standaloneSeconds:Pe};function Rn(n,e,r,t){if(n.startToken.indexOf("-")!==-1)return b(Z(n.fires,t),e,r,t);let i=n.startToken==="*"?0:+n.startToken,o=n.interval;return i!==0?n.fires.length<=3?b(Z(n.fires,t),e,r,t):"every "+c(o,t)+" "+e+"s from "+c(i,t)+" "+P(i,e)+" past the "+r:60%o===0?"every "+c(o,t)+" "+e+"s":n.fires.length<=2?b(Z(n.fires,t),e,r,t):"every "+c(o,t)+" "+e+"s past the "+r}function Mn(n,e){if(n.startToken.indexOf("-")!==-1)return"at "+X(n.fires,e);let r=n.startToken==="*"?0:+n.startToken,t=n.interval;return r===0&&24%t===0?"every "+c(t,e)+" hours":n.fires.length<=3?"at "+X(n.fires,e):r===0?"every "+c(t,e)+" hours from midnight":"every "+c(t,e)+" hours from "+l({hour:r,minute:0},e)}function A(n,e){let r=n.some(function(i){return+i>10});return function(i){return r?""+i:c(i,e)}}function Z(n,e){return n.map(A(n,e))}function T(n,e){let r=n.flatMap(function(o){return o.kind==="range"?o.bounds:o.kind==="step"?o.fires:[o.value]}),t=A(r,e);return n.flatMap(function(o){return o.kind==="range"?[t(o.bounds[0])+O(e)+t(o.bounds[1])]:o.kind==="step"?o.fires.map(t):[t(o.value)]})}function b(n,e,r,t){return"at "+S(n,t)+" "+e+"s past the "+r}function Je(n,e,r){return(+n==0||+n==12)&&+e==0&&!(typeof r=="number"&&r>0)}function tn(n){let e=n.filter(function(t){return Je(t.hour,t.minute,t.second)});return e.length>0&&e.length<n.length}function X(n,e){let r=tn(n.map(function(o){return{hour:o,minute:0}})),t=n.map(function(o){return l({hour:o,minute:0,plain:r},e)});return S(t,e)}function _(n,e,r,t){return e.kind==="fires"?X(e.fires,t):nn(n,{minute:0,second:null},r,t)}function $e(n){return n.kind==="range"?n.bounds:n.kind==="step"?n.fires:[n.value]}function nn(n,e,r,t){let{minute:i,second:o}=e,u=n.analyses.segments.hour,m=tn(u.flatMap(function(p){return $e(p).map(function(j){return{hour:+j,minute:i,second:o}})})),f=[];return u.forEach(function(p){p.kind==="step"?f.push(...p.fires.map(function(j){return l({hour:j,minute:i,second:o,plain:m},t)})):p.kind==="range"?f.push(l({hour:p.bounds[0],minute:i,second:o,plain:m},t)+O(t)+l({hour:p.bounds[1],minute:i,second:o,plain:m},t)):f.push(l({hour:p.value,minute:i,second:o,plain:m},t))}),S(Ye(f,u,r),t)}function Ye(n,e,r){let t=e.some(function(o){return o.kind==="range"});return!r||!t?n:n.map(function(o,u){return u===0?o:"at "+o})}function S(n,e){if(n.length<=1)return n.join("");if(n.length===2)return n[0]+" and "+n[1];let r=e.style.serialComma?", and ":" and ";return n.slice(0,-1).join(", ")+r+n[n.length-1]}var Be={all:"",month:"in ",stepDate:"on ",weekday:"on "},Ge={all:"every day",month:"every day in ",stepDate:"",weekday:"every "};function a(n,e){let r=Tn(n,Be,e);return r&&" "+r}function xn(n,e){return Tn(n,Ge,e)+" "}function Tn(n,e,r){let t=n.pattern;return t.date!=="*"&&t.weekday!=="*"?Ze(n,r):t.date!=="*"?Ke(n,e,r):t.weekday!=="*"?(Hn(t.weekday,r)||e.weekday+Wn(n,r))+z(n,r):t.month!=="*"?e.month+E(n,r):e.all}function Ke(n,e,r){let t=n.pattern,i=In(t.date,r);return i?i+z(n,r):on(t.date)?e.stepDate+An(t.date)+z(n,r):t.month!=="*"&&!Fn(n)?"on the "+en(n,r)+z(n,r):t.month!=="*"?"on "+Ln(n,r):"on the "+en(n,r)}function Fn(n){return!En(n.pattern.month)&&n.analyses.segments.month.every(function(r){return r.kind!=="range"})}function Ze(n,e){let r=n.pattern,t=Hn(r.weekday,e)||"on "+Wn(n,e),i=In(r.date,e);return i?i+z(n,e)+" or "+t:on(r.date)?An(r.date)+z(n,e)+" or "+t:r.month!=="*"&&Fn(n)?"on "+Ln(n,e)+" or "+t+" in "+E(n,e):"on the "+en(n,e)+" or "+t+z(n,e)}function In(n,e){if(n==="L")return"on the last day of the month";if(n==="LW"||n==="WL")return"on the last weekday of the month";let r=/^L-(\d{1,2})$/.exec(n);if(r)return c(+r[1],e)+" "+P(r[1],"day")+" before the last day of the month";let t=/^(\d{1,2})W$|^W(\d{1,2})$/.exec(n);if(t)return"on the weekday nearest the "+x(t[1]||t[2])}function Hn(n,e){let r=n.split("#");if(r.length===2)return"on the "+Oe[+r[1]]+" "+rn(r[0],e)+" of the month";if(/L$/.test(n))return"on the last "+rn(n.slice(0,-1),e)+" of the month"}function Ln(n,e){let r=E(n,e),t=W(n.analyses.segments.date,e.style.ordinals?x:Xe,e);return e.style.dayFirst?t+" "+r:r+" "+t}function Xe(n){return""+n}function z(n,e){return n.pattern.month==="*"?"":" in "+E(n,e)}function An(n){let e=n.split("/"),r=+e[1],t=e[0],o=(r===2?"every other":"every "+x(r))+" day of the month";return t!=="*"&&t!=="1"&&(o+=" from the "+x(t)),o}function en(n,e){return W(n.analyses.segments.date,x,e)}function E(n,e){let r=En(n.pattern.month);return r||W(n.analyses.segments.month,function(i){return tr(i,e)},e)}function En(n){if(!on(n))return null;let[e,r]=n.split("/");return+r!=2?null:e==="*"||e==="1"?"every odd-numbered month":e==="2"?"every even-numbered month":null}function Wn(n,e){return W(n.analyses.segments.weekday,function(t){return rn(t,e)},e)}function W(n,e,r){let t=[];return n.forEach(function(o){o.kind==="step"?t.push(...o.fires.map(e)):o.kind==="range"?t.push(o.bounds.map(e).join(O(r))):t.push(e(o.value))}),S(t,r)}function on(n){return n.indexOf("/")!==-1&&n.indexOf("-")===-1&&n.indexOf(",")===-1}function _e(n,e,r){let t=e.pattern.year;if(t==="*")return n;if(t.indexOf("/")!==-1)return n+" "+er(t,r);let i=nr(t,r);if(t.indexOf("-")===-1&&t.indexOf(",")===-1&&e.pattern.date!=="*"&&n.indexOf(" at ")!==-1){let o=r.style.dayFirst?" ":", ";return n.replace(" at ",o+i+" at ")}return n+" in "+i}function nr(n,e){return n.indexOf(",")!==-1?S(n.split(","),e):n}function er(n,e){let r=n.split("/"),t=+r[1],i=r[0];if(t<=1)return"every year";let o="every "+c(t,e)+" years";return i!=="*"&&i!=="0"&&(o+=" from "+i),o}function l(n,e){let{hour:r,minute:t,plain:i}=n,o=typeof n.second=="number"&&n.second>0?n.second:0;return e.ampm?rr({hour:r,minute:t,second:o,plain:i},e):B({hour:r,minute:t,second:o},{pad:!0,sep:e.style.sep})}function rr(n,e){let{hour:r,minute:t,second:i,plain:o}=n,u=e.style;if(!o&&+t==0&&!i){if(+r==0)return u.midnight;if(+r==12)return u.midday}return B({hour:r%12||12,minute:t,second:i},{lean:!0,sep:u.sep})+(u.closeUp?"":" ")+(r<12?u.am:u.pm)}function c(n,e){return Nn(n,ye,e)}function P(n,e){return+n==1?e:e+"s"}function O(n){return n.short?"-":n.style.through}function x(n){let e=Math.abs(n),r=K[e];return r||(e=(e%100-20)%10,r=K[e]||K[0]),n+r}function tr(n,e){let r=g[n]||be[n];return r&&r[e.short?1:0]}function rn(n,e){let r=n===7||n==="7"?0:n,t=y[r]||Se[r];return t&&t[e.short?1:0]}var ir={describe:Ne,fallback:"an unrecognizable cron pattern",options:ke,reboot:"at system startup",sentence:n=>"Runs "+n+"."},Dn=ir;/**
|
|
1
|
+
"use strict";(()=>{var qn={SUN:0,MON:1,TUE:2,WED:3,THU:4,FRI:5,SAT:6},Vn={JAN:1,FEB:2,MAR:3,APR:4,MAY:5,JUN:6,JUL:7,AUG:8,SEP:9,OCT:10,NOV:11,DEC:12},p={second:{cyclic:!0,max:59,min:0,top:59},minute:{cyclic:!0,max:59,min:0,top:59},hour:{cyclic:!0,max:23,min:0,top:23},date:{aliases:{"?":"*"},cyclic:!0,max:31,min:1,top:31},month:{cyclic:!0,max:12,min:1,numbers:Vn,top:12},weekday:{aliases:{"?":"*",L:"6"},cyclic:!0,max:7,min:0,numbers:qn,top:6},year:{max:9999,min:1970}},O=["second","minute","hour","date","month","weekday","year"],U={"@annually":"0 0 1 1 *","@yearly":"0 0 1 1 *","@monthly":"0 0 1 * *","@weekly":"0 0 * * 0","@daily":"0 0 * * *","@midnight":"0 0 * * *","@hourly":"0 * * * *"},Q=6;function s(n,e){return(""+n).indexOf(e)!==-1}function T(n){return Array.from(new Set(n))}function I(n){return/^\d+$/.test(n)}function d(n,e){return I(n)?+n:e[n.toUpperCase()]}function sn(n){return O.forEach(function(r){Jn(n[r],p[r],r)}),n}function Jn(n,e,r){typeof n!="string"&&typeof n!="number"&&un(n,r);let t=""+n;t!=="*"&&(r==="date"&&v(t)||r==="weekday"&&w(t,e)||t.split(",").forEach(function(o){$n(o,e)||un(o,r)}))}function v(n){if(n==="L"||n==="LW"||n==="WL")return!0;let e=/^L-(\d{1,2})$/.exec(n);if(e)return+e[1]>=1&&+e[1]<=30;let r=/^(\d{1,2})W$|^W(\d{1,2})$/.exec(n);if(r){let t=+(r[1]||r[2]);return t>=1&&t<=31}return!1}function w(n,e){if(/L$/.test(n))return C(n.slice(0,-1),e);let r=n.split("#");return r.length===2?C(r[0],e)&&/^[1-5]$/.test(r[1]):!1}function $n(n,e){return s(n,"/")?Yn(n,e):s(n,"-")?an(n,e):C(n,e)}function Yn(n,e){let r=n.split("/");return r.length!==2||!I(r[1])||+r[1]<1?!1:r[0]==="*"||C(r[0],e)||an(r[0],e,!0)}function an(n,e,r){let t=n.split("-");return t.length!==2||!C(t[0],e)||!C(t[1],e)?!1:e.cyclic&&!r?!0:d(t[0],e.numbers)<=d(t[1],e.numbers)}function C(n,e){return n==="*"?!1:I(n)?+n>=e.min&&+n<=e.max:e.numbers?n.toUpperCase()in e.numbers:!1}function un(n,e){throw new Error('`cronli5` was passed an invalid field value "'+n+'" for the '+e+" field.")}var Bn={hour:24,minute:60,second:60};function cn(n){O.forEach(function(r){let t=p[r].aliases,i=t&&t[""+n[r]];i&&(n[r]=i)})}function mn(n){return O.forEach(function(r){let t=""+n[r];if(r==="date"&&v(t)||r==="weekday"&&w(t,p[r])){n[r]=t;return}n[r]=Gn(t,r,p[r])}),n}function Gn(n,e,r){let t=""+n;if(t==="*")return t;let i=Bn[e],o=t.split(",").map(function(a){return Xn(_n(Zn(Kn(a,r),r),r),r,i)}).join(",").split(",");return o.indexOf("*")!==-1?"*":T(o).sort(function(a,c){return ln(a,r)-ln(c,r)}).join(",")}function Kn(n,e){let r=n.split("/");if(!e.cyclic||r.length!==2||+r[1]!=1)return n;let t=r[0];return s(t,"-")?t:t==="*"||d(t,e.numbers)===e.min?"*":t+"-"+e.top}function Zn(n,e){let r=n.split("/");if(!e.cyclic||typeof e.top!="number"||r.length!==2||s(r[0],"-"))return n;let t=r[0];return(t==="*"?e.min:d(t,e.numbers))+ +r[1]<=e.top?n:t==="*"?""+e.min:t}function Xn(n,e,r){let t=n.split("/");if(typeof r!="number"||t.length!==2||s(t[0],"-"))return n;let i=+t[1],o=t[0]==="*"?e.min:d(t[0]);if(r%i===0&&o<i)return n;let u=[];for(let a=o;a<=e.top;a+=i)u.push(a);return u.join(",")}function _n(n,e){let r=n.split("/")[0];if(!s(r,"-"))return n;let t=r.split("-");return d(t[0],e.numbers)!==d(t[1],e.numbers)?n:t[0]}function ln(n,e){let r=n.split("/")[0].split("-")[0];return r==="*"?e.min:d(r,e.numbers)}function dn(n,e){let r=n instanceof Array;if(n===null||typeof n>"u"||n===""||r&&n.length===0)throw new Error("`cronli5` expects a non-empty cron pattern as the first argument.");if(r)return fn(n,e);if(typeof n=="object")return ne(n);if(typeof n=="string")return ee(n,e);throw new Error("`cronli5` was passed an unexpected type.")}function fn(n,e){if(n.length>7)throw new Error("`cronli5` was passed a cron pattern with more than seven fields.");return!e.seconds&&n.length<(e.years?7:6)&&n.unshift("0"),{second:n[0]||"0",minute:n[1]||"*",hour:n[2]||"*",date:n[3]||"*",month:n[4]||"*",weekday:n[5]||"*",year:n[6]||"*"}}function ne(n){if(!n.second&&!n.minute&&!n.hour)throw new Error("`cronli5` expects that any object being interpreted as a cron pattern have at least one of the following properties: `second`, `minute`, or `hour`");let e=typeof n.second<"u",r=typeof n.minute<"u",t=e?"*":"0",i=e||r?"*":"0";return{second:k(n.second,"0"),minute:k(n.minute,t),hour:k(n.hour,i),date:k(n.date,"*"),month:k(n.month,"*"),weekday:k(n.weekday,"*"),year:k(n.year,"*")}}function k(n,e){return typeof n>"u"?e:n}function ee(n,e){let r=re(n).split(/\s+/);return fn(r,e)}function re(n){let e=n.trim();if(e.charAt(0)!=="@")return n;let r=e.toLowerCase();if(Object.hasOwn(U,r))return U[r];throw new Error("`cronli5` does not recognize the macro `"+e+"`.")}function gn(n){return n!=="*"&&!s(n,",")&&!s(n,"-")&&!s(n,"/")}function q(n){return s(n,"-")&&!s(n,",")&&!s(n,"/")}function te(n){return s(n,"/")&&!s(n,",")}function V(n){return n!=="*"&&!s(n,"-")&&!s(n,"/")}function J(n){return n!=="*"&&!q(n)&&!te(n)}function R(n,e,r){let t=[],i=n;for(;i<=r;)t.push(i),i+=e;return t}function pn(n,e,r,t){let i=n.split("/"),o=+i[1];if(s(i[0],"-")){let a=i[0].split("-");return R(d(a[0],t),o,d(a[1],t))}let u=i[0]==="*"?e:d(i[0],t);return R(u,o,r)}function $(n,e,r){let t=[];return n.split(",").forEach(function(o){if(s(o,"/"))t.push(...pn(o,e,r));else if(s(o,"-")){let u=o.split("-");+u[0]<=+u[1]?t.push(...R(+u[0],1,+u[1])):(t.push(...R(+u[0],1,r)),t.push(...R(e,1,+u[1])))}else t.push(+o)}),T(t)}function ie(n){return V(n)?n.split(",").map(Number):[0]}function oe(n){if(n==="*")return[0,59];if(q(n)){let e=n.split("-");if(+e[0]<=+e[1])return[+e[0],+e[1]]}return null}function ue(n){return n==="*"?59:Math.max(...$(n,0,59))}function se(n){if(gn(n)&&n!=="0")return+n}function ae(n,e){return n==="*"?"wildcard":e==="date"&&v(n)||e==="weekday"&&w(n,p.weekday)?"quartz":s(n,",")?"list":s(n,"/")?"step":s(n,"-")?"range":"single"}function le(n,e,r){return e==="wildcard"||e==="quartz"?null:n.split(",").map(function(i){if(s(i,"/")){let o=i.split("/");return{fires:pn(i,r.min,r.top,r.numbers),interval:+o[1],kind:"step",startToken:o[0]}}return s(i,"-")?{bounds:i.split("-"),kind:"range"}:{kind:"single",value:i}})}function hn(n){let e={},r={};O.forEach(function(u){e[u]=ae(n[u],u),r[u]=le(n[u],e[u],p[u])});let i={analyses:{clockSecond:se(n.second),lastMinuteFire:ue(n.minute),minuteSpan:oe(n.minute),segments:r},pattern:n,shapes:e};return{...i,plan:ce(i)}}function ce(n){let{analyses:e,pattern:r,shapes:t}=n;if(r.second!=="0"){let i=me(r,t,e);if(i)return i}return yn(r,t,e)||Sn(r,t,e)}function me(n,e,r){let t=de(n,e);return t||(n.hour==="*"&&e.minute==="single"&&n.second!=="*"?{kind:"secondsWithinMinute",singleSecond:e.second==="single"}:e.second==="single"&&V(n.minute)&&J(n.hour)?null:{kind:"composeSeconds",rest:yn(n,e,r,!0)||Sn(n,e,r,!0)})}function de(n,e){return n.minute!=="*"||n.hour!=="*"?null:n.second==="*"?{kind:"everySecond"}:e.second==="single"?{kind:"secondPastMinute"}:{kind:"standaloneSeconds"}}function yn(n,e,r,t=!1){if(e.minute==="step")return{hours:ge(n,e,r),kind:"minuteFrequency"};if(e.hour==="single"&&r.minuteSpan)return{hour:+n.hour,kind:"minuteSpanInHour",span:r.minuteSpan};let i=pe(n,e);if(i)return i;let o=fe(n,e);if(o)return o;if(n.hour==="*")return he(n,e,t)}function bn(n){let[e,r]=n.split("/"),t=e==="*"?0:+e;return e.indexOf("-")===-1&&24%+r===0&&t<+r}function fe(n,e){return e.hour!=="step"?null:n.minute==="*"?bn(n.hour)?{form:"wildcard",kind:"minuteSpanAcrossHourStep"}:{form:"wildcard",kind:"minutesAcrossHours",times:M(n.hour)}:e.minute==="range"?{form:"range",kind:"minuteSpanAcrossHourStep"}:null}function ge(n,e,r){if(e.hour==="list")return{kind:"during",times:M(n.hour)};if(e.hour==="range"){let t=n.hour.split("-");return{from:+t[0],kind:"window",last:r.lastMinuteFire,to:+t[1]}}return e.hour==="single"?{from:+n.hour,kind:"window",last:r.lastMinuteFire,to:+n.hour}:e.hour==="step"?bn(n.hour)?{kind:"step"}:{kind:"during",times:M(n.hour)}:{kind:"none"}}function pe(n,e){return J(n.hour)?n.minute==="*"?{form:"wildcard",kind:"minutesAcrossHours",times:M(n.hour)}:e.minute==="range"||e.minute==="list"&&s(n.minute,"-")&&!s(n.minute,"/")?{form:e.minute==="range"?"range":"list",kind:"minutesAcrossHours",times:M(n.hour)}:null:null}function he(n,e,r){if(e.minute==="range")return{kind:"rangeOfMinutes"};if(e.minute==="list")return{kind:"multipleMinutes"};if(n.minute==="*")return{kind:"everyMinute"};if(n.minute!=="0"||r)return{kind:"singleMinute"}}function Sn(n,e,r,t=!1){let i=t&&n.minute==="0";return e.hour==="range"&&!i?ye(n,e,r):e.hour==="step"&&n.minute==="0"&&!t?{kind:"hourStep"}:n.hour==="*"&&!i?{kind:"everyHour"}:be(n,r,i)}function ye(n,e,r){let t=n.hour.split("-"),i="lead";return n.minute==="*"?i="wildcard":e.minute==="range"&&(i="range"),{boundMinute:e.minute==="range"||e.minute==="list"?null:r.lastMinuteFire,from:+t[0],kind:"hourRange",last:r.lastMinuteFire,minuteForm:i,to:+t[1]}}function be(n,e,r=!1){let t=$(n.hour,0,23),i=ie(n.minute);if(!r&&t.length*i.length>Q)return{fold:i.length===1,kind:"compactClockTimes",minute:i[0]};let o=[];return t.forEach(function(a){i.forEach(function(j){o.push({hour:a,minute:j,second:e.clockSecond})})}),{kind:"clockTimes",times:o}}function M(n){let e=$(n,0,23);return e.length<=Q?{fires:e,kind:"fires"}:{kind:"segments"}}function On(n,e){let r=dn(n,e);return cn(r),sn(r),mn(r)}function Y(n){return n=""+n,n.length<2?"0"+n:n}function kn(n,e,r){return r.short?n:e[n]||n}function B(n,{sep:e,pad:r,lean:t}){let i=r?Y(n.hour):""+n.hour;return t&&!n.minute&&!n.second?i:i+e+Y(n.minute)+(n.second?e+Y(n.second):"")}var G={gb:{am:"am",closeUp:!0,dayFirst:!0,midday:"midday",midnight:"midnight",ordinals:!1,pm:"pm",sep:".",serialComma:!1,through:" to "},us:{am:"a.m.",closeUp:!1,dayFirst:!1,midday:"noon",midnight:"midnight",ordinals:!1,pm:"p.m.",sep:":",serialComma:!0,through:" through "},house:{am:"AM",closeUp:!1,dayFirst:!1,midday:"noon",midnight:"midnight",ordinals:!0,pm:"PM",sep:":",serialComma:!0,through:" - "}};function Nn(n){return typeof n=="object"&&n!==null?{...G.us,...n}:G[n==="uk"?"gb":n]||G.us}var Se=["zero","one","two","three","four","five","six","seven","eight","nine","ten"],K=["th","st","nd","rd"],f=[null,["January","Jan"],["February","Feb"],["March","Mar"],["April","Apr"],["May","May"],["June","Jun"],["July","Jul"],["August","Aug"],["September","Sep"],["October","Oct"],["November","Nov"],["December","Dec"]],y=[["Sunday","Sun"],["Monday","Mon"],["Tuesday","Tue"],["Wednesday","Wed"],["Thursday","Thu"],["Friday","Fri"],["Saturday","Sat"]],Oe={JAN:f[1],FEB:f[2],MAR:f[3],APR:f[4],MAY:f[5],JUN:f[6],JUL:f[7],AUG:f[8],SEP:f[9],OCT:f[10],NOV:f[11],DEC:f[12]},ke={SUN:y[0],MON:y[1],TUE:y[2],WED:y[3],THU:y[4],FRI:y[5],SAT:y[6]},Ne=[null,"first","second","third","fourth","fifth"];function ze(n){return n=n||{},{ampm:typeof n.ampm=="boolean"?n.ampm:!0,lenient:!!n.lenient,seconds:!!n.seconds,short:!!n.short,style:Nn(n.dialect),years:!!n.years}}function Pe(n,e){return er(Pn(n,n.plan,e),n,e)}function Pn(n,e,r){let t=$e[e.kind];return t(n,e,r)}function Ce(n,e,r){return"every second"+l(n,r)}function ve(n,e,r){return H(n,r)+l(n,r)}function we(n,e,r){let t=n.pattern.second;return g(t,r)+" "+P(t,"second")+" past the minute, every minute"+l(n,r)}function Re(n,e,r){let t=n.pattern.minute,i=g(t,r),o=P(t,"minute");if(e.singleSecond){let u=n.pattern.second;return i+" "+o+" and "+g(u,r)+" "+P(u,"second")+" past the hour, every hour"+l(n,r)}return H(n,r)+", "+i+" "+o+" past the hour, every hour"+l(n,r)}function Me(n,e,r){return H(n,r)+", "+Pn(n,e.rest,r)}function H(n,e){let r=n.pattern.second,t=n.shapes.second;if(r==="*")return"every second";if(t==="step")return Rn(n.analyses.segments.second[0],"second","minute",e);if(t==="range"){let i=r.split("-"),o=A(i,e);return"every second from "+o(i[0])+S(e)+o(i[1])+" past the minute"}return t==="single"?"at "+g(r,e)+" "+P(r,"second")+" past the minute":z(F(n.analyses.segments.second,e),"second","minute",e)}function xe(n,e,r){return"every minute"+l(n,r)}function Fe(n,e,r){let t=n.pattern.minute;return g(t,r)+" "+P(t,"minute")+" past the hour, every hour"+l(n,r)}function Te(n,e,r){return L(n.pattern.minute,r)+l(n,r)}function Ie(n,e,r){return z(F(n.analyses.segments.minute,r),"minute","hour",r)+l(n,r)}function He(n,e,r){let t=Rn(n.analyses.segments.minute[0],"minute","hour",r);return e.hours.kind==="during"?t+=" during the "+X(n,e.hours.times,!1,r)+" hours":e.hours.kind==="window"?t+=" "+wn(e.hours,r):e.hours.kind==="step"&&(t+=" "+Cn(n.analyses.segments.hour[0],r)),t+l(n,r)}function Le(n,e,r){return"every minute from "+m({hour:e.hour,minute:e.span[0]},r)+S(r)+m({hour:e.hour,minute:e.span[1]},r)+l(n,r)}function Ae(n,e,r){if(e.form==="wildcard")return"every minute during the "+X(n,e.times,!1,r)+" hours"+l(n,r);let t=X(n,e.times,!0,r);return(e.form==="range"?L(n.pattern.minute,r):z(F(n.analyses.segments.minute,r),"minute","hour",r))+", at "+t+l(n,r)}var Ee={2:"other",3:"third",4:"fourth",6:"sixth",8:"eighth",12:"twelfth"};function Cn(n,e){let r="during every "+Ee[n.interval]+" hour",t=n.startToken==="*"?0:+n.startToken;return t===0?r:r+" starting at "+m({hour:t,minute:0},e)}function We(n,e,r){let t=n.analyses.segments.hour[0];return e.form==="wildcard"?"every minute "+Cn(t,r)+l(n,r):L(n.pattern.minute,r)+", "+Mn(t,r)+l(n,r)}function L(n,e){let r=n.split("-"),t=A(r,e);return"every minute from "+t(r[0])+S(e)+t(r[1])+" past the hour"}function je(n,e,r){return"every hour"+l(n,r)}function De(n,e,r){let t=wn(Qe(e),r);return e.minuteForm==="wildcard"?"every minute "+t+l(n,r):e.minuteForm==="range"?L(n.pattern.minute,r)+", "+t+l(n,r):vn(n,r)+" "+t+l(n,r)}function vn(n,e){return n.pattern.minute==="0"?"every hour":z(F(n.analyses.segments.minute,e),"minute","hour",e)}function Ue(n,e,r){return Mn(n.analyses.segments.hour[0],r)+l(n,r)}function Qe(n){return{from:n.from,last:n.boundMinute??0,to:n.to}}function wn(n,e){return"from "+m({hour:n.from,minute:0},e)+S(e)+m({hour:n.to,minute:n.last},e)}function qe(n,e,r){let t=rn(e.times),i=e.times.map(function(u){return m({hour:u.hour,minute:u.minute,second:u.second,plain:t},r)});return xn(n,r)+"at "+b(i,r)}function Ve(n,e,r){if(e.fold){if(n.analyses.segments.hour.some(function(a){return a.kind==="range"})&&!n.analyses.clockSecond)return Je(n,e,r)+l(n,r);let o={minute:e.minute,second:n.analyses.clockSecond};return xn(n,r)+"at "+_(n,o,!0,r)}let t=z(F(n.analyses.segments.minute,r),"minute","hour",r)+", at "+_(n,{minute:0,second:null},!0,r)+l(n,r);return n.analyses.clockSecond?H(n,r)+", "+t:t}function Je(n,e,r){let t=e.minute,i=[],o=[];n.analyses.segments.hour.forEach(function(c){c.kind==="range"?i.push("from "+m({hour:c.bounds[0],minute:0},r)+S(r)+m({hour:c.bounds[1],minute:t},r)):c.kind==="step"?o.push(...c.fires):o.push(+c.value)});let u=vn(n,r)+" "+b(i,r);return o.length&&(u+=" and at "+b(o.map(function(c){return m({hour:c,minute:t},r)}),r)),u}var $e={clockTimes:qe,compactClockTimes:Ve,composeSeconds:Me,everyHour:je,everyMinute:xe,everySecond:Ce,hourRange:De,hourStep:Ue,minuteFrequency:He,minuteSpanAcrossHourStep:We,minuteSpanInHour:Le,minutesAcrossHours:Ae,multipleMinutes:Ie,rangeOfMinutes:Te,secondPastMinute:we,secondsWithinMinute:Re,singleMinute:Fe,standaloneSeconds:ve};function Rn(n,e,r,t){if(n.startToken.indexOf("-")!==-1)return z(zn(n.fires,t),e,r,t);let i=n.startToken==="*"?0:+n.startToken,o=n.interval;return i!==0?n.fires.length<=3?z(zn(n.fires,t),e,r,t):"every "+g(o,t)+" "+e+"s from "+g(i,t)+" "+P(i,e)+" past the "+r:"every "+g(o,t)+" "+e+"s"}function Mn(n,e){if(n.startToken.indexOf("-")!==-1)return"at "+Z(n.fires,e);let r=n.startToken==="*"?0:+n.startToken,t=n.interval;return r===0?"every "+g(t,e)+" hours":n.fires.length<=3?"at "+Z(n.fires,e):"every "+g(t,e)+" hours from "+m({hour:r,minute:0},e)}function A(n,e){let r=n.some(function(i){return+i>10});return function(i){return r?""+i:g(i,e)}}function zn(n,e){return n.map(A(n,e))}function F(n,e){let r=n.flatMap(function(o){return o.kind==="range"?o.bounds:o.kind==="step"?o.fires:[o.value]}),t=A(r,e);return n.flatMap(function(o){return o.kind==="range"?[t(o.bounds[0])+S(e)+t(o.bounds[1])]:o.kind==="step"?o.fires.map(t):[t(o.value)]})}function z(n,e,r,t){return"at "+b(n,t)+" "+e+"s past the "+r}function Ye(n,e,r){return(+n==0||+n==12)&&+e==0&&!(typeof r=="number"&&r>0)}function rn(n){let e=n.filter(function(t){return Ye(t.hour,t.minute,t.second)});return e.length>0&&e.length<n.length}function Z(n,e){let r=rn(n.map(function(o){return{hour:o,minute:0}})),t=n.map(function(o){return m({hour:o,minute:0,plain:r},e)});return b(t,e)}function X(n,e,r,t){return e.kind==="fires"?Z(e.fires,t):_(n,{minute:0,second:null},r,t)}function Be(n){return n.kind==="range"?n.bounds:n.kind==="step"?n.fires:[n.value]}function _(n,e,r,t){let{minute:i,second:o}=e,u=n.analyses.segments.hour,a=rn(u.flatMap(function(h){return Be(h).map(function(D){return{hour:+D,minute:i,second:o}})})),c=[];return u.forEach(function(h){h.kind==="step"?c.push(...h.fires.map(function(D){return m({hour:D,minute:i,second:o,plain:a},t)})):h.kind==="range"?c.push(m({hour:h.bounds[0],minute:i,second:o,plain:a},t)+S(t)+m({hour:h.bounds[1],minute:i,second:o,plain:a},t)):c.push(m({hour:h.value,minute:i,second:o,plain:a},t))}),b(Ge(c,u,r),t)}function Ge(n,e,r){let t=e.some(function(o){return o.kind==="range"});return!r||!t?n:n.map(function(o,u){return u===0?o:"at "+o})}function b(n,e){if(n.length<=1)return n.join("");if(n.length===2)return n[0]+" and "+n[1];let r=e.style.serialComma?", and ":" and ";return n.slice(0,-1).join(", ")+r+n[n.length-1]}var Ke={all:"",month:"in ",stepDate:"on ",weekday:"on "},Ze={all:"every day",month:"every day in ",stepDate:"",weekday:"every "};function l(n,e){let r=Fn(n,Ke,e);return r&&" "+r}function xn(n,e){return Fn(n,Ze,e)+" "}function Fn(n,e,r){let t=n.pattern;return t.date!=="*"&&t.weekday!=="*"?_e(n,r):t.date!=="*"?Xe(n,e,r):t.weekday!=="*"?(Hn(t.weekday,r)||e.weekday+Wn(n,r))+N(n,r):t.month!=="*"?e.month+E(n,r):e.all}function Xe(n,e,r){let t=n.pattern,i=In(t.date,r);return i?i+N(n,r):tn(t.date)?e.stepDate+An(t.date)+N(n,r):t.month!=="*"&&!Tn(n)?"on the "+nn(n,r)+N(n,r):t.month!=="*"?"on "+Ln(n,r):"on the "+nn(n,r)}function Tn(n){return!En(n.pattern.month)&&n.analyses.segments.month.every(function(r){return r.kind!=="range"})}function _e(n,e){let r=n.pattern,t=Hn(r.weekday,e)||"on "+Wn(n,e),i=In(r.date,e);return i?i+N(n,e)+" or "+t:tn(r.date)?An(r.date)+N(n,e)+" or "+t:r.month!=="*"&&Tn(n)?"on "+Ln(n,e)+" or "+t+" in "+E(n,e):"on the "+nn(n,e)+" or "+t+N(n,e)}function In(n,e){if(n==="L")return"on the last day of the month";if(n==="LW"||n==="WL")return"on the last weekday of the month";let r=/^L-(\d{1,2})$/.exec(n);if(r)return g(+r[1],e)+" "+P(r[1],"day")+" before the last day of the month";let t=/^(\d{1,2})W$|^W(\d{1,2})$/.exec(n);if(t)return"on the weekday nearest the "+x(t[1]||t[2])}function Hn(n,e){let r=n.split("#");if(r.length===2)return"on the "+Ne[+r[1]]+" "+en(r[0],e)+" of the month";if(/L$/.test(n))return"on the last "+en(n.slice(0,-1),e)+" of the month"}function Ln(n,e){let r=E(n,e),t=W(n.analyses.segments.date,e.style.ordinals?x:nr,e);return e.style.dayFirst?t+" "+r:r+" "+t}function nr(n){return""+n}function N(n,e){return n.pattern.month==="*"?"":" in "+E(n,e)}function An(n){let e=n.split("/"),r=+e[1],t=e[0],o=(r===2?"every other":"every "+x(r))+" day of the month";return t!=="*"&&t!=="1"&&(o+=" from the "+x(t)),o}function nn(n,e){return W(n.analyses.segments.date,x,e)}function E(n,e){let r=En(n.pattern.month);return r||W(n.analyses.segments.month,function(i){return or(i,e)},e)}function En(n){if(!tn(n))return null;let[e,r]=n.split("/");return+r!=2?null:e==="*"||e==="1"?"every odd-numbered month":e==="2"?"every even-numbered month":null}function Wn(n,e){return W(n.analyses.segments.weekday,function(t){return en(t,e)},e)}function W(n,e,r){let t=[];return n.forEach(function(o){o.kind==="step"?t.push(...o.fires.map(e)):o.kind==="range"?t.push(o.bounds.map(e).join(S(r))):t.push(e(o.value))}),b(t,r)}function tn(n){return n.indexOf("/")!==-1&&n.indexOf("-")===-1&&n.indexOf(",")===-1}function er(n,e,r){let t=e.pattern.year;if(t==="*")return n;if(t.indexOf("/")!==-1)return n+" "+tr(t,r);let i=rr(t,r);if(t.indexOf("-")===-1&&t.indexOf(",")===-1&&e.pattern.date!=="*"&&n.indexOf(" at ")!==-1){let o=r.style.dayFirst?" ":", ";return n.replace(" at ",o+i+" at ")}return n+" in "+i}function rr(n,e){return n.indexOf(",")!==-1?b(n.split(","),e):n}function tr(n,e){let r=n.split("/"),t=+r[1],i=r[0];if(t<=1)return"every year";let o="every "+g(t,e)+" years";return i!=="*"&&i!=="0"&&(o+=" from "+i),o}function m(n,e){let{hour:r,minute:t,plain:i}=n,o=typeof n.second=="number"&&n.second>0?n.second:0;return e.ampm?ir({hour:r,minute:t,second:o,plain:i},e):B({hour:r,minute:t,second:o},{pad:!0,sep:e.style.sep})}function ir(n,e){let{hour:r,minute:t,second:i,plain:o}=n,u=e.style;if(!o&&+t==0&&!i){if(+r==0)return u.midnight;if(+r==12)return u.midday}return B({hour:r%12||12,minute:t,second:i},{lean:!0,sep:u.sep})+(u.closeUp?"":" ")+(r<12?u.am:u.pm)}function g(n,e){return kn(n,Se,e)}function P(n,e){return+n==1?e:e+"s"}function S(n){return n.short?"-":n.style.through}function x(n){let e=Math.abs(n),r=K[e];return r||(e=(e%100-20)%10,r=K[e]||K[0]),n+r}function or(n,e){let r=f[n]||Oe[n];return r&&r[e.short?1:0]}function en(n,e){let r=n===7||n==="7"?0:n,t=y[r]||ke[r];return t&&t[e.short?1:0]}var ur={describe:Pe,fallback:"an unrecognizable cron pattern",options:ze,reboot:"at system startup",sentence:n=>"Runs "+n+"."},jn=ur;/**
|
|
2
2
|
* @license MIT, Copyright (c) 2026 Andrew Brož
|
|
3
|
-
*/function
|
|
3
|
+
*/function sr(n,e){let r=e&&e.lang||jn,t=r.options(e);if(!t.lenient)return Dn(Un(n,r,t),r,e);try{return Dn(Un(n,r,t),r,e)}catch{return r.fallback}}function Dn(n,e,r){return r&&r.sentence?e.sentence(n):n}function Un(n,e,r){if(typeof n=="string"&&n.trim().toLowerCase()==="@reboot")return e.reboot;let t=hn(On(n,r)),i=e.strategy?e.strategy(t,t.plan):t.plan;return e.describe({...t,plan:i},r)}var on=sr;typeof globalThis<"u"&&Object.assign(globalThis,{cronli5:on});var qr=on;})();
|
package/dist/cronli5.cjs
CHANGED
|
@@ -194,6 +194,11 @@ function throwInvalidField(value, field) {
|
|
|
194
194
|
}
|
|
195
195
|
|
|
196
196
|
// src/core/normalize.ts
|
|
197
|
+
var timeFieldCycle = {
|
|
198
|
+
hour: 24,
|
|
199
|
+
minute: 60,
|
|
200
|
+
second: 60
|
|
201
|
+
};
|
|
197
202
|
function applyQuartzAliases(cronPattern) {
|
|
198
203
|
fieldOrder.forEach(function apply(field) {
|
|
199
204
|
const aliases = fieldSpecs[field].aliases;
|
|
@@ -210,21 +215,26 @@ function normalizeCronPattern(cronPattern) {
|
|
|
210
215
|
cronPattern[field] = value;
|
|
211
216
|
return;
|
|
212
217
|
}
|
|
213
|
-
cronPattern[field] = normalizeField(value, fieldSpecs[field]);
|
|
218
|
+
cronPattern[field] = normalizeField(value, field, fieldSpecs[field]);
|
|
214
219
|
});
|
|
215
220
|
return cronPattern;
|
|
216
221
|
}
|
|
217
|
-
function normalizeField(value, spec) {
|
|
222
|
+
function normalizeField(value, field, spec) {
|
|
218
223
|
const stringValue = "" + value;
|
|
219
224
|
if (stringValue === "*") {
|
|
220
225
|
return stringValue;
|
|
221
226
|
}
|
|
227
|
+
const cycle = timeFieldCycle[field];
|
|
222
228
|
const segments = stringValue.split(",").map(function canonical(segment) {
|
|
223
|
-
return
|
|
224
|
-
|
|
225
|
-
|
|
229
|
+
return enumerateNonUniformStep(
|
|
230
|
+
collapseDegenerateRange(
|
|
231
|
+
collapseOnceStep(collapseUnitStep(segment, spec), spec),
|
|
232
|
+
spec
|
|
233
|
+
),
|
|
234
|
+
spec,
|
|
235
|
+
cycle
|
|
226
236
|
);
|
|
227
|
-
});
|
|
237
|
+
}).join(",").split(",");
|
|
228
238
|
if (segments.indexOf("*") !== -1) {
|
|
229
239
|
return "*";
|
|
230
240
|
}
|
|
@@ -258,6 +268,22 @@ function collapseOnceStep(segment, spec) {
|
|
|
258
268
|
}
|
|
259
269
|
return start === "*" ? "" + spec.min : start;
|
|
260
270
|
}
|
|
271
|
+
function enumerateNonUniformStep(segment, spec, cycle) {
|
|
272
|
+
const parts = segment.split("/");
|
|
273
|
+
if (typeof cycle !== "number" || parts.length !== 2 || includes(parts[0], "-")) {
|
|
274
|
+
return segment;
|
|
275
|
+
}
|
|
276
|
+
const interval = +parts[1];
|
|
277
|
+
const start = parts[0] === "*" ? spec.min : toFieldNumber(parts[0]);
|
|
278
|
+
if (cycle % interval === 0 && start < interval) {
|
|
279
|
+
return segment;
|
|
280
|
+
}
|
|
281
|
+
const fires = [];
|
|
282
|
+
for (let value = start; value <= spec.top; value += interval) {
|
|
283
|
+
fires.push(value);
|
|
284
|
+
}
|
|
285
|
+
return fires.join(",");
|
|
286
|
+
}
|
|
261
287
|
function collapseDegenerateRange(segment, spec) {
|
|
262
288
|
const start = segment.split("/")[0];
|
|
263
289
|
if (!includes(start, "-")) {
|
|
@@ -1126,13 +1152,7 @@ function stepCycle60(segment, unit, anchor, opts) {
|
|
|
1126
1152
|
}
|
|
1127
1153
|
return "every " + getNumber(interval, opts) + " " + unit + "s from " + getNumber(start, opts) + " " + pluralize(start, unit) + " past the " + anchor;
|
|
1128
1154
|
}
|
|
1129
|
-
|
|
1130
|
-
return "every " + getNumber(interval, opts) + " " + unit + "s";
|
|
1131
|
-
}
|
|
1132
|
-
if (segment.fires.length <= 2) {
|
|
1133
|
-
return listPastThe(numberWords(segment.fires, opts), unit, anchor, opts);
|
|
1134
|
-
}
|
|
1135
|
-
return "every " + getNumber(interval, opts) + " " + unit + "s past the " + anchor;
|
|
1155
|
+
return "every " + getNumber(interval, opts) + " " + unit + "s";
|
|
1136
1156
|
}
|
|
1137
1157
|
function stepHours(segment, opts) {
|
|
1138
1158
|
if (segment.startToken.indexOf("-") !== -1) {
|
|
@@ -1140,15 +1160,12 @@ function stepHours(segment, opts) {
|
|
|
1140
1160
|
}
|
|
1141
1161
|
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
1142
1162
|
const interval = segment.interval;
|
|
1143
|
-
if (start === 0
|
|
1163
|
+
if (start === 0) {
|
|
1144
1164
|
return "every " + getNumber(interval, opts) + " hours";
|
|
1145
1165
|
}
|
|
1146
1166
|
if (segment.fires.length <= 3) {
|
|
1147
1167
|
return "at " + hourTimes(segment.fires, opts);
|
|
1148
1168
|
}
|
|
1149
|
-
if (start === 0) {
|
|
1150
|
-
return "every " + getNumber(interval, opts) + " hours from midnight";
|
|
1151
|
-
}
|
|
1152
1169
|
return "every " + getNumber(interval, opts) + " hours from " + getTime({ hour: start, minute: 0 }, opts);
|
|
1153
1170
|
}
|
|
1154
1171
|
function seriesNumber(values, opts) {
|
package/dist/cronli5.js
CHANGED
|
@@ -168,6 +168,11 @@ function throwInvalidField(value, field) {
|
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
// src/core/normalize.ts
|
|
171
|
+
var timeFieldCycle = {
|
|
172
|
+
hour: 24,
|
|
173
|
+
minute: 60,
|
|
174
|
+
second: 60
|
|
175
|
+
};
|
|
171
176
|
function applyQuartzAliases(cronPattern) {
|
|
172
177
|
fieldOrder.forEach(function apply(field) {
|
|
173
178
|
const aliases = fieldSpecs[field].aliases;
|
|
@@ -184,21 +189,26 @@ function normalizeCronPattern(cronPattern) {
|
|
|
184
189
|
cronPattern[field] = value;
|
|
185
190
|
return;
|
|
186
191
|
}
|
|
187
|
-
cronPattern[field] = normalizeField(value, fieldSpecs[field]);
|
|
192
|
+
cronPattern[field] = normalizeField(value, field, fieldSpecs[field]);
|
|
188
193
|
});
|
|
189
194
|
return cronPattern;
|
|
190
195
|
}
|
|
191
|
-
function normalizeField(value, spec) {
|
|
196
|
+
function normalizeField(value, field, spec) {
|
|
192
197
|
const stringValue = "" + value;
|
|
193
198
|
if (stringValue === "*") {
|
|
194
199
|
return stringValue;
|
|
195
200
|
}
|
|
201
|
+
const cycle = timeFieldCycle[field];
|
|
196
202
|
const segments = stringValue.split(",").map(function canonical(segment) {
|
|
197
|
-
return
|
|
198
|
-
|
|
199
|
-
|
|
203
|
+
return enumerateNonUniformStep(
|
|
204
|
+
collapseDegenerateRange(
|
|
205
|
+
collapseOnceStep(collapseUnitStep(segment, spec), spec),
|
|
206
|
+
spec
|
|
207
|
+
),
|
|
208
|
+
spec,
|
|
209
|
+
cycle
|
|
200
210
|
);
|
|
201
|
-
});
|
|
211
|
+
}).join(",").split(",");
|
|
202
212
|
if (segments.indexOf("*") !== -1) {
|
|
203
213
|
return "*";
|
|
204
214
|
}
|
|
@@ -232,6 +242,22 @@ function collapseOnceStep(segment, spec) {
|
|
|
232
242
|
}
|
|
233
243
|
return start === "*" ? "" + spec.min : start;
|
|
234
244
|
}
|
|
245
|
+
function enumerateNonUniformStep(segment, spec, cycle) {
|
|
246
|
+
const parts = segment.split("/");
|
|
247
|
+
if (typeof cycle !== "number" || parts.length !== 2 || includes(parts[0], "-")) {
|
|
248
|
+
return segment;
|
|
249
|
+
}
|
|
250
|
+
const interval = +parts[1];
|
|
251
|
+
const start = parts[0] === "*" ? spec.min : toFieldNumber(parts[0]);
|
|
252
|
+
if (cycle % interval === 0 && start < interval) {
|
|
253
|
+
return segment;
|
|
254
|
+
}
|
|
255
|
+
const fires = [];
|
|
256
|
+
for (let value = start; value <= spec.top; value += interval) {
|
|
257
|
+
fires.push(value);
|
|
258
|
+
}
|
|
259
|
+
return fires.join(",");
|
|
260
|
+
}
|
|
235
261
|
function collapseDegenerateRange(segment, spec) {
|
|
236
262
|
const start = segment.split("/")[0];
|
|
237
263
|
if (!includes(start, "-")) {
|
|
@@ -1100,13 +1126,7 @@ function stepCycle60(segment, unit, anchor, opts) {
|
|
|
1100
1126
|
}
|
|
1101
1127
|
return "every " + getNumber(interval, opts) + " " + unit + "s from " + getNumber(start, opts) + " " + pluralize(start, unit) + " past the " + anchor;
|
|
1102
1128
|
}
|
|
1103
|
-
|
|
1104
|
-
return "every " + getNumber(interval, opts) + " " + unit + "s";
|
|
1105
|
-
}
|
|
1106
|
-
if (segment.fires.length <= 2) {
|
|
1107
|
-
return listPastThe(numberWords(segment.fires, opts), unit, anchor, opts);
|
|
1108
|
-
}
|
|
1109
|
-
return "every " + getNumber(interval, opts) + " " + unit + "s past the " + anchor;
|
|
1129
|
+
return "every " + getNumber(interval, opts) + " " + unit + "s";
|
|
1110
1130
|
}
|
|
1111
1131
|
function stepHours(segment, opts) {
|
|
1112
1132
|
if (segment.startToken.indexOf("-") !== -1) {
|
|
@@ -1114,15 +1134,12 @@ function stepHours(segment, opts) {
|
|
|
1114
1134
|
}
|
|
1115
1135
|
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
1116
1136
|
const interval = segment.interval;
|
|
1117
|
-
if (start === 0
|
|
1137
|
+
if (start === 0) {
|
|
1118
1138
|
return "every " + getNumber(interval, opts) + " hours";
|
|
1119
1139
|
}
|
|
1120
1140
|
if (segment.fires.length <= 3) {
|
|
1121
1141
|
return "at " + hourTimes(segment.fires, opts);
|
|
1122
1142
|
}
|
|
1123
|
-
if (start === 0) {
|
|
1124
|
-
return "every " + getNumber(interval, opts) + " hours from midnight";
|
|
1125
|
-
}
|
|
1126
1143
|
return "every " + getNumber(interval, opts) + " hours from " + getTime({ hour: start, minute: 0 }, opts);
|
|
1127
1144
|
}
|
|
1128
1145
|
function seriesNumber(values, opts) {
|
package/dist/lang/de.cjs
CHANGED
|
@@ -352,7 +352,7 @@ function duringHours(ir, times, sep) {
|
|
|
352
352
|
if (windows.length <= 3 || times.kind !== "fires") {
|
|
353
353
|
return joinList(windows);
|
|
354
354
|
}
|
|
355
|
-
return "in den Stunden
|
|
355
|
+
return "in den Stunden " + joinList(times.fires.map(String)) + " Uhr";
|
|
356
356
|
}
|
|
357
357
|
function renderEverySecond() {
|
|
358
358
|
return everyUnit(UNITS.second);
|
|
@@ -545,7 +545,9 @@ var de2 = {
|
|
|
545
545
|
fallback: "ein unlesbares Cron-Muster",
|
|
546
546
|
options: normalizeOptions,
|
|
547
547
|
reboot: "beim Systemstart",
|
|
548
|
-
|
|
548
|
+
// A description ending in a German ordinal already carries its period
|
|
549
|
+
// ("…am 8."), so closing the sentence must not double it.
|
|
550
|
+
sentence: (description) => "L\xE4uft " + description + (description.endsWith(".") ? "" : ".")
|
|
549
551
|
};
|
|
550
552
|
var index_default = de2;
|
|
551
553
|
module.exports = module.exports.default;
|
package/dist/lang/de.js
CHANGED
|
@@ -326,7 +326,7 @@ function duringHours(ir, times, sep) {
|
|
|
326
326
|
if (windows.length <= 3 || times.kind !== "fires") {
|
|
327
327
|
return joinList(windows);
|
|
328
328
|
}
|
|
329
|
-
return "in den Stunden
|
|
329
|
+
return "in den Stunden " + joinList(times.fires.map(String)) + " Uhr";
|
|
330
330
|
}
|
|
331
331
|
function renderEverySecond() {
|
|
332
332
|
return everyUnit(UNITS.second);
|
|
@@ -519,7 +519,9 @@ var de2 = {
|
|
|
519
519
|
fallback: "ein unlesbares Cron-Muster",
|
|
520
520
|
options: normalizeOptions,
|
|
521
521
|
reboot: "beim Systemstart",
|
|
522
|
-
|
|
522
|
+
// A description ending in a German ordinal already carries its period
|
|
523
|
+
// ("…am 8."), so closing the sentence must not double it.
|
|
524
|
+
sentence: (description) => "L\xE4uft " + description + (description.endsWith(".") ? "" : ".")
|
|
523
525
|
};
|
|
524
526
|
var index_default = de2;
|
|
525
527
|
export {
|
package/dist/lang/en.cjs
CHANGED
|
@@ -431,13 +431,7 @@ function stepCycle60(segment, unit, anchor, opts) {
|
|
|
431
431
|
}
|
|
432
432
|
return "every " + getNumber(interval, opts) + " " + unit + "s from " + getNumber(start, opts) + " " + pluralize(start, unit) + " past the " + anchor;
|
|
433
433
|
}
|
|
434
|
-
|
|
435
|
-
return "every " + getNumber(interval, opts) + " " + unit + "s";
|
|
436
|
-
}
|
|
437
|
-
if (segment.fires.length <= 2) {
|
|
438
|
-
return listPastThe(numberWords(segment.fires, opts), unit, anchor, opts);
|
|
439
|
-
}
|
|
440
|
-
return "every " + getNumber(interval, opts) + " " + unit + "s past the " + anchor;
|
|
434
|
+
return "every " + getNumber(interval, opts) + " " + unit + "s";
|
|
441
435
|
}
|
|
442
436
|
function stepHours(segment, opts) {
|
|
443
437
|
if (segment.startToken.indexOf("-") !== -1) {
|
|
@@ -445,15 +439,12 @@ function stepHours(segment, opts) {
|
|
|
445
439
|
}
|
|
446
440
|
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
447
441
|
const interval = segment.interval;
|
|
448
|
-
if (start === 0
|
|
442
|
+
if (start === 0) {
|
|
449
443
|
return "every " + getNumber(interval, opts) + " hours";
|
|
450
444
|
}
|
|
451
445
|
if (segment.fires.length <= 3) {
|
|
452
446
|
return "at " + hourTimes(segment.fires, opts);
|
|
453
447
|
}
|
|
454
|
-
if (start === 0) {
|
|
455
|
-
return "every " + getNumber(interval, opts) + " hours from midnight";
|
|
456
|
-
}
|
|
457
448
|
return "every " + getNumber(interval, opts) + " hours from " + getTime({ hour: start, minute: 0 }, opts);
|
|
458
449
|
}
|
|
459
450
|
function seriesNumber(values, opts) {
|
package/dist/lang/en.js
CHANGED
|
@@ -405,13 +405,7 @@ function stepCycle60(segment, unit, anchor, opts) {
|
|
|
405
405
|
}
|
|
406
406
|
return "every " + getNumber(interval, opts) + " " + unit + "s from " + getNumber(start, opts) + " " + pluralize(start, unit) + " past the " + anchor;
|
|
407
407
|
}
|
|
408
|
-
|
|
409
|
-
return "every " + getNumber(interval, opts) + " " + unit + "s";
|
|
410
|
-
}
|
|
411
|
-
if (segment.fires.length <= 2) {
|
|
412
|
-
return listPastThe(numberWords(segment.fires, opts), unit, anchor, opts);
|
|
413
|
-
}
|
|
414
|
-
return "every " + getNumber(interval, opts) + " " + unit + "s past the " + anchor;
|
|
408
|
+
return "every " + getNumber(interval, opts) + " " + unit + "s";
|
|
415
409
|
}
|
|
416
410
|
function stepHours(segment, opts) {
|
|
417
411
|
if (segment.startToken.indexOf("-") !== -1) {
|
|
@@ -419,15 +413,12 @@ function stepHours(segment, opts) {
|
|
|
419
413
|
}
|
|
420
414
|
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
421
415
|
const interval = segment.interval;
|
|
422
|
-
if (start === 0
|
|
416
|
+
if (start === 0) {
|
|
423
417
|
return "every " + getNumber(interval, opts) + " hours";
|
|
424
418
|
}
|
|
425
419
|
if (segment.fires.length <= 3) {
|
|
426
420
|
return "at " + hourTimes(segment.fires, opts);
|
|
427
421
|
}
|
|
428
|
-
if (start === 0) {
|
|
429
|
-
return "every " + getNumber(interval, opts) + " hours from midnight";
|
|
430
|
-
}
|
|
431
422
|
return "every " + getNumber(interval, opts) + " hours from " + getTime({ hour: start, minute: 0 }, opts);
|
|
432
423
|
}
|
|
433
424
|
function seriesNumber(values, opts) {
|
package/dist/lang/es.cjs
CHANGED
|
@@ -600,13 +600,7 @@ function stepCycle60(segment, unit, anchor, opts) {
|
|
|
600
600
|
}
|
|
601
601
|
return "cada " + numero(interval, opts) + " " + unit + "s a partir del " + unit + " " + start + " de cada " + anchor;
|
|
602
602
|
}
|
|
603
|
-
|
|
604
|
-
return "cada " + numero(interval, opts) + " " + unit + "s";
|
|
605
|
-
}
|
|
606
|
-
if (segment.fires.length <= 2) {
|
|
607
|
-
return "en los " + unit + "s " + joinList(wordList(segment.fires)) + " de cada " + anchor;
|
|
608
|
-
}
|
|
609
|
-
return "cada " + numero(interval, opts) + " " + unit + "s de cada " + anchor;
|
|
603
|
+
return "cada " + numero(interval, opts) + " " + unit + "s";
|
|
610
604
|
}
|
|
611
605
|
function stepHours(segment, opts) {
|
|
612
606
|
if (segment.startToken.indexOf("-") !== -1) {
|
|
@@ -614,15 +608,12 @@ function stepHours(segment, opts) {
|
|
|
614
608
|
}
|
|
615
609
|
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
616
610
|
const interval = segment.interval;
|
|
617
|
-
if (start === 0
|
|
611
|
+
if (start === 0) {
|
|
618
612
|
return "cada " + numero(interval, opts) + " horas";
|
|
619
613
|
}
|
|
620
614
|
if (segment.fires.length <= 3) {
|
|
621
615
|
return groupClockTimesByArticle(atTimes(segment.fires, opts));
|
|
622
616
|
}
|
|
623
|
-
if (start === 0) {
|
|
624
|
-
return "cada " + numero(interval, opts) + " horas desde medianoche";
|
|
625
|
-
}
|
|
626
617
|
return "cada " + numero(interval, opts) + " horas a partir de " + timePhrase(start, 0, null, opts);
|
|
627
618
|
}
|
|
628
619
|
function atTimes(hours, opts) {
|
package/dist/lang/es.js
CHANGED
|
@@ -574,13 +574,7 @@ function stepCycle60(segment, unit, anchor, opts) {
|
|
|
574
574
|
}
|
|
575
575
|
return "cada " + numero(interval, opts) + " " + unit + "s a partir del " + unit + " " + start + " de cada " + anchor;
|
|
576
576
|
}
|
|
577
|
-
|
|
578
|
-
return "cada " + numero(interval, opts) + " " + unit + "s";
|
|
579
|
-
}
|
|
580
|
-
if (segment.fires.length <= 2) {
|
|
581
|
-
return "en los " + unit + "s " + joinList(wordList(segment.fires)) + " de cada " + anchor;
|
|
582
|
-
}
|
|
583
|
-
return "cada " + numero(interval, opts) + " " + unit + "s de cada " + anchor;
|
|
577
|
+
return "cada " + numero(interval, opts) + " " + unit + "s";
|
|
584
578
|
}
|
|
585
579
|
function stepHours(segment, opts) {
|
|
586
580
|
if (segment.startToken.indexOf("-") !== -1) {
|
|
@@ -588,15 +582,12 @@ function stepHours(segment, opts) {
|
|
|
588
582
|
}
|
|
589
583
|
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
590
584
|
const interval = segment.interval;
|
|
591
|
-
if (start === 0
|
|
585
|
+
if (start === 0) {
|
|
592
586
|
return "cada " + numero(interval, opts) + " horas";
|
|
593
587
|
}
|
|
594
588
|
if (segment.fires.length <= 3) {
|
|
595
589
|
return groupClockTimesByArticle(atTimes(segment.fires, opts));
|
|
596
590
|
}
|
|
597
|
-
if (start === 0) {
|
|
598
|
-
return "cada " + numero(interval, opts) + " horas desde medianoche";
|
|
599
|
-
}
|
|
600
591
|
return "cada " + numero(interval, opts) + " horas a partir de " + timePhrase(start, 0, null, opts);
|
|
601
592
|
}
|
|
602
593
|
function atTimes(hours, opts) {
|
package/dist/lang/fi.cjs
CHANGED
|
@@ -194,15 +194,13 @@ var units = {
|
|
|
194
194
|
mark: "joka tunti",
|
|
195
195
|
anchor: "jokaisen tunnin",
|
|
196
196
|
ela: "minuutista",
|
|
197
|
-
gen: "minuutin"
|
|
198
|
-
restart: "tasatunnista alkaen"
|
|
197
|
+
gen: "minuutin"
|
|
199
198
|
},
|
|
200
199
|
second: {
|
|
201
200
|
mark: "joka minuutti",
|
|
202
201
|
anchor: "jokaisen minuutin",
|
|
203
202
|
ela: "sekunnista",
|
|
204
|
-
gen: "sekunnin"
|
|
205
|
-
restart: "joka minuutti"
|
|
203
|
+
gen: "sekunnin"
|
|
206
204
|
}
|
|
207
205
|
};
|
|
208
206
|
function atMarks(values, unit, withMark) {
|
|
@@ -561,13 +559,7 @@ function stepCycle60(segment, unit, opts) {
|
|
|
561
559
|
}
|
|
562
560
|
return cadence + " " + unit.anchor + " " + unit.ela + " " + start + " alkaen";
|
|
563
561
|
}
|
|
564
|
-
|
|
565
|
-
return cadence;
|
|
566
|
-
}
|
|
567
|
-
if (segment.fires.length <= 2) {
|
|
568
|
-
return atMarks(joinList(wordList(segment.fires)), unit, true);
|
|
569
|
-
}
|
|
570
|
-
return cadence + " " + unit.restart;
|
|
562
|
+
return cadence;
|
|
571
563
|
}
|
|
572
564
|
function stepHours(segment, opts) {
|
|
573
565
|
if (segment.startToken.indexOf("-") !== -1) {
|
|
@@ -576,15 +568,12 @@ function stepHours(segment, opts) {
|
|
|
576
568
|
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
577
569
|
const interval = segment.interval;
|
|
578
570
|
const cadence = genitive(interval, opts) + " tunnin v\xE4lein";
|
|
579
|
-
if (start === 0
|
|
571
|
+
if (start === 0) {
|
|
580
572
|
return cadence;
|
|
581
573
|
}
|
|
582
574
|
if (segment.fires.length <= 3) {
|
|
583
575
|
return kloList(segment.fires, opts);
|
|
584
576
|
}
|
|
585
|
-
if (start === 0) {
|
|
586
|
-
return cadence + " keskiy\xF6st\xE4 alkaen";
|
|
587
|
-
}
|
|
588
577
|
return cadence + " klo " + hourElatives[start] + " alkaen";
|
|
589
578
|
}
|
|
590
579
|
function kloList(hours, opts) {
|
package/dist/lang/fi.js
CHANGED
|
@@ -168,15 +168,13 @@ var units = {
|
|
|
168
168
|
mark: "joka tunti",
|
|
169
169
|
anchor: "jokaisen tunnin",
|
|
170
170
|
ela: "minuutista",
|
|
171
|
-
gen: "minuutin"
|
|
172
|
-
restart: "tasatunnista alkaen"
|
|
171
|
+
gen: "minuutin"
|
|
173
172
|
},
|
|
174
173
|
second: {
|
|
175
174
|
mark: "joka minuutti",
|
|
176
175
|
anchor: "jokaisen minuutin",
|
|
177
176
|
ela: "sekunnista",
|
|
178
|
-
gen: "sekunnin"
|
|
179
|
-
restart: "joka minuutti"
|
|
177
|
+
gen: "sekunnin"
|
|
180
178
|
}
|
|
181
179
|
};
|
|
182
180
|
function atMarks(values, unit, withMark) {
|
|
@@ -535,13 +533,7 @@ function stepCycle60(segment, unit, opts) {
|
|
|
535
533
|
}
|
|
536
534
|
return cadence + " " + unit.anchor + " " + unit.ela + " " + start + " alkaen";
|
|
537
535
|
}
|
|
538
|
-
|
|
539
|
-
return cadence;
|
|
540
|
-
}
|
|
541
|
-
if (segment.fires.length <= 2) {
|
|
542
|
-
return atMarks(joinList(wordList(segment.fires)), unit, true);
|
|
543
|
-
}
|
|
544
|
-
return cadence + " " + unit.restart;
|
|
536
|
+
return cadence;
|
|
545
537
|
}
|
|
546
538
|
function stepHours(segment, opts) {
|
|
547
539
|
if (segment.startToken.indexOf("-") !== -1) {
|
|
@@ -550,15 +542,12 @@ function stepHours(segment, opts) {
|
|
|
550
542
|
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
551
543
|
const interval = segment.interval;
|
|
552
544
|
const cadence = genitive(interval, opts) + " tunnin v\xE4lein";
|
|
553
|
-
if (start === 0
|
|
545
|
+
if (start === 0) {
|
|
554
546
|
return cadence;
|
|
555
547
|
}
|
|
556
548
|
if (segment.fires.length <= 3) {
|
|
557
549
|
return kloList(segment.fires, opts);
|
|
558
550
|
}
|
|
559
|
-
if (start === 0) {
|
|
560
|
-
return cadence + " keskiy\xF6st\xE4 alkaen";
|
|
561
|
-
}
|
|
562
551
|
return cadence + " klo " + hourElatives[start] + " alkaen";
|
|
563
552
|
}
|
|
564
553
|
function kloList(hours, opts) {
|
package/dist/lang/zh.cjs
CHANGED
|
@@ -197,7 +197,8 @@ function hourFrame(ir) {
|
|
|
197
197
|
return "\u5728" + hourList(ir) + "\uFF0C";
|
|
198
198
|
}
|
|
199
199
|
function renderMinuteFrequency(ir, plan) {
|
|
200
|
-
const
|
|
200
|
+
const minuteStep = stepSegment(ir, "minute");
|
|
201
|
+
const base = minuteStep.startToken === "*" ? cadence(minuteStep.interval, UNITS.minute) : renderMinutePast(ir);
|
|
201
202
|
const { hours } = plan;
|
|
202
203
|
if (hours.kind === "step") {
|
|
203
204
|
return cadence(stepSegment(ir, "hour").interval, UNITS.hour) + base;
|
|
@@ -265,9 +266,6 @@ function renderHourStep(ir) {
|
|
|
265
266
|
if (segment.fires.length <= 2) {
|
|
266
267
|
return joinAnd(segment.fires.map(hourWord));
|
|
267
268
|
}
|
|
268
|
-
if (24 % segment.interval !== 0) {
|
|
269
|
-
return "\u4ECE" + hourWord(segment.fires[0]) + "\u8D77\uFF0C" + cadence(segment.interval, UNITS.hour);
|
|
270
|
-
}
|
|
271
269
|
return cadence(segment.interval, UNITS.hour);
|
|
272
270
|
}
|
|
273
271
|
function renderRangeOfMinutes(ir) {
|
package/dist/lang/zh.js
CHANGED
|
@@ -171,7 +171,8 @@ function hourFrame(ir) {
|
|
|
171
171
|
return "\u5728" + hourList(ir) + "\uFF0C";
|
|
172
172
|
}
|
|
173
173
|
function renderMinuteFrequency(ir, plan) {
|
|
174
|
-
const
|
|
174
|
+
const minuteStep = stepSegment(ir, "minute");
|
|
175
|
+
const base = minuteStep.startToken === "*" ? cadence(minuteStep.interval, UNITS.minute) : renderMinutePast(ir);
|
|
175
176
|
const { hours } = plan;
|
|
176
177
|
if (hours.kind === "step") {
|
|
177
178
|
return cadence(stepSegment(ir, "hour").interval, UNITS.hour) + base;
|
|
@@ -239,9 +240,6 @@ function renderHourStep(ir) {
|
|
|
239
240
|
if (segment.fires.length <= 2) {
|
|
240
241
|
return joinAnd(segment.fires.map(hourWord));
|
|
241
242
|
}
|
|
242
|
-
if (24 % segment.interval !== 0) {
|
|
243
|
-
return "\u4ECE" + hourWord(segment.fires[0]) + "\u8D77\uFF0C" + cadence(segment.interval, UNITS.hour);
|
|
244
|
-
}
|
|
245
243
|
return cadence(segment.interval, UNITS.hour);
|
|
246
244
|
}
|
|
247
245
|
function renderRangeOfMinutes(ir) {
|
package/package.json
CHANGED
package/src/core/normalize.ts
CHANGED
|
@@ -4,10 +4,20 @@
|
|
|
4
4
|
|
|
5
5
|
import {fieldOrder, fieldSpecs} from './specs.js';
|
|
6
6
|
import type {CronLike, FieldSpec} from './specs.js';
|
|
7
|
-
import type {Pattern} from './ir.js';
|
|
7
|
+
import type {Field, Pattern} from './ir.js';
|
|
8
8
|
import {includes, toFieldNumber, unique} from './util.js';
|
|
9
9
|
import {isQuartzDate, isQuartzWeekday} from './validate.js';
|
|
10
10
|
|
|
11
|
+
// The fixed-cycle time fields: their step intervals are measured against a
|
|
12
|
+
// closed cycle (60 seconds, 60 minutes, 24 hours), so a step is a true
|
|
13
|
+
// "every N" cadence only when it tiles that cycle. The calendar fields
|
|
14
|
+
// (date/month/weekday) have variable cycles and keep their step form.
|
|
15
|
+
const timeFieldCycle: Partial<Record<Field, number>> = {
|
|
16
|
+
hour: 24,
|
|
17
|
+
minute: 60,
|
|
18
|
+
second: 60
|
|
19
|
+
};
|
|
20
|
+
|
|
11
21
|
// Quartz aliases: `?` reads "no specific value" (equivalent to `*`) in the
|
|
12
22
|
// date and weekday fields, and a bare `L` weekday means Saturday.
|
|
13
23
|
function applyQuartzAliases(cronPattern: CronLike): void {
|
|
@@ -40,7 +50,7 @@ function normalizeCronPattern(cronPattern: CronLike): Pattern {
|
|
|
40
50
|
return;
|
|
41
51
|
}
|
|
42
52
|
|
|
43
|
-
cronPattern[field] = normalizeField(value, fieldSpecs[field]);
|
|
53
|
+
cronPattern[field] = normalizeField(value, field, fieldSpecs[field]);
|
|
44
54
|
});
|
|
45
55
|
|
|
46
56
|
// Every field is now a canonical string.
|
|
@@ -48,17 +58,20 @@ function normalizeCronPattern(cronPattern: CronLike): Pattern {
|
|
|
48
58
|
}
|
|
49
59
|
|
|
50
60
|
// Canonicalize a single validated field value to a string.
|
|
51
|
-
function normalizeField(value: string, spec: FieldSpec): string {
|
|
61
|
+
function normalizeField(value: string, field: Field, spec: FieldSpec): string {
|
|
52
62
|
const stringValue = '' + value;
|
|
53
63
|
|
|
54
64
|
if (stringValue === '*') {
|
|
55
65
|
return stringValue;
|
|
56
66
|
}
|
|
57
67
|
|
|
68
|
+
const cycle = timeFieldCycle[field];
|
|
58
69
|
const segments = stringValue.split(',').map(function canonical(segment) {
|
|
59
|
-
return
|
|
60
|
-
|
|
61
|
-
|
|
70
|
+
return enumerateNonUniformStep(
|
|
71
|
+
collapseDegenerateRange(
|
|
72
|
+
collapseOnceStep(collapseUnitStep(segment, spec), spec), spec),
|
|
73
|
+
spec, cycle);
|
|
74
|
+
}).join(',').split(',');
|
|
62
75
|
|
|
63
76
|
// A full-cycle segment covers the whole field.
|
|
64
77
|
if (segments.indexOf('*') !== -1) {
|
|
@@ -115,6 +128,41 @@ function collapseOnceStep(segment: string, spec: FieldSpec): string {
|
|
|
115
128
|
return start === '*' ? '' + spec.min : start;
|
|
116
129
|
}
|
|
117
130
|
|
|
131
|
+
// An unbounded step in a fixed-cycle time field is a true "every N" cadence
|
|
132
|
+
// only when it tiles the cycle: the interval divides it evenly and the start
|
|
133
|
+
// falls within the first interval (`*/15`, `5/6`). A step that fails either
|
|
134
|
+
// test fires at irregular points within the cycle, so it reads as the literal
|
|
135
|
+
// list of those fires (`*/7` is `0,7,14,…`), the same as if it were written
|
|
136
|
+
// out. Calendar fields (no `cycle`), bounded steps (`9-17/2`, a per-window
|
|
137
|
+
// stride), and non-step segments are left untouched.
|
|
138
|
+
function enumerateNonUniformStep(
|
|
139
|
+
segment: string,
|
|
140
|
+
spec: FieldSpec,
|
|
141
|
+
cycle: number | undefined
|
|
142
|
+
): string {
|
|
143
|
+
const parts = segment.split('/');
|
|
144
|
+
|
|
145
|
+
if (typeof cycle !== 'number' || parts.length !== 2 ||
|
|
146
|
+
includes(parts[0], '-')) {
|
|
147
|
+
return segment;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const interval = +parts[1];
|
|
151
|
+
const start = parts[0] === '*' ? spec.min : toFieldNumber(parts[0]);
|
|
152
|
+
|
|
153
|
+
if (cycle % interval === 0 && start < interval) {
|
|
154
|
+
return segment;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const fires = [];
|
|
158
|
+
|
|
159
|
+
for (let value = start; value <= (spec.top as number); value += interval) {
|
|
160
|
+
fires.push(value);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return fires.join(',');
|
|
164
|
+
}
|
|
165
|
+
|
|
118
166
|
// A degenerate range (`9-9`) fires once, so it reads as its single value.
|
|
119
167
|
// A stepped degenerate range (`9-9/5`) likewise fires only at its start.
|
|
120
168
|
function collapseDegenerateRange(segment: string, spec: FieldSpec): string {
|
package/src/lang/de/index.ts
CHANGED
|
@@ -462,7 +462,9 @@ function duringHours(ir: IR, times: HourTimesPlan, sep: string): string {
|
|
|
462
462
|
return joinList(windows);
|
|
463
463
|
}
|
|
464
464
|
|
|
465
|
-
|
|
465
|
+
// A discrete set of hours is a list, not a range, so it takes no "von"
|
|
466
|
+
// (which would read as "von X bis Y"); it mirrors the minute list form.
|
|
467
|
+
return 'in den Stunden ' + joinList(times.fires.map(String)) + ' Uhr';
|
|
466
468
|
}
|
|
467
469
|
|
|
468
470
|
// --- Renderers. ---
|
|
@@ -818,7 +820,10 @@ const de: Language<GermanStyle> = {
|
|
|
818
820
|
fallback: 'ein unlesbares Cron-Muster',
|
|
819
821
|
options: normalizeOptions,
|
|
820
822
|
reboot: 'beim Systemstart',
|
|
821
|
-
|
|
823
|
+
// A description ending in a German ordinal already carries its period
|
|
824
|
+
// ("…am 8."), so closing the sentence must not double it.
|
|
825
|
+
sentence: (description) =>
|
|
826
|
+
'Läuft ' + description + (description.endsWith('.') ? '' : '.')
|
|
822
827
|
};
|
|
823
828
|
|
|
824
829
|
export default de;
|
package/src/lang/en/index.ts
CHANGED
|
@@ -547,7 +547,10 @@ const renderers = {
|
|
|
547
547
|
// Phrase a `start/interval` step segment for a field that cycles every 60
|
|
548
548
|
// units (seconds and minutes). `unit` is the singular noun and `anchor` is
|
|
549
549
|
// the larger unit the values are counted against. Interval-one steps never
|
|
550
|
-
// arrive here: normalization collapses them to ranges or `*`.
|
|
550
|
+
// arrive here: normalization collapses them to ranges or `*`. Nor do uneven
|
|
551
|
+
// steps that fail to tile the cycle: normalization rewrites those to the
|
|
552
|
+
// literal list of their fires, so only a clean cadence (interval dividing
|
|
553
|
+
// 60, start within the first interval) reaches a step renderer.
|
|
551
554
|
function stepCycle60(segment: StepSegment, unit: string,
|
|
552
555
|
anchor: string, opts: NormalizedOptions): string {
|
|
553
556
|
// A bounded start (`a-b/n`) applies the interval within the range.
|
|
@@ -559,6 +562,8 @@ function stepCycle60(segment: StepSegment, unit: string,
|
|
|
559
562
|
const interval = segment.interval;
|
|
560
563
|
|
|
561
564
|
if (start !== 0) {
|
|
565
|
+
// A short offset cadence lists its fires; a longer one names the
|
|
566
|
+
// interval and its starting offset ("every six minutes from five …").
|
|
562
567
|
if (segment.fires.length <= 3) {
|
|
563
568
|
return listPastThe(numberWords(segment.fires, opts), unit, anchor,
|
|
564
569
|
opts);
|
|
@@ -569,18 +574,8 @@ function stepCycle60(segment: StepSegment, unit: string,
|
|
|
569
574
|
' past the ' + anchor;
|
|
570
575
|
}
|
|
571
576
|
|
|
572
|
-
// A
|
|
573
|
-
|
|
574
|
-
if (60 % interval === 0) {
|
|
575
|
-
return 'every ' + getNumber(interval, opts) + ' ' + unit + 's';
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
if (segment.fires.length <= 2) {
|
|
579
|
-
return listPastThe(numberWords(segment.fires, opts), unit, anchor, opts);
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
return 'every ' + getNumber(interval, opts) + ' ' + unit +
|
|
583
|
-
's past the ' + anchor;
|
|
577
|
+
// A clean stride from the top of the cycle is the bare cadence.
|
|
578
|
+
return 'every ' + getNumber(interval, opts) + ' ' + unit + 's';
|
|
584
579
|
}
|
|
585
580
|
|
|
586
581
|
// Phrase a `start/interval` step segment for the hour field (cycles every
|
|
@@ -594,18 +589,18 @@ function stepHours(segment: StepSegment, opts: NormalizedOptions): string {
|
|
|
594
589
|
const start = segment.startToken === '*' ? 0 : +segment.startToken;
|
|
595
590
|
const interval = segment.interval;
|
|
596
591
|
|
|
597
|
-
|
|
592
|
+
// A clean stride from midnight is the bare cadence. (An uneven stride is
|
|
593
|
+
// rewritten to its fires upstream and never reaches here.)
|
|
594
|
+
if (start === 0) {
|
|
598
595
|
return 'every ' + getNumber(interval, opts) + ' hours';
|
|
599
596
|
}
|
|
600
597
|
|
|
598
|
+
// A short offset cadence lists its fires; a longer one names the interval
|
|
599
|
+
// and its start ("every three hours from 2 a.m.").
|
|
601
600
|
if (segment.fires.length <= 3) {
|
|
602
601
|
return 'at ' + hourTimes(segment.fires, opts);
|
|
603
602
|
}
|
|
604
603
|
|
|
605
|
-
if (start === 0) {
|
|
606
|
-
return 'every ' + getNumber(interval, opts) + ' hours from midnight';
|
|
607
|
-
}
|
|
608
|
-
|
|
609
604
|
return 'every ' + getNumber(interval, opts) + ' hours from ' +
|
|
610
605
|
getTime({hour: start, minute: 0}, opts);
|
|
611
606
|
}
|
package/src/lang/es/index.ts
CHANGED
|
@@ -1015,17 +1015,9 @@ function stepCycle60(
|
|
|
1015
1015
|
unit + ' ' + start + ' de cada ' + anchor;
|
|
1016
1016
|
}
|
|
1017
1017
|
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
if (segment.fires.length <= 2) {
|
|
1023
|
-
return 'en los ' + unit + 's ' + joinList(wordList(segment.fires)) +
|
|
1024
|
-
' de cada ' + anchor;
|
|
1025
|
-
}
|
|
1026
|
-
|
|
1027
|
-
return 'cada ' + numero(interval, opts) + ' ' + unit + 's de cada ' +
|
|
1028
|
-
anchor;
|
|
1018
|
+
// A clean stride from the top of the cycle is the bare cadence. (An uneven
|
|
1019
|
+
// stride is rewritten to its fires upstream and never reaches here.)
|
|
1020
|
+
return 'cada ' + numero(interval, opts) + ' ' + unit + 's';
|
|
1029
1021
|
}
|
|
1030
1022
|
|
|
1031
1023
|
// "cada seis horas", "a las 9:00, a las 11:00 y a la 1:00", or "cada
|
|
@@ -1038,7 +1030,9 @@ function stepHours(segment: StepSegment, opts: Opts): string {
|
|
|
1038
1030
|
const start = segment.startToken === '*' ? 0 : +segment.startToken;
|
|
1039
1031
|
const interval = segment.interval;
|
|
1040
1032
|
|
|
1041
|
-
|
|
1033
|
+
// A clean stride from midnight is the bare cadence. (An uneven stride is
|
|
1034
|
+
// rewritten to its fires upstream and never reaches here.)
|
|
1035
|
+
if (start === 0) {
|
|
1042
1036
|
return 'cada ' + numero(interval, opts) + ' horas';
|
|
1043
1037
|
}
|
|
1044
1038
|
|
|
@@ -1046,10 +1040,6 @@ function stepHours(segment: StepSegment, opts: Opts): string {
|
|
|
1046
1040
|
return groupClockTimesByArticle(atTimes(segment.fires, opts));
|
|
1047
1041
|
}
|
|
1048
1042
|
|
|
1049
|
-
if (start === 0) {
|
|
1050
|
-
return 'cada ' + numero(interval, opts) + ' horas desde medianoche';
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
1043
|
return 'cada ' + numero(interval, opts) + ' horas a partir de ' +
|
|
1054
1044
|
timePhrase(start, 0, null, opts);
|
|
1055
1045
|
}
|
package/src/lang/fi/index.ts
CHANGED
|
@@ -62,7 +62,6 @@ interface UnitForms {
|
|
|
62
62
|
anchor: string;
|
|
63
63
|
ela: string;
|
|
64
64
|
gen: string;
|
|
65
|
-
restart: string;
|
|
66
65
|
}
|
|
67
66
|
|
|
68
67
|
// Genitive numerals for the "N <unit>in välein" construction, spelled
|
|
@@ -179,15 +178,13 @@ const units: {minute: UnitForms; second: UnitForms} = {
|
|
|
179
178
|
mark: 'joka tunti',
|
|
180
179
|
anchor: 'jokaisen tunnin',
|
|
181
180
|
ela: 'minuutista',
|
|
182
|
-
gen: 'minuutin'
|
|
183
|
-
restart: 'tasatunnista alkaen'
|
|
181
|
+
gen: 'minuutin'
|
|
184
182
|
},
|
|
185
183
|
second: {
|
|
186
184
|
mark: 'joka minuutti',
|
|
187
185
|
anchor: 'jokaisen minuutin',
|
|
188
186
|
ela: 'sekunnista',
|
|
189
|
-
gen: 'sekunnin'
|
|
190
|
-
restart: 'joka minuutti'
|
|
187
|
+
gen: 'sekunnin'
|
|
191
188
|
}
|
|
192
189
|
};
|
|
193
190
|
|
|
@@ -858,15 +855,9 @@ function stepCycle60(
|
|
|
858
855
|
' alkaen';
|
|
859
856
|
}
|
|
860
857
|
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
if (segment.fires.length <= 2) {
|
|
866
|
-
return atMarks(joinList(wordList(segment.fires)), unit, true);
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
return cadence + ' ' + unit.restart;
|
|
858
|
+
// A clean stride from the top of the cycle is the bare cadence. (An uneven
|
|
859
|
+
// stride is rewritten to its fires upstream and never reaches here.)
|
|
860
|
+
return cadence;
|
|
870
861
|
}
|
|
871
862
|
|
|
872
863
|
// "kahden tunnin välein", "klo 0, 10 ja 20", or "viiden tunnin välein
|
|
@@ -880,7 +871,9 @@ function stepHours(segment: StepSegment, opts: NormalizedOptions): string {
|
|
|
880
871
|
const interval = segment.interval;
|
|
881
872
|
const cadence = genitive(interval, opts) + ' tunnin välein';
|
|
882
873
|
|
|
883
|
-
|
|
874
|
+
// A clean stride from midnight is the bare cadence. (An uneven stride is
|
|
875
|
+
// rewritten to its fires upstream and never reaches here.)
|
|
876
|
+
if (start === 0) {
|
|
884
877
|
return cadence;
|
|
885
878
|
}
|
|
886
879
|
|
|
@@ -888,10 +881,6 @@ function stepHours(segment: StepSegment, opts: NormalizedOptions): string {
|
|
|
888
881
|
return kloList(segment.fires, opts);
|
|
889
882
|
}
|
|
890
883
|
|
|
891
|
-
if (start === 0) {
|
|
892
|
-
return cadence + ' keskiyöstä alkaen';
|
|
893
|
-
}
|
|
894
|
-
|
|
895
884
|
return cadence + ' klo ' + hourElatives[start] + ' alkaen';
|
|
896
885
|
}
|
|
897
886
|
|
package/src/lang/zh/index.ts
CHANGED
|
@@ -217,7 +217,12 @@ function hourFrame(ir: IR): string {
|
|
|
217
217
|
|
|
218
218
|
// A repeating minute step, optionally confined to active hours.
|
|
219
219
|
function renderMinuteFrequency(ir: IR, plan: PlanNode): string {
|
|
220
|
-
const
|
|
220
|
+
const minuteStep = stepSegment(ir, 'minute');
|
|
221
|
+
// A "每N分钟" cadence is only faithful from the top of the hour; an offset
|
|
222
|
+
// step (5/6 fires at :05,:11,…) enumerates its fires instead.
|
|
223
|
+
const base = minuteStep.startToken === '*' ?
|
|
224
|
+
cadence(minuteStep.interval, UNITS.minute) :
|
|
225
|
+
renderMinutePast(ir);
|
|
221
226
|
const {hours} = plan as Extract<PlanNode, {kind: 'minuteFrequency'}>;
|
|
222
227
|
|
|
223
228
|
if (hours.kind === 'step') {
|
|
@@ -323,8 +328,9 @@ function renderHourRange(ir: IR, plan: PlanNode): string {
|
|
|
323
328
|
range.last + '分之间,每分钟';
|
|
324
329
|
}
|
|
325
330
|
|
|
326
|
-
// A stepped hour field: "每2小时", or
|
|
327
|
-
//
|
|
331
|
+
// A stepped hour field: "每2小时", or its two fires as clock words when the
|
|
332
|
+
// stride fires only twice. An uneven stride (one that does not divide 24) is
|
|
333
|
+
// rewritten to its fire list upstream and never reaches here.
|
|
328
334
|
function renderHourStep(ir: IR): string {
|
|
329
335
|
const segment = stepSegment(ir, 'hour');
|
|
330
336
|
|
|
@@ -332,16 +338,11 @@ function renderHourStep(ir: IR): string {
|
|
|
332
338
|
return hourList(ir);
|
|
333
339
|
}
|
|
334
340
|
|
|
335
|
-
// A step that fires only twice reads as two clock times ("凌晨0
|
|
341
|
+
// A step that fires only twice reads as two clock times ("凌晨0点和正午").
|
|
336
342
|
if (segment.fires.length <= 2) {
|
|
337
343
|
return joinAnd(segment.fires.map(hourWord));
|
|
338
344
|
}
|
|
339
345
|
|
|
340
|
-
if (24 % segment.interval !== 0) {
|
|
341
|
-
return '从' + hourWord(segment.fires[0]) + '起,' +
|
|
342
|
-
cadence(segment.interval, UNITS.hour);
|
|
343
|
-
}
|
|
344
|
-
|
|
345
346
|
return cadence(segment.interval, UNITS.hour);
|
|
346
347
|
}
|
|
347
348
|
|