commit aee6466a5e0bf911c9943ed55af653f18ad053b0 Author: Raoul Date: Mon Jan 8 21:32:04 2024 +0100 Huginfo DGWK 2024 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6a426b1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +# Hugo +.hugo_build.lock +/public/ +/resources/_gen/ +/assets/jsconfig.json + +# Backup files +*~ diff --git a/assets/css/custom/core/_index.scss b/assets/css/custom/core/_index.scss new file mode 100644 index 0000000..a655765 --- /dev/null +++ b/assets/css/custom/core/_index.scss @@ -0,0 +1,93 @@ +@import "../../fonts/fonts"; +@import "../styles/_variables"; + +* { + box-sizing: border-box; +} + +body { + margin: 0px; + padding: 0px; + color: white; + background: rgb(80,80,80); +} + +.header { + margin: 0px; + + padding-left: 60px; + padding-top: 30px; + padding-bottom: 30px; + + margin-bottom: 40px; + + // color: lavender; + // background: cornflowerblue; + // border-bottom: 12px solid royalblue; + + // color: white; + // background: #217867; + // border-bottom: 12px solid #165044; + + color: white; + background: mediumseagreen; + border-bottom: 12px solid seagreen; + + font-family: 'Permanent Marker'; + font-size: 5em; + font-weight: 400; +} + +.content { + margin-left: 60px; + + h2 { + margin-bottom: 10px; + + font-family: 'Architects Daughter'; + font-size: 2em; + font-weight: 400; + } + + ul { + list-style: none; + } + + .infopointitem { + padding-bottom: 5px; + line-height: 20px; + + // white-space: nowrap; + + display: flex; + } + + .bullet { + padding-right: 0.5em; + } + + // ul li::before { + // content: "-> "; + // } + + .infopoint { + padding-left: 0.5em; + text-decoration: none; + + // color: #ff6600; + color: mediumaquamarine; + + &:hover { + // color: #d45500; + color: aquamarine; + } + } + + .redirect { + font-size: 0.8rem; + + li { + padding: 0px; + } + } +} diff --git a/assets/css/custom/nodes/default.scss b/assets/css/custom/nodes/default.scss new file mode 100644 index 0000000..0771b98 --- /dev/null +++ b/assets/css/custom/nodes/default.scss @@ -0,0 +1 @@ +@import "../styles/_base"; diff --git a/assets/css/custom/nodes/schedule-hall1.scss b/assets/css/custom/nodes/schedule-hall1.scss new file mode 100644 index 0000000..7c189d7 --- /dev/null +++ b/assets/css/custom/nodes/schedule-hall1.scss @@ -0,0 +1,5 @@ +@import "../styles/_base"; + +@import "../styles/_logo"; +@import "../styles/_schedule"; +@import "../styles/_clock"; diff --git a/assets/css/custom/nodes/schedule-hall2.scss b/assets/css/custom/nodes/schedule-hall2.scss new file mode 100644 index 0000000..7c189d7 --- /dev/null +++ b/assets/css/custom/nodes/schedule-hall2.scss @@ -0,0 +1,5 @@ +@import "../styles/_base"; + +@import "../styles/_logo"; +@import "../styles/_schedule"; +@import "../styles/_clock"; diff --git a/assets/css/custom/nodes/schedule-hall3.scss b/assets/css/custom/nodes/schedule-hall3.scss new file mode 100644 index 0000000..7c189d7 --- /dev/null +++ b/assets/css/custom/nodes/schedule-hall3.scss @@ -0,0 +1,5 @@ +@import "../styles/_base"; + +@import "../styles/_logo"; +@import "../styles/_schedule"; +@import "../styles/_clock"; diff --git a/assets/css/custom/nodes/schedule.scss b/assets/css/custom/nodes/schedule.scss new file mode 100644 index 0000000..7c189d7 --- /dev/null +++ b/assets/css/custom/nodes/schedule.scss @@ -0,0 +1,5 @@ +@import "../styles/_base"; + +@import "../styles/_logo"; +@import "../styles/_schedule"; +@import "../styles/_clock"; diff --git a/assets/css/custom/nodes/speaker-info-hall1.scss b/assets/css/custom/nodes/speaker-info-hall1.scss new file mode 100644 index 0000000..83cb99b --- /dev/null +++ b/assets/css/custom/nodes/speaker-info-hall1.scss @@ -0,0 +1,3 @@ +@import "../styles/_base"; + +@import "../styles/_banner-speaker"; diff --git a/assets/css/custom/nodes/speaker-info-hall2.scss b/assets/css/custom/nodes/speaker-info-hall2.scss new file mode 100644 index 0000000..83cb99b --- /dev/null +++ b/assets/css/custom/nodes/speaker-info-hall2.scss @@ -0,0 +1,3 @@ +@import "../styles/_base"; + +@import "../styles/_banner-speaker"; diff --git a/assets/css/custom/nodes/speaker-info-hall3.scss b/assets/css/custom/nodes/speaker-info-hall3.scss new file mode 100644 index 0000000..83cb99b --- /dev/null +++ b/assets/css/custom/nodes/speaker-info-hall3.scss @@ -0,0 +1,3 @@ +@import "../styles/_base"; + +@import "../styles/_banner-speaker"; diff --git a/assets/css/custom/nodes/talk-info-hall1.scss b/assets/css/custom/nodes/talk-info-hall1.scss new file mode 100644 index 0000000..44868c1 --- /dev/null +++ b/assets/css/custom/nodes/talk-info-hall1.scss @@ -0,0 +1,3 @@ +@import "../styles/_base"; + +@import "../styles/_banner-talk"; diff --git a/assets/css/custom/nodes/talk-info-hall2.scss b/assets/css/custom/nodes/talk-info-hall2.scss new file mode 100644 index 0000000..44868c1 --- /dev/null +++ b/assets/css/custom/nodes/talk-info-hall2.scss @@ -0,0 +1,3 @@ +@import "../styles/_base"; + +@import "../styles/_banner-talk"; diff --git a/assets/css/custom/nodes/talk-info-hall3.scss b/assets/css/custom/nodes/talk-info-hall3.scss new file mode 100644 index 0000000..44868c1 --- /dev/null +++ b/assets/css/custom/nodes/talk-info-hall3.scss @@ -0,0 +1,3 @@ +@import "../styles/_base"; + +@import "../styles/_banner-talk"; diff --git a/assets/css/custom/nodes/upcoming-talk-hall1.scss b/assets/css/custom/nodes/upcoming-talk-hall1.scss new file mode 100644 index 0000000..4b7a75d --- /dev/null +++ b/assets/css/custom/nodes/upcoming-talk-hall1.scss @@ -0,0 +1,4 @@ +@import "../styles/_base"; + +@import "../styles/_logo"; +@import "../styles/_upcoming-talk"; diff --git a/assets/css/custom/nodes/upcoming-talk-hall2.scss b/assets/css/custom/nodes/upcoming-talk-hall2.scss new file mode 100644 index 0000000..4b7a75d --- /dev/null +++ b/assets/css/custom/nodes/upcoming-talk-hall2.scss @@ -0,0 +1,4 @@ +@import "../styles/_base"; + +@import "../styles/_logo"; +@import "../styles/_upcoming-talk"; diff --git a/assets/css/custom/nodes/upcoming-talk-hall3.scss b/assets/css/custom/nodes/upcoming-talk-hall3.scss new file mode 100644 index 0000000..4b7a75d --- /dev/null +++ b/assets/css/custom/nodes/upcoming-talk-hall3.scss @@ -0,0 +1,4 @@ +@import "../styles/_base"; + +@import "../styles/_logo"; +@import "../styles/_upcoming-talk"; diff --git a/assets/css/custom/nodes/voc-schedule.scss b/assets/css/custom/nodes/voc-schedule.scss new file mode 100644 index 0000000..ab96778 --- /dev/null +++ b/assets/css/custom/nodes/voc-schedule.scss @@ -0,0 +1,3 @@ +@import "../styles/_base"; + +@import "../styles/_voc-schedule"; diff --git a/assets/css/custom/nodes/voc-speaker.scss b/assets/css/custom/nodes/voc-speaker.scss new file mode 100644 index 0000000..830be5d --- /dev/null +++ b/assets/css/custom/nodes/voc-speaker.scss @@ -0,0 +1,3 @@ +@import "../styles/_base"; + +@import "../styles/_voc-speaker"; diff --git a/assets/css/custom/nodes/voc-talks.scss b/assets/css/custom/nodes/voc-talks.scss new file mode 100644 index 0000000..ca4a3c1 --- /dev/null +++ b/assets/css/custom/nodes/voc-talks.scss @@ -0,0 +1,3 @@ +@import "../styles/_base"; + +@import "../styles/_voc-talks"; diff --git a/assets/css/custom/styles/_banner-speaker.scss b/assets/css/custom/styles/_banner-speaker.scss new file mode 100644 index 0000000..a0cf4cc --- /dev/null +++ b/assets/css/custom/styles/_banner-speaker.scss @@ -0,0 +1,70 @@ +@import "_variables"; +@import "_base"; + +.slide { + background-color: $color-bg; +} + +.speaker-box { + // position: absolute; + position: relative; + // top: 963px; + // top: 975px; + // top: 947px; + top: 910px; + + // left: 50px; + left: 150px; + + width: auto; + + // max-width: 1350px; + // max-width: 1400px; + max-width: 1600px; +} + +.speaker { + // background-color: $color-ci-gray; + // background-color: $color-ci-lightgreen; + background-color: $color-ci-darkgreen; + + // border-width: 5px; + // border-style: solid; + // border-color: $color-ci-lightgreen; + + // box-shadow: 0px 0px 5px 5px rgba(0,0,0,0.2); + box-shadow: 8px 6px 0px $color-bg; + + // vertical-align: middle; + white-space: normal; + + // padding: 10px 15px; + padding: 5px 15px; + + font-family: 'Lato'; + font-weight: 700; + font-size: 60px; +} + +.speaker .title { + // color: $color-ci-lightgreen; +} + +.speaker .names { + display: -webkit-box; + -webkit-line-clamp: 1; + box-orient: vertical; + -webkit-box-orient: vertical; + + overflow: hidden; + text-overflow: ellipsis; + + white-space: normal; +} + +img { + display: none; + position: absolute; + top: 0; + left: 0; +} diff --git a/assets/css/custom/styles/_banner-talk.scss b/assets/css/custom/styles/_banner-talk.scss new file mode 100644 index 0000000..407fb4a --- /dev/null +++ b/assets/css/custom/styles/_banner-talk.scss @@ -0,0 +1,84 @@ +@import "_variables"; +@import "_base"; + +.slide { + background-color: $color-bg; +} + +.talk-box { + // position: absolute; + position: relative; + top: 975px; + // left: 50px; + left: 100px; + + width: auto; + + // max-width: 1350px; + max-width: 1400px; +} + +.talk { + background-color: $color-ci-gray; + background-color: $color-ci-lightgreen; + // background-color: $color-ci-darkgreen; + + // border-width: 5px; + // border-style: solid; + // border-color: $color-ci-lightgreen; + + // box-shadow: 0px 0px 5px 5px rgba(0,0,0,0.2); + + // vertical-align: middle; + white-space: normal; + + // padding: 10px 15px; + padding: 5px 10px; + + font-family: 'Lato'; + font-weight: 400; +} + +.talk .title { + display: -webkit-box; + -webkit-line-clamp: 1; + box-orient: vertical; + -webkit-box-orient: vertical; + + overflow: hidden; + text-overflow: ellipsis; + + font-size: 25px; + + // color: $color-ci-lightgreen; + + &:before { + content: "«"; + padding: 0; + } + + &:after { + content: "»"; + padding: 0; + } +} + +.talk .names { + display: -webkit-box; + -webkit-line-clamp: 1; + box-orient: vertical; + -webkit-box-orient: vertical; + + overflow: hidden; + text-overflow: ellipsis; + + font-size: 23px; + font-style: italic; +} + +img { + display: none; + position: absolute; + top: 0; + left: 0; +} diff --git a/assets/css/custom/styles/_base.scss b/assets/css/custom/styles/_base.scss new file mode 100644 index 0000000..3b383ef --- /dev/null +++ b/assets/css/custom/styles/_base.scss @@ -0,0 +1,26 @@ +@import "../../fonts/fonts"; +@import "_variables"; + +* { + box-sizing: border-box; +} + +body { + color: rgb(255,255,255); + background: rgb(100,100,100); + margin: 0px; + padding: 0px; +} + +#main { + position: absolute; + top: 0px; + left: 0px; +} + +.slide { + position: relative; + width: $full-width; + height: $full-height; + overflow: hidden; +} diff --git a/assets/css/custom/styles/_clock.scss b/assets/css/custom/styles/_clock.scss new file mode 100644 index 0000000..91f4f3d --- /dev/null +++ b/assets/css/custom/styles/_clock.scss @@ -0,0 +1,23 @@ +#clock { + position: relative; + top: 0px; + left: 0px; + + width: $full-width; + height: $full-height; + overflow: hidden; + + z-index: 1000; +} + +.clock { + position: absolute; + + top: 240px; + // left: 1080px; + right: 655px; + + font-family: 'Source Code Pro'; + font-weight: 600; + font-size: 60px; +} diff --git a/assets/css/custom/styles/_logo-anim-darkgreen.scss b/assets/css/custom/styles/_logo-anim-darkgreen.scss new file mode 100644 index 0000000..5b7c0b8 --- /dev/null +++ b/assets/css/custom/styles/_logo-anim-darkgreen.scss @@ -0,0 +1,134 @@ +@keyframes logo-anim-darkgreen { + + 0.00% { + opacity: 0.5335; + } + + 3.12% { + opacity: 0.5133; + } + + 6.25% { + opacity: 0.5021; + } + + 9.38% { + opacity: 0.5005; + } + + 12.50% { + opacity: 0.5085; + } + + 15.62% { + opacity: 0.5258; + } + + 18.75% { + opacity: 0.5517; + } + + 21.88% { + opacity: 0.5852; + } + + 25.00% { + opacity: 0.6250; + } + + 28.12% { + opacity: 0.6696; + } + + 31.25% { + opacity: 0.7174; + } + + 34.38% { + opacity: 0.7664; + } + + 37.50% { + opacity: 0.8147; + } + + 40.62% { + opacity: 0.8606; + } + + 43.75% { + opacity: 0.9022; + } + + 46.88% { + opacity: 0.9380; + } + + 50.00% { + opacity: 0.9665; + } + + 53.12% { + opacity: 0.9867; + } + + 56.25% { + opacity: 0.9979; + } + + 59.38% { + opacity: 0.9995; + } + + 62.50% { + opacity: 0.9915; + } + + 65.62% { + opacity: 0.9742; + } + + 68.75% { + opacity: 0.9483; + } + + 71.88% { + opacity: 0.9148; + } + + 75.00% { + opacity: 0.8750; + } + + 78.12% { + opacity: 0.8304; + } + + 81.25% { + opacity: 0.7826; + } + + 84.38% { + opacity: 0.7336; + } + + 87.50% { + opacity: 0.6853; + } + + 90.62% { + opacity: 0.6394; + } + + 93.75% { + opacity: 0.5978; + } + + 96.88% { + opacity: 0.5620; + } + + 100.00% { + opacity: 0.5335; + } +} diff --git a/assets/css/custom/styles/_logo-anim-gray.scss b/assets/css/custom/styles/_logo-anim-gray.scss new file mode 100644 index 0000000..faaee4c --- /dev/null +++ b/assets/css/custom/styles/_logo-anim-gray.scss @@ -0,0 +1,134 @@ +@keyframes logo-anim-gray { + + 0.00% { + opacity: 0.7500; + } + + 3.12% { + opacity: 0.7988; + } + + 6.25% { + opacity: 0.8457; + } + + 9.38% { + opacity: 0.8889; + } + + 12.50% { + opacity: 0.9268; + } + + 15.62% { + opacity: 0.9579; + } + + 18.75% { + opacity: 0.9810; + } + + 21.88% { + opacity: 0.9952; + } + + 25.00% { + opacity: 1.0000; + } + + 28.12% { + opacity: 0.9952; + } + + 31.25% { + opacity: 0.9810; + } + + 34.38% { + opacity: 0.9579; + } + + 37.50% { + opacity: 0.9268; + } + + 40.62% { + opacity: 0.8889; + } + + 43.75% { + opacity: 0.8457; + } + + 46.88% { + opacity: 0.7988; + } + + 50.00% { + opacity: 0.7500; + } + + 53.12% { + opacity: 0.7012; + } + + 56.25% { + opacity: 0.6543; + } + + 59.38% { + opacity: 0.6111; + } + + 62.50% { + opacity: 0.5732; + } + + 65.62% { + opacity: 0.5421; + } + + 68.75% { + opacity: 0.5190; + } + + 71.88% { + opacity: 0.5048; + } + + 75.00% { + opacity: 0.5000; + } + + 78.12% { + opacity: 0.5048; + } + + 81.25% { + opacity: 0.5190; + } + + 84.38% { + opacity: 0.5421; + } + + 87.50% { + opacity: 0.5732; + } + + 90.62% { + opacity: 0.6111; + } + + 93.75% { + opacity: 0.6543; + } + + 96.88% { + opacity: 0.7012; + } + + 100.00% { + opacity: 0.7500; + } +} diff --git a/assets/css/custom/styles/_logo-anim-lightgreen.scss b/assets/css/custom/styles/_logo-anim-lightgreen.scss new file mode 100644 index 0000000..82a488f --- /dev/null +++ b/assets/css/custom/styles/_logo-anim-lightgreen.scss @@ -0,0 +1,134 @@ +@keyframes logo-anim-lightgreen { + + 0.00% { + opacity: 0.9665; + } + + 3.12% { + opacity: 0.9380; + } + + 6.25% { + opacity: 0.9022; + } + + 9.38% { + opacity: 0.8606; + } + + 12.50% { + opacity: 0.8147; + } + + 15.62% { + opacity: 0.7664; + } + + 18.75% { + opacity: 0.7174; + } + + 21.88% { + opacity: 0.6696; + } + + 25.00% { + opacity: 0.6250; + } + + 28.12% { + opacity: 0.5852; + } + + 31.25% { + opacity: 0.5517; + } + + 34.38% { + opacity: 0.5258; + } + + 37.50% { + opacity: 0.5085; + } + + 40.62% { + opacity: 0.5005; + } + + 43.75% { + opacity: 0.5021; + } + + 46.88% { + opacity: 0.5133; + } + + 50.00% { + opacity: 0.5335; + } + + 53.12% { + opacity: 0.5620; + } + + 56.25% { + opacity: 0.5978; + } + + 59.38% { + opacity: 0.6394; + } + + 62.50% { + opacity: 0.6853; + } + + 65.62% { + opacity: 0.7336; + } + + 68.75% { + opacity: 0.7826; + } + + 71.88% { + opacity: 0.8304; + } + + 75.00% { + opacity: 0.8750; + } + + 78.12% { + opacity: 0.9148; + } + + 81.25% { + opacity: 0.9483; + } + + 84.38% { + opacity: 0.9742; + } + + 87.50% { + opacity: 0.9915; + } + + 90.62% { + opacity: 0.9995; + } + + 93.75% { + opacity: 0.9979; + } + + 96.88% { + opacity: 0.9867; + } + + 100.00% { + opacity: 0.9665; + } +} diff --git a/assets/css/custom/styles/_logo.scss b/assets/css/custom/styles/_logo.scss new file mode 100644 index 0000000..248003e --- /dev/null +++ b/assets/css/custom/styles/_logo.scss @@ -0,0 +1,38 @@ +@import "_logo-anim-gray"; +@import "_logo-anim-lightgreen"; +@import "_logo-anim-darkgreen"; + +.logo-box { + position: absolute; + top: 20px; + left: 1300px; + + width: 190px; + height: 190px; + overflow: hidden; + + z-index: 2000; +} + +.logo { + position: absolute; + + top: 0px; + right: 0px; + + animation-duration: 10s; + animation-iteration-count: infinite; + animation-timing-function: linear; +} + +.logo-gray { + animation-name: logo-anim-gray; +} + +.logo-lightgreen { + animation-name: logo-anim-lightgreen; +} + +.logo-darkgreen { + animation-name: logo-anim-darkgreen; +} diff --git a/assets/css/custom/styles/_music.scss b/assets/css/custom/styles/_music.scss new file mode 100644 index 0000000..e11863a --- /dev/null +++ b/assets/css/custom/styles/_music.scss @@ -0,0 +1,38 @@ +.music-info { + font-family: 'Lato'; + font-weight: 400; + font-size: 22px; + // background-color: magenta; +} + +.music-track { + padding-left: 0.5em; + padding-right: 0.5em; + font-style: italic; + &:before { + content: "«"; + padding: 0; + } + &:after { + content: "»"; + padding: 0; + } +} + +.music-artist { + padding-left: 0.5em; + padding-right: 3em; + font-weight: 700; +} + +.music-licence { + padding-left: 0.5em; + padding-right: 3em; +} + +.music-link { + padding-left: 0.5em; + font-family: 'Source Code Pro'; + font-weight: 400; + font-size: 20px; +} diff --git a/assets/css/custom/styles/_schedule.scss b/assets/css/custom/styles/_schedule.scss new file mode 100644 index 0000000..b6e1a00 --- /dev/null +++ b/assets/css/custom/styles/_schedule.scss @@ -0,0 +1,213 @@ +@import "_variables"; +@import "_base"; +@import "_music"; + + +.slide { + background-color: $color-bg; +} + + +.header { + position: absolute; + top: 0; + left: 0; + z-index: 10; +} + + +.room-location { + position: absolute; + // top: 240px; + top: 255px; + right: 65px; + + z-index: 20; + + font-family: 'Source Code Pro'; + font-weight: 700; + font-size: 40px; + + text-align: end; + color: khaki; + + // box-align: center; + // -moz-box-align: center; + // -webkit-box-align: center; + + // background-color: purple; +} + +.schedule { + position: absolute; + top: 240px; + left: 65px; + // left: 50px; + + /* 1920 - 2 * 65 */ + width: 1790px; + /* 1920 - 2 * 50 */ + // width: 1820px; + + // background-color: orange; +} + +.schedule .title { + // position: static; + + font-family: 'Source Code Pro'; + font-weight: 700; + font-size: 60px; + + //text-align: bottom; +} + + +.events { + position: absolute; + top: 340px; + left: 65px; + + width: 1790px; + // width: 1820px; + // 5 * 110 + 4 * 25 + height: 650px; + + overflow: hidden; + // background-color: red; +} + +.event { + position: relative; + // left: 0px; + + margin-bottom: 25px; + width: 100%; + + // overflow: hidden; + // background-color: teal; +} + +.event-time { + position: absolute; + // top: 0; + left: 0px; + + font-family: 'Source Code Pro'; + font-weight: 400; + font-size: 50px; + + // background-color: crimson; + // max-width: 50px; +} + +.event-location { + position: absolute; + left: 200px; + + font-family: 'Lato'; + font-weight: 400; + font-size: 50px; + + // width: 100px; + // max-width: 100px; + // background-color: purple; +} + +.this-room { + font-style: italic; + color: khaki; +} + + + +.event-info { + position: relative; + // left: 550px; + // width: 1240px; + left: 520px; + width: 1270px; + // width: 1280px; + + overflow: hidden; + text-overflow: ellipsis; + white-space: normal; + + // word-break: break-all; + // overflow-wrap: break-word; + + font-family: 'Lato'; + font-weight: 400; + font-size: 50px; + + // max-width: 100px; + // background-color: dodgerblue; +} + +.event-title { + display: -webkit-box; + -webkit-line-clamp: 1; + // -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + + overflow: hidden; + text-overflow: ellipsis; +} + +.event-speaker { + display: -webkit-box; + -webkit-line-clamp: 1; + // -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + + overflow: hidden; + text-overflow: ellipsis; + + font-style: italic; + font-size: 40px; +} + + +.footer { + position: absolute; + left: 65px; + bottom: 0px; + + width: 1790px; + // height: 65px; +} + +.track-info { + display: flex; + flex-direction: row; + justify-content: space-between; + // justify-content: space-around; + + margin-bottom: 10px; + + font-family: 'Source Code Pro'; + font-weight: 600; + font-size: 22px; + + // background-color: chartreuse; +} + +.track { + // background-color: lightblue; +} + +.track-1 { + color: #40a56a; +} + +.track-2 { + color: #ffc91a; +} + +.track-3 { + color: #d92635; +} + +.track-4 { + color: #3caec3; +} diff --git a/assets/css/custom/styles/_upcoming-talk.scss b/assets/css/custom/styles/_upcoming-talk.scss new file mode 100644 index 0000000..ae20059 --- /dev/null +++ b/assets/css/custom/styles/_upcoming-talk.scss @@ -0,0 +1,254 @@ +@import "_variables"; +@import "_base"; +@import "_music"; + + +.header { + position: absolute; + top: 0; + left: 0; + z-index: 10; +} + + +.slide { + background-color: $color-bg; +} + + +.upper { + position: absolute; + left: 200px; + top: 240px; + + width: 1520px; + height: 250px; + + overflow: hidden; +} + +.lower { + position: absolute; + top: 540px; + left: 200px; + + width: 1520px; + height: 490px; + + overflow: hidden; + + background-color: $color-ci-darkgreen; +} + + +.event-meta { + height: 250px; + + background-color: $color-ci-lightgreen; + + font-family: 'Lato'; + font-weight: 600; + font-size: 50px; + + overflow: hidden; + text-overflow: ellipsis; + white-space: normal; +} + +.title { + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + + overflow: hidden; + text-overflow: ellipsis; + + padding: 0px 100px; + + + + text-align: center; +} + +.subtitle { + display: none; +} + +.speakers { + display: -webkit-box; + -webkit-line-clamp: 1; + -webkit-box-orient: vertical; + + overflow: hidden; + text-overflow: ellipsis; + + padding-top: 10px; + padding-left: 15px; + + font-weight: 400; + font-style: italic; + font-size: 30px; + + margin-bottom: 20px; +} + +.starttime { + position: absolute; + right: 0px; + bottom: 0px; + + padding-bottom: 15px; + padding-right: 25px; + + font-family: 'Source Code Pro'; + font-weight: 500; + font-size: 30px; +} + + +.event-content { + position: absolute; + left: 0px; + + width: 735px; + hight: 490px; + + font-family: 'Lato'; + font-weight: 400; +} + +.event-description { +} + +.event-description-title { + padding-top: 10px; + padding-left: 15px; + + margin-bottom: 20px; + + font-size: 30px; +} + +.event-description-text { + height: 420px; + + display: -webkit-box; + -webkit-line-clamp: 14; + -webkit-box-orient: vertical; + + overflow: hidden; + text-overflow: ellipsis; + + padding-left: 50px; + padding-right: 50px; + + font-size: 25px; + + text-align: justify; + word-wrap: break-word; + word-break: break-word; + // word-break: break-all; + hyphens: auto; +} + + +.speaker-meta { + position: absolute; + right: 0px; + + width: 745px; + // width: 700px; + + padding-top: 15px; + padding-right: 15px; + + + // background-color: navy; +} + +.speaker-info { + margin-bottom: 20px; + + font-family: 'Lato'; + font-weight: 400; + font-size: 25px; + + // background-color: red; +} + +.speaker-name { + margin-bottom: 8px; + + font-style: italic; + // font-size: 25px; +} + +.speaker-bio { + padding-left: 30px; + // padding-right: 50px; + + font-size: 22px; + + text-align: justify; + word-wrap: break-word; + word-break: break-word; + // word-break: break-all; + hyphens: auto; + // font-size: 20px; +} + +.speaker-count-1 { + display: -webkit-box; + -webkit-line-clamp: 14; + -webkit-box-orient: vertical; + + overflow: hidden; + text-overflow: ellipsis; +} + +.speaker-count-2 { + display: -webkit-box; + -webkit-line-clamp: 6; + -webkit-box-orient: vertical; + + overflow: hidden; + text-overflow: ellipsis; +} + +.speaker-count-3 { + display: -webkit-box; + -webkit-line-clamp: 4; + -webkit-box-orient: vertical; + + overflow: hidden; + text-overflow: ellipsis; +} + +.speaker-count-4 { + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + + overflow: hidden; + text-overflow: ellipsis; +} + +.speaker-count-5 { + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-line-clamp: 7; + -webkit-box-orient: vertical; + + overflow: hidden; + text-overflow: ellipsis; +} + + +.footer { + position: absolute; + left: 200px; + bottom: 0px; + + width: 1520px; + // height: 65px; +} diff --git a/assets/css/custom/styles/_variables.scss b/assets/css/custom/styles/_variables.scss new file mode 100644 index 0000000..a75a719 --- /dev/null +++ b/assets/css/custom/styles/_variables.scss @@ -0,0 +1,38 @@ +$full-width: 1920px; +$full-height: 1080px; + +$color-bg: rgb(30, 30, 30); + +$color-ci-gray: rgb(101, 103, 103); +$color-ci-darkgreen: rgb(5, 114, 72); +$color-ci-lightgreen: rgb(0, 156, 71); + + + +// $margin-top: 30px; +// $margin-bottom: 50px; +// $margin-left: 60px; +// $margin-right: 60px; + +// $color-highlight1: #98adb0; +// $color-highlight1-header: #bdc7cc; +// $highlight1-gradient: linear-gradient(110deg, rgba(95, 124, 125, 0.6) 0%, rgba(33, 106, 99, 0.2) 85%, rgba(77,120,18,0) 100%); +// $highlight1-gradient2: linear-gradient(5deg, rgba(95,124,125,.5) 0%, rgba(33,106,99,.4) 42%, rgba(77,120,18,0) 65%, rgba(77,120,18,0) 100%); +// $highlight1-gradient-mirror: linear-gradient(290deg, rgba(95, 124, 125, 0.6) 0%, rgba(33, 106, 99, 0.2) 85%, rgba(77,120,18,0) 100%); + +// $color-highlight2: rgb(111, 173, 26); +// $highlight2-gradient: linear-gradient(110deg, rgba(77, 120, 18, 0.6) 0%, rgba(77, 120, 18, 0.2) 85%, rgba(77, 120, 18, 0) 100%); + +// $color-highlight3: chartreuse; +// $highlight3-gradient: linear-gradient(110deg, rgba(127, 255, 0, 0.6) 0%, rgba(127, 255, 0, 0.2) 85%, rgba(127, 255, 0, 0) 100%); + +// $color-highlight4: #475337; +// $highlight4-gradient: linear-gradient(110deg, rgba(72, 90, 48, 0.6) 0%, rgba(72, 90, 48, 0.2) 85%, rgba(72, 90, 48, 0) 100%); + +// $color-donot: crimson; + +// $color-background: rgba(0, 0, 0, 0.8); +// $color-background2: rgba(0, 0, 0, 0.3); + +// $headline-size: 45px; +// $headline-shadow: 1px 1px 1px black, 2px 2px 8px rgba(0,0,0,0.8); diff --git a/assets/css/custom/styles/_voc-schedule.scss b/assets/css/custom/styles/_voc-schedule.scss new file mode 100644 index 0000000..8761506 --- /dev/null +++ b/assets/css/custom/styles/_voc-schedule.scss @@ -0,0 +1,29 @@ +@import "_variables"; +@import "_base"; +@import "_voc"; + + +.speaker-cnt-1 { + color: lime; +} + +.speaker-cnt-2 { + color: yellow; +} + +.speaker-cnt-3 { + color: orangered; +} + +.speaker-cnt-many { + color: red; +} + + +.dnr-true { + color: crimson; +} + +.dnr-false { + color: chartreuse; +} diff --git a/assets/css/custom/styles/_voc-speaker.scss b/assets/css/custom/styles/_voc-speaker.scss new file mode 100644 index 0000000..91ade1a --- /dev/null +++ b/assets/css/custom/styles/_voc-speaker.scss @@ -0,0 +1,3 @@ +@import "_variables"; +@import "_base"; +@import "_voc"; diff --git a/assets/css/custom/styles/_voc-talks.scss b/assets/css/custom/styles/_voc-talks.scss new file mode 100644 index 0000000..91ade1a --- /dev/null +++ b/assets/css/custom/styles/_voc-talks.scss @@ -0,0 +1,3 @@ +@import "_variables"; +@import "_base"; +@import "_voc"; diff --git a/assets/css/custom/styles/_voc.scss b/assets/css/custom/styles/_voc.scss new file mode 100644 index 0000000..1084408 --- /dev/null +++ b/assets/css/custom/styles/_voc.scss @@ -0,0 +1,11 @@ +#main { + left: 20px; +} + +table { + border-spacing: 25px 2px; +} + +th { + text-align: left; +} diff --git a/assets/css/fonts/architects-daughter.css b/assets/css/fonts/architects-daughter.css new file mode 100644 index 0000000..cffeffb --- /dev/null +++ b/assets/css/fonts/architects-daughter.css @@ -0,0 +1,8 @@ +/* architects-daughter-regular - latin */ +@font-face { + font-family: 'Architects Daughter'; + font-style: normal; + font-weight: 400; + src: url('./fonts/architects-daughter-v11-latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/architects-daughter-v11-latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} diff --git a/assets/css/fonts/fonts.scss b/assets/css/fonts/fonts.scss new file mode 100644 index 0000000..d30b3f1 --- /dev/null +++ b/assets/css/fonts/fonts.scss @@ -0,0 +1,5 @@ +@import "permanent-marker"; +@import "architects-daughter"; + +@import "source-code-pro"; +@import "lato"; diff --git a/assets/css/fonts/lato.css b/assets/css/fonts/lato.css new file mode 100644 index 0000000..a5e076a --- /dev/null +++ b/assets/css/fonts/lato.css @@ -0,0 +1,89 @@ +/* lato-100 - latin-ext_latin */ +@font-face { + font-family: 'Lato'; + font-style: normal; + font-weight: 100; + src: url('./fonts/lato-v22-latin-ext_latin-100.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/lato-v22-latin-ext_latin-100.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* lato-300 - latin-ext_latin */ +@font-face { + font-family: 'Lato'; + font-style: normal; + font-weight: 300; + src: url('./fonts/lato-v22-latin-ext_latin-300.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/lato-v22-latin-ext_latin-300.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* lato-100italic - latin-ext_latin */ +@font-face { + font-family: 'Lato'; + font-style: italic; + font-weight: 100; + src: url('./fonts/lato-v22-latin-ext_latin-100italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/lato-v22-latin-ext_latin-100italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* lato-300italic - latin-ext_latin */ +@font-face { + font-family: 'Lato'; + font-style: italic; + font-weight: 300; + src: url('./fonts/lato-v22-latin-ext_latin-300italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/lato-v22-latin-ext_latin-300italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* lato-regular - latin-ext_latin */ +@font-face { + font-family: 'Lato'; + font-style: normal; + font-weight: 400; + src: url('./fonts/lato-v22-latin-ext_latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/lato-v22-latin-ext_latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* lato-italic - latin-ext_latin */ +@font-face { + font-family: 'Lato'; + font-style: italic; + font-weight: 400; + src: url('./fonts/lato-v22-latin-ext_latin-italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/lato-v22-latin-ext_latin-italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* lato-700 - latin-ext_latin */ +@font-face { + font-family: 'Lato'; + font-style: normal; + font-weight: 700; + src: url('./fonts/lato-v22-latin-ext_latin-700.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/lato-v22-latin-ext_latin-700.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* lato-700italic - latin-ext_latin */ +@font-face { + font-family: 'Lato'; + font-style: italic; + font-weight: 700; + src: url('./fonts/lato-v22-latin-ext_latin-700italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/lato-v22-latin-ext_latin-700italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* lato-900 - latin-ext_latin */ +@font-face { + font-family: 'Lato'; + font-style: normal; + font-weight: 900; + src: url('./fonts/lato-v22-latin-ext_latin-900.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/lato-v22-latin-ext_latin-900.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* lato-900italic - latin-ext_latin */ +@font-face { + font-family: 'Lato'; + font-style: italic; + font-weight: 900; + src: url('./fonts/lato-v22-latin-ext_latin-900italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/lato-v22-latin-ext_latin-900italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} diff --git a/assets/css/fonts/permanent-marker.css b/assets/css/fonts/permanent-marker.css new file mode 100644 index 0000000..88da917 --- /dev/null +++ b/assets/css/fonts/permanent-marker.css @@ -0,0 +1,7 @@ +@font-face { + font-family: 'Permanent Marker'; + font-style: normal; + font-weight: 400; + src: url('./fonts/permanent-marker-v10-latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/permanent-marker-v10-latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} diff --git a/assets/css/fonts/source-code-pro.css b/assets/css/fonts/source-code-pro.css new file mode 100644 index 0000000..c9c3285 --- /dev/null +++ b/assets/css/fonts/source-code-pro.css @@ -0,0 +1,143 @@ +/* source-code-pro-200 - latin-ext_latin */ +@font-face { + font-family: 'Source Code Pro'; + font-style: normal; + font-weight: 200; + src: url('./fonts/source-code-pro-v20-latin-ext_latin-200.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/source-code-pro-v20-latin-ext_latin-200.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* source-code-pro-300 - latin-ext_latin */ +@font-face { + font-family: 'Source Code Pro'; + font-style: normal; + font-weight: 300; + src: url('./fonts/source-code-pro-v20-latin-ext_latin-300.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/source-code-pro-v20-latin-ext_latin-300.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* source-code-pro-regular - latin-ext_latin */ +@font-face { + font-family: 'Source Code Pro'; + font-style: normal; + font-weight: 400; + src: url('./fonts/source-code-pro-v20-latin-ext_latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/source-code-pro-v20-latin-ext_latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* source-code-pro-500 - latin-ext_latin */ +@font-face { + font-family: 'Source Code Pro'; + font-style: normal; + font-weight: 500; + src: url('./fonts/source-code-pro-v20-latin-ext_latin-500.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/source-code-pro-v20-latin-ext_latin-500.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* source-code-pro-600 - latin-ext_latin */ +@font-face { + font-family: 'Source Code Pro'; + font-style: normal; + font-weight: 600; + src: url('./fonts/source-code-pro-v20-latin-ext_latin-600.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/source-code-pro-v20-latin-ext_latin-600.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* source-code-pro-700 - latin-ext_latin */ +@font-face { + font-family: 'Source Code Pro'; + font-style: normal; + font-weight: 700; + src: url('./fonts/source-code-pro-v20-latin-ext_latin-700.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/source-code-pro-v20-latin-ext_latin-700.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* source-code-pro-800 - latin-ext_latin */ +@font-face { + font-family: 'Source Code Pro'; + font-style: normal; + font-weight: 800; + src: url('./fonts/source-code-pro-v20-latin-ext_latin-800.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/source-code-pro-v20-latin-ext_latin-800.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* source-code-pro-900 - latin-ext_latin */ +@font-face { + font-family: 'Source Code Pro'; + font-style: normal; + font-weight: 900; + src: url('./fonts/source-code-pro-v20-latin-ext_latin-900.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/source-code-pro-v20-latin-ext_latin-900.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* source-code-pro-200italic - latin-ext_latin */ +@font-face { + font-family: 'Source Code Pro'; + font-style: italic; + font-weight: 200; + src: url('./fonts/source-code-pro-v20-latin-ext_latin-200italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/source-code-pro-v20-latin-ext_latin-200italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* source-code-pro-300italic - latin-ext_latin */ +@font-face { + font-family: 'Source Code Pro'; + font-style: italic; + font-weight: 300; + src: url('./fonts/source-code-pro-v20-latin-ext_latin-300italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/source-code-pro-v20-latin-ext_latin-300italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* source-code-pro-500italic - latin-ext_latin */ +@font-face { + font-family: 'Source Code Pro'; + font-style: italic; + font-weight: 500; + src: url('./fonts/source-code-pro-v20-latin-ext_latin-500italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/source-code-pro-v20-latin-ext_latin-500italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* source-code-pro-italic - latin-ext_latin */ +@font-face { + font-family: 'Source Code Pro'; + font-style: italic; + font-weight: 400; + src: url('./fonts/source-code-pro-v20-latin-ext_latin-italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/source-code-pro-v20-latin-ext_latin-italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* source-code-pro-600italic - latin-ext_latin */ +@font-face { + font-family: 'Source Code Pro'; + font-style: italic; + font-weight: 600; + src: url('./fonts/source-code-pro-v20-latin-ext_latin-600italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/source-code-pro-v20-latin-ext_latin-600italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* source-code-pro-700italic - latin-ext_latin */ +@font-face { + font-family: 'Source Code Pro'; + font-style: italic; + font-weight: 700; + src: url('./fonts/source-code-pro-v20-latin-ext_latin-700italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/source-code-pro-v20-latin-ext_latin-700italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* source-code-pro-800italic - latin-ext_latin */ +@font-face { + font-family: 'Source Code Pro'; + font-style: italic; + font-weight: 800; + src: url('./fonts/source-code-pro-v20-latin-ext_latin-800italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/source-code-pro-v20-latin-ext_latin-800italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* source-code-pro-900italic - latin-ext_latin */ +@font-face { + font-family: 'Source Code Pro'; + font-style: italic; + font-weight: 900; + src: url('./fonts/source-code-pro-v20-latin-ext_latin-900italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./fonts/source-code-pro-v20-latin-ext_latin-900italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} diff --git a/assets/js/custom/core/config.js b/assets/js/custom/core/config.js new file mode 100644 index 0000000..a003304 --- /dev/null +++ b/assets/js/custom/core/config.js @@ -0,0 +1,23 @@ +import * as params from '@params'; + +// Values injected from Hugo configuration +window.infoBeamerConfig = new Map(); +window.infoBeamerConfig.set('workerBaseURL', params.workerBaseURL); + +window.infoBeamerConfig.set('scheduleURL', params.scheduleURL); +window.infoBeamerConfig.set('scheduleFetchInterval', params.scheduleFetchInterval); + +window.infoBeamerConfig.set('twitterURL', params.twitterURL); +window.infoBeamerConfig.set('twitterFetchInterval', params.twitterFetchInterval); + +window.infoBeamerConfig.set('mastodonURL', params.mastodonURL); +window.infoBeamerConfig.set('mastodonFetchInterval', params.mastodonFetchInterval); + +window.infoBeamerConfig.set('musicURL', params.musicURL); +window.infoBeamerConfig.set('musicFetchInterval', params.musicFetchInterval); + +window.infoBeamerConfig.set('cmsURL', params.cmsURL); +window.infoBeamerConfig.set('cmsFetchInterval', params.cmsFetchInterval); + +console.log('Info Beamer Configuration: '); +console.log(window.infoBeamerConfig); diff --git a/assets/js/custom/core/fetcher.js b/assets/js/custom/core/fetcher.js new file mode 100644 index 0000000..f5ce64d --- /dev/null +++ b/assets/js/custom/core/fetcher.js @@ -0,0 +1,63 @@ +'use strict'; + + +const configure = (configuration, service) => { + + const fetchIt = (storage) => { + + // Setup fetching in web workers + if (window.Worker) { + const workerBaseURL = window.infoBeamerConfig.get('workerBaseURL'); + const fetchWorkerCode = workerBaseURL + "/generic_fetch_worker.js"; + + // Schedule fetch worker + const scheduleWorker = new Worker(fetchWorkerCode); + const scheduleType = 'Schedule'; + const scheduleURL = window.infoBeamerConfig.get('scheduleURL'); + const scheduleFetchInterval = window.infoBeamerConfig.get('scheduleFetchInterval'); + + // Configure schedule worker + scheduleWorker.postMessage({fetchType: scheduleType, + fetchURL: scheduleURL, + fetchInterval: scheduleFetchInterval + }); + + // Obtain schedule results and call back + scheduleWorker.onmessage = function(e) { + if (e.data.msgType === scheduleType) { + let jsonData = e.data.json; + + console.log("Got it"); + console.log(jsonData); + console.log("---"); + + + let scheduleData = service.process_data(jsonData); + //let scheduleData = e.data.json; + + console.log(scheduleData); + + storage.scheduleData = scheduleData; + console.log("Got it"); + console.log(storage); + console.log("---"); + // update_screen(); + } + }; + + + // Add more workers here + } else { + console.log("Your browser doesn't support web workers."); + } + + }; + + + return fetchIt; +}; + + +export { + configure +}; diff --git a/assets/js/custom/core/generic_fetch_worker.js b/assets/js/custom/core/generic_fetch_worker.js new file mode 100644 index 0000000..94874aa --- /dev/null +++ b/assets/js/custom/core/generic_fetch_worker.js @@ -0,0 +1,36 @@ +let fetchType; +let fetchInterval; +let fetchURL; + + +onmessage = function(e) { + let msgType = e.data.msgType; + + // console.log("Configuration Message:"); + console.log(e.data); + + fetchType = e.data.fetchType; + fetchURL = e.data.fetchURL; + fetchInterval = 1000 * e.data.fetchInterval; +}; + + +function doFetch() { + let now = new Date(); + + if (fetchURL) { + fetch(fetchURL).then( + b => b.json()).then( + j => postMessage({msgType: fetchType, + json: j, + timestamp: now})) + .catch(e => console.log(e.message)); + } +} + + +// Periodic resource fetching +(function periodicFetch() { + doFetch(); + setTimeout(periodicFetch, fetchInterval); +})(); diff --git a/assets/js/custom/core/mainLoop.js b/assets/js/custom/core/mainLoop.js new file mode 100644 index 0000000..46ec65e --- /dev/null +++ b/assets/js/custom/core/mainLoop.js @@ -0,0 +1,14 @@ +'use strict'; + + + + +let configure = () => undefined; + + + + + +export { + configure +} diff --git a/assets/js/custom/core/screen.js b/assets/js/custom/core/screen.js new file mode 100644 index 0000000..531e35d --- /dev/null +++ b/assets/js/custom/core/screen.js @@ -0,0 +1,28 @@ +'use strict'; + + +function configure(service, view) { + + const update_screen = (storage, time, config) => { + + let now = time.now(); + + console.log('Updating Screen with:'); + console.log(storage); + console.log(now); + console.log(config); + + view.update_main_slide( + storage, + now, + config); + }; + + + return update_screen; +}; + + +export { + configure +} diff --git a/assets/js/custom/core/time.js b/assets/js/custom/core/time.js new file mode 100644 index 0000000..ed80d9e --- /dev/null +++ b/assets/js/custom/core/time.js @@ -0,0 +1,43 @@ +'use strict'; + +// Fake 'now' date time for testing +// const fakeNow = null; + +// Test transitions +// const fakeNow = Date.parse("2024-03-01T18:53:50"); + +// Test Fr +const fakeNow = Date.parse("2024-03-01T19:00:00"); +// const fakeNow = Date.parse("2024-03-01T19:15:00"); +// const fakeNow = Date.parse("2024-03-01T20:15:00"); +// const fakeNow = Date.parse("2024-03-01T21:00:00"); + +// Test Sa +// const fakeNow = Date.parse("2024-03-02T11:00:00"); +// const fakeNow = Date.parse("2024-03-02T11:15:00"); +// const fakeNow = Date.parse("2024-03-02T12:00:00"); +// const fakeNow = Date.parse("2024-03-02T13:00:00"); + +// const fakeNow = Date.parse("2024-03-02T14:45:00"); +// const fakeNow = Date.parse("2024-03-02T15:30:00"); +// const fakeNow = Date.parse("2024-03-02T16:30:00"); + +// const fakeNow = Date.parse("2024-03-02T18:00:00"); +// const fakeNow = Date.parse("2024-03-02T19:00:00"); +// const fakeNow = Date.parse("2024-03-02T20:00:00"); +// const fakeNow = Date.parse("2024-03-02T20:15:00"); + + +const fakeTimeDelta = fakeNow === null ? 0 : fakeNow - Date.now(); + + +// Real 'now' date time for production +const nowJS = () => Date.now() + fakeTimeDelta; + +// Real 'now' date time for production as luxon DateTime object +const now = () => luxon.DateTime.fromMillis(nowJS()); + + +export { + now +} diff --git a/assets/js/custom/dom/clock.js b/assets/js/custom/dom/clock.js new file mode 100644 index 0000000..5a45ea9 --- /dev/null +++ b/assets/js/custom/dom/clock.js @@ -0,0 +1,21 @@ +'use strict'; + +const html = htm.bind(preact.h); + + +const update_main_slide = (data, time, config) => { + const hour = time.toFormat('HH'); + const minute = time.toFormat('mm'); + const sep = time.second % 2 === 0 ? ':' : '.'; + + const inner = html`
${hour}${sep}${minute}
`; + + const anchorElId = "clock"; + const el = document.getElementById(anchorElId); + preact.render(inner, el); +}; + + +export { + update_main_slide +}; diff --git a/assets/js/custom/dom/music.js b/assets/js/custom/dom/music.js new file mode 100644 index 0000000..140ba25 --- /dev/null +++ b/assets/js/custom/dom/music.js @@ -0,0 +1,38 @@ +'use strict'; + +import * as sol from "../../solight/sol.js"; + +import * as serv from "../services/service.js"; + + +const html = htm.bind(preact.h); + + +const music_credits = (config) => { + let inner; + if (sol.defined(config.music)) { + inner = html` +
+ Musik: + ${config.music.title} + von + ${config.music.artist} + Lizenz: + + ${config.music.licence} + + Link: + + ${config.music.url} + +
`; + } else { + inner = html``; + } + return inner; +}; + + +export { + music_credits +} diff --git a/assets/js/custom/dom/schedule.js b/assets/js/custom/dom/schedule.js new file mode 100644 index 0000000..65166c6 --- /dev/null +++ b/assets/js/custom/dom/schedule.js @@ -0,0 +1,170 @@ +'use strict'; + +import * as sol from "../../solight/sol.js"; + +import * as serv from "../services/service.js"; +import * as music from "./music.js"; + + +const html = htm.bind(preact.h); + +const max_events = 5; + +const title_string = 'Nächste Events:'; + +const local_room = 'Hier'; + + +const this_room = (config) => sol.optional(config.roomName); + + +const this_location = (config) => { + const here = this_room(config); + return sol.defined(here) ? html`@${here}` : html``; +}; + + +const schedule_table_header = () => + html` +
+
${title_string}
+
`; + + +const event_time = (event) => { + const esd = sol.eventStartDate(event); + const time = esd.setLocale('de').toLocaleString(luxon.DateTime.TIME_24_SIMPLE); + return html`
${time}
`; +}; + + +const event_location = (event, config) => { + const here_room = this_room(config); + const event_room = sol.eventRoomName(event); + + let inner; + if (sol.defined(here_room) && (event_room === here_room)) { + inner = html`
${local_room}
`; + } else { + inner = html`
${event_room}
`; + } + return inner; +}; + + +const event_title = (event) => { + const title = serv.fix_dash(sol.eventTitle(event)); + const ti = serv.track_index(sol.eventTrack(event)); + return html`
${title}
`; +}; + + +const event_speaker = (event) => { + const speaker = serv.fix_dash(serv.person_names_concat(sol.eventPersons(event))); + return html`
${speaker}
`; +}; + + +const schedule_table_event = (event, config) => + html` +
+ ${event_time(event)} + ${event_location(event, config)} +
+ ${event_title(event)} + ${event_speaker(event)} +
+
`; + + +const schedule_table_events = (events, config) => + html` +
+ ${events.map(e => schedule_table_event(e, config))} +
`; + + +const schedule_table = (events, config) => + html` + ${schedule_table_header()} + ${schedule_table_events(events, config)}`; + + +const header = (config) => + html`
${this_location(config)}
`; + + +const list_track = (track) => + html`${track}`; + + +const list_tracks = (tracks) => + html`
${tracks.map(t => list_track(t))}
`; + + +const footer = (tracks, config) => + html` + `; + + +const update_main_slide = (data, time, config) => { + // console.log("Updating Main Slide with:"); + // console.log(data); + // console.log(time); + // console.log(config); + + if (sol.defined(data.scheduleData)) { + const schedule = data.scheduleData; + + // const allDays = sol.allDays(schedule); + // const currentDays = sol.currentDays(allDays, time); + // const futureDays = sol.futureDays(allDays, time); + // const nextDays = currentDays.concat(futureDays); + + // const nextDaysSorted = sol.sortDaysByStartDate(nextDays, time); + // Hack: if we do not have a next day, all days are in the past and it does not matter. + // const nextDay = nextDaysSorted.length > 0 ? nextDaysSorted[0] : allDays[0]; + + const allEvents = sol.allEvents(schedule); + const nextEvents = allEvents; + //const nextEvents = allEventssol.eventsByDay(allEvents, nextDay); + + const dt = luxon.Duration.fromObject({minutes: 10}); + + const startedEvents = sol.startedEvents(nextEvents, time, dt); + const futureEvents = sol.futureEvents(nextEvents, time); + + // const upcomingEvents = futureEvents; + // const upcomingEvents = sol.futureEvents(nextEvents, time); + const upcomingEvents = sol.distinctEvents(startedEvents.concat(futureEvents)); + + const upcomingEventsSorted = sol.sortEventsByStartDate(upcomingEvents); + + const allTracks = sol.allTracks(schedule); + const tracks = allTracks.filter(t => t !== "Andere"); + + // Take first n events + const events = upcomingEventsSorted.slice(0, max_events); + + // Assemble dom + const inner = html` +
+ ${header(config)} + ${schedule_table(events, config)} + ${footer(tracks, config)} +
`; + + // Add main slide to info beamer + const anchorElId = "main"; + const el = document.getElementById(anchorElId); + preact.render(inner, el); + }; +}; + + +export { + update_main_slide +}; diff --git a/assets/js/custom/dom/speaker-info.js b/assets/js/custom/dom/speaker-info.js new file mode 100644 index 0000000..874d1ba --- /dev/null +++ b/assets/js/custom/dom/speaker-info.js @@ -0,0 +1,51 @@ +'use strict'; + +import * as sol from "../../solight/sol.js"; + +import * as serv from "../services/service.js"; + + +const html = htm.bind(preact.h); + + +const event_info = (event) => + html` +
+
+
${serv.fix_dash(serv.person_names_concat(sol.eventPersons(event)))}
+
+
`; + + +const update_main_slide = (data, time, config) => { + if (sol.defined(data.scheduleData)) { + const schedule = data.scheduleData; + + const thisRoom = config.roomName; + + // const dt = luxon.Duration.fromObject({minutes: 5}); + + const events = sol.allEvents(schedule); + const eventsHere = sol.eventsByRoomName(events, thisRoom); + + // const startingEventsHere = sol.startingEvents(eventsHere, time, dt); + // const currentEventsHere = sol.currentEvents(eventsHere, time); + // const endedEventsHere = sol.endedEvents(eventsHere, time, dt); + // const upcomingEventsHere = sol.distinctEvents(startingEventsHere.concat(currentEventsHere, endedEventsHere)); + + const upcomingEventsHere = sol.currentEvents(eventsHere, time); + + const inner = html` + ${upcomingEventsHere.slice(0,1).map(e => event_info(e))}`; + + // Add main slide to frame + const anchorElId = "main"; + const el = document.getElementById(anchorElId); + preact.render(inner, el); + }; +}; + + +export { + update_main_slide +}; diff --git a/assets/js/custom/dom/talk-info.js b/assets/js/custom/dom/talk-info.js new file mode 100644 index 0000000..2db4e3c --- /dev/null +++ b/assets/js/custom/dom/talk-info.js @@ -0,0 +1,56 @@ +'use strict'; + +import * as sol from "../../solight/sol.js"; + +import * as serv from "../services/service.js"; + + +const html = htm.bind(preact.h); + + +const event_info = (event) => { + const title = serv.fix_dash(sol.eventTitle(event)); + const names = serv.fix_dash(serv.person_names_concat(sol.eventPersons(event))); + return html` +
+
+
${title}
+
${names}
+
+
`; +}; + + +const update_main_slide = (data, time, config) => { + if (sol.defined(data.scheduleData)) { + const schedule = data.scheduleData; + + const thisRoom = config.roomName; + + // const dt = luxon.Duration.fromObject({minutes: 5}); + + const events = sol.allEvents(schedule); + const eventsHere = sol.eventsByRoomName(events, thisRoom); + + // const startingEventsHere = sol.startingEvents(eventsHere, time, dt); + // const currentEventsHere = sol.currentEvents(eventsHere, time); + // const endedEventsHere = sol.endedEvents(eventsHere, time, dt); + // const upcomingEventsHere = sol.distinctEvents(startingEventsHere.concat(currentEventsHere, endedEventsHere)); + + const upcomingEventsHere = sol.currentEvents(eventsHere, time); + + const inner = html` + ${upcomingEventsHere.slice(0,1).map(e => event_info(e))} + `; + + // Add main slide to frame + const anchorElId = "main"; + const el = document.getElementById(anchorElId); + preact.render(inner, el); + }; +}; + + +export { + update_main_slide +}; diff --git a/assets/js/custom/dom/upcoming-talk.js b/assets/js/custom/dom/upcoming-talk.js new file mode 100644 index 0000000..6208379 --- /dev/null +++ b/assets/js/custom/dom/upcoming-talk.js @@ -0,0 +1,123 @@ +'use strict'; + +import * as sol from "../../solight/sol.js"; + +import * as serv from "../services/service.js"; +import * as music from "./music.js"; + + +const html = htm.bind(preact.h); + +const nowString = 'Jetzt'; + +const minBioLength = 20; + +const event_persons = (persons) => + html`
${serv.fix_dash(serv.person_names_concat(persons))}:
`; + +const event_time = (event, time) => { + const esd = sol.eventStartDate(event); + const nowish = luxon.Interval.fromDateTimes(esd.minus({minutes: 1}), esd.plus({minutes: 1})); + const stime = nowish.contains(time) ? + nowString : + esd.setLocale('de').toRelative({base: time, unit: 'minutes'}); + + return html`
${stime}
`; +}; + +const event_meta = (event, time) => + html` +
+ ${event_persons(sol.eventPersons(event))} +
${serv.fix_dash(sol.eventTitle(event))}
+
${sol.eventSubtitle(event)}
+ ${event_time(event, time)} +
`; + +const event_description = (event) => { + const description = sol.eventAbstract(event); + const abstract = sol.eventAbstract(event); + + const atext = sol.defined(abstract) ? abstract : ""; + const dtext = sol.defined(description) ? description : ""; + + const text = atext.length >= dtext.length ? atext : dtext; + + return html` +
+
Beschreibung:
+
${text}
+
`; +}; + +const event_content = (event) => + html`
${event_description(event)}
`; + +const speaker_info = (speaker, count) => { + const name = serv.fix_dash(sol.personName(speaker)); + const bio = sol.personBiography(speaker); + + let inner; + if (sol.defined(bio) && bio.length >= minBioLength) { + inner = html` +
+
${name}
+
${bio}
+
`; + } else { + inner = html``; + } + return inner; +}; + +const speaker_meta = (event) => { + const speakers = sol.eventPersons(event); + const n = speakers.length; + return html`
${speakers.map(s => speaker_info(s, n))}
`; +}; + +const event_info = (event, time) => + html` +
+ ${event_meta(event, time)} +
+
+ ${event_content(event)} + ${speaker_meta(event)} +
`; + +const footer = (config) => + html``; + +const update_main_slide = (data, time, config) => { + if (sol.defined(data.scheduleData)) { + const schedule = data.scheduleData; + + const thisRoom = config.roomName; + + const dt = luxon.Duration.fromObject({minutes: 6}); + + const events = sol.allEvents(schedule); + const eventsHere = sol.eventsByRoomName(events, thisRoom); + const startingEventsHere = sol.startingEvents(eventsHere, time, dt); + const currentEventsHere = sol.currentEvents(eventsHere, time); + const endedEventsHere = sol.endedEvents(eventsHere, time, dt); + const upcomingEventsHere = sol.distinctEvents(startingEventsHere.concat(currentEventsHere, endedEventsHere)); + + const inner = html` +
+ ${upcomingEventsHere.slice(0,1).map(e => event_info(e, time))} + ${footer(config)} +
`; + + // Add main slide to frame + const anchorElId = "main"; + const el = document.getElementById(anchorElId); + preact.render(inner, el); + }; +}; + + +export { + update_main_slide +}; diff --git a/assets/js/custom/dom/voc-schedule-hall.js b/assets/js/custom/dom/voc-schedule-hall.js new file mode 100644 index 0000000..444f4f4 --- /dev/null +++ b/assets/js/custom/dom/voc-schedule-hall.js @@ -0,0 +1,112 @@ +'use strict'; + +import * as sol from "../../solight/sol.js"; + +import * as serv from "../services/service.js"; + +const html = htm.bind(preact.h); + + +const schedule_event_modus = (event) => + html`${serv.event_modus_string(event)}`; + +const schedule_persons = (persons) => + html`${persons.map(p => sol.personName(p)).join(', ')}`; + +const schedule_time = (event) => + html`${sol.eventStartDate(event).toFormat('HH:mm')} – ${sol.eventEndDate(event).toFormat('HH:mm')}`; + +const person_count_class = (count) => { + switch (true) { + case count === 1: return 'speaker-cnt-1'; + case count === 2: return 'speaker-cnt-2'; + case count === 3: return 'speaker-cnt-3'; + default: return 'speaker-cnt-many'; + } +}; + +const schedule_event = (event) => { + const dnrString = sol.eventDoNotRecord(event) ? '✘' : '✔'; + const dnrClass = sol.eventDoNotRecord(event) ? 'dnr-true' : 'dnr-false'; + const speakerCnt = sol.eventPersonCount(event); + const speakerCntClass = person_count_class(speakerCnt); + return html` + + ${sol.eventTitle(event).slice(0, 30)} + ${schedule_persons(sol.eventPersons(event))} + ${speakerCnt} + ${sol.eventType(event)} + ${schedule_time(event)} + ${dnrString} + `; +}; + +const schedule_room = (events, room) => { + const rn = sol.roomName(room); + const evs = sol.eventsByRoomName(events, rn); + const evss = sol.sortEventsByStartDate(evs); + + return html` +

Room: ${rn}

+ + + + + + + + + + ${evss.map(e => schedule_event(e))} +
TitleSpeakers#SpeakersTypeTimeRecord?
`; +}; + +const schedule_day = (con, events, room, day) => { + const dt = sol.dayStartDate(day); + const di = sol.dayIndex(day); + + const evs = sol.eventsByDayIndex(events, di); + // const rms = sol.roomsByDayIndex(con, rooms, di); + + return html` +

Day ${di}: ${dt.setLocale('de-DE').toFormat('EEEE')}

+ ${schedule_room(evs, room)}`; +}; + +const schedule_table = (schedule, thisRoomName) => { + const con = sol.conference(schedule); + + const days = sol.allDays(schedule); + const events = sol.allEvents(schedule); + const rooms = sol.allRooms(schedule); + const room = sol.roomsByName(rooms, thisRoomName).at(0); + + return html` +

Schedule (v ${sol.scheduleVersion(schedule)})

+ ${days.map(d => schedule_day(con, events, room, d))}`; +}; + + +const update_main_slide = (data, time, config) => { + console.log("Our data:"); + console.log(data); + + if (sol.defined(data.scheduleData)) { + const schedule = data.scheduleData; + + const thisRoomName = config.roomName; + + const inner = html` + ${schedule_table(schedule, thisRoomName)}`; + + // Add main slide to info beamer + const anchorElId = "main"; + const el = document.getElementById(anchorElId); + preact.render(inner, el); + }; +}; + + +export { + update_main_slide +}; diff --git a/assets/js/custom/dom/voc-schedule.js b/assets/js/custom/dom/voc-schedule.js new file mode 100644 index 0000000..42e6098 --- /dev/null +++ b/assets/js/custom/dom/voc-schedule.js @@ -0,0 +1,109 @@ +'use strict'; + +import * as sol from "../../solight/sol.js"; + +import * as serv from "../services/service.js"; + +const html = htm.bind(preact.h); + + +const schedule_event_modus = (event) => + html`${serv.event_modus_string(event)}`; + +const schedule_persons = (persons) => + html`${persons.map(p => sol.personName(p)).join(', ')}`; + +const schedule_time = (event) => + html`${sol.eventStartDate(event).toFormat('HH:mm')} – ${sol.eventEndDate(event).toFormat('HH:mm')}`; + +const person_count_class = (count) => { + switch (true) { + case count === 1: return 'speaker-cnt-1'; + case count === 2: return 'speaker-cnt-2'; + case count === 3: return 'speaker-cnt-3'; + default: return 'speaker-cnt-many'; + } +}; + +const schedule_event = (event) => { + const dnrString = sol.eventDoNotRecord(event) ? '✘' : '✔'; + const dnrClass = sol.eventDoNotRecord(event) ? 'dnr-true' : 'dnr-false'; + const speakerCnt = sol.eventPersonCount(event); + const speakerCntClass = person_count_class(speakerCnt); + return html` + + ${sol.eventTitle(event).slice(0, 30)} + ${schedule_persons(sol.eventPersons(event))} + ${speakerCnt} + ${sol.eventType(event)} + ${schedule_time(event)} + ${dnrString} + `; +}; + +const schedule_room = (events, room) => { + const rn = sol.roomName(room); + const evs = sol.eventsByRoomName(events, rn); + const evss = sol.sortEventsByStartDate(evs); + + return html` +

Room: ${rn}

+ + + + + + + + + + ${evss.map(e => schedule_event(e))} +
TitleSpeakers#SpeakersTypeTimeRecord?
`; +}; + +const schedule_day = (con, events, rooms, day) => { + const dt = sol.dayStartDate(day); + const di = sol.dayIndex(day); + + const evs = sol.eventsByDayIndex(events, di); + const rms = sol.roomsByDayIndex(con, rooms, di); + + return html` +

Day ${di}: ${dt.setLocale('de-DE').toFormat('EEEE')}

+ ${rms.map(r => schedule_room(evs, r))}`; +}; + +const schedule_table = (schedule) => { + const con = sol.conference(schedule); + + const days = sol.allDays(schedule); + const events = sol.allEvents(schedule); + const rooms = sol.allRooms(schedule); + + return html` +

Schedule (v ${sol.scheduleVersion(schedule)})

+ ${days.map(d => schedule_day(con, events, rooms, d))}`; +}; + + +const update_main_slide = (data, time) => { + console.log("Our data:"); + console.log(data); + + if (sol.defined(data.scheduleData)) { + const schedule = data.scheduleData; + + const inner = html` + ${schedule_table(schedule)}`; + + // Add main slide to info beamer + const anchorElId = "main"; + const el = document.getElementById(anchorElId); + preact.render(inner, el); + }; +}; + + +export { + update_main_slide +}; diff --git a/assets/js/custom/dom/voc-speaker.js b/assets/js/custom/dom/voc-speaker.js new file mode 100644 index 0000000..586a296 --- /dev/null +++ b/assets/js/custom/dom/voc-speaker.js @@ -0,0 +1,56 @@ +'use strict'; + +import * as sol from "../../solight/sol.js"; + +import * as serv from "../services/service.js"; + +const html = htm.bind(preact.h); + + +const person_row = (events, person) => + html` + + ${sol.personName(person)} + `; + + +const persons_table = (events, persons) => { + const ps = sol.sortPersonsByName(persons); + return html` +

Persons (${ps.length})

+ + + + + ${ps.map(p => person_row(events, p))} +
Name
`; +}; + + +const persons_overview = (schedule) => { + const persons = sol.allPersons(schedule); + const events = sol.allEvents(schedule); + return html` +

Schedule (v ${sol.scheduleVersion(schedule)})

+ ${persons_table(events, persons)}`; +}; + + +const update_main_slide = (data, time) => { + if (sol.defined(data.scheduleData)) { + const schedule = data.scheduleData; + + const inner = html` + ${persons_overview(schedule)}`; + + // Add main slide to info beamer + const anchorElId = "main"; + const el = document.getElementById(anchorElId); + preact.render(inner, el); + }; +}; + + +export { + update_main_slide +}; diff --git a/assets/js/custom/dom/voc-talks.js b/assets/js/custom/dom/voc-talks.js new file mode 100644 index 0000000..b20fb26 --- /dev/null +++ b/assets/js/custom/dom/voc-talks.js @@ -0,0 +1,68 @@ +'use strict'; + +import * as sol from "../../solight/sol.js"; + +import * as serv from "../services/service.js"; + +const html = htm.bind(preact.h); + + +const speaker = (event) => { + const speaker = sol.eventPersons(event); + const names = speaker.map(s => sol.personName(s)).join(", "); + return html`${names}`; +}; + +const num_speaker = (event) => + sol.eventPersons(event).length; + +const event_row = (event) => + html` + + ${sol.eventTitle(event)} + ${speaker(event)} + ${num_speaker(event)} + `; + + +const talks_table = (events) => { + const evs = sol.sortEventsByStartDate(events); + return html` +

Events (${evs.length})

+ + + + + + + ${evs.map(e => event_row(e))} +
Event TitlePerson(s)#Person(s)
`; +}; + + +const talks_overview = (schedule) => { + const events = sol.allEvents(schedule); + return html` +

Schedule (v ${sol.scheduleVersion(schedule)})

+ ${talks_table(events)}`; +}; + + +const update_main_slide = (data, time) => { + if (sol.defined(data.scheduleData)) { + const schedule = data.scheduleData; + + const inner = html` + ${talks_overview(schedule)}`; + + // Add main slide to info beamer + const anchorElId = "main"; + const el = document.getElementById(anchorElId); + preact.render(inner, el); + }; +}; + + +export { + update_main_slide +}; diff --git a/assets/js/custom/nodes/schedule-hall1.js b/assets/js/custom/nodes/schedule-hall1.js new file mode 100644 index 0000000..f88285a --- /dev/null +++ b/assets/js/custom/nodes/schedule-hall1.js @@ -0,0 +1,55 @@ +'use strict'; + + +import * as fe from "../core/fetcher.js"; + +import * as ti from "../core/time.js"; + +import * as sc from "../core/screen.js"; + +// Import services +import * as serv from "../services/service.js"; + +// Import views +import * as domman from "../dom/schedule.js"; +import * as clk from "../dom/clock.js"; + + +// Empty JSON lists for data +let storage = { + scheduleData: undefined +}; + + +let do_fetch = fe.configure({}, serv); + +do_fetch(storage); + + + +// Main Loop +let screen_update = sc.configure(serv, domman); +let clock_update = sc.configure(serv, clk); + + +let cfg = { + "roomName": "Festsaal", + "music": { + "artist": "luss", + "title": "dub techno session #5", + "licence": "CC-BY", + "url": "https://lussdub.bandcamp.com/" + } +}; + + +// Just do it +function main_loop() { + screen_update(storage, ti, cfg); + clock_update(storage, ti, cfg); + // update_screen(); + // setTimeout(main_loop, 1 * 1000); + setTimeout(main_loop, 1 * 50); +}; + +main_loop(); diff --git a/assets/js/custom/nodes/schedule-hall2.js b/assets/js/custom/nodes/schedule-hall2.js new file mode 100644 index 0000000..e4a4fbc --- /dev/null +++ b/assets/js/custom/nodes/schedule-hall2.js @@ -0,0 +1,55 @@ +'use strict'; + + +import * as fe from "../core/fetcher.js"; + +import * as ti from "../core/time.js"; + +import * as sc from "../core/screen.js"; + +// Import services +import * as serv from "../services/service.js"; + +// Import views +import * as domman from "../dom/schedule.js"; +import * as clk from "../dom/clock.js"; + + +// Empty JSON lists for data +let storage = { + scheduleData: undefined +}; + + +let do_fetch = fe.configure({}, serv); + +do_fetch(storage); + + + +// Main Loop +let screen_update = sc.configure(serv, domman); +let clock_update = sc.configure(serv, clk); + + +let cfg = { + "roomName": "Bankettsaal", + "music": { + "artist": "luss", + "title": "dub techno session #5", + "licence": "CC-BY", + "url": "https://lussdub.bandcamp.com/" + } +}; + + +// Just do it +function main_loop() { + screen_update(storage, ti, cfg); + clock_update(storage, ti, cfg); + // update_screen(); + // setTimeout(main_loop, 1 * 1000); + setTimeout(main_loop, 1 * 50); +}; + +main_loop(); diff --git a/assets/js/custom/nodes/schedule-hall3.js b/assets/js/custom/nodes/schedule-hall3.js new file mode 100644 index 0000000..9315cbc --- /dev/null +++ b/assets/js/custom/nodes/schedule-hall3.js @@ -0,0 +1,55 @@ +'use strict'; + + +import * as fe from "../core/fetcher.js"; + +import * as ti from "../core/time.js"; + +import * as sc from "../core/screen.js"; + +// Import services +import * as serv from "../services/service.js"; + +// Import views +import * as domman from "../dom/schedule.js"; +import * as clk from "../dom/clock.js"; + + +// Empty JSON lists for data +let storage = { + scheduleData: undefined +}; + + +let do_fetch = fe.configure({}, serv); + +do_fetch(storage); + + + +// Main Loop +let screen_update = sc.configure(serv, domman); +let clock_update = sc.configure(serv, clk); + + +let cfg = { + "roomName": "Tanzsaal", + "music": { + "artist": "luss", + "title": "dub techno session #5", + "licence": "CC-BY", + "url": "https://lussdub.bandcamp.com/" + } +}; + + +// Just do it +function main_loop() { + screen_update(storage, ti, cfg); + clock_update(storage, ti, cfg); + // update_screen(); + // setTimeout(main_loop, 1 * 1000); + setTimeout(main_loop, 1 * 50); +}; + +main_loop(); diff --git a/assets/js/custom/nodes/schedule.js b/assets/js/custom/nodes/schedule.js new file mode 100644 index 0000000..40e861c --- /dev/null +++ b/assets/js/custom/nodes/schedule.js @@ -0,0 +1,54 @@ +'use strict'; + + +import * as fe from "../core/fetcher.js"; + +import * as ti from "../core/time.js"; + +import * as sc from "../core/screen.js"; + +// Import services +import * as serv from "../services/service.js"; + +// Import views +import * as domman from "../dom/schedule.js"; +import * as clk from "../dom/clock.js"; + + +// Empty JSON lists for data +let storage = { + scheduleData: undefined +}; + + +let do_fetch = fe.configure({}, serv); + +do_fetch(storage); + + + +// Main Loop +let screen_update = sc.configure(serv, domman); +let clock_update = sc.configure(serv, clk); + + +let cfg = { + "music": { + "artist": "luss", + "title": "dub techno session #5", + "licence": "CC-BY", + "url": "https://lussdub.bandcamp.com/" + } +}; + + +// Just do it +function main_loop() { + screen_update(storage, ti, cfg); + clock_update(storage, ti, cfg); + // update_screen(); + // setTimeout(main_loop, 1 * 1000); + setTimeout(main_loop, 1 * 50); +}; + +main_loop(); diff --git a/assets/js/custom/nodes/speaker-info-hall1.js b/assets/js/custom/nodes/speaker-info-hall1.js new file mode 100644 index 0000000..c38547d --- /dev/null +++ b/assets/js/custom/nodes/speaker-info-hall1.js @@ -0,0 +1,42 @@ +'use strict'; + + +import * as fe from "../core/fetcher.js"; + +import * as ti from "../core/time.js"; + +import * as sc from "../core/screen.js"; + +// Import services +import * as serv from "../services/service.js"; + +// Import views +import * as dom from "../dom/speaker-info.js"; + + +// Empty JSON lists for data +let storage = { + scheduleData: undefined +}; + +let cfg = { + "roomName": "Festsaal" +}; + + + +let do_fetch = fe.configure({}, serv); + +do_fetch(storage); + + +// Main Loop +let screen_update = sc.configure(serv, dom); + +// Just do it +function main_loop() { + screen_update(storage, ti, cfg); + setTimeout(main_loop, 1 * 1000); +}; + +main_loop(); diff --git a/assets/js/custom/nodes/speaker-info-hall2.js b/assets/js/custom/nodes/speaker-info-hall2.js new file mode 100644 index 0000000..17027ea --- /dev/null +++ b/assets/js/custom/nodes/speaker-info-hall2.js @@ -0,0 +1,42 @@ +'use strict'; + + +import * as fe from "../core/fetcher.js"; + +import * as ti from "../core/time.js"; + +import * as sc from "../core/screen.js"; + +// Import services +import * as serv from "../services/service.js"; + +// Import views +import * as dom from "../dom/speaker-info.js"; + + +// Empty JSON lists for data +let storage = { + scheduleData: undefined +}; + +let cfg = { + "roomName": "Bankettsaal" +}; + + + +let do_fetch = fe.configure({}, serv); + +do_fetch(storage); + + +// Main Loop +let screen_update = sc.configure(serv, dom); + +// Just do it +function main_loop() { + screen_update(storage, ti, cfg); + setTimeout(main_loop, 1 * 1000); +}; + +main_loop(); diff --git a/assets/js/custom/nodes/speaker-info-hall3.js b/assets/js/custom/nodes/speaker-info-hall3.js new file mode 100644 index 0000000..904640a --- /dev/null +++ b/assets/js/custom/nodes/speaker-info-hall3.js @@ -0,0 +1,42 @@ +'use strict'; + + +import * as fe from "../core/fetcher.js"; + +import * as ti from "../core/time.js"; + +import * as sc from "../core/screen.js"; + +// Import services +import * as serv from "../services/service.js"; + +// Import views +import * as dom from "../dom/speaker-info.js"; + + +// Empty JSON lists for data +let storage = { + scheduleData: undefined +}; + +let cfg = { + "roomName": "Tanzsaal" +}; + + + +let do_fetch = fe.configure({}, serv); + +do_fetch(storage); + + +// Main Loop +let screen_update = sc.configure(serv, dom); + +// Just do it +function main_loop() { + screen_update(storage, ti, cfg); + setTimeout(main_loop, 1 * 1000); +}; + +main_loop(); diff --git a/assets/js/custom/nodes/talk-info-hall1.js b/assets/js/custom/nodes/talk-info-hall1.js new file mode 100644 index 0000000..b77207f --- /dev/null +++ b/assets/js/custom/nodes/talk-info-hall1.js @@ -0,0 +1,42 @@ +'use strict'; + + +import * as fe from "../core/fetcher.js"; + +import * as ti from "../core/time.js"; + +import * as sc from "../core/screen.js"; + +// Import services +import * as serv from "../services/service.js"; + +// Import views +import * as dom from "../dom/talk-info.js"; + + +// Empty JSON lists for data +let storage = { + scheduleData: undefined +}; + +let cfg = { + "roomName": "Festsaal" +}; + + + +let do_fetch = fe.configure({}, serv); + +do_fetch(storage); + + +// Main Loop +let screen_update = sc.configure(serv, dom); + +// Just do it +function main_loop() { + screen_update(storage, ti, cfg); + setTimeout(main_loop, 1 * 1000); +}; + +main_loop(); diff --git a/assets/js/custom/nodes/talk-info-hall2.js b/assets/js/custom/nodes/talk-info-hall2.js new file mode 100644 index 0000000..3ad49c4 --- /dev/null +++ b/assets/js/custom/nodes/talk-info-hall2.js @@ -0,0 +1,42 @@ +'use strict'; + + +import * as fe from "../core/fetcher.js"; + +import * as ti from "../core/time.js"; + +import * as sc from "../core/screen.js"; + +// Import services +import * as serv from "../services/service.js"; + +// Import views +import * as dom from "../dom/talk-info.js"; + + +// Empty JSON lists for data +let storage = { + scheduleData: undefined +}; + +let cfg = { + "roomName": "Bankettsaal" +}; + + + +let do_fetch = fe.configure({}, serv); + +do_fetch(storage); + + +// Main Loop +let screen_update = sc.configure(serv, dom); + +// Just do it +function main_loop() { + screen_update(storage, ti, cfg); + setTimeout(main_loop, 1 * 1000); +}; + +main_loop(); diff --git a/assets/js/custom/nodes/talk-info-hall3.js b/assets/js/custom/nodes/talk-info-hall3.js new file mode 100644 index 0000000..488e983 --- /dev/null +++ b/assets/js/custom/nodes/talk-info-hall3.js @@ -0,0 +1,42 @@ +'use strict'; + + +import * as fe from "../core/fetcher.js"; + +import * as ti from "../core/time.js"; + +import * as sc from "../core/screen.js"; + +// Import services +import * as serv from "../services/service.js"; + +// Import views +import * as dom from "../dom/talk-info.js"; + + +// Empty JSON lists for data +let storage = { + scheduleData: undefined +}; + +let cfg = { + "roomName": "Tanzsaal" +}; + + + +let do_fetch = fe.configure({}, serv); + +do_fetch(storage); + + +// Main Loop +let screen_update = sc.configure(serv, dom); + +// Just do it +function main_loop() { + screen_update(storage, ti, cfg); + setTimeout(main_loop, 1 * 1000); +}; + +main_loop(); diff --git a/assets/js/custom/nodes/upcoming-talk-hall1.js b/assets/js/custom/nodes/upcoming-talk-hall1.js new file mode 100644 index 0000000..7d8b4cd --- /dev/null +++ b/assets/js/custom/nodes/upcoming-talk-hall1.js @@ -0,0 +1,48 @@ +'use strict'; + + +import * as fe from "../core/fetcher.js"; + +import * as ti from "../core/time.js"; + +import * as sc from "../core/screen.js"; + +// Import services +import * as serv from "../services/service.js"; + +// Import views +import * as dom from "../dom/upcoming-talk.js"; + + +// Empty JSON lists for data +let storage = { + scheduleData: undefined +}; + +let cfg = { + "roomName": "Festsaal", + "music": { + "artist": "luss", + "title": "dub techno session #5", + "licence": "CC-BY", + "url": "https://lussdub.bandcamp.com/" + } +}; + + + +let do_fetch = fe.configure({}, serv); + +do_fetch(storage); + + +// Main Loop +let screen_update = sc.configure(serv, dom); + +// Just do it +function main_loop() { + screen_update(storage, ti, cfg); + setTimeout(main_loop, 1 * 1000); +}; + +main_loop(); diff --git a/assets/js/custom/nodes/upcoming-talk-hall2.js b/assets/js/custom/nodes/upcoming-talk-hall2.js new file mode 100644 index 0000000..9b8eea0 --- /dev/null +++ b/assets/js/custom/nodes/upcoming-talk-hall2.js @@ -0,0 +1,48 @@ +'use strict'; + + +import * as fe from "../core/fetcher.js"; + +import * as ti from "../core/time.js"; + +import * as sc from "../core/screen.js"; + +// Import services +import * as serv from "../services/service.js"; + +// Import views +import * as dom from "../dom/upcoming-talk.js"; + + +// Empty JSON lists for data +let storage = { + scheduleData: undefined +}; + +let cfg = { + "roomName": "Bankettsaal", + "music": { + "artist": "luss", + "title": "dub techno session #5", + "licence": "CC-BY", + "url": "https://lussdub.bandcamp.com/" + } +}; + + + +let do_fetch = fe.configure({}, serv); + +do_fetch(storage); + + +// Main Loop +let screen_update = sc.configure(serv, dom); + +// Just do it +function main_loop() { + screen_update(storage, ti, cfg); + setTimeout(main_loop, 1 * 1000); +}; + +main_loop(); diff --git a/assets/js/custom/nodes/upcoming-talk-hall3.js b/assets/js/custom/nodes/upcoming-talk-hall3.js new file mode 100644 index 0000000..abc457e --- /dev/null +++ b/assets/js/custom/nodes/upcoming-talk-hall3.js @@ -0,0 +1,48 @@ +'use strict'; + + +import * as fe from "../core/fetcher.js"; + +import * as ti from "../core/time.js"; + +import * as sc from "../core/screen.js"; + +// Import services +import * as serv from "../services/service.js"; + +// Import views +import * as dom from "../dom/upcoming-talk.js"; + + +// Empty JSON lists for data +let storage = { + scheduleData: undefined +}; + +let cfg = { + "roomName": "Tanzsaal", + "music": { + "artist": "luss", + "title": "dub techno session #5", + "licence": "CC-BY", + "url": "https://lussdub.bandcamp.com/" + } +}; + + + +let do_fetch = fe.configure({}, serv); + +do_fetch(storage); + + +// Main Loop +let screen_update = sc.configure(serv, dom); + +// Just do it +function main_loop() { + screen_update(storage, ti, cfg); + setTimeout(main_loop, 1 * 1000); +}; + +main_loop(); diff --git a/assets/js/custom/nodes/voc-schedule-hall1.js b/assets/js/custom/nodes/voc-schedule-hall1.js new file mode 100644 index 0000000..3f52a90 --- /dev/null +++ b/assets/js/custom/nodes/voc-schedule-hall1.js @@ -0,0 +1,45 @@ +'use strict'; + + +import * as fe from "../core/fetcher.js"; + +import * as ti from "../core/time.js"; + +import * as sc from "../core/screen.js"; + +// Import services +import * as serv from "../services/service.js"; + +// Import views +import * as domman from "../dom/voc-schedule-hall.js"; + + +// Empty JSON lists for data +let storage = { + scheduleData: undefined +}; + + +let do_fetch = fe.configure({}, serv); + +do_fetch(storage); + + + +// Main Loop +let screen_update = sc.configure(serv, domman); + + +let cfg = { + "roomName": "Festsaal", +}; + + +// Just do it +function main_loop() { + screen_update(storage, ti, cfg); + // update_screen(); + setTimeout(main_loop, 1 * 100); +}; + +main_loop(); diff --git a/assets/js/custom/nodes/voc-schedule-hall2.js b/assets/js/custom/nodes/voc-schedule-hall2.js new file mode 100644 index 0000000..81e8e61 --- /dev/null +++ b/assets/js/custom/nodes/voc-schedule-hall2.js @@ -0,0 +1,45 @@ +'use strict'; + + +import * as fe from "../core/fetcher.js"; + +import * as ti from "../core/time.js"; + +import * as sc from "../core/screen.js"; + +// Import services +import * as serv from "../services/service.js"; + +// Import views +import * as domman from "../dom/voc-schedule-hall.js"; + + +// Empty JSON lists for data +let storage = { + scheduleData: undefined +}; + + +let do_fetch = fe.configure({}, serv); + +do_fetch(storage); + + + +// Main Loop +let screen_update = sc.configure(serv, domman); + + +let cfg = { + "roomName": "Bankettsaal", +}; + + +// Just do it +function main_loop() { + screen_update(storage, ti, cfg); + // update_screen(); + setTimeout(main_loop, 1 * 100); +}; + +main_loop(); diff --git a/assets/js/custom/nodes/voc-schedule-hall3.js b/assets/js/custom/nodes/voc-schedule-hall3.js new file mode 100644 index 0000000..84f7f45 --- /dev/null +++ b/assets/js/custom/nodes/voc-schedule-hall3.js @@ -0,0 +1,45 @@ +'use strict'; + + +import * as fe from "../core/fetcher.js"; + +import * as ti from "../core/time.js"; + +import * as sc from "../core/screen.js"; + +// Import services +import * as serv from "../services/service.js"; + +// Import views +import * as domman from "../dom/voc-schedule-hall.js"; + + +// Empty JSON lists for data +let storage = { + scheduleData: undefined +}; + + +let do_fetch = fe.configure({}, serv); + +do_fetch(storage); + + + +// Main Loop +let screen_update = sc.configure(serv, domman); + + +let cfg = { + "roomName": "Tanzsaal", +}; + + +// Just do it +function main_loop() { + screen_update(storage, ti, cfg); + // update_screen(); + setTimeout(main_loop, 1 * 100); +}; + +main_loop(); diff --git a/assets/js/custom/nodes/voc-schedule.js b/assets/js/custom/nodes/voc-schedule.js new file mode 100644 index 0000000..3bfaf34 --- /dev/null +++ b/assets/js/custom/nodes/voc-schedule.js @@ -0,0 +1,40 @@ +'use strict'; + + +import * as fe from "../core/fetcher.js"; + +import * as ti from "../core/time.js"; + +import * as sc from "../core/screen.js"; + +// Import services +import * as serv from "../services/service.js"; + +// Import views +import * as domman from "../dom/voc-schedule.js"; + + +// Empty JSON lists for data +let storage = { + scheduleData: undefined +}; + + +let do_fetch = fe.configure({}, serv); + +do_fetch(storage); + + + +// Main Loop +let screen_update = sc.configure(serv ,domman); + + +// Just do it +function main_loop() { + screen_update(storage, ti); + // update_screen(); + setTimeout(main_loop, 1 * 100); +}; + +main_loop(); diff --git a/assets/js/custom/nodes/voc-speaker.js b/assets/js/custom/nodes/voc-speaker.js new file mode 100644 index 0000000..3afbc21 --- /dev/null +++ b/assets/js/custom/nodes/voc-speaker.js @@ -0,0 +1,40 @@ +'use strict'; + + +import * as fe from "../core/fetcher.js"; + +import * as ti from "../core/time.js"; + +import * as sc from "../core/screen.js"; + +// Import services +import * as serv from "../services/service.js"; + +// Import views +import * as domman from "../dom/voc-speaker.js"; + + +// Empty JSON lists for data +let storage = { + scheduleData: undefined +}; + + +let do_fetch = fe.configure({}, serv); + +do_fetch(storage); + + + +// Main Loop +let screen_update = sc.configure(serv ,domman); + + +// Just do it +function main_loop() { + screen_update(storage, ti); + // update_screen(); + setTimeout(main_loop, 1 * 100); +}; + +main_loop(); diff --git a/assets/js/custom/nodes/voc-talks.js b/assets/js/custom/nodes/voc-talks.js new file mode 100644 index 0000000..7778e52 --- /dev/null +++ b/assets/js/custom/nodes/voc-talks.js @@ -0,0 +1,40 @@ +'use strict'; + + +import * as fe from "../core/fetcher.js"; + +import * as ti from "../core/time.js"; + +import * as sc from "../core/screen.js"; + +// Import services +import * as serv from "../services/service.js"; + +// Import views +import * as domman from "../dom/voc-talks.js"; + + +// Empty JSON lists for data +let storage = { + scheduleData: undefined +}; + + +let do_fetch = fe.configure({}, serv); + +do_fetch(storage); + + + +// Main Loop +let screen_update = sc.configure(serv ,domman); + + +// Just do it +function main_loop() { + screen_update(storage, ti); + // update_screen(); + setTimeout(main_loop, 1 * 100); +}; + +main_loop(); diff --git a/assets/js/custom/services/service.js b/assets/js/custom/services/service.js new file mode 100644 index 0000000..cd79fe0 --- /dev/null +++ b/assets/js/custom/services/service.js @@ -0,0 +1,49 @@ +'use strict'; + +import * as sol from "../../solight/sol.js"; + + +const process_data = (scheduleFile) => + sol.processScheduleFile(scheduleFile); + + +const event_modus_string = (event) => { + const questionId = 1392; + const answers = sol.eventAnswers(event); + const answer = answers.filter(a => a.get('question') === questionId); + const modus = answer.length > 0 ? answer[0].get('answer') : '???'; + return modus; +}; + + +const trackIndexMap = new Map([ + ['Andere', 0], + ['Ethik, Wissenschaft, Kultur & Gesellschaft', 1], + ['Recht & Politik', 2], + ['Digitale Selbstverteidigung', 3], + ['Netzwerke, Security, Hard- & Software', 4]]); + +const track_index = (track) => + trackIndexMap.get(track); + + +const person_names_concat = (persons) => + // persons.map(p => sol.personName(p)).join(', '); + // persons.map(p => sol.personName(p)).join(' & '); + persons.map(p => sol.personName(p)).join(' · '); + + +const ndash_fix_regexp = RegExp('\\s+-\\s+'); +const ndash_fix_replacement = ' – '; + +const fix_dash = (string) => + string.replace(ndash_fix_regexp, ndash_fix_replacement); + + +export { + process_data, + event_modus_string, + track_index, + person_names_concat, + fix_dash +} diff --git a/assets/js/htm/htm.d.ts b/assets/js/htm/htm.d.ts new file mode 100644 index 0000000..d5108ca --- /dev/null +++ b/assets/js/htm/htm.d.ts @@ -0,0 +1,6 @@ +declare const htm: { + bind( + h: (type: any, props: Record, ...children: any[]) => HResult + ): (strings: TemplateStringsArray, ...values: any[]) => HResult | HResult[]; +}; +export default htm; diff --git a/assets/js/htm/htm.js b/assets/js/htm/htm.js new file mode 100644 index 0000000..7c81f4b --- /dev/null +++ b/assets/js/htm/htm.js @@ -0,0 +1 @@ +!function(){var n=function(t,e,s,u){var r;e[0]=0;for(var h=1;h=5&&((u||!n&&5===s)&&(h.push(s,0,u,e),s=6),n&&(h.push(s,n,0,e),s=6)),u=""},a=0;a"===t?(s=1,u=""):u=t+u[0]:r?t===r?r="":u+=t:'"'===t||"'"===t?r=t:">"===t?(p(),s=1):s&&("="===t?(s=5,e=u,u=""):"/"===t&&(s<5||">"===n[a][o+1])?(p(),3===s&&(h=h[0]),s=h,(h=h[0]).push(2,0,s),s=0):" "===t||"\t"===t||"\n"===t||"\r"===t?(p(),s=2):u+=t),3===s&&"!--"===u&&(s=4,h=h[0])}return p(),h}(e)),s),arguments,[])).length>1?s:s[0]};"undefined"!=typeof module?module.exports=e:self.htm=e}(); diff --git a/assets/js/htm/htm.mjs b/assets/js/htm/htm.mjs new file mode 100644 index 0000000..4a6228f --- /dev/null +++ b/assets/js/htm/htm.mjs @@ -0,0 +1 @@ +var n=function(t,s,r,e){var u;s[0]=0;for(var h=1;h=5&&((e||!n&&5===r)&&(h.push(r,0,e,s),r=6),n&&(h.push(r,n,0,s),r=6)),e=""},a=0;a"===t?(r=1,e=""):e=t+e[0]:u?t===u?u="":e+=t:'"'===t||"'"===t?u=t:">"===t?(p(),r=1):r&&("="===t?(r=5,s=e,e=""):"/"===t&&(r<5||">"===n[a][l+1])?(p(),3===r&&(h=h[0]),r=h,(h=h[0]).push(2,0,r),r=0):" "===t||"\t"===t||"\n"===t||"\r"===t?(p(),r=2):e+=t),3===r&&"!--"===e&&(r=4,h=h[0])}return p(),h}(s)),r),arguments,[])).length>1?r:r[0]} diff --git a/assets/js/htm/htm.module.js b/assets/js/htm/htm.module.js new file mode 100644 index 0000000..4a6228f --- /dev/null +++ b/assets/js/htm/htm.module.js @@ -0,0 +1 @@ +var n=function(t,s,r,e){var u;s[0]=0;for(var h=1;h=5&&((e||!n&&5===r)&&(h.push(r,0,e,s),r=6),n&&(h.push(r,n,0,s),r=6)),e=""},a=0;a"===t?(r=1,e=""):e=t+e[0]:u?t===u?u="":e+=t:'"'===t||"'"===t?u=t:">"===t?(p(),r=1):r&&("="===t?(r=5,s=e,e=""):"/"===t&&(r<5||">"===n[a][l+1])?(p(),3===r&&(h=h[0]),r=h,(h=h[0]).push(2,0,r),r=0):" "===t||"\t"===t||"\n"===t||"\r"===t?(p(),r=2):e+=t),3===r&&"!--"===e&&(r=4,h=h[0])}return p(),h}(s)),r),arguments,[])).length>1?r:r[0]} diff --git a/assets/js/htm/htm.umd.js b/assets/js/htm/htm.umd.js new file mode 100644 index 0000000..81bc89f --- /dev/null +++ b/assets/js/htm/htm.umd.js @@ -0,0 +1 @@ +!function(n,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):n.htm=e()}(this,function(){var n=function(e,t,u,s){var r;t[0]=0;for(var p=1;p=5&&((s||!n&&5===u)&&(p.push(u,0,s,t),u=6),n&&(p.push(u,n,0,t),u=6)),s=""},o=0;o"===e?(u=1,s=""):s=e+s[0]:r?e===r?r="":s+=e:'"'===e||"'"===e?r=e:">"===e?(h(),u=1):u&&("="===e?(u=5,t=s,s=""):"/"===e&&(u<5||">"===n[o][f+1])?(h(),3===u&&(p=p[0]),u=p,(p=p[0]).push(2,0,u),u=0):" "===e||"\t"===e||"\n"===e||"\r"===e?(h(),u=2):s+=e),3===u&&"!--"===s&&(u=4,p=p[0])}return h(),p}(t)),u),arguments,[])).length>1?u:u[0]}}); diff --git a/assets/js/luxon/luxon.es6.js b/assets/js/luxon/luxon.es6.js new file mode 100644 index 0000000..8c91a1e --- /dev/null +++ b/assets/js/luxon/luxon.es6.js @@ -0,0 +1,6978 @@ +// these aren't really private, but nor are they really useful to document + +/** + * @private + */ +class LuxonError extends Error {} + +/** + * @private + */ +class InvalidDateTimeError extends LuxonError { + constructor(reason) { + super(`Invalid DateTime: ${reason.toMessage()}`); + } +} + +/** + * @private + */ +class InvalidIntervalError extends LuxonError { + constructor(reason) { + super(`Invalid Interval: ${reason.toMessage()}`); + } +} + +/** + * @private + */ +class InvalidDurationError extends LuxonError { + constructor(reason) { + super(`Invalid Duration: ${reason.toMessage()}`); + } +} + +/** + * @private + */ +class ConflictingSpecificationError extends LuxonError {} + +/** + * @private + */ +class InvalidUnitError extends LuxonError { + constructor(unit) { + super(`Invalid unit ${unit}`); + } +} + +/** + * @private + */ +class InvalidArgumentError extends LuxonError {} + +/** + * @private + */ +class ZoneIsAbstractError extends LuxonError { + constructor() { + super("Zone is an abstract class"); + } +} + +/** + * @private + */ + +const n = "numeric", + s = "short", + l = "long"; + +const DATE_SHORT = { + year: n, + month: n, + day: n, +}; + +const DATE_MED = { + year: n, + month: s, + day: n, +}; + +const DATE_MED_WITH_WEEKDAY = { + year: n, + month: s, + day: n, + weekday: s, +}; + +const DATE_FULL = { + year: n, + month: l, + day: n, +}; + +const DATE_HUGE = { + year: n, + month: l, + day: n, + weekday: l, +}; + +const TIME_SIMPLE = { + hour: n, + minute: n, +}; + +const TIME_WITH_SECONDS = { + hour: n, + minute: n, + second: n, +}; + +const TIME_WITH_SHORT_OFFSET = { + hour: n, + minute: n, + second: n, + timeZoneName: s, +}; + +const TIME_WITH_LONG_OFFSET = { + hour: n, + minute: n, + second: n, + timeZoneName: l, +}; + +const TIME_24_SIMPLE = { + hour: n, + minute: n, + hourCycle: "h23", +}; + +const TIME_24_WITH_SECONDS = { + hour: n, + minute: n, + second: n, + hourCycle: "h23", +}; + +const TIME_24_WITH_SHORT_OFFSET = { + hour: n, + minute: n, + second: n, + hourCycle: "h23", + timeZoneName: s, +}; + +const TIME_24_WITH_LONG_OFFSET = { + hour: n, + minute: n, + second: n, + hourCycle: "h23", + timeZoneName: l, +}; + +const DATETIME_SHORT = { + year: n, + month: n, + day: n, + hour: n, + minute: n, +}; + +const DATETIME_SHORT_WITH_SECONDS = { + year: n, + month: n, + day: n, + hour: n, + minute: n, + second: n, +}; + +const DATETIME_MED = { + year: n, + month: s, + day: n, + hour: n, + minute: n, +}; + +const DATETIME_MED_WITH_SECONDS = { + year: n, + month: s, + day: n, + hour: n, + minute: n, + second: n, +}; + +const DATETIME_MED_WITH_WEEKDAY = { + year: n, + month: s, + day: n, + weekday: s, + hour: n, + minute: n, +}; + +const DATETIME_FULL = { + year: n, + month: l, + day: n, + hour: n, + minute: n, + timeZoneName: s, +}; + +const DATETIME_FULL_WITH_SECONDS = { + year: n, + month: l, + day: n, + hour: n, + minute: n, + second: n, + timeZoneName: s, +}; + +const DATETIME_HUGE = { + year: n, + month: l, + day: n, + weekday: l, + hour: n, + minute: n, + timeZoneName: l, +}; + +const DATETIME_HUGE_WITH_SECONDS = { + year: n, + month: l, + day: n, + weekday: l, + hour: n, + minute: n, + second: n, + timeZoneName: l, +}; + +/* + This is just a junk drawer, containing anything used across multiple classes. + Because Luxon is small(ish), this should stay small and we won't worry about splitting + it up into, say, parsingUtil.js and basicUtil.js and so on. But they are divided up by feature area. +*/ + +/** + * @private + */ + +// TYPES + +function isUndefined(o) { + return typeof o === "undefined"; +} + +function isNumber(o) { + return typeof o === "number"; +} + +function isInteger(o) { + return typeof o === "number" && o % 1 === 0; +} + +function isString(o) { + return typeof o === "string"; +} + +function isDate(o) { + return Object.prototype.toString.call(o) === "[object Date]"; +} + +// CAPABILITIES + +function hasRelative() { + try { + return typeof Intl !== "undefined" && !!Intl.RelativeTimeFormat; + } catch (e) { + return false; + } +} + +// OBJECTS AND ARRAYS + +function maybeArray(thing) { + return Array.isArray(thing) ? thing : [thing]; +} + +function bestBy(arr, by, compare) { + if (arr.length === 0) { + return undefined; + } + return arr.reduce((best, next) => { + const pair = [by(next), next]; + if (!best) { + return pair; + } else if (compare(best[0], pair[0]) === best[0]) { + return best; + } else { + return pair; + } + }, null)[1]; +} + +function pick(obj, keys) { + return keys.reduce((a, k) => { + a[k] = obj[k]; + return a; + }, {}); +} + +function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +} + +// NUMBERS AND STRINGS + +function integerBetween(thing, bottom, top) { + return isInteger(thing) && thing >= bottom && thing <= top; +} + +// x % n but takes the sign of n instead of x +function floorMod(x, n) { + return x - n * Math.floor(x / n); +} + +function padStart(input, n = 2) { + const isNeg = input < 0; + let padded; + if (isNeg) { + padded = "-" + ("" + -input).padStart(n, "0"); + } else { + padded = ("" + input).padStart(n, "0"); + } + return padded; +} + +function parseInteger(string) { + if (isUndefined(string) || string === null || string === "") { + return undefined; + } else { + return parseInt(string, 10); + } +} + +function parseFloating(string) { + if (isUndefined(string) || string === null || string === "") { + return undefined; + } else { + return parseFloat(string); + } +} + +function parseMillis(fraction) { + // Return undefined (instead of 0) in these cases, where fraction is not set + if (isUndefined(fraction) || fraction === null || fraction === "") { + return undefined; + } else { + const f = parseFloat("0." + fraction) * 1000; + return Math.floor(f); + } +} + +function roundTo(number, digits, towardZero = false) { + const factor = 10 ** digits, + rounder = towardZero ? Math.trunc : Math.round; + return rounder(number * factor) / factor; +} + +// DATE BASICS + +function isLeapYear(year) { + return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0); +} + +function daysInYear(year) { + return isLeapYear(year) ? 366 : 365; +} + +function daysInMonth(year, month) { + const modMonth = floorMod(month - 1, 12) + 1, + modYear = year + (month - modMonth) / 12; + + if (modMonth === 2) { + return isLeapYear(modYear) ? 29 : 28; + } else { + return [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][modMonth - 1]; + } +} + +// covert a calendar object to a local timestamp (epoch, but with the offset baked in) +function objToLocalTS(obj) { + let d = Date.UTC( + obj.year, + obj.month - 1, + obj.day, + obj.hour, + obj.minute, + obj.second, + obj.millisecond + ); + + // for legacy reasons, years between 0 and 99 are interpreted as 19XX; revert that + if (obj.year < 100 && obj.year >= 0) { + d = new Date(d); + d.setUTCFullYear(d.getUTCFullYear() - 1900); + } + return +d; +} + +function weeksInWeekYear(weekYear) { + const p1 = + (weekYear + + Math.floor(weekYear / 4) - + Math.floor(weekYear / 100) + + Math.floor(weekYear / 400)) % + 7, + last = weekYear - 1, + p2 = (last + Math.floor(last / 4) - Math.floor(last / 100) + Math.floor(last / 400)) % 7; + return p1 === 4 || p2 === 3 ? 53 : 52; +} + +function untruncateYear(year) { + if (year > 99) { + return year; + } else return year > 60 ? 1900 + year : 2000 + year; +} + +// PARSING + +function parseZoneInfo(ts, offsetFormat, locale, timeZone = null) { + const date = new Date(ts), + intlOpts = { + hourCycle: "h23", + year: "numeric", + month: "2-digit", + day: "2-digit", + hour: "2-digit", + minute: "2-digit", + }; + + if (timeZone) { + intlOpts.timeZone = timeZone; + } + + const modified = { timeZoneName: offsetFormat, ...intlOpts }; + + const parsed = new Intl.DateTimeFormat(locale, modified) + .formatToParts(date) + .find((m) => m.type.toLowerCase() === "timezonename"); + return parsed ? parsed.value : null; +} + +// signedOffset('-5', '30') -> -330 +function signedOffset(offHourStr, offMinuteStr) { + let offHour = parseInt(offHourStr, 10); + + // don't || this because we want to preserve -0 + if (Number.isNaN(offHour)) { + offHour = 0; + } + + const offMin = parseInt(offMinuteStr, 10) || 0, + offMinSigned = offHour < 0 || Object.is(offHour, -0) ? -offMin : offMin; + return offHour * 60 + offMinSigned; +} + +// COERCION + +function asNumber(value) { + const numericValue = Number(value); + if (typeof value === "boolean" || value === "" || Number.isNaN(numericValue)) + throw new InvalidArgumentError(`Invalid unit value ${value}`); + return numericValue; +} + +function normalizeObject(obj, normalizer) { + const normalized = {}; + for (const u in obj) { + if (hasOwnProperty(obj, u)) { + const v = obj[u]; + if (v === undefined || v === null) continue; + normalized[normalizer(u)] = asNumber(v); + } + } + return normalized; +} + +function formatOffset(offset, format) { + const hours = Math.trunc(Math.abs(offset / 60)), + minutes = Math.trunc(Math.abs(offset % 60)), + sign = offset >= 0 ? "+" : "-"; + + switch (format) { + case "short": + return `${sign}${padStart(hours, 2)}:${padStart(minutes, 2)}`; + case "narrow": + return `${sign}${hours}${minutes > 0 ? `:${minutes}` : ""}`; + case "techie": + return `${sign}${padStart(hours, 2)}${padStart(minutes, 2)}`; + default: + throw new RangeError(`Value format ${format} is out of range for property format`); + } +} + +function timeObject(obj) { + return pick(obj, ["hour", "minute", "second", "millisecond"]); +} + +const ianaRegex = /[A-Za-z_+-]{1,256}(:?\/[A-Za-z0-9_+-]{1,256}(\/[A-Za-z0-9_+-]{1,256})?)?/; + +/** + * @private + */ + +const monthsLong = [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December", +]; + +const monthsShort = [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec", +]; + +const monthsNarrow = ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"]; + +function months(length) { + switch (length) { + case "narrow": + return [...monthsNarrow]; + case "short": + return [...monthsShort]; + case "long": + return [...monthsLong]; + case "numeric": + return ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"]; + case "2-digit": + return ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"]; + default: + return null; + } +} + +const weekdaysLong = [ + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", + "Sunday", +]; + +const weekdaysShort = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]; + +const weekdaysNarrow = ["M", "T", "W", "T", "F", "S", "S"]; + +function weekdays(length) { + switch (length) { + case "narrow": + return [...weekdaysNarrow]; + case "short": + return [...weekdaysShort]; + case "long": + return [...weekdaysLong]; + case "numeric": + return ["1", "2", "3", "4", "5", "6", "7"]; + default: + return null; + } +} + +const meridiems = ["AM", "PM"]; + +const erasLong = ["Before Christ", "Anno Domini"]; + +const erasShort = ["BC", "AD"]; + +const erasNarrow = ["B", "A"]; + +function eras(length) { + switch (length) { + case "narrow": + return [...erasNarrow]; + case "short": + return [...erasShort]; + case "long": + return [...erasLong]; + default: + return null; + } +} + +function meridiemForDateTime(dt) { + return meridiems[dt.hour < 12 ? 0 : 1]; +} + +function weekdayForDateTime(dt, length) { + return weekdays(length)[dt.weekday - 1]; +} + +function monthForDateTime(dt, length) { + return months(length)[dt.month - 1]; +} + +function eraForDateTime(dt, length) { + return eras(length)[dt.year < 0 ? 0 : 1]; +} + +function formatRelativeTime(unit, count, numeric = "always", narrow = false) { + const units = { + years: ["year", "yr."], + quarters: ["quarter", "qtr."], + months: ["month", "mo."], + weeks: ["week", "wk."], + days: ["day", "day", "days"], + hours: ["hour", "hr."], + minutes: ["minute", "min."], + seconds: ["second", "sec."], + }; + + const lastable = ["hours", "minutes", "seconds"].indexOf(unit) === -1; + + if (numeric === "auto" && lastable) { + const isDay = unit === "days"; + switch (count) { + case 1: + return isDay ? "tomorrow" : `next ${units[unit][0]}`; + case -1: + return isDay ? "yesterday" : `last ${units[unit][0]}`; + case 0: + return isDay ? "today" : `this ${units[unit][0]}`; + } + } + + const isInPast = Object.is(count, -0) || count < 0, + fmtValue = Math.abs(count), + singular = fmtValue === 1, + lilUnits = units[unit], + fmtUnit = narrow + ? singular + ? lilUnits[1] + : lilUnits[2] || lilUnits[1] + : singular + ? units[unit][0] + : unit; + return isInPast ? `${fmtValue} ${fmtUnit} ago` : `in ${fmtValue} ${fmtUnit}`; +} + +function stringifyTokens(splits, tokenToString) { + let s = ""; + for (const token of splits) { + if (token.literal) { + s += token.val; + } else { + s += tokenToString(token.val); + } + } + return s; +} + +const macroTokenToFormatOpts = { + D: DATE_SHORT, + DD: DATE_MED, + DDD: DATE_FULL, + DDDD: DATE_HUGE, + t: TIME_SIMPLE, + tt: TIME_WITH_SECONDS, + ttt: TIME_WITH_SHORT_OFFSET, + tttt: TIME_WITH_LONG_OFFSET, + T: TIME_24_SIMPLE, + TT: TIME_24_WITH_SECONDS, + TTT: TIME_24_WITH_SHORT_OFFSET, + TTTT: TIME_24_WITH_LONG_OFFSET, + f: DATETIME_SHORT, + ff: DATETIME_MED, + fff: DATETIME_FULL, + ffff: DATETIME_HUGE, + F: DATETIME_SHORT_WITH_SECONDS, + FF: DATETIME_MED_WITH_SECONDS, + FFF: DATETIME_FULL_WITH_SECONDS, + FFFF: DATETIME_HUGE_WITH_SECONDS, +}; + +/** + * @private + */ + +class Formatter { + static create(locale, opts = {}) { + return new Formatter(locale, opts); + } + + static parseFormat(fmt) { + let current = null, + currentFull = "", + bracketed = false; + const splits = []; + for (let i = 0; i < fmt.length; i++) { + const c = fmt.charAt(i); + if (c === "'") { + if (currentFull.length > 0) { + splits.push({ literal: bracketed, val: currentFull }); + } + current = null; + currentFull = ""; + bracketed = !bracketed; + } else if (bracketed) { + currentFull += c; + } else if (c === current) { + currentFull += c; + } else { + if (currentFull.length > 0) { + splits.push({ literal: false, val: currentFull }); + } + currentFull = c; + current = c; + } + } + + if (currentFull.length > 0) { + splits.push({ literal: bracketed, val: currentFull }); + } + + return splits; + } + + static macroTokenToFormatOpts(token) { + return macroTokenToFormatOpts[token]; + } + + constructor(locale, formatOpts) { + this.opts = formatOpts; + this.loc = locale; + this.systemLoc = null; + } + + formatWithSystemDefault(dt, opts) { + if (this.systemLoc === null) { + this.systemLoc = this.loc.redefaultToSystem(); + } + const df = this.systemLoc.dtFormatter(dt, { ...this.opts, ...opts }); + return df.format(); + } + + formatDateTime(dt, opts = {}) { + const df = this.loc.dtFormatter(dt, { ...this.opts, ...opts }); + return df.format(); + } + + formatDateTimeParts(dt, opts = {}) { + const df = this.loc.dtFormatter(dt, { ...this.opts, ...opts }); + return df.formatToParts(); + } + + resolvedOptions(dt, opts = {}) { + const df = this.loc.dtFormatter(dt, { ...this.opts, ...opts }); + return df.resolvedOptions(); + } + + num(n, p = 0) { + // we get some perf out of doing this here, annoyingly + if (this.opts.forceSimple) { + return padStart(n, p); + } + + const opts = { ...this.opts }; + + if (p > 0) { + opts.padTo = p; + } + + return this.loc.numberFormatter(opts).format(n); + } + + formatDateTimeFromString(dt, fmt) { + const knownEnglish = this.loc.listingMode() === "en", + useDateTimeFormatter = this.loc.outputCalendar && this.loc.outputCalendar !== "gregory", + string = (opts, extract) => this.loc.extract(dt, opts, extract), + formatOffset = (opts) => { + if (dt.isOffsetFixed && dt.offset === 0 && opts.allowZ) { + return "Z"; + } + + return dt.isValid ? dt.zone.formatOffset(dt.ts, opts.format) : ""; + }, + meridiem = () => + knownEnglish + ? meridiemForDateTime(dt) + : string({ hour: "numeric", hourCycle: "h12" }, "dayperiod"), + month = (length, standalone) => + knownEnglish + ? monthForDateTime(dt, length) + : string(standalone ? { month: length } : { month: length, day: "numeric" }, "month"), + weekday = (length, standalone) => + knownEnglish + ? weekdayForDateTime(dt, length) + : string( + standalone ? { weekday: length } : { weekday: length, month: "long", day: "numeric" }, + "weekday" + ), + maybeMacro = (token) => { + const formatOpts = Formatter.macroTokenToFormatOpts(token); + if (formatOpts) { + return this.formatWithSystemDefault(dt, formatOpts); + } else { + return token; + } + }, + era = (length) => + knownEnglish ? eraForDateTime(dt, length) : string({ era: length }, "era"), + tokenToString = (token) => { + // Where possible: http://cldr.unicode.org/translation/date-time-1/date-time#TOC-Standalone-vs.-Format-Styles + switch (token) { + // ms + case "S": + return this.num(dt.millisecond); + case "u": + // falls through + case "SSS": + return this.num(dt.millisecond, 3); + // seconds + case "s": + return this.num(dt.second); + case "ss": + return this.num(dt.second, 2); + // fractional seconds + case "uu": + return this.num(Math.floor(dt.millisecond / 10), 2); + case "uuu": + return this.num(Math.floor(dt.millisecond / 100)); + // minutes + case "m": + return this.num(dt.minute); + case "mm": + return this.num(dt.minute, 2); + // hours + case "h": + return this.num(dt.hour % 12 === 0 ? 12 : dt.hour % 12); + case "hh": + return this.num(dt.hour % 12 === 0 ? 12 : dt.hour % 12, 2); + case "H": + return this.num(dt.hour); + case "HH": + return this.num(dt.hour, 2); + // offset + case "Z": + // like +6 + return formatOffset({ format: "narrow", allowZ: this.opts.allowZ }); + case "ZZ": + // like +06:00 + return formatOffset({ format: "short", allowZ: this.opts.allowZ }); + case "ZZZ": + // like +0600 + return formatOffset({ format: "techie", allowZ: this.opts.allowZ }); + case "ZZZZ": + // like EST + return dt.zone.offsetName(dt.ts, { format: "short", locale: this.loc.locale }); + case "ZZZZZ": + // like Eastern Standard Time + return dt.zone.offsetName(dt.ts, { format: "long", locale: this.loc.locale }); + // zone + case "z": + // like America/New_York + return dt.zoneName; + // meridiems + case "a": + return meridiem(); + // dates + case "d": + return useDateTimeFormatter ? string({ day: "numeric" }, "day") : this.num(dt.day); + case "dd": + return useDateTimeFormatter ? string({ day: "2-digit" }, "day") : this.num(dt.day, 2); + // weekdays - standalone + case "c": + // like 1 + return this.num(dt.weekday); + case "ccc": + // like 'Tues' + return weekday("short", true); + case "cccc": + // like 'Tuesday' + return weekday("long", true); + case "ccccc": + // like 'T' + return weekday("narrow", true); + // weekdays - format + case "E": + // like 1 + return this.num(dt.weekday); + case "EEE": + // like 'Tues' + return weekday("short", false); + case "EEEE": + // like 'Tuesday' + return weekday("long", false); + case "EEEEE": + // like 'T' + return weekday("narrow", false); + // months - standalone + case "L": + // like 1 + return useDateTimeFormatter + ? string({ month: "numeric", day: "numeric" }, "month") + : this.num(dt.month); + case "LL": + // like 01, doesn't seem to work + return useDateTimeFormatter + ? string({ month: "2-digit", day: "numeric" }, "month") + : this.num(dt.month, 2); + case "LLL": + // like Jan + return month("short", true); + case "LLLL": + // like January + return month("long", true); + case "LLLLL": + // like J + return month("narrow", true); + // months - format + case "M": + // like 1 + return useDateTimeFormatter + ? string({ month: "numeric" }, "month") + : this.num(dt.month); + case "MM": + // like 01 + return useDateTimeFormatter + ? string({ month: "2-digit" }, "month") + : this.num(dt.month, 2); + case "MMM": + // like Jan + return month("short", false); + case "MMMM": + // like January + return month("long", false); + case "MMMMM": + // like J + return month("narrow", false); + // years + case "y": + // like 2014 + return useDateTimeFormatter ? string({ year: "numeric" }, "year") : this.num(dt.year); + case "yy": + // like 14 + return useDateTimeFormatter + ? string({ year: "2-digit" }, "year") + : this.num(dt.year.toString().slice(-2), 2); + case "yyyy": + // like 0012 + return useDateTimeFormatter + ? string({ year: "numeric" }, "year") + : this.num(dt.year, 4); + case "yyyyyy": + // like 000012 + return useDateTimeFormatter + ? string({ year: "numeric" }, "year") + : this.num(dt.year, 6); + // eras + case "G": + // like AD + return era("short"); + case "GG": + // like Anno Domini + return era("long"); + case "GGGGG": + return era("narrow"); + case "kk": + return this.num(dt.weekYear.toString().slice(-2), 2); + case "kkkk": + return this.num(dt.weekYear, 4); + case "W": + return this.num(dt.weekNumber); + case "WW": + return this.num(dt.weekNumber, 2); + case "o": + return this.num(dt.ordinal); + case "ooo": + return this.num(dt.ordinal, 3); + case "q": + // like 1 + return this.num(dt.quarter); + case "qq": + // like 01 + return this.num(dt.quarter, 2); + case "X": + return this.num(Math.floor(dt.ts / 1000)); + case "x": + return this.num(dt.ts); + default: + return maybeMacro(token); + } + }; + + return stringifyTokens(Formatter.parseFormat(fmt), tokenToString); + } + + formatDurationFromString(dur, fmt) { + const tokenToField = (token) => { + switch (token[0]) { + case "S": + return "millisecond"; + case "s": + return "second"; + case "m": + return "minute"; + case "h": + return "hour"; + case "d": + return "day"; + case "M": + return "month"; + case "y": + return "year"; + default: + return null; + } + }, + tokenToString = (lildur) => (token) => { + const mapped = tokenToField(token); + if (mapped) { + return this.num(lildur.get(mapped), token.length); + } else { + return token; + } + }, + tokens = Formatter.parseFormat(fmt), + realTokens = tokens.reduce( + (found, { literal, val }) => (literal ? found : found.concat(val)), + [] + ), + collapsed = dur.shiftTo(...realTokens.map(tokenToField).filter((t) => t)); + return stringifyTokens(tokens, tokenToString(collapsed)); + } +} + +class Invalid { + constructor(reason, explanation) { + this.reason = reason; + this.explanation = explanation; + } + + toMessage() { + if (this.explanation) { + return `${this.reason}: ${this.explanation}`; + } else { + return this.reason; + } + } +} + +/** + * @interface + */ +class Zone { + /** + * The type of zone + * @abstract + * @type {string} + */ + get type() { + throw new ZoneIsAbstractError(); + } + + /** + * The name of this zone. + * @abstract + * @type {string} + */ + get name() { + throw new ZoneIsAbstractError(); + } + + /** + * Returns whether the offset is known to be fixed for the whole year. + * @abstract + * @type {boolean} + */ + get isUniversal() { + throw new ZoneIsAbstractError(); + } + + /** + * Returns the offset's common name (such as EST) at the specified timestamp + * @abstract + * @param {number} ts - Epoch milliseconds for which to get the name + * @param {Object} opts - Options to affect the format + * @param {string} opts.format - What style of offset to return. Accepts 'long' or 'short'. + * @param {string} opts.locale - What locale to return the offset name in. + * @return {string} + */ + offsetName(ts, opts) { + throw new ZoneIsAbstractError(); + } + + /** + * Returns the offset's value as a string + * @abstract + * @param {number} ts - Epoch milliseconds for which to get the offset + * @param {string} format - What style of offset to return. + * Accepts 'narrow', 'short', or 'techie'. Returning '+6', '+06:00', or '+0600' respectively + * @return {string} + */ + formatOffset(ts, format) { + throw new ZoneIsAbstractError(); + } + + /** + * Return the offset in minutes for this zone at the specified timestamp. + * @abstract + * @param {number} ts - Epoch milliseconds for which to compute the offset + * @return {number} + */ + offset(ts) { + throw new ZoneIsAbstractError(); + } + + /** + * Return whether this Zone is equal to another zone + * @abstract + * @param {Zone} otherZone - the zone to compare + * @return {boolean} + */ + equals(otherZone) { + throw new ZoneIsAbstractError(); + } + + /** + * Return whether this Zone is valid. + * @abstract + * @type {boolean} + */ + get isValid() { + throw new ZoneIsAbstractError(); + } +} + +let singleton$1 = null; + +/** + * Represents the local zone for this JavaScript environment. + * @implements {Zone} + */ +class SystemZone extends Zone { + /** + * Get a singleton instance of the local zone + * @return {SystemZone} + */ + static get instance() { + if (singleton$1 === null) { + singleton$1 = new SystemZone(); + } + return singleton$1; + } + + /** @override **/ + get type() { + return "system"; + } + + /** @override **/ + get name() { + return new Intl.DateTimeFormat().resolvedOptions().timeZone; + } + + /** @override **/ + get isUniversal() { + return false; + } + + /** @override **/ + offsetName(ts, { format, locale }) { + return parseZoneInfo(ts, format, locale); + } + + /** @override **/ + formatOffset(ts, format) { + return formatOffset(this.offset(ts), format); + } + + /** @override **/ + offset(ts) { + return -new Date(ts).getTimezoneOffset(); + } + + /** @override **/ + equals(otherZone) { + return otherZone.type === "system"; + } + + /** @override **/ + get isValid() { + return true; + } +} + +const matchingRegex = RegExp(`^${ianaRegex.source}$`); + +let dtfCache = {}; +function makeDTF(zone) { + if (!dtfCache[zone]) { + dtfCache[zone] = new Intl.DateTimeFormat("en-US", { + hour12: false, + timeZone: zone, + year: "numeric", + month: "2-digit", + day: "2-digit", + hour: "2-digit", + minute: "2-digit", + second: "2-digit", + }); + } + return dtfCache[zone]; +} + +const typeToPos = { + year: 0, + month: 1, + day: 2, + hour: 3, + minute: 4, + second: 5, +}; + +function hackyOffset(dtf, date) { + const formatted = dtf.format(date).replace(/\u200E/g, ""), + parsed = /(\d+)\/(\d+)\/(\d+),? (\d+):(\d+):(\d+)/.exec(formatted), + [, fMonth, fDay, fYear, fHour, fMinute, fSecond] = parsed; + return [fYear, fMonth, fDay, fHour, fMinute, fSecond]; +} + +function partsOffset(dtf, date) { + const formatted = dtf.formatToParts(date), + filled = []; + for (let i = 0; i < formatted.length; i++) { + const { type, value } = formatted[i], + pos = typeToPos[type]; + + if (!isUndefined(pos)) { + filled[pos] = parseInt(value, 10); + } + } + return filled; +} + +let ianaZoneCache = {}; +/** + * A zone identified by an IANA identifier, like America/New_York + * @implements {Zone} + */ +class IANAZone extends Zone { + /** + * @param {string} name - Zone name + * @return {IANAZone} + */ + static create(name) { + if (!ianaZoneCache[name]) { + ianaZoneCache[name] = new IANAZone(name); + } + return ianaZoneCache[name]; + } + + /** + * Reset local caches. Should only be necessary in testing scenarios. + * @return {void} + */ + static resetCache() { + ianaZoneCache = {}; + dtfCache = {}; + } + + /** + * Returns whether the provided string is a valid specifier. This only checks the string's format, not that the specifier identifies a known zone; see isValidZone for that. + * @param {string} s - The string to check validity on + * @example IANAZone.isValidSpecifier("America/New_York") //=> true + * @example IANAZone.isValidSpecifier("Fantasia/Castle") //=> true + * @example IANAZone.isValidSpecifier("Sport~~blorp") //=> false + * @return {boolean} + */ + static isValidSpecifier(s) { + return !!(s && s.match(matchingRegex)); + } + + /** + * Returns whether the provided string identifies a real zone + * @param {string} zone - The string to check + * @example IANAZone.isValidZone("America/New_York") //=> true + * @example IANAZone.isValidZone("Fantasia/Castle") //=> false + * @example IANAZone.isValidZone("Sport~~blorp") //=> false + * @return {boolean} + */ + static isValidZone(zone) { + if (!zone) { + return false; + } + try { + new Intl.DateTimeFormat("en-US", { timeZone: zone }).format(); + return true; + } catch (e) { + return false; + } + } + + constructor(name) { + super(); + /** @private **/ + this.zoneName = name; + /** @private **/ + this.valid = IANAZone.isValidZone(name); + } + + /** @override **/ + get type() { + return "iana"; + } + + /** @override **/ + get name() { + return this.zoneName; + } + + /** @override **/ + get isUniversal() { + return false; + } + + /** @override **/ + offsetName(ts, { format, locale }) { + return parseZoneInfo(ts, format, locale, this.name); + } + + /** @override **/ + formatOffset(ts, format) { + return formatOffset(this.offset(ts), format); + } + + /** @override **/ + offset(ts) { + const date = new Date(ts); + + if (isNaN(date)) return NaN; + + const dtf = makeDTF(this.name), + [year, month, day, hour, minute, second] = dtf.formatToParts + ? partsOffset(dtf, date) + : hackyOffset(dtf, date); + + // because we're using hour12 and https://bugs.chromium.org/p/chromium/issues/detail?id=1025564&can=2&q=%2224%3A00%22%20datetimeformat + const adjustedHour = hour === 24 ? 0 : hour; + + const asUTC = objToLocalTS({ + year, + month, + day, + hour: adjustedHour, + minute, + second, + millisecond: 0, + }); + + let asTS = +date; + const over = asTS % 1000; + asTS -= over >= 0 ? over : 1000 + over; + return (asUTC - asTS) / (60 * 1000); + } + + /** @override **/ + equals(otherZone) { + return otherZone.type === "iana" && otherZone.name === this.name; + } + + /** @override **/ + get isValid() { + return this.valid; + } +} + +let singleton = null; + +/** + * A zone with a fixed offset (meaning no DST) + * @implements {Zone} + */ +class FixedOffsetZone extends Zone { + /** + * Get a singleton instance of UTC + * @return {FixedOffsetZone} + */ + static get utcInstance() { + if (singleton === null) { + singleton = new FixedOffsetZone(0); + } + return singleton; + } + + /** + * Get an instance with a specified offset + * @param {number} offset - The offset in minutes + * @return {FixedOffsetZone} + */ + static instance(offset) { + return offset === 0 ? FixedOffsetZone.utcInstance : new FixedOffsetZone(offset); + } + + /** + * Get an instance of FixedOffsetZone from a UTC offset string, like "UTC+6" + * @param {string} s - The offset string to parse + * @example FixedOffsetZone.parseSpecifier("UTC+6") + * @example FixedOffsetZone.parseSpecifier("UTC+06") + * @example FixedOffsetZone.parseSpecifier("UTC-6:00") + * @return {FixedOffsetZone} + */ + static parseSpecifier(s) { + if (s) { + const r = s.match(/^utc(?:([+-]\d{1,2})(?::(\d{2}))?)?$/i); + if (r) { + return new FixedOffsetZone(signedOffset(r[1], r[2])); + } + } + return null; + } + + constructor(offset) { + super(); + /** @private **/ + this.fixed = offset; + } + + /** @override **/ + get type() { + return "fixed"; + } + + /** @override **/ + get name() { + return this.fixed === 0 ? "UTC" : `UTC${formatOffset(this.fixed, "narrow")}`; + } + + /** @override **/ + offsetName() { + return this.name; + } + + /** @override **/ + formatOffset(ts, format) { + return formatOffset(this.fixed, format); + } + + /** @override **/ + get isUniversal() { + return true; + } + + /** @override **/ + offset() { + return this.fixed; + } + + /** @override **/ + equals(otherZone) { + return otherZone.type === "fixed" && otherZone.fixed === this.fixed; + } + + /** @override **/ + get isValid() { + return true; + } +} + +/** + * A zone that failed to parse. You should never need to instantiate this. + * @implements {Zone} + */ +class InvalidZone extends Zone { + constructor(zoneName) { + super(); + /** @private */ + this.zoneName = zoneName; + } + + /** @override **/ + get type() { + return "invalid"; + } + + /** @override **/ + get name() { + return this.zoneName; + } + + /** @override **/ + get isUniversal() { + return false; + } + + /** @override **/ + offsetName() { + return null; + } + + /** @override **/ + formatOffset() { + return ""; + } + + /** @override **/ + offset() { + return NaN; + } + + /** @override **/ + equals() { + return false; + } + + /** @override **/ + get isValid() { + return false; + } +} + +/** + * @private + */ + +function normalizeZone(input, defaultZone) { + if (isUndefined(input) || input === null) { + return defaultZone; + } else if (input instanceof Zone) { + return input; + } else if (isString(input)) { + const lowered = input.toLowerCase(); + if (lowered === "local" || lowered === "system") return defaultZone; + else if (lowered === "utc" || lowered === "gmt") return FixedOffsetZone.utcInstance; + else if (IANAZone.isValidSpecifier(lowered)) return IANAZone.create(input); + else return FixedOffsetZone.parseSpecifier(lowered) || new InvalidZone(input); + } else if (isNumber(input)) { + return FixedOffsetZone.instance(input); + } else if (typeof input === "object" && input.offset && typeof input.offset === "number") { + // This is dumb, but the instanceof check above doesn't seem to really work + // so we're duck checking it + return input; + } else { + return new InvalidZone(input); + } +} + +let now = () => Date.now(), + defaultZone = "system", + defaultLocale = null, + defaultNumberingSystem = null, + defaultOutputCalendar = null, + throwOnInvalid; + +/** + * Settings contains static getters and setters that control Luxon's overall behavior. Luxon is a simple library with few options, but the ones it does have live here. + */ +class Settings { + /** + * Get the callback for returning the current timestamp. + * @type {function} + */ + static get now() { + return now; + } + + /** + * Set the callback for returning the current timestamp. + * The function should return a number, which will be interpreted as an Epoch millisecond count + * @type {function} + * @example Settings.now = () => Date.now() + 3000 // pretend it is 3 seconds in the future + * @example Settings.now = () => 0 // always pretend it's Jan 1, 1970 at midnight in UTC time + */ + static set now(n) { + now = n; + } + + /** + * Set the default time zone to create DateTimes in. Does not affect existing instances. + * Use the value "system" to reset this value to the system's time zone. + * @type {string} + */ + static set defaultZone(zone) { + defaultZone = zone; + } + + /** + * Get the default time zone object currently used to create DateTimes. Does not affect existing instances. + * The default value is the system's time zone (the one set on the machine that runs this code). + * @type {Zone} + */ + static get defaultZone() { + return normalizeZone(defaultZone, SystemZone.instance); + } + + /** + * Get the default locale to create DateTimes with. Does not affect existing instances. + * @type {string} + */ + static get defaultLocale() { + return defaultLocale; + } + + /** + * Set the default locale to create DateTimes with. Does not affect existing instances. + * @type {string} + */ + static set defaultLocale(locale) { + defaultLocale = locale; + } + + /** + * Get the default numbering system to create DateTimes with. Does not affect existing instances. + * @type {string} + */ + static get defaultNumberingSystem() { + return defaultNumberingSystem; + } + + /** + * Set the default numbering system to create DateTimes with. Does not affect existing instances. + * @type {string} + */ + static set defaultNumberingSystem(numberingSystem) { + defaultNumberingSystem = numberingSystem; + } + + /** + * Get the default output calendar to create DateTimes with. Does not affect existing instances. + * @type {string} + */ + static get defaultOutputCalendar() { + return defaultOutputCalendar; + } + + /** + * Set the default output calendar to create DateTimes with. Does not affect existing instances. + * @type {string} + */ + static set defaultOutputCalendar(outputCalendar) { + defaultOutputCalendar = outputCalendar; + } + + /** + * Get whether Luxon will throw when it encounters invalid DateTimes, Durations, or Intervals + * @type {boolean} + */ + static get throwOnInvalid() { + return throwOnInvalid; + } + + /** + * Set whether Luxon will throw when it encounters invalid DateTimes, Durations, or Intervals + * @type {boolean} + */ + static set throwOnInvalid(t) { + throwOnInvalid = t; + } + + /** + * Reset Luxon's global caches. Should only be necessary in testing scenarios. + * @return {void} + */ + static resetCaches() { + Locale.resetCache(); + IANAZone.resetCache(); + } +} + +// todo - remap caching + +let intlLFCache = {}; +function getCachedLF(locString, opts = {}) { + const key = JSON.stringify([locString, opts]); + let dtf = intlLFCache[key]; + if (!dtf) { + dtf = new Intl.ListFormat(locString, opts); + intlLFCache[key] = dtf; + } + return dtf; +} + +let intlDTCache = {}; +function getCachedDTF(locString, opts = {}) { + const key = JSON.stringify([locString, opts]); + let dtf = intlDTCache[key]; + if (!dtf) { + dtf = new Intl.DateTimeFormat(locString, opts); + intlDTCache[key] = dtf; + } + return dtf; +} + +let intlNumCache = {}; +function getCachedINF(locString, opts = {}) { + const key = JSON.stringify([locString, opts]); + let inf = intlNumCache[key]; + if (!inf) { + inf = new Intl.NumberFormat(locString, opts); + intlNumCache[key] = inf; + } + return inf; +} + +let intlRelCache = {}; +function getCachedRTF(locString, opts = {}) { + const { base, ...cacheKeyOpts } = opts; // exclude `base` from the options + const key = JSON.stringify([locString, cacheKeyOpts]); + let inf = intlRelCache[key]; + if (!inf) { + inf = new Intl.RelativeTimeFormat(locString, opts); + intlRelCache[key] = inf; + } + return inf; +} + +let sysLocaleCache = null; +function systemLocale() { + if (sysLocaleCache) { + return sysLocaleCache; + } else { + sysLocaleCache = new Intl.DateTimeFormat().resolvedOptions().locale; + return sysLocaleCache; + } +} + +function parseLocaleString(localeStr) { + // I really want to avoid writing a BCP 47 parser + // see, e.g. https://github.com/wooorm/bcp-47 + // Instead, we'll do this: + + // a) if the string has no -u extensions, just leave it alone + // b) if it does, use Intl to resolve everything + // c) if Intl fails, try again without the -u + + const uIndex = localeStr.indexOf("-u-"); + if (uIndex === -1) { + return [localeStr]; + } else { + let options; + const smaller = localeStr.substring(0, uIndex); + try { + options = getCachedDTF(localeStr).resolvedOptions(); + } catch (e) { + options = getCachedDTF(smaller).resolvedOptions(); + } + + const { numberingSystem, calendar } = options; + // return the smaller one so that we can append the calendar and numbering overrides to it + return [smaller, numberingSystem, calendar]; + } +} + +function intlConfigString(localeStr, numberingSystem, outputCalendar) { + if (outputCalendar || numberingSystem) { + localeStr += "-u"; + + if (outputCalendar) { + localeStr += `-ca-${outputCalendar}`; + } + + if (numberingSystem) { + localeStr += `-nu-${numberingSystem}`; + } + return localeStr; + } else { + return localeStr; + } +} + +function mapMonths(f) { + const ms = []; + for (let i = 1; i <= 12; i++) { + const dt = DateTime.utc(2016, i, 1); + ms.push(f(dt)); + } + return ms; +} + +function mapWeekdays(f) { + const ms = []; + for (let i = 1; i <= 7; i++) { + const dt = DateTime.utc(2016, 11, 13 + i); + ms.push(f(dt)); + } + return ms; +} + +function listStuff(loc, length, defaultOK, englishFn, intlFn) { + const mode = loc.listingMode(defaultOK); + + if (mode === "error") { + return null; + } else if (mode === "en") { + return englishFn(length); + } else { + return intlFn(length); + } +} + +function supportsFastNumbers(loc) { + if (loc.numberingSystem && loc.numberingSystem !== "latn") { + return false; + } else { + return ( + loc.numberingSystem === "latn" || + !loc.locale || + loc.locale.startsWith("en") || + new Intl.DateTimeFormat(loc.intl).resolvedOptions().numberingSystem === "latn" + ); + } +} + +/** + * @private + */ + +class PolyNumberFormatter { + constructor(intl, forceSimple, opts) { + this.padTo = opts.padTo || 0; + this.floor = opts.floor || false; + + const { padTo, floor, ...otherOpts } = opts; + + if (!forceSimple || Object.keys(otherOpts).length > 0) { + const intlOpts = { useGrouping: false, ...opts }; + if (opts.padTo > 0) intlOpts.minimumIntegerDigits = opts.padTo; + this.inf = getCachedINF(intl, intlOpts); + } + } + + format(i) { + if (this.inf) { + const fixed = this.floor ? Math.floor(i) : i; + return this.inf.format(fixed); + } else { + // to match the browser's numberformatter defaults + const fixed = this.floor ? Math.floor(i) : roundTo(i, 3); + return padStart(fixed, this.padTo); + } + } +} + +/** + * @private + */ + +class PolyDateFormatter { + constructor(dt, intl, opts) { + this.opts = opts; + + let z; + if (dt.zone.isUniversal) { + // UTC-8 or Etc/UTC-8 are not part of tzdata, only Etc/GMT+8 and the like. + // That is why fixed-offset TZ is set to that unless it is: + // 1. Representing offset 0 when UTC is used to maintain previous behavior and does not become GMT. + // 2. Unsupported by the browser: + // - some do not support Etc/ + // - < Etc/GMT-14, > Etc/GMT+12, and 30-minute or 45-minute offsets are not part of tzdata + const gmtOffset = -1 * (dt.offset / 60); + const offsetZ = gmtOffset >= 0 ? `Etc/GMT+${gmtOffset}` : `Etc/GMT${gmtOffset}`; + if (dt.offset !== 0 && IANAZone.create(offsetZ).valid) { + z = offsetZ; + this.dt = dt; + } else { + // Not all fixed-offset zones like Etc/+4:30 are present in tzdata. + // So we have to make do. Two cases: + // 1. The format options tell us to show the zone. We can't do that, so the best + // we can do is format the date in UTC. + // 2. The format options don't tell us to show the zone. Then we can adjust them + // the time and tell the formatter to show it to us in UTC, so that the time is right + // and the bad zone doesn't show up. + z = "UTC"; + if (opts.timeZoneName) { + this.dt = dt; + } else { + this.dt = dt.offset === 0 ? dt : DateTime.fromMillis(dt.ts + dt.offset * 60 * 1000); + } + } + } else if (dt.zone.type === "system") { + this.dt = dt; + } else { + this.dt = dt; + z = dt.zone.name; + } + + const intlOpts = { ...this.opts }; + if (z) { + intlOpts.timeZone = z; + } + this.dtf = getCachedDTF(intl, intlOpts); + } + + format() { + return this.dtf.format(this.dt.toJSDate()); + } + + formatToParts() { + return this.dtf.formatToParts(this.dt.toJSDate()); + } + + resolvedOptions() { + return this.dtf.resolvedOptions(); + } +} + +/** + * @private + */ +class PolyRelFormatter { + constructor(intl, isEnglish, opts) { + this.opts = { style: "long", ...opts }; + if (!isEnglish && hasRelative()) { + this.rtf = getCachedRTF(intl, opts); + } + } + + format(count, unit) { + if (this.rtf) { + return this.rtf.format(count, unit); + } else { + return formatRelativeTime(unit, count, this.opts.numeric, this.opts.style !== "long"); + } + } + + formatToParts(count, unit) { + if (this.rtf) { + return this.rtf.formatToParts(count, unit); + } else { + return []; + } + } +} + +/** + * @private + */ + +class Locale { + static fromOpts(opts) { + return Locale.create(opts.locale, opts.numberingSystem, opts.outputCalendar, opts.defaultToEN); + } + + static create(locale, numberingSystem, outputCalendar, defaultToEN = false) { + const specifiedLocale = locale || Settings.defaultLocale; + // the system locale is useful for human readable strings but annoying for parsing/formatting known formats + const localeR = specifiedLocale || (defaultToEN ? "en-US" : systemLocale()); + const numberingSystemR = numberingSystem || Settings.defaultNumberingSystem; + const outputCalendarR = outputCalendar || Settings.defaultOutputCalendar; + return new Locale(localeR, numberingSystemR, outputCalendarR, specifiedLocale); + } + + static resetCache() { + sysLocaleCache = null; + intlDTCache = {}; + intlNumCache = {}; + intlRelCache = {}; + } + + static fromObject({ locale, numberingSystem, outputCalendar } = {}) { + return Locale.create(locale, numberingSystem, outputCalendar); + } + + constructor(locale, numbering, outputCalendar, specifiedLocale) { + const [parsedLocale, parsedNumberingSystem, parsedOutputCalendar] = parseLocaleString(locale); + + this.locale = parsedLocale; + this.numberingSystem = numbering || parsedNumberingSystem || null; + this.outputCalendar = outputCalendar || parsedOutputCalendar || null; + this.intl = intlConfigString(this.locale, this.numberingSystem, this.outputCalendar); + + this.weekdaysCache = { format: {}, standalone: {} }; + this.monthsCache = { format: {}, standalone: {} }; + this.meridiemCache = null; + this.eraCache = {}; + + this.specifiedLocale = specifiedLocale; + this.fastNumbersCached = null; + } + + get fastNumbers() { + if (this.fastNumbersCached == null) { + this.fastNumbersCached = supportsFastNumbers(this); + } + + return this.fastNumbersCached; + } + + listingMode() { + const isActuallyEn = this.isEnglish(); + const hasNoWeirdness = + (this.numberingSystem === null || this.numberingSystem === "latn") && + (this.outputCalendar === null || this.outputCalendar === "gregory"); + return isActuallyEn && hasNoWeirdness ? "en" : "intl"; + } + + clone(alts) { + if (!alts || Object.getOwnPropertyNames(alts).length === 0) { + return this; + } else { + return Locale.create( + alts.locale || this.specifiedLocale, + alts.numberingSystem || this.numberingSystem, + alts.outputCalendar || this.outputCalendar, + alts.defaultToEN || false + ); + } + } + + redefaultToEN(alts = {}) { + return this.clone({ ...alts, defaultToEN: true }); + } + + redefaultToSystem(alts = {}) { + return this.clone({ ...alts, defaultToEN: false }); + } + + months(length, format = false, defaultOK = true) { + return listStuff(this, length, defaultOK, months, () => { + const intl = format ? { month: length, day: "numeric" } : { month: length }, + formatStr = format ? "format" : "standalone"; + if (!this.monthsCache[formatStr][length]) { + this.monthsCache[formatStr][length] = mapMonths((dt) => this.extract(dt, intl, "month")); + } + return this.monthsCache[formatStr][length]; + }); + } + + weekdays(length, format = false, defaultOK = true) { + return listStuff(this, length, defaultOK, weekdays, () => { + const intl = format + ? { weekday: length, year: "numeric", month: "long", day: "numeric" } + : { weekday: length }, + formatStr = format ? "format" : "standalone"; + if (!this.weekdaysCache[formatStr][length]) { + this.weekdaysCache[formatStr][length] = mapWeekdays((dt) => + this.extract(dt, intl, "weekday") + ); + } + return this.weekdaysCache[formatStr][length]; + }); + } + + meridiems(defaultOK = true) { + return listStuff( + this, + undefined, + defaultOK, + () => meridiems, + () => { + // In theory there could be aribitrary day periods. We're gonna assume there are exactly two + // for AM and PM. This is probably wrong, but it's makes parsing way easier. + if (!this.meridiemCache) { + const intl = { hour: "numeric", hourCycle: "h12" }; + this.meridiemCache = [DateTime.utc(2016, 11, 13, 9), DateTime.utc(2016, 11, 13, 19)].map( + (dt) => this.extract(dt, intl, "dayperiod") + ); + } + + return this.meridiemCache; + } + ); + } + + eras(length, defaultOK = true) { + return listStuff(this, length, defaultOK, eras, () => { + const intl = { era: length }; + + // This is problematic. Different calendars are going to define eras totally differently. What I need is the minimum set of dates + // to definitely enumerate them. + if (!this.eraCache[length]) { + this.eraCache[length] = [DateTime.utc(-40, 1, 1), DateTime.utc(2017, 1, 1)].map((dt) => + this.extract(dt, intl, "era") + ); + } + + return this.eraCache[length]; + }); + } + + extract(dt, intlOpts, field) { + const df = this.dtFormatter(dt, intlOpts), + results = df.formatToParts(), + matching = results.find((m) => m.type.toLowerCase() === field); + return matching ? matching.value : null; + } + + numberFormatter(opts = {}) { + // this forcesimple option is never used (the only caller short-circuits on it, but it seems safer to leave) + // (in contrast, the rest of the condition is used heavily) + return new PolyNumberFormatter(this.intl, opts.forceSimple || this.fastNumbers, opts); + } + + dtFormatter(dt, intlOpts = {}) { + return new PolyDateFormatter(dt, this.intl, intlOpts); + } + + relFormatter(opts = {}) { + return new PolyRelFormatter(this.intl, this.isEnglish(), opts); + } + + listFormatter(opts = {}) { + return getCachedLF(this.intl, opts); + } + + isEnglish() { + return ( + this.locale === "en" || + this.locale.toLowerCase() === "en-us" || + new Intl.DateTimeFormat(this.intl).resolvedOptions().locale.startsWith("en-us") + ); + } + + equals(other) { + return ( + this.locale === other.locale && + this.numberingSystem === other.numberingSystem && + this.outputCalendar === other.outputCalendar + ); + } +} + +/* + * This file handles parsing for well-specified formats. Here's how it works: + * Two things go into parsing: a regex to match with and an extractor to take apart the groups in the match. + * An extractor is just a function that takes a regex match array and returns a { year: ..., month: ... } object + * parse() does the work of executing the regex and applying the extractor. It takes multiple regex/extractor pairs to try in sequence. + * Extractors can take a "cursor" representing the offset in the match to look at. This makes it easy to combine extractors. + * combineExtractors() does the work of combining them, keeping track of the cursor through multiple extractions. + * Some extractions are super dumb and simpleParse and fromStrings help DRY them. + */ + +function combineRegexes(...regexes) { + const full = regexes.reduce((f, r) => f + r.source, ""); + return RegExp(`^${full}$`); +} + +function combineExtractors(...extractors) { + return (m) => + extractors + .reduce( + ([mergedVals, mergedZone, cursor], ex) => { + const [val, zone, next] = ex(m, cursor); + return [{ ...mergedVals, ...val }, mergedZone || zone, next]; + }, + [{}, null, 1] + ) + .slice(0, 2); +} + +function parse(s, ...patterns) { + if (s == null) { + return [null, null]; + } + + for (const [regex, extractor] of patterns) { + const m = regex.exec(s); + if (m) { + return extractor(m); + } + } + return [null, null]; +} + +function simpleParse(...keys) { + return (match, cursor) => { + const ret = {}; + let i; + + for (i = 0; i < keys.length; i++) { + ret[keys[i]] = parseInteger(match[cursor + i]); + } + return [ret, null, cursor + i]; + }; +} + +// ISO and SQL parsing +const offsetRegex = /(?:(Z)|([+-]\d\d)(?::?(\d\d))?)/, + isoTimeBaseRegex = /(\d\d)(?::?(\d\d)(?::?(\d\d)(?:[.,](\d{1,30}))?)?)?/, + isoTimeRegex = RegExp(`${isoTimeBaseRegex.source}${offsetRegex.source}?`), + isoTimeExtensionRegex = RegExp(`(?:T${isoTimeRegex.source})?`), + isoYmdRegex = /([+-]\d{6}|\d{4})(?:-?(\d\d)(?:-?(\d\d))?)?/, + isoWeekRegex = /(\d{4})-?W(\d\d)(?:-?(\d))?/, + isoOrdinalRegex = /(\d{4})-?(\d{3})/, + extractISOWeekData = simpleParse("weekYear", "weekNumber", "weekDay"), + extractISOOrdinalData = simpleParse("year", "ordinal"), + sqlYmdRegex = /(\d{4})-(\d\d)-(\d\d)/, // dumbed-down version of the ISO one + sqlTimeRegex = RegExp( + `${isoTimeBaseRegex.source} ?(?:${offsetRegex.source}|(${ianaRegex.source}))?` + ), + sqlTimeExtensionRegex = RegExp(`(?: ${sqlTimeRegex.source})?`); + +function int(match, pos, fallback) { + const m = match[pos]; + return isUndefined(m) ? fallback : parseInteger(m); +} + +function extractISOYmd(match, cursor) { + const item = { + year: int(match, cursor), + month: int(match, cursor + 1, 1), + day: int(match, cursor + 2, 1), + }; + + return [item, null, cursor + 3]; +} + +function extractISOTime(match, cursor) { + const item = { + hours: int(match, cursor, 0), + minutes: int(match, cursor + 1, 0), + seconds: int(match, cursor + 2, 0), + milliseconds: parseMillis(match[cursor + 3]), + }; + + return [item, null, cursor + 4]; +} + +function extractISOOffset(match, cursor) { + const local = !match[cursor] && !match[cursor + 1], + fullOffset = signedOffset(match[cursor + 1], match[cursor + 2]), + zone = local ? null : FixedOffsetZone.instance(fullOffset); + return [{}, zone, cursor + 3]; +} + +function extractIANAZone(match, cursor) { + const zone = match[cursor] ? IANAZone.create(match[cursor]) : null; + return [{}, zone, cursor + 1]; +} + +// ISO time parsing + +const isoTimeOnly = RegExp(`^T?${isoTimeBaseRegex.source}$`); + +// ISO duration parsing + +const isoDuration = + /^-?P(?:(?:(-?\d{1,9}(?:\.\d{1,9})?)Y)?(?:(-?\d{1,9}(?:\.\d{1,9})?)M)?(?:(-?\d{1,9}(?:\.\d{1,9})?)W)?(?:(-?\d{1,9}(?:\.\d{1,9})?)D)?(?:T(?:(-?\d{1,9}(?:\.\d{1,9})?)H)?(?:(-?\d{1,9}(?:\.\d{1,9})?)M)?(?:(-?\d{1,20})(?:[.,](-?\d{1,9}))?S)?)?)$/; + +function extractISODuration(match) { + const [s, yearStr, monthStr, weekStr, dayStr, hourStr, minuteStr, secondStr, millisecondsStr] = + match; + + const hasNegativePrefix = s[0] === "-"; + const negativeSeconds = secondStr && secondStr[0] === "-"; + + const maybeNegate = (num, force = false) => + num !== undefined && (force || (num && hasNegativePrefix)) ? -num : num; + + return [ + { + years: maybeNegate(parseFloating(yearStr)), + months: maybeNegate(parseFloating(monthStr)), + weeks: maybeNegate(parseFloating(weekStr)), + days: maybeNegate(parseFloating(dayStr)), + hours: maybeNegate(parseFloating(hourStr)), + minutes: maybeNegate(parseFloating(minuteStr)), + seconds: maybeNegate(parseFloating(secondStr), secondStr === "-0"), + milliseconds: maybeNegate(parseMillis(millisecondsStr), negativeSeconds), + }, + ]; +} + +// These are a little braindead. EDT *should* tell us that we're in, say, America/New_York +// and not just that we're in -240 *right now*. But since I don't think these are used that often +// I'm just going to ignore that +const obsOffsets = { + GMT: 0, + EDT: -4 * 60, + EST: -5 * 60, + CDT: -5 * 60, + CST: -6 * 60, + MDT: -6 * 60, + MST: -7 * 60, + PDT: -7 * 60, + PST: -8 * 60, +}; + +function fromStrings(weekdayStr, yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) { + const result = { + year: yearStr.length === 2 ? untruncateYear(parseInteger(yearStr)) : parseInteger(yearStr), + month: monthsShort.indexOf(monthStr) + 1, + day: parseInteger(dayStr), + hour: parseInteger(hourStr), + minute: parseInteger(minuteStr), + }; + + if (secondStr) result.second = parseInteger(secondStr); + if (weekdayStr) { + result.weekday = + weekdayStr.length > 3 + ? weekdaysLong.indexOf(weekdayStr) + 1 + : weekdaysShort.indexOf(weekdayStr) + 1; + } + + return result; +} + +// RFC 2822/5322 +const rfc2822 = + /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|(?:([+-]\d\d)(\d\d)))$/; + +function extractRFC2822(match) { + const [ + , + weekdayStr, + dayStr, + monthStr, + yearStr, + hourStr, + minuteStr, + secondStr, + obsOffset, + milOffset, + offHourStr, + offMinuteStr, + ] = match, + result = fromStrings(weekdayStr, yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr); + + let offset; + if (obsOffset) { + offset = obsOffsets[obsOffset]; + } else if (milOffset) { + offset = 0; + } else { + offset = signedOffset(offHourStr, offMinuteStr); + } + + return [result, new FixedOffsetZone(offset)]; +} + +function preprocessRFC2822(s) { + // Remove comments and folding whitespace and replace multiple-spaces with a single space + return s + .replace(/\([^)]*\)|[\n\t]/g, " ") + .replace(/(\s\s+)/g, " ") + .trim(); +} + +// http date + +const rfc1123 = + /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun), (\d\d) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{4}) (\d\d):(\d\d):(\d\d) GMT$/, + rfc850 = + /^(Monday|Tuesday|Wedsday|Thursday|Friday|Saturday|Sunday), (\d\d)-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(\d\d) (\d\d):(\d\d):(\d\d) GMT$/, + ascii = + /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ( \d|\d\d) (\d\d):(\d\d):(\d\d) (\d{4})$/; + +function extractRFC1123Or850(match) { + const [, weekdayStr, dayStr, monthStr, yearStr, hourStr, minuteStr, secondStr] = match, + result = fromStrings(weekdayStr, yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr); + return [result, FixedOffsetZone.utcInstance]; +} + +function extractASCII(match) { + const [, weekdayStr, monthStr, dayStr, hourStr, minuteStr, secondStr, yearStr] = match, + result = fromStrings(weekdayStr, yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr); + return [result, FixedOffsetZone.utcInstance]; +} + +const isoYmdWithTimeExtensionRegex = combineRegexes(isoYmdRegex, isoTimeExtensionRegex); +const isoWeekWithTimeExtensionRegex = combineRegexes(isoWeekRegex, isoTimeExtensionRegex); +const isoOrdinalWithTimeExtensionRegex = combineRegexes(isoOrdinalRegex, isoTimeExtensionRegex); +const isoTimeCombinedRegex = combineRegexes(isoTimeRegex); + +const extractISOYmdTimeAndOffset = combineExtractors( + extractISOYmd, + extractISOTime, + extractISOOffset +); +const extractISOWeekTimeAndOffset = combineExtractors( + extractISOWeekData, + extractISOTime, + extractISOOffset +); +const extractISOOrdinalDateAndTime = combineExtractors( + extractISOOrdinalData, + extractISOTime, + extractISOOffset +); +const extractISOTimeAndOffset = combineExtractors(extractISOTime, extractISOOffset); + +/** + * @private + */ + +function parseISODate(s) { + return parse( + s, + [isoYmdWithTimeExtensionRegex, extractISOYmdTimeAndOffset], + [isoWeekWithTimeExtensionRegex, extractISOWeekTimeAndOffset], + [isoOrdinalWithTimeExtensionRegex, extractISOOrdinalDateAndTime], + [isoTimeCombinedRegex, extractISOTimeAndOffset] + ); +} + +function parseRFC2822Date(s) { + return parse(preprocessRFC2822(s), [rfc2822, extractRFC2822]); +} + +function parseHTTPDate(s) { + return parse( + s, + [rfc1123, extractRFC1123Or850], + [rfc850, extractRFC1123Or850], + [ascii, extractASCII] + ); +} + +function parseISODuration(s) { + return parse(s, [isoDuration, extractISODuration]); +} + +const extractISOTimeOnly = combineExtractors(extractISOTime); + +function parseISOTimeOnly(s) { + return parse(s, [isoTimeOnly, extractISOTimeOnly]); +} + +const sqlYmdWithTimeExtensionRegex = combineRegexes(sqlYmdRegex, sqlTimeExtensionRegex); +const sqlTimeCombinedRegex = combineRegexes(sqlTimeRegex); + +const extractISOYmdTimeOffsetAndIANAZone = combineExtractors( + extractISOYmd, + extractISOTime, + extractISOOffset, + extractIANAZone +); +const extractISOTimeOffsetAndIANAZone = combineExtractors( + extractISOTime, + extractISOOffset, + extractIANAZone +); + +function parseSQL(s) { + return parse( + s, + [sqlYmdWithTimeExtensionRegex, extractISOYmdTimeOffsetAndIANAZone], + [sqlTimeCombinedRegex, extractISOTimeOffsetAndIANAZone] + ); +} + +const INVALID$2 = "Invalid Duration"; + +// unit conversion constants +const lowOrderMatrix = { + weeks: { + days: 7, + hours: 7 * 24, + minutes: 7 * 24 * 60, + seconds: 7 * 24 * 60 * 60, + milliseconds: 7 * 24 * 60 * 60 * 1000, + }, + days: { + hours: 24, + minutes: 24 * 60, + seconds: 24 * 60 * 60, + milliseconds: 24 * 60 * 60 * 1000, + }, + hours: { minutes: 60, seconds: 60 * 60, milliseconds: 60 * 60 * 1000 }, + minutes: { seconds: 60, milliseconds: 60 * 1000 }, + seconds: { milliseconds: 1000 }, + }, + casualMatrix = { + years: { + quarters: 4, + months: 12, + weeks: 52, + days: 365, + hours: 365 * 24, + minutes: 365 * 24 * 60, + seconds: 365 * 24 * 60 * 60, + milliseconds: 365 * 24 * 60 * 60 * 1000, + }, + quarters: { + months: 3, + weeks: 13, + days: 91, + hours: 91 * 24, + minutes: 91 * 24 * 60, + seconds: 91 * 24 * 60 * 60, + milliseconds: 91 * 24 * 60 * 60 * 1000, + }, + months: { + weeks: 4, + days: 30, + hours: 30 * 24, + minutes: 30 * 24 * 60, + seconds: 30 * 24 * 60 * 60, + milliseconds: 30 * 24 * 60 * 60 * 1000, + }, + + ...lowOrderMatrix, + }, + daysInYearAccurate = 146097.0 / 400, + daysInMonthAccurate = 146097.0 / 4800, + accurateMatrix = { + years: { + quarters: 4, + months: 12, + weeks: daysInYearAccurate / 7, + days: daysInYearAccurate, + hours: daysInYearAccurate * 24, + minutes: daysInYearAccurate * 24 * 60, + seconds: daysInYearAccurate * 24 * 60 * 60, + milliseconds: daysInYearAccurate * 24 * 60 * 60 * 1000, + }, + quarters: { + months: 3, + weeks: daysInYearAccurate / 28, + days: daysInYearAccurate / 4, + hours: (daysInYearAccurate * 24) / 4, + minutes: (daysInYearAccurate * 24 * 60) / 4, + seconds: (daysInYearAccurate * 24 * 60 * 60) / 4, + milliseconds: (daysInYearAccurate * 24 * 60 * 60 * 1000) / 4, + }, + months: { + weeks: daysInMonthAccurate / 7, + days: daysInMonthAccurate, + hours: daysInMonthAccurate * 24, + minutes: daysInMonthAccurate * 24 * 60, + seconds: daysInMonthAccurate * 24 * 60 * 60, + milliseconds: daysInMonthAccurate * 24 * 60 * 60 * 1000, + }, + ...lowOrderMatrix, + }; + +// units ordered by size +const orderedUnits$1 = [ + "years", + "quarters", + "months", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", +]; + +const reverseUnits = orderedUnits$1.slice(0).reverse(); + +// clone really means "create another instance just like this one, but with these changes" +function clone$1(dur, alts, clear = false) { + // deep merge for vals + const conf = { + values: clear ? alts.values : { ...dur.values, ...(alts.values || {}) }, + loc: dur.loc.clone(alts.loc), + conversionAccuracy: alts.conversionAccuracy || dur.conversionAccuracy, + }; + return new Duration(conf); +} + +function antiTrunc(n) { + return n < 0 ? Math.floor(n) : Math.ceil(n); +} + +// NB: mutates parameters +function convert(matrix, fromMap, fromUnit, toMap, toUnit) { + const conv = matrix[toUnit][fromUnit], + raw = fromMap[fromUnit] / conv, + sameSign = Math.sign(raw) === Math.sign(toMap[toUnit]), + // ok, so this is wild, but see the matrix in the tests + added = + !sameSign && toMap[toUnit] !== 0 && Math.abs(raw) <= 1 ? antiTrunc(raw) : Math.trunc(raw); + toMap[toUnit] += added; + fromMap[fromUnit] -= added * conv; +} + +// NB: mutates parameters +function normalizeValues(matrix, vals) { + reverseUnits.reduce((previous, current) => { + if (!isUndefined(vals[current])) { + if (previous) { + convert(matrix, vals, previous, vals, current); + } + return current; + } else { + return previous; + } + }, null); +} + +/** + * A Duration object represents a period of time, like "2 months" or "1 day, 1 hour". Conceptually, it's just a map of units to their quantities, accompanied by some additional configuration and methods for creating, parsing, interrogating, transforming, and formatting them. They can be used on their own or in conjunction with other Luxon types; for example, you can use {@link DateTime#plus} to add a Duration object to a DateTime, producing another DateTime. + * + * Here is a brief overview of commonly used methods and getters in Duration: + * + * * **Creation** To create a Duration, use {@link Duration#fromMillis}, {@link Duration#fromObject}, or {@link Duration#fromISO}. + * * **Unit values** See the {@link Duration#years}, {@link Duration.months}, {@link Duration#weeks}, {@link Duration#days}, {@link Duration#hours}, {@link Duration#minutes}, {@link Duration#seconds}, {@link Duration#milliseconds} accessors. + * * **Configuration** See {@link Duration#locale} and {@link Duration#numberingSystem} accessors. + * * **Transformation** To create new Durations out of old ones use {@link Duration#plus}, {@link Duration#minus}, {@link Duration#normalize}, {@link Duration#set}, {@link Duration#reconfigure}, {@link Duration#shiftTo}, and {@link Duration#negate}. + * * **Output** To convert the Duration into other representations, see {@link Duration#as}, {@link Duration#toISO}, {@link Duration#toFormat}, and {@link Duration#toJSON} + * + * There's are more methods documented below. In addition, for more information on subtler topics like internationalization and validity, see the external documentation. + */ +class Duration { + /** + * @private + */ + constructor(config) { + const accurate = config.conversionAccuracy === "longterm" || false; + /** + * @access private + */ + this.values = config.values; + /** + * @access private + */ + this.loc = config.loc || Locale.create(); + /** + * @access private + */ + this.conversionAccuracy = accurate ? "longterm" : "casual"; + /** + * @access private + */ + this.invalid = config.invalid || null; + /** + * @access private + */ + this.matrix = accurate ? accurateMatrix : casualMatrix; + /** + * @access private + */ + this.isLuxonDuration = true; + } + + /** + * Create Duration from a number of milliseconds. + * @param {number} count of milliseconds + * @param {Object} opts - options for parsing + * @param {string} [opts.locale='en-US'] - the locale to use + * @param {string} opts.numberingSystem - the numbering system to use + * @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use + * @return {Duration} + */ + static fromMillis(count, opts) { + return Duration.fromObject({ milliseconds: count }, opts); + } + + /** + * Create a Duration from a JavaScript object with keys like 'years' and 'hours'. + * If this object is empty then a zero milliseconds duration is returned. + * @param {Object} obj - the object to create the DateTime from + * @param {number} obj.years + * @param {number} obj.quarters + * @param {number} obj.months + * @param {number} obj.weeks + * @param {number} obj.days + * @param {number} obj.hours + * @param {number} obj.minutes + * @param {number} obj.seconds + * @param {number} obj.milliseconds + * @param {Object} [opts=[]] - options for creating this Duration + * @param {string} [opts.locale='en-US'] - the locale to use + * @param {string} opts.numberingSystem - the numbering system to use + * @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use + * @return {Duration} + */ + static fromObject(obj, opts = {}) { + if (obj == null || typeof obj !== "object") { + throw new InvalidArgumentError( + `Duration.fromObject: argument expected to be an object, got ${ + obj === null ? "null" : typeof obj + }` + ); + } + + return new Duration({ + values: normalizeObject(obj, Duration.normalizeUnit), + loc: Locale.fromObject(opts), + conversionAccuracy: opts.conversionAccuracy, + }); + } + + /** + * Create a Duration from DurationLike. + * + * @param {Object | number | Duration} durationLike + * One of: + * - object with keys like 'years' and 'hours'. + * - number representing milliseconds + * - Duration instance + * @return {Duration} + */ + static fromDurationLike(durationLike) { + if (isNumber(durationLike)) { + return Duration.fromMillis(durationLike); + } else if (Duration.isDuration(durationLike)) { + return durationLike; + } else if (typeof durationLike === "object") { + return Duration.fromObject(durationLike); + } else { + throw new InvalidArgumentError( + `Unknown duration argument ${durationLike} of type ${typeof durationLike}` + ); + } + } + + /** + * Create a Duration from an ISO 8601 duration string. + * @param {string} text - text to parse + * @param {Object} opts - options for parsing + * @param {string} [opts.locale='en-US'] - the locale to use + * @param {string} opts.numberingSystem - the numbering system to use + * @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use + * @see https://en.wikipedia.org/wiki/ISO_8601#Durations + * @example Duration.fromISO('P3Y6M1W4DT12H30M5S').toObject() //=> { years: 3, months: 6, weeks: 1, days: 4, hours: 12, minutes: 30, seconds: 5 } + * @example Duration.fromISO('PT23H').toObject() //=> { hours: 23 } + * @example Duration.fromISO('P5Y3M').toObject() //=> { years: 5, months: 3 } + * @return {Duration} + */ + static fromISO(text, opts) { + const [parsed] = parseISODuration(text); + if (parsed) { + return Duration.fromObject(parsed, opts); + } else { + return Duration.invalid("unparsable", `the input "${text}" can't be parsed as ISO 8601`); + } + } + + /** + * Create a Duration from an ISO 8601 time string. + * @param {string} text - text to parse + * @param {Object} opts - options for parsing + * @param {string} [opts.locale='en-US'] - the locale to use + * @param {string} opts.numberingSystem - the numbering system to use + * @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use + * @see https://en.wikipedia.org/wiki/ISO_8601#Times + * @example Duration.fromISOTime('11:22:33.444').toObject() //=> { hours: 11, minutes: 22, seconds: 33, milliseconds: 444 } + * @example Duration.fromISOTime('11:00').toObject() //=> { hours: 11, minutes: 0, seconds: 0 } + * @example Duration.fromISOTime('T11:00').toObject() //=> { hours: 11, minutes: 0, seconds: 0 } + * @example Duration.fromISOTime('1100').toObject() //=> { hours: 11, minutes: 0, seconds: 0 } + * @example Duration.fromISOTime('T1100').toObject() //=> { hours: 11, minutes: 0, seconds: 0 } + * @return {Duration} + */ + static fromISOTime(text, opts) { + const [parsed] = parseISOTimeOnly(text); + if (parsed) { + return Duration.fromObject(parsed, opts); + } else { + return Duration.invalid("unparsable", `the input "${text}" can't be parsed as ISO 8601`); + } + } + + /** + * Create an invalid Duration. + * @param {string} reason - simple string of why this datetime is invalid. Should not contain parameters or anything else data-dependent + * @param {string} [explanation=null] - longer explanation, may include parameters and other useful debugging information + * @return {Duration} + */ + static invalid(reason, explanation = null) { + if (!reason) { + throw new InvalidArgumentError("need to specify a reason the Duration is invalid"); + } + + const invalid = reason instanceof Invalid ? reason : new Invalid(reason, explanation); + + if (Settings.throwOnInvalid) { + throw new InvalidDurationError(invalid); + } else { + return new Duration({ invalid }); + } + } + + /** + * @private + */ + static normalizeUnit(unit) { + const normalized = { + year: "years", + years: "years", + quarter: "quarters", + quarters: "quarters", + month: "months", + months: "months", + week: "weeks", + weeks: "weeks", + day: "days", + days: "days", + hour: "hours", + hours: "hours", + minute: "minutes", + minutes: "minutes", + second: "seconds", + seconds: "seconds", + millisecond: "milliseconds", + milliseconds: "milliseconds", + }[unit ? unit.toLowerCase() : unit]; + + if (!normalized) throw new InvalidUnitError(unit); + + return normalized; + } + + /** + * Check if an object is a Duration. Works across context boundaries + * @param {object} o + * @return {boolean} + */ + static isDuration(o) { + return (o && o.isLuxonDuration) || false; + } + + /** + * Get the locale of a Duration, such 'en-GB' + * @type {string} + */ + get locale() { + return this.isValid ? this.loc.locale : null; + } + + /** + * Get the numbering system of a Duration, such 'beng'. The numbering system is used when formatting the Duration + * + * @type {string} + */ + get numberingSystem() { + return this.isValid ? this.loc.numberingSystem : null; + } + + /** + * Returns a string representation of this Duration formatted according to the specified format string. You may use these tokens: + * * `S` for milliseconds + * * `s` for seconds + * * `m` for minutes + * * `h` for hours + * * `d` for days + * * `M` for months + * * `y` for years + * Notes: + * * Add padding by repeating the token, e.g. "yy" pads the years to two digits, "hhhh" pads the hours out to four digits + * * The duration will be converted to the set of units in the format string using {@link Duration#shiftTo} and the Durations's conversion accuracy setting. + * @param {string} fmt - the format string + * @param {Object} opts - options + * @param {boolean} [opts.floor=true] - floor numerical values + * @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toFormat("y d s") //=> "1 6 2" + * @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toFormat("yy dd sss") //=> "01 06 002" + * @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toFormat("M S") //=> "12 518402000" + * @return {string} + */ + toFormat(fmt, opts = {}) { + // reverse-compat since 1.2; we always round down now, never up, and we do it by default + const fmtOpts = { + ...opts, + floor: opts.round !== false && opts.floor !== false, + }; + return this.isValid + ? Formatter.create(this.loc, fmtOpts).formatDurationFromString(this, fmt) + : INVALID$2; + } + + /** + * Returns a string representation of a Duration with all units included + * To modify its behavior use the `listStyle` and any Intl.NumberFormat option, though `unitDisplay` is especially relevant. See {@link Intl.NumberFormat}. + * @param opts - On option object to override the formatting. Accepts the same keys as the options parameter of the native `Int.NumberFormat` constructor, as well as `listStyle`. + * @example + * ```js + * var dur = Duration.fromObject({ days: 1, hours: 5, minutes: 6 }) + * dur.toHuman() //=> '1 day, 5 hours, 6 minutes' + * dur.toHuman({ listStyle: "long" }) //=> '1 day, 5 hours, and 6 minutes' + * dur.toHuman({ unitDisplay: "short" }) //=> '1 day, 5 hr, 6 min' + * ``` + */ + toHuman(opts = {}) { + const l = orderedUnits$1 + .map((unit) => { + const val = this.values[unit]; + if (isUndefined(val)) { + return null; + } + return this.loc + .numberFormatter({ style: "unit", unitDisplay: "long", ...opts, unit: unit.slice(0, -1) }) + .format(val); + }) + .filter((n) => n); + + return this.loc + .listFormatter({ type: "conjunction", style: opts.listStyle || "narrow", ...opts }) + .format(l); + } + + /** + * Returns a JavaScript object with this Duration's values. + * @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toObject() //=> { years: 1, days: 6, seconds: 2 } + * @return {Object} + */ + toObject() { + if (!this.isValid) return {}; + return { ...this.values }; + } + + /** + * Returns an ISO 8601-compliant string representation of this Duration. + * @see https://en.wikipedia.org/wiki/ISO_8601#Durations + * @example Duration.fromObject({ years: 3, seconds: 45 }).toISO() //=> 'P3YT45S' + * @example Duration.fromObject({ months: 4, seconds: 45 }).toISO() //=> 'P4MT45S' + * @example Duration.fromObject({ months: 5 }).toISO() //=> 'P5M' + * @example Duration.fromObject({ minutes: 5 }).toISO() //=> 'PT5M' + * @example Duration.fromObject({ milliseconds: 6 }).toISO() //=> 'PT0.006S' + * @return {string} + */ + toISO() { + // we could use the formatter, but this is an easier way to get the minimum string + if (!this.isValid) return null; + + let s = "P"; + if (this.years !== 0) s += this.years + "Y"; + if (this.months !== 0 || this.quarters !== 0) s += this.months + this.quarters * 3 + "M"; + if (this.weeks !== 0) s += this.weeks + "W"; + if (this.days !== 0) s += this.days + "D"; + if (this.hours !== 0 || this.minutes !== 0 || this.seconds !== 0 || this.milliseconds !== 0) + s += "T"; + if (this.hours !== 0) s += this.hours + "H"; + if (this.minutes !== 0) s += this.minutes + "M"; + if (this.seconds !== 0 || this.milliseconds !== 0) + // this will handle "floating point madness" by removing extra decimal places + // https://stackoverflow.com/questions/588004/is-floating-point-math-broken + s += roundTo(this.seconds + this.milliseconds / 1000, 3) + "S"; + if (s === "P") s += "T0S"; + return s; + } + + /** + * Returns an ISO 8601-compliant string representation of this Duration, formatted as a time of day. + * Note that this will return null if the duration is invalid, negative, or equal to or greater than 24 hours. + * @see https://en.wikipedia.org/wiki/ISO_8601#Times + * @param {Object} opts - options + * @param {boolean} [opts.suppressMilliseconds=false] - exclude milliseconds from the format if they're 0 + * @param {boolean} [opts.suppressSeconds=false] - exclude seconds from the format if they're 0 + * @param {boolean} [opts.includePrefix=false] - include the `T` prefix + * @param {string} [opts.format='extended'] - choose between the basic and extended format + * @example Duration.fromObject({ hours: 11 }).toISOTime() //=> '11:00:00.000' + * @example Duration.fromObject({ hours: 11 }).toISOTime({ suppressMilliseconds: true }) //=> '11:00:00' + * @example Duration.fromObject({ hours: 11 }).toISOTime({ suppressSeconds: true }) //=> '11:00' + * @example Duration.fromObject({ hours: 11 }).toISOTime({ includePrefix: true }) //=> 'T11:00:00.000' + * @example Duration.fromObject({ hours: 11 }).toISOTime({ format: 'basic' }) //=> '110000.000' + * @return {string} + */ + toISOTime(opts = {}) { + if (!this.isValid) return null; + + const millis = this.toMillis(); + if (millis < 0 || millis >= 86400000) return null; + + opts = { + suppressMilliseconds: false, + suppressSeconds: false, + includePrefix: false, + format: "extended", + ...opts, + }; + + const value = this.shiftTo("hours", "minutes", "seconds", "milliseconds"); + + let fmt = opts.format === "basic" ? "hhmm" : "hh:mm"; + + if (!opts.suppressSeconds || value.seconds !== 0 || value.milliseconds !== 0) { + fmt += opts.format === "basic" ? "ss" : ":ss"; + if (!opts.suppressMilliseconds || value.milliseconds !== 0) { + fmt += ".SSS"; + } + } + + let str = value.toFormat(fmt); + + if (opts.includePrefix) { + str = "T" + str; + } + + return str; + } + + /** + * Returns an ISO 8601 representation of this Duration appropriate for use in JSON. + * @return {string} + */ + toJSON() { + return this.toISO(); + } + + /** + * Returns an ISO 8601 representation of this Duration appropriate for use in debugging. + * @return {string} + */ + toString() { + return this.toISO(); + } + + /** + * Returns an milliseconds value of this Duration. + * @return {number} + */ + toMillis() { + return this.as("milliseconds"); + } + + /** + * Returns an milliseconds value of this Duration. Alias of {@link toMillis} + * @return {number} + */ + valueOf() { + return this.toMillis(); + } + + /** + * Make this Duration longer by the specified amount. Return a newly-constructed Duration. + * @param {Duration|Object|number} duration - The amount to add. Either a Luxon Duration, a number of milliseconds, the object argument to Duration.fromObject() + * @return {Duration} + */ + plus(duration) { + if (!this.isValid) return this; + + const dur = Duration.fromDurationLike(duration), + result = {}; + + for (const k of orderedUnits$1) { + if (hasOwnProperty(dur.values, k) || hasOwnProperty(this.values, k)) { + result[k] = dur.get(k) + this.get(k); + } + } + + return clone$1(this, { values: result }, true); + } + + /** + * Make this Duration shorter by the specified amount. Return a newly-constructed Duration. + * @param {Duration|Object|number} duration - The amount to subtract. Either a Luxon Duration, a number of milliseconds, the object argument to Duration.fromObject() + * @return {Duration} + */ + minus(duration) { + if (!this.isValid) return this; + + const dur = Duration.fromDurationLike(duration); + return this.plus(dur.negate()); + } + + /** + * Scale this Duration by the specified amount. Return a newly-constructed Duration. + * @param {function} fn - The function to apply to each unit. Arity is 1 or 2: the value of the unit and, optionally, the unit name. Must return a number. + * @example Duration.fromObject({ hours: 1, minutes: 30 }).mapUnits(x => x * 2) //=> { hours: 2, minutes: 60 } + * @example Duration.fromObject({ hours: 1, minutes: 30 }).mapUnits((x, u) => u === "hour" ? x * 2 : x) //=> { hours: 2, minutes: 30 } + * @return {Duration} + */ + mapUnits(fn) { + if (!this.isValid) return this; + const result = {}; + for (const k of Object.keys(this.values)) { + result[k] = asNumber(fn(this.values[k], k)); + } + return clone$1(this, { values: result }, true); + } + + /** + * Get the value of unit. + * @param {string} unit - a unit such as 'minute' or 'day' + * @example Duration.fromObject({years: 2, days: 3}).get('years') //=> 2 + * @example Duration.fromObject({years: 2, days: 3}).get('months') //=> 0 + * @example Duration.fromObject({years: 2, days: 3}).get('days') //=> 3 + * @return {number} + */ + get(unit) { + return this[Duration.normalizeUnit(unit)]; + } + + /** + * "Set" the values of specified units. Return a newly-constructed Duration. + * @param {Object} values - a mapping of units to numbers + * @example dur.set({ years: 2017 }) + * @example dur.set({ hours: 8, minutes: 30 }) + * @return {Duration} + */ + set(values) { + if (!this.isValid) return this; + + const mixed = { ...this.values, ...normalizeObject(values, Duration.normalizeUnit) }; + return clone$1(this, { values: mixed }); + } + + /** + * "Set" the locale and/or numberingSystem. Returns a newly-constructed Duration. + * @example dur.reconfigure({ locale: 'en-GB' }) + * @return {Duration} + */ + reconfigure({ locale, numberingSystem, conversionAccuracy } = {}) { + const loc = this.loc.clone({ locale, numberingSystem }), + opts = { loc }; + + if (conversionAccuracy) { + opts.conversionAccuracy = conversionAccuracy; + } + + return clone$1(this, opts); + } + + /** + * Return the length of the duration in the specified unit. + * @param {string} unit - a unit such as 'minutes' or 'days' + * @example Duration.fromObject({years: 1}).as('days') //=> 365 + * @example Duration.fromObject({years: 1}).as('months') //=> 12 + * @example Duration.fromObject({hours: 60}).as('days') //=> 2.5 + * @return {number} + */ + as(unit) { + return this.isValid ? this.shiftTo(unit).get(unit) : NaN; + } + + /** + * Reduce this Duration to its canonical representation in its current units. + * @example Duration.fromObject({ years: 2, days: 5000 }).normalize().toObject() //=> { years: 15, days: 255 } + * @example Duration.fromObject({ hours: 12, minutes: -45 }).normalize().toObject() //=> { hours: 11, minutes: 15 } + * @return {Duration} + */ + normalize() { + if (!this.isValid) return this; + const vals = this.toObject(); + normalizeValues(this.matrix, vals); + return clone$1(this, { values: vals }, true); + } + + /** + * Convert this Duration into its representation in a different set of units. + * @example Duration.fromObject({ hours: 1, seconds: 30 }).shiftTo('minutes', 'milliseconds').toObject() //=> { minutes: 60, milliseconds: 30000 } + * @return {Duration} + */ + shiftTo(...units) { + if (!this.isValid) return this; + + if (units.length === 0) { + return this; + } + + units = units.map((u) => Duration.normalizeUnit(u)); + + const built = {}, + accumulated = {}, + vals = this.toObject(); + let lastUnit; + + for (const k of orderedUnits$1) { + if (units.indexOf(k) >= 0) { + lastUnit = k; + + let own = 0; + + // anything we haven't boiled down yet should get boiled to this unit + for (const ak in accumulated) { + own += this.matrix[ak][k] * accumulated[ak]; + accumulated[ak] = 0; + } + + // plus anything that's already in this unit + if (isNumber(vals[k])) { + own += vals[k]; + } + + const i = Math.trunc(own); + built[k] = i; + accumulated[k] = (own * 1000 - i * 1000) / 1000; + + // plus anything further down the chain that should be rolled up in to this + for (const down in vals) { + if (orderedUnits$1.indexOf(down) > orderedUnits$1.indexOf(k)) { + convert(this.matrix, vals, down, built, k); + } + } + // otherwise, keep it in the wings to boil it later + } else if (isNumber(vals[k])) { + accumulated[k] = vals[k]; + } + } + + // anything leftover becomes the decimal for the last unit + // lastUnit must be defined since units is not empty + for (const key in accumulated) { + if (accumulated[key] !== 0) { + built[lastUnit] += + key === lastUnit ? accumulated[key] : accumulated[key] / this.matrix[lastUnit][key]; + } + } + + return clone$1(this, { values: built }, true).normalize(); + } + + /** + * Return the negative of this Duration. + * @example Duration.fromObject({ hours: 1, seconds: 30 }).negate().toObject() //=> { hours: -1, seconds: -30 } + * @return {Duration} + */ + negate() { + if (!this.isValid) return this; + const negated = {}; + for (const k of Object.keys(this.values)) { + negated[k] = -this.values[k]; + } + return clone$1(this, { values: negated }, true); + } + + /** + * Get the years. + * @type {number} + */ + get years() { + return this.isValid ? this.values.years || 0 : NaN; + } + + /** + * Get the quarters. + * @type {number} + */ + get quarters() { + return this.isValid ? this.values.quarters || 0 : NaN; + } + + /** + * Get the months. + * @type {number} + */ + get months() { + return this.isValid ? this.values.months || 0 : NaN; + } + + /** + * Get the weeks + * @type {number} + */ + get weeks() { + return this.isValid ? this.values.weeks || 0 : NaN; + } + + /** + * Get the days. + * @type {number} + */ + get days() { + return this.isValid ? this.values.days || 0 : NaN; + } + + /** + * Get the hours. + * @type {number} + */ + get hours() { + return this.isValid ? this.values.hours || 0 : NaN; + } + + /** + * Get the minutes. + * @type {number} + */ + get minutes() { + return this.isValid ? this.values.minutes || 0 : NaN; + } + + /** + * Get the seconds. + * @return {number} + */ + get seconds() { + return this.isValid ? this.values.seconds || 0 : NaN; + } + + /** + * Get the milliseconds. + * @return {number} + */ + get milliseconds() { + return this.isValid ? this.values.milliseconds || 0 : NaN; + } + + /** + * Returns whether the Duration is invalid. Invalid durations are returned by diff operations + * on invalid DateTimes or Intervals. + * @return {boolean} + */ + get isValid() { + return this.invalid === null; + } + + /** + * Returns an error code if this Duration became invalid, or null if the Duration is valid + * @return {string} + */ + get invalidReason() { + return this.invalid ? this.invalid.reason : null; + } + + /** + * Returns an explanation of why this Duration became invalid, or null if the Duration is valid + * @type {string} + */ + get invalidExplanation() { + return this.invalid ? this.invalid.explanation : null; + } + + /** + * Equality check + * Two Durations are equal iff they have the same units and the same values for each unit. + * @param {Duration} other + * @return {boolean} + */ + equals(other) { + if (!this.isValid || !other.isValid) { + return false; + } + + if (!this.loc.equals(other.loc)) { + return false; + } + + function eq(v1, v2) { + // Consider 0 and undefined as equal + if (v1 === undefined || v1 === 0) return v2 === undefined || v2 === 0; + return v1 === v2; + } + + for (const u of orderedUnits$1) { + if (!eq(this.values[u], other.values[u])) { + return false; + } + } + return true; + } +} + +const INVALID$1 = "Invalid Interval"; + +// checks if the start is equal to or before the end +function validateStartEnd(start, end) { + if (!start || !start.isValid) { + return Interval.invalid("missing or invalid start"); + } else if (!end || !end.isValid) { + return Interval.invalid("missing or invalid end"); + } else if (end < start) { + return Interval.invalid( + "end before start", + `The end of an interval must be after its start, but you had start=${start.toISO()} and end=${end.toISO()}` + ); + } else { + return null; + } +} + +/** + * An Interval object represents a half-open interval of time, where each endpoint is a {@link DateTime}. Conceptually, it's a container for those two endpoints, accompanied by methods for creating, parsing, interrogating, comparing, transforming, and formatting them. + * + * Here is a brief overview of the most commonly used methods and getters in Interval: + * + * * **Creation** To create an Interval, use {@link Interval#fromDateTimes}, {@link Interval#after}, {@link Interval#before}, or {@link Interval#fromISO}. + * * **Accessors** Use {@link Interval#start} and {@link Interval#end} to get the start and end. + * * **Interrogation** To analyze the Interval, use {@link Interval#count}, {@link Interval#length}, {@link Interval#hasSame}, {@link Interval#contains}, {@link Interval#isAfter}, or {@link Interval#isBefore}. + * * **Transformation** To create other Intervals out of this one, use {@link Interval#set}, {@link Interval#splitAt}, {@link Interval#splitBy}, {@link Interval#divideEqually}, {@link Interval#merge}, {@link Interval#xor}, {@link Interval#union}, {@link Interval#intersection}, or {@link Interval#difference}. + * * **Comparison** To compare this Interval to another one, use {@link Interval#equals}, {@link Interval#overlaps}, {@link Interval#abutsStart}, {@link Interval#abutsEnd}, {@link Interval#engulfs} + * * **Output** To convert the Interval into other representations, see {@link Interval#toString}, {@link Interval#toISO}, {@link Interval#toISODate}, {@link Interval#toISOTime}, {@link Interval#toFormat}, and {@link Interval#toDuration}. + */ +class Interval { + /** + * @private + */ + constructor(config) { + /** + * @access private + */ + this.s = config.start; + /** + * @access private + */ + this.e = config.end; + /** + * @access private + */ + this.invalid = config.invalid || null; + /** + * @access private + */ + this.isLuxonInterval = true; + } + + /** + * Create an invalid Interval. + * @param {string} reason - simple string of why this Interval is invalid. Should not contain parameters or anything else data-dependent + * @param {string} [explanation=null] - longer explanation, may include parameters and other useful debugging information + * @return {Interval} + */ + static invalid(reason, explanation = null) { + if (!reason) { + throw new InvalidArgumentError("need to specify a reason the Interval is invalid"); + } + + const invalid = reason instanceof Invalid ? reason : new Invalid(reason, explanation); + + if (Settings.throwOnInvalid) { + throw new InvalidIntervalError(invalid); + } else { + return new Interval({ invalid }); + } + } + + /** + * Create an Interval from a start DateTime and an end DateTime. Inclusive of the start but not the end. + * @param {DateTime|Date|Object} start + * @param {DateTime|Date|Object} end + * @return {Interval} + */ + static fromDateTimes(start, end) { + const builtStart = friendlyDateTime(start), + builtEnd = friendlyDateTime(end); + + const validateError = validateStartEnd(builtStart, builtEnd); + + if (validateError == null) { + return new Interval({ + start: builtStart, + end: builtEnd, + }); + } else { + return validateError; + } + } + + /** + * Create an Interval from a start DateTime and a Duration to extend to. + * @param {DateTime|Date|Object} start + * @param {Duration|Object|number} duration - the length of the Interval. + * @return {Interval} + */ + static after(start, duration) { + const dur = Duration.fromDurationLike(duration), + dt = friendlyDateTime(start); + return Interval.fromDateTimes(dt, dt.plus(dur)); + } + + /** + * Create an Interval from an end DateTime and a Duration to extend backwards to. + * @param {DateTime|Date|Object} end + * @param {Duration|Object|number} duration - the length of the Interval. + * @return {Interval} + */ + static before(end, duration) { + const dur = Duration.fromDurationLike(duration), + dt = friendlyDateTime(end); + return Interval.fromDateTimes(dt.minus(dur), dt); + } + + /** + * Create an Interval from an ISO 8601 string. + * Accepts `/`, `/`, and `/` formats. + * @param {string} text - the ISO string to parse + * @param {Object} [opts] - options to pass {@link DateTime#fromISO} and optionally {@link Duration#fromISO} + * @see https://en.wikipedia.org/wiki/ISO_8601#Time_intervals + * @return {Interval} + */ + static fromISO(text, opts) { + const [s, e] = (text || "").split("/", 2); + if (s && e) { + let start, startIsValid; + try { + start = DateTime.fromISO(s, opts); + startIsValid = start.isValid; + } catch (e) { + startIsValid = false; + } + + let end, endIsValid; + try { + end = DateTime.fromISO(e, opts); + endIsValid = end.isValid; + } catch (e) { + endIsValid = false; + } + + if (startIsValid && endIsValid) { + return Interval.fromDateTimes(start, end); + } + + if (startIsValid) { + const dur = Duration.fromISO(e, opts); + if (dur.isValid) { + return Interval.after(start, dur); + } + } else if (endIsValid) { + const dur = Duration.fromISO(s, opts); + if (dur.isValid) { + return Interval.before(end, dur); + } + } + } + return Interval.invalid("unparsable", `the input "${text}" can't be parsed as ISO 8601`); + } + + /** + * Check if an object is an Interval. Works across context boundaries + * @param {object} o + * @return {boolean} + */ + static isInterval(o) { + return (o && o.isLuxonInterval) || false; + } + + /** + * Returns the start of the Interval + * @type {DateTime} + */ + get start() { + return this.isValid ? this.s : null; + } + + /** + * Returns the end of the Interval + * @type {DateTime} + */ + get end() { + return this.isValid ? this.e : null; + } + + /** + * Returns whether this Interval's end is at least its start, meaning that the Interval isn't 'backwards'. + * @type {boolean} + */ + get isValid() { + return this.invalidReason === null; + } + + /** + * Returns an error code if this Interval is invalid, or null if the Interval is valid + * @type {string} + */ + get invalidReason() { + return this.invalid ? this.invalid.reason : null; + } + + /** + * Returns an explanation of why this Interval became invalid, or null if the Interval is valid + * @type {string} + */ + get invalidExplanation() { + return this.invalid ? this.invalid.explanation : null; + } + + /** + * Returns the length of the Interval in the specified unit. + * @param {string} unit - the unit (such as 'hours' or 'days') to return the length in. + * @return {number} + */ + length(unit = "milliseconds") { + return this.isValid ? this.toDuration(...[unit]).get(unit) : NaN; + } + + /** + * Returns the count of minutes, hours, days, months, or years included in the Interval, even in part. + * Unlike {@link Interval#length} this counts sections of the calendar, not periods of time, e.g. specifying 'day' + * asks 'what dates are included in this interval?', not 'how many days long is this interval?' + * @param {string} [unit='milliseconds'] - the unit of time to count. + * @return {number} + */ + count(unit = "milliseconds") { + if (!this.isValid) return NaN; + const start = this.start.startOf(unit), + end = this.end.startOf(unit); + return Math.floor(end.diff(start, unit).get(unit)) + 1; + } + + /** + * Returns whether this Interval's start and end are both in the same unit of time + * @param {string} unit - the unit of time to check sameness on + * @return {boolean} + */ + hasSame(unit) { + return this.isValid ? this.isEmpty() || this.e.minus(1).hasSame(this.s, unit) : false; + } + + /** + * Return whether this Interval has the same start and end DateTimes. + * @return {boolean} + */ + isEmpty() { + return this.s.valueOf() === this.e.valueOf(); + } + + /** + * Return whether this Interval's start is after the specified DateTime. + * @param {DateTime} dateTime + * @return {boolean} + */ + isAfter(dateTime) { + if (!this.isValid) return false; + return this.s > dateTime; + } + + /** + * Return whether this Interval's end is before the specified DateTime. + * @param {DateTime} dateTime + * @return {boolean} + */ + isBefore(dateTime) { + if (!this.isValid) return false; + return this.e <= dateTime; + } + + /** + * Return whether this Interval contains the specified DateTime. + * @param {DateTime} dateTime + * @return {boolean} + */ + contains(dateTime) { + if (!this.isValid) return false; + return this.s <= dateTime && this.e > dateTime; + } + + /** + * "Sets" the start and/or end dates. Returns a newly-constructed Interval. + * @param {Object} values - the values to set + * @param {DateTime} values.start - the starting DateTime + * @param {DateTime} values.end - the ending DateTime + * @return {Interval} + */ + set({ start, end } = {}) { + if (!this.isValid) return this; + return Interval.fromDateTimes(start || this.s, end || this.e); + } + + /** + * Split this Interval at each of the specified DateTimes + * @param {...DateTime} dateTimes - the unit of time to count. + * @return {Array} + */ + splitAt(...dateTimes) { + if (!this.isValid) return []; + const sorted = dateTimes + .map(friendlyDateTime) + .filter((d) => this.contains(d)) + .sort(), + results = []; + let { s } = this, + i = 0; + + while (s < this.e) { + const added = sorted[i] || this.e, + next = +added > +this.e ? this.e : added; + results.push(Interval.fromDateTimes(s, next)); + s = next; + i += 1; + } + + return results; + } + + /** + * Split this Interval into smaller Intervals, each of the specified length. + * Left over time is grouped into a smaller interval + * @param {Duration|Object|number} duration - The length of each resulting interval. + * @return {Array} + */ + splitBy(duration) { + const dur = Duration.fromDurationLike(duration); + + if (!this.isValid || !dur.isValid || dur.as("milliseconds") === 0) { + return []; + } + + let { s } = this, + idx = 1, + next; + + const results = []; + while (s < this.e) { + const added = this.start.plus(dur.mapUnits((x) => x * idx)); + next = +added > +this.e ? this.e : added; + results.push(Interval.fromDateTimes(s, next)); + s = next; + idx += 1; + } + + return results; + } + + /** + * Split this Interval into the specified number of smaller intervals. + * @param {number} numberOfParts - The number of Intervals to divide the Interval into. + * @return {Array} + */ + divideEqually(numberOfParts) { + if (!this.isValid) return []; + return this.splitBy(this.length() / numberOfParts).slice(0, numberOfParts); + } + + /** + * Return whether this Interval overlaps with the specified Interval + * @param {Interval} other + * @return {boolean} + */ + overlaps(other) { + return this.e > other.s && this.s < other.e; + } + + /** + * Return whether this Interval's end is adjacent to the specified Interval's start. + * @param {Interval} other + * @return {boolean} + */ + abutsStart(other) { + if (!this.isValid) return false; + return +this.e === +other.s; + } + + /** + * Return whether this Interval's start is adjacent to the specified Interval's end. + * @param {Interval} other + * @return {boolean} + */ + abutsEnd(other) { + if (!this.isValid) return false; + return +other.e === +this.s; + } + + /** + * Return whether this Interval engulfs the start and end of the specified Interval. + * @param {Interval} other + * @return {boolean} + */ + engulfs(other) { + if (!this.isValid) return false; + return this.s <= other.s && this.e >= other.e; + } + + /** + * Return whether this Interval has the same start and end as the specified Interval. + * @param {Interval} other + * @return {boolean} + */ + equals(other) { + if (!this.isValid || !other.isValid) { + return false; + } + + return this.s.equals(other.s) && this.e.equals(other.e); + } + + /** + * Return an Interval representing the intersection of this Interval and the specified Interval. + * Specifically, the resulting Interval has the maximum start time and the minimum end time of the two Intervals. + * Returns null if the intersection is empty, meaning, the intervals don't intersect. + * @param {Interval} other + * @return {Interval} + */ + intersection(other) { + if (!this.isValid) return this; + const s = this.s > other.s ? this.s : other.s, + e = this.e < other.e ? this.e : other.e; + + if (s >= e) { + return null; + } else { + return Interval.fromDateTimes(s, e); + } + } + + /** + * Return an Interval representing the union of this Interval and the specified Interval. + * Specifically, the resulting Interval has the minimum start time and the maximum end time of the two Intervals. + * @param {Interval} other + * @return {Interval} + */ + union(other) { + if (!this.isValid) return this; + const s = this.s < other.s ? this.s : other.s, + e = this.e > other.e ? this.e : other.e; + return Interval.fromDateTimes(s, e); + } + + /** + * Merge an array of Intervals into a equivalent minimal set of Intervals. + * Combines overlapping and adjacent Intervals. + * @param {Array} intervals + * @return {Array} + */ + static merge(intervals) { + const [found, final] = intervals + .sort((a, b) => a.s - b.s) + .reduce( + ([sofar, current], item) => { + if (!current) { + return [sofar, item]; + } else if (current.overlaps(item) || current.abutsStart(item)) { + return [sofar, current.union(item)]; + } else { + return [sofar.concat([current]), item]; + } + }, + [[], null] + ); + if (final) { + found.push(final); + } + return found; + } + + /** + * Return an array of Intervals representing the spans of time that only appear in one of the specified Intervals. + * @param {Array} intervals + * @return {Array} + */ + static xor(intervals) { + let start = null, + currentCount = 0; + const results = [], + ends = intervals.map((i) => [ + { time: i.s, type: "s" }, + { time: i.e, type: "e" }, + ]), + flattened = Array.prototype.concat(...ends), + arr = flattened.sort((a, b) => a.time - b.time); + + for (const i of arr) { + currentCount += i.type === "s" ? 1 : -1; + + if (currentCount === 1) { + start = i.time; + } else { + if (start && +start !== +i.time) { + results.push(Interval.fromDateTimes(start, i.time)); + } + + start = null; + } + } + + return Interval.merge(results); + } + + /** + * Return an Interval representing the span of time in this Interval that doesn't overlap with any of the specified Intervals. + * @param {...Interval} intervals + * @return {Array} + */ + difference(...intervals) { + return Interval.xor([this].concat(intervals)) + .map((i) => this.intersection(i)) + .filter((i) => i && !i.isEmpty()); + } + + /** + * Returns a string representation of this Interval appropriate for debugging. + * @return {string} + */ + toString() { + if (!this.isValid) return INVALID$1; + return `[${this.s.toISO()} – ${this.e.toISO()})`; + } + + /** + * Returns an ISO 8601-compliant string representation of this Interval. + * @see https://en.wikipedia.org/wiki/ISO_8601#Time_intervals + * @param {Object} opts - The same options as {@link DateTime#toISO} + * @return {string} + */ + toISO(opts) { + if (!this.isValid) return INVALID$1; + return `${this.s.toISO(opts)}/${this.e.toISO(opts)}`; + } + + /** + * Returns an ISO 8601-compliant string representation of date of this Interval. + * The time components are ignored. + * @see https://en.wikipedia.org/wiki/ISO_8601#Time_intervals + * @return {string} + */ + toISODate() { + if (!this.isValid) return INVALID$1; + return `${this.s.toISODate()}/${this.e.toISODate()}`; + } + + /** + * Returns an ISO 8601-compliant string representation of time of this Interval. + * The date components are ignored. + * @see https://en.wikipedia.org/wiki/ISO_8601#Time_intervals + * @param {Object} opts - The same options as {@link DateTime#toISO} + * @return {string} + */ + toISOTime(opts) { + if (!this.isValid) return INVALID$1; + return `${this.s.toISOTime(opts)}/${this.e.toISOTime(opts)}`; + } + + /** + * Returns a string representation of this Interval formatted according to the specified format string. + * @param {string} dateFormat - the format string. This string formats the start and end time. See {@link DateTime#toFormat} for details. + * @param {Object} opts - options + * @param {string} [opts.separator = ' – '] - a separator to place between the start and end representations + * @return {string} + */ + toFormat(dateFormat, { separator = " – " } = {}) { + if (!this.isValid) return INVALID$1; + return `${this.s.toFormat(dateFormat)}${separator}${this.e.toFormat(dateFormat)}`; + } + + /** + * Return a Duration representing the time spanned by this interval. + * @param {string|string[]} [unit=['milliseconds']] - the unit or units (such as 'hours' or 'days') to include in the duration. + * @param {Object} opts - options that affect the creation of the Duration + * @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use + * @example Interval.fromDateTimes(dt1, dt2).toDuration().toObject() //=> { milliseconds: 88489257 } + * @example Interval.fromDateTimes(dt1, dt2).toDuration('days').toObject() //=> { days: 1.0241812152777778 } + * @example Interval.fromDateTimes(dt1, dt2).toDuration(['hours', 'minutes']).toObject() //=> { hours: 24, minutes: 34.82095 } + * @example Interval.fromDateTimes(dt1, dt2).toDuration(['hours', 'minutes', 'seconds']).toObject() //=> { hours: 24, minutes: 34, seconds: 49.257 } + * @example Interval.fromDateTimes(dt1, dt2).toDuration('seconds').toObject() //=> { seconds: 88489.257 } + * @return {Duration} + */ + toDuration(unit, opts) { + if (!this.isValid) { + return Duration.invalid(this.invalidReason); + } + return this.e.diff(this.s, unit, opts); + } + + /** + * Run mapFn on the interval start and end, returning a new Interval from the resulting DateTimes + * @param {function} mapFn + * @return {Interval} + * @example Interval.fromDateTimes(dt1, dt2).mapEndpoints(endpoint => endpoint.toUTC()) + * @example Interval.fromDateTimes(dt1, dt2).mapEndpoints(endpoint => endpoint.plus({ hours: 2 })) + */ + mapEndpoints(mapFn) { + return Interval.fromDateTimes(mapFn(this.s), mapFn(this.e)); + } +} + +/** + * The Info class contains static methods for retrieving general time and date related data. For example, it has methods for finding out if a time zone has a DST, for listing the months in any supported locale, and for discovering which of Luxon features are available in the current environment. + */ +class Info { + /** + * Return whether the specified zone contains a DST. + * @param {string|Zone} [zone='local'] - Zone to check. Defaults to the environment's local zone. + * @return {boolean} + */ + static hasDST(zone = Settings.defaultZone) { + const proto = DateTime.now().setZone(zone).set({ month: 12 }); + + return !zone.isUniversal && proto.offset !== proto.set({ month: 6 }).offset; + } + + /** + * Return whether the specified zone is a valid IANA specifier. + * @param {string} zone - Zone to check + * @return {boolean} + */ + static isValidIANAZone(zone) { + return IANAZone.isValidSpecifier(zone) && IANAZone.isValidZone(zone); + } + + /** + * Converts the input into a {@link Zone} instance. + * + * * If `input` is already a Zone instance, it is returned unchanged. + * * If `input` is a string containing a valid time zone name, a Zone instance + * with that name is returned. + * * If `input` is a string that doesn't refer to a known time zone, a Zone + * instance with {@link Zone#isValid} == false is returned. + * * If `input is a number, a Zone instance with the specified fixed offset + * in minutes is returned. + * * If `input` is `null` or `undefined`, the default zone is returned. + * @param {string|Zone|number} [input] - the value to be converted + * @return {Zone} + */ + static normalizeZone(input) { + return normalizeZone(input, Settings.defaultZone); + } + + /** + * Return an array of standalone month names. + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat + * @param {string} [length='long'] - the length of the month representation, such as "numeric", "2-digit", "narrow", "short", "long" + * @param {Object} opts - options + * @param {string} [opts.locale] - the locale code + * @param {string} [opts.numberingSystem=null] - the numbering system + * @param {string} [opts.locObj=null] - an existing locale object to use + * @param {string} [opts.outputCalendar='gregory'] - the calendar + * @example Info.months()[0] //=> 'January' + * @example Info.months('short')[0] //=> 'Jan' + * @example Info.months('numeric')[0] //=> '1' + * @example Info.months('short', { locale: 'fr-CA' } )[0] //=> 'janv.' + * @example Info.months('numeric', { locale: 'ar' })[0] //=> '١' + * @example Info.months('long', { outputCalendar: 'islamic' })[0] //=> 'Rabiʻ I' + * @return {Array} + */ + static months( + length = "long", + { locale = null, numberingSystem = null, locObj = null, outputCalendar = "gregory" } = {} + ) { + return (locObj || Locale.create(locale, numberingSystem, outputCalendar)).months(length); + } + + /** + * Return an array of format month names. + * Format months differ from standalone months in that they're meant to appear next to the day of the month. In some languages, that + * changes the string. + * See {@link Info#months} + * @param {string} [length='long'] - the length of the month representation, such as "numeric", "2-digit", "narrow", "short", "long" + * @param {Object} opts - options + * @param {string} [opts.locale] - the locale code + * @param {string} [opts.numberingSystem=null] - the numbering system + * @param {string} [opts.locObj=null] - an existing locale object to use + * @param {string} [opts.outputCalendar='gregory'] - the calendar + * @return {Array} + */ + static monthsFormat( + length = "long", + { locale = null, numberingSystem = null, locObj = null, outputCalendar = "gregory" } = {} + ) { + return (locObj || Locale.create(locale, numberingSystem, outputCalendar)).months(length, true); + } + + /** + * Return an array of standalone week names. + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat + * @param {string} [length='long'] - the length of the weekday representation, such as "narrow", "short", "long". + * @param {Object} opts - options + * @param {string} [opts.locale] - the locale code + * @param {string} [opts.numberingSystem=null] - the numbering system + * @param {string} [opts.locObj=null] - an existing locale object to use + * @example Info.weekdays()[0] //=> 'Monday' + * @example Info.weekdays('short')[0] //=> 'Mon' + * @example Info.weekdays('short', { locale: 'fr-CA' })[0] //=> 'lun.' + * @example Info.weekdays('short', { locale: 'ar' })[0] //=> 'الاثنين' + * @return {Array} + */ + static weekdays(length = "long", { locale = null, numberingSystem = null, locObj = null } = {}) { + return (locObj || Locale.create(locale, numberingSystem, null)).weekdays(length); + } + + /** + * Return an array of format week names. + * Format weekdays differ from standalone weekdays in that they're meant to appear next to more date information. In some languages, that + * changes the string. + * See {@link Info#weekdays} + * @param {string} [length='long'] - the length of the month representation, such as "narrow", "short", "long". + * @param {Object} opts - options + * @param {string} [opts.locale=null] - the locale code + * @param {string} [opts.numberingSystem=null] - the numbering system + * @param {string} [opts.locObj=null] - an existing locale object to use + * @return {Array} + */ + static weekdaysFormat( + length = "long", + { locale = null, numberingSystem = null, locObj = null } = {} + ) { + return (locObj || Locale.create(locale, numberingSystem, null)).weekdays(length, true); + } + + /** + * Return an array of meridiems. + * @param {Object} opts - options + * @param {string} [opts.locale] - the locale code + * @example Info.meridiems() //=> [ 'AM', 'PM' ] + * @example Info.meridiems({ locale: 'my' }) //=> [ 'နံနက်', 'ညနေ' ] + * @return {Array} + */ + static meridiems({ locale = null } = {}) { + return Locale.create(locale).meridiems(); + } + + /** + * Return an array of eras, such as ['BC', 'AD']. The locale can be specified, but the calendar system is always Gregorian. + * @param {string} [length='short'] - the length of the era representation, such as "short" or "long". + * @param {Object} opts - options + * @param {string} [opts.locale] - the locale code + * @example Info.eras() //=> [ 'BC', 'AD' ] + * @example Info.eras('long') //=> [ 'Before Christ', 'Anno Domini' ] + * @example Info.eras('long', { locale: 'fr' }) //=> [ 'avant Jésus-Christ', 'après Jésus-Christ' ] + * @return {Array} + */ + static eras(length = "short", { locale = null } = {}) { + return Locale.create(locale, null, "gregory").eras(length); + } + + /** + * Return the set of available features in this environment. + * Some features of Luxon are not available in all environments. For example, on older browsers, relative time formatting support is not available. Use this function to figure out if that's the case. + * Keys: + * * `relative`: whether this environment supports relative time formatting + * @example Info.features() //=> { relative: false } + * @return {Object} + */ + static features() { + return { relative: hasRelative() }; + } +} + +function dayDiff(earlier, later) { + const utcDayStart = (dt) => dt.toUTC(0, { keepLocalTime: true }).startOf("day").valueOf(), + ms = utcDayStart(later) - utcDayStart(earlier); + return Math.floor(Duration.fromMillis(ms).as("days")); +} + +function highOrderDiffs(cursor, later, units) { + const differs = [ + ["years", (a, b) => b.year - a.year], + ["quarters", (a, b) => b.quarter - a.quarter], + ["months", (a, b) => b.month - a.month + (b.year - a.year) * 12], + [ + "weeks", + (a, b) => { + const days = dayDiff(a, b); + return (days - (days % 7)) / 7; + }, + ], + ["days", dayDiff], + ]; + + const results = {}; + let lowestOrder, highWater; + + for (const [unit, differ] of differs) { + if (units.indexOf(unit) >= 0) { + lowestOrder = unit; + + let delta = differ(cursor, later); + highWater = cursor.plus({ [unit]: delta }); + + if (highWater > later) { + cursor = cursor.plus({ [unit]: delta - 1 }); + delta -= 1; + } else { + cursor = highWater; + } + + results[unit] = delta; + } + } + + return [cursor, results, highWater, lowestOrder]; +} + +function diff (earlier, later, units, opts) { + let [cursor, results, highWater, lowestOrder] = highOrderDiffs(earlier, later, units); + + const remainingMillis = later - cursor; + + const lowerOrderUnits = units.filter( + (u) => ["hours", "minutes", "seconds", "milliseconds"].indexOf(u) >= 0 + ); + + if (lowerOrderUnits.length === 0) { + if (highWater < later) { + highWater = cursor.plus({ [lowestOrder]: 1 }); + } + + if (highWater !== cursor) { + results[lowestOrder] = (results[lowestOrder] || 0) + remainingMillis / (highWater - cursor); + } + } + + const duration = Duration.fromObject(results, opts); + + if (lowerOrderUnits.length > 0) { + return Duration.fromMillis(remainingMillis, opts) + .shiftTo(...lowerOrderUnits) + .plus(duration); + } else { + return duration; + } +} + +const numberingSystems = { + arab: "[\u0660-\u0669]", + arabext: "[\u06F0-\u06F9]", + bali: "[\u1B50-\u1B59]", + beng: "[\u09E6-\u09EF]", + deva: "[\u0966-\u096F]", + fullwide: "[\uFF10-\uFF19]", + gujr: "[\u0AE6-\u0AEF]", + hanidec: "[〇|一|二|三|四|五|六|七|八|九]", + khmr: "[\u17E0-\u17E9]", + knda: "[\u0CE6-\u0CEF]", + laoo: "[\u0ED0-\u0ED9]", + limb: "[\u1946-\u194F]", + mlym: "[\u0D66-\u0D6F]", + mong: "[\u1810-\u1819]", + mymr: "[\u1040-\u1049]", + orya: "[\u0B66-\u0B6F]", + tamldec: "[\u0BE6-\u0BEF]", + telu: "[\u0C66-\u0C6F]", + thai: "[\u0E50-\u0E59]", + tibt: "[\u0F20-\u0F29]", + latn: "\\d", +}; + +const numberingSystemsUTF16 = { + arab: [1632, 1641], + arabext: [1776, 1785], + bali: [6992, 7001], + beng: [2534, 2543], + deva: [2406, 2415], + fullwide: [65296, 65303], + gujr: [2790, 2799], + khmr: [6112, 6121], + knda: [3302, 3311], + laoo: [3792, 3801], + limb: [6470, 6479], + mlym: [3430, 3439], + mong: [6160, 6169], + mymr: [4160, 4169], + orya: [2918, 2927], + tamldec: [3046, 3055], + telu: [3174, 3183], + thai: [3664, 3673], + tibt: [3872, 3881], +}; + +const hanidecChars = numberingSystems.hanidec.replace(/[\[|\]]/g, "").split(""); + +function parseDigits(str) { + let value = parseInt(str, 10); + if (isNaN(value)) { + value = ""; + for (let i = 0; i < str.length; i++) { + const code = str.charCodeAt(i); + + if (str[i].search(numberingSystems.hanidec) !== -1) { + value += hanidecChars.indexOf(str[i]); + } else { + for (const key in numberingSystemsUTF16) { + const [min, max] = numberingSystemsUTF16[key]; + if (code >= min && code <= max) { + value += code - min; + } + } + } + } + return parseInt(value, 10); + } else { + return value; + } +} + +function digitRegex({ numberingSystem }, append = "") { + return new RegExp(`${numberingSystems[numberingSystem || "latn"]}${append}`); +} + +const MISSING_FTP = "missing Intl.DateTimeFormat.formatToParts support"; + +function intUnit(regex, post = (i) => i) { + return { regex, deser: ([s]) => post(parseDigits(s)) }; +} + +const NBSP = String.fromCharCode(160); +const spaceOrNBSP = `( |${NBSP})`; +const spaceOrNBSPRegExp = new RegExp(spaceOrNBSP, "g"); + +function fixListRegex(s) { + // make dots optional and also make them literal + // make space and non breakable space characters interchangeable + return s.replace(/\./g, "\\.?").replace(spaceOrNBSPRegExp, spaceOrNBSP); +} + +function stripInsensitivities(s) { + return s + .replace(/\./g, "") // ignore dots that were made optional + .replace(spaceOrNBSPRegExp, " ") // interchange space and nbsp + .toLowerCase(); +} + +function oneOf(strings, startIndex) { + if (strings === null) { + return null; + } else { + return { + regex: RegExp(strings.map(fixListRegex).join("|")), + deser: ([s]) => + strings.findIndex((i) => stripInsensitivities(s) === stripInsensitivities(i)) + startIndex, + }; + } +} + +function offset(regex, groups) { + return { regex, deser: ([, h, m]) => signedOffset(h, m), groups }; +} + +function simple(regex) { + return { regex, deser: ([s]) => s }; +} + +function escapeToken(value) { + return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"); +} + +function unitForToken(token, loc) { + const one = digitRegex(loc), + two = digitRegex(loc, "{2}"), + three = digitRegex(loc, "{3}"), + four = digitRegex(loc, "{4}"), + six = digitRegex(loc, "{6}"), + oneOrTwo = digitRegex(loc, "{1,2}"), + oneToThree = digitRegex(loc, "{1,3}"), + oneToSix = digitRegex(loc, "{1,6}"), + oneToNine = digitRegex(loc, "{1,9}"), + twoToFour = digitRegex(loc, "{2,4}"), + fourToSix = digitRegex(loc, "{4,6}"), + literal = (t) => ({ regex: RegExp(escapeToken(t.val)), deser: ([s]) => s, literal: true }), + unitate = (t) => { + if (token.literal) { + return literal(t); + } + switch (t.val) { + // era + case "G": + return oneOf(loc.eras("short", false), 0); + case "GG": + return oneOf(loc.eras("long", false), 0); + // years + case "y": + return intUnit(oneToSix); + case "yy": + return intUnit(twoToFour, untruncateYear); + case "yyyy": + return intUnit(four); + case "yyyyy": + return intUnit(fourToSix); + case "yyyyyy": + return intUnit(six); + // months + case "M": + return intUnit(oneOrTwo); + case "MM": + return intUnit(two); + case "MMM": + return oneOf(loc.months("short", true, false), 1); + case "MMMM": + return oneOf(loc.months("long", true, false), 1); + case "L": + return intUnit(oneOrTwo); + case "LL": + return intUnit(two); + case "LLL": + return oneOf(loc.months("short", false, false), 1); + case "LLLL": + return oneOf(loc.months("long", false, false), 1); + // dates + case "d": + return intUnit(oneOrTwo); + case "dd": + return intUnit(two); + // ordinals + case "o": + return intUnit(oneToThree); + case "ooo": + return intUnit(three); + // time + case "HH": + return intUnit(two); + case "H": + return intUnit(oneOrTwo); + case "hh": + return intUnit(two); + case "h": + return intUnit(oneOrTwo); + case "mm": + return intUnit(two); + case "m": + return intUnit(oneOrTwo); + case "q": + return intUnit(oneOrTwo); + case "qq": + return intUnit(two); + case "s": + return intUnit(oneOrTwo); + case "ss": + return intUnit(two); + case "S": + return intUnit(oneToThree); + case "SSS": + return intUnit(three); + case "u": + return simple(oneToNine); + case "uu": + return simple(oneOrTwo); + case "uuu": + return intUnit(one); + // meridiem + case "a": + return oneOf(loc.meridiems(), 0); + // weekYear (k) + case "kkkk": + return intUnit(four); + case "kk": + return intUnit(twoToFour, untruncateYear); + // weekNumber (W) + case "W": + return intUnit(oneOrTwo); + case "WW": + return intUnit(two); + // weekdays + case "E": + case "c": + return intUnit(one); + case "EEE": + return oneOf(loc.weekdays("short", false, false), 1); + case "EEEE": + return oneOf(loc.weekdays("long", false, false), 1); + case "ccc": + return oneOf(loc.weekdays("short", true, false), 1); + case "cccc": + return oneOf(loc.weekdays("long", true, false), 1); + // offset/zone + case "Z": + case "ZZ": + return offset(new RegExp(`([+-]${oneOrTwo.source})(?::(${two.source}))?`), 2); + case "ZZZ": + return offset(new RegExp(`([+-]${oneOrTwo.source})(${two.source})?`), 2); + // we don't support ZZZZ (PST) or ZZZZZ (Pacific Standard Time) in parsing + // because we don't have any way to figure out what they are + case "z": + return simple(/[a-z_+-/]{1,256}?/i); + default: + return literal(t); + } + }; + + const unit = unitate(token) || { + invalidReason: MISSING_FTP, + }; + + unit.token = token; + + return unit; +} + +const partTypeStyleToTokenVal = { + year: { + "2-digit": "yy", + numeric: "yyyyy", + }, + month: { + numeric: "M", + "2-digit": "MM", + short: "MMM", + long: "MMMM", + }, + day: { + numeric: "d", + "2-digit": "dd", + }, + weekday: { + short: "EEE", + long: "EEEE", + }, + dayperiod: "a", + dayPeriod: "a", + hour: { + numeric: "h", + "2-digit": "hh", + }, + minute: { + numeric: "m", + "2-digit": "mm", + }, + second: { + numeric: "s", + "2-digit": "ss", + }, +}; + +function tokenForPart(part, locale, formatOpts) { + const { type, value } = part; + + if (type === "literal") { + return { + literal: true, + val: value, + }; + } + + const style = formatOpts[type]; + + let val = partTypeStyleToTokenVal[type]; + if (typeof val === "object") { + val = val[style]; + } + + if (val) { + return { + literal: false, + val, + }; + } + + return undefined; +} + +function buildRegex(units) { + const re = units.map((u) => u.regex).reduce((f, r) => `${f}(${r.source})`, ""); + return [`^${re}$`, units]; +} + +function match(input, regex, handlers) { + const matches = input.match(regex); + + if (matches) { + const all = {}; + let matchIndex = 1; + for (const i in handlers) { + if (hasOwnProperty(handlers, i)) { + const h = handlers[i], + groups = h.groups ? h.groups + 1 : 1; + if (!h.literal && h.token) { + all[h.token.val[0]] = h.deser(matches.slice(matchIndex, matchIndex + groups)); + } + matchIndex += groups; + } + } + return [matches, all]; + } else { + return [matches, {}]; + } +} + +function dateTimeFromMatches(matches) { + const toField = (token) => { + switch (token) { + case "S": + return "millisecond"; + case "s": + return "second"; + case "m": + return "minute"; + case "h": + case "H": + return "hour"; + case "d": + return "day"; + case "o": + return "ordinal"; + case "L": + case "M": + return "month"; + case "y": + return "year"; + case "E": + case "c": + return "weekday"; + case "W": + return "weekNumber"; + case "k": + return "weekYear"; + case "q": + return "quarter"; + default: + return null; + } + }; + + let zone = null; + let specificOffset; + if (!isUndefined(matches.z)) { + zone = IANAZone.create(matches.z); + } + + if (!isUndefined(matches.Z)) { + if (!zone) { + zone = new FixedOffsetZone(matches.Z); + } + specificOffset = matches.Z; + } + + if (!isUndefined(matches.q)) { + matches.M = (matches.q - 1) * 3 + 1; + } + + if (!isUndefined(matches.h)) { + if (matches.h < 12 && matches.a === 1) { + matches.h += 12; + } else if (matches.h === 12 && matches.a === 0) { + matches.h = 0; + } + } + + if (matches.G === 0 && matches.y) { + matches.y = -matches.y; + } + + if (!isUndefined(matches.u)) { + matches.S = parseMillis(matches.u); + } + + const vals = Object.keys(matches).reduce((r, k) => { + const f = toField(k); + if (f) { + r[f] = matches[k]; + } + + return r; + }, {}); + + return [vals, zone, specificOffset]; +} + +let dummyDateTimeCache = null; + +function getDummyDateTime() { + if (!dummyDateTimeCache) { + dummyDateTimeCache = DateTime.fromMillis(1555555555555); + } + + return dummyDateTimeCache; +} + +function maybeExpandMacroToken(token, locale) { + if (token.literal) { + return token; + } + + const formatOpts = Formatter.macroTokenToFormatOpts(token.val); + + if (!formatOpts) { + return token; + } + + const formatter = Formatter.create(locale, formatOpts); + const parts = formatter.formatDateTimeParts(getDummyDateTime()); + + const tokens = parts.map((p) => tokenForPart(p, locale, formatOpts)); + + if (tokens.includes(undefined)) { + return token; + } + + return tokens; +} + +function expandMacroTokens(tokens, locale) { + return Array.prototype.concat(...tokens.map((t) => maybeExpandMacroToken(t, locale))); +} + +/** + * @private + */ + +function explainFromTokens(locale, input, format) { + const tokens = expandMacroTokens(Formatter.parseFormat(format), locale), + units = tokens.map((t) => unitForToken(t, locale)), + disqualifyingUnit = units.find((t) => t.invalidReason); + + if (disqualifyingUnit) { + return { input, tokens, invalidReason: disqualifyingUnit.invalidReason }; + } else { + const [regexString, handlers] = buildRegex(units), + regex = RegExp(regexString, "i"), + [rawMatches, matches] = match(input, regex, handlers), + [result, zone, specificOffset] = matches + ? dateTimeFromMatches(matches) + : [null, null, undefined]; + if (hasOwnProperty(matches, "a") && hasOwnProperty(matches, "H")) { + throw new ConflictingSpecificationError( + "Can't include meridiem when specifying 24-hour format" + ); + } + return { input, tokens, regex, rawMatches, matches, result, zone, specificOffset }; + } +} + +function parseFromTokens(locale, input, format) { + const { result, zone, specificOffset, invalidReason } = explainFromTokens(locale, input, format); + return [result, zone, specificOffset, invalidReason]; +} + +const nonLeapLadder = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334], + leapLadder = [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335]; + +function unitOutOfRange(unit, value) { + return new Invalid( + "unit out of range", + `you specified ${value} (of type ${typeof value}) as a ${unit}, which is invalid` + ); +} + +function dayOfWeek(year, month, day) { + const js = new Date(Date.UTC(year, month - 1, day)).getUTCDay(); + return js === 0 ? 7 : js; +} + +function computeOrdinal(year, month, day) { + return day + (isLeapYear(year) ? leapLadder : nonLeapLadder)[month - 1]; +} + +function uncomputeOrdinal(year, ordinal) { + const table = isLeapYear(year) ? leapLadder : nonLeapLadder, + month0 = table.findIndex((i) => i < ordinal), + day = ordinal - table[month0]; + return { month: month0 + 1, day }; +} + +/** + * @private + */ + +function gregorianToWeek(gregObj) { + const { year, month, day } = gregObj, + ordinal = computeOrdinal(year, month, day), + weekday = dayOfWeek(year, month, day); + + let weekNumber = Math.floor((ordinal - weekday + 10) / 7), + weekYear; + + if (weekNumber < 1) { + weekYear = year - 1; + weekNumber = weeksInWeekYear(weekYear); + } else if (weekNumber > weeksInWeekYear(year)) { + weekYear = year + 1; + weekNumber = 1; + } else { + weekYear = year; + } + + return { weekYear, weekNumber, weekday, ...timeObject(gregObj) }; +} + +function weekToGregorian(weekData) { + const { weekYear, weekNumber, weekday } = weekData, + weekdayOfJan4 = dayOfWeek(weekYear, 1, 4), + yearInDays = daysInYear(weekYear); + + let ordinal = weekNumber * 7 + weekday - weekdayOfJan4 - 3, + year; + + if (ordinal < 1) { + year = weekYear - 1; + ordinal += daysInYear(year); + } else if (ordinal > yearInDays) { + year = weekYear + 1; + ordinal -= daysInYear(weekYear); + } else { + year = weekYear; + } + + const { month, day } = uncomputeOrdinal(year, ordinal); + return { year, month, day, ...timeObject(weekData) }; +} + +function gregorianToOrdinal(gregData) { + const { year, month, day } = gregData; + const ordinal = computeOrdinal(year, month, day); + return { year, ordinal, ...timeObject(gregData) }; +} + +function ordinalToGregorian(ordinalData) { + const { year, ordinal } = ordinalData; + const { month, day } = uncomputeOrdinal(year, ordinal); + return { year, month, day, ...timeObject(ordinalData) }; +} + +function hasInvalidWeekData(obj) { + const validYear = isInteger(obj.weekYear), + validWeek = integerBetween(obj.weekNumber, 1, weeksInWeekYear(obj.weekYear)), + validWeekday = integerBetween(obj.weekday, 1, 7); + + if (!validYear) { + return unitOutOfRange("weekYear", obj.weekYear); + } else if (!validWeek) { + return unitOutOfRange("week", obj.week); + } else if (!validWeekday) { + return unitOutOfRange("weekday", obj.weekday); + } else return false; +} + +function hasInvalidOrdinalData(obj) { + const validYear = isInteger(obj.year), + validOrdinal = integerBetween(obj.ordinal, 1, daysInYear(obj.year)); + + if (!validYear) { + return unitOutOfRange("year", obj.year); + } else if (!validOrdinal) { + return unitOutOfRange("ordinal", obj.ordinal); + } else return false; +} + +function hasInvalidGregorianData(obj) { + const validYear = isInteger(obj.year), + validMonth = integerBetween(obj.month, 1, 12), + validDay = integerBetween(obj.day, 1, daysInMonth(obj.year, obj.month)); + + if (!validYear) { + return unitOutOfRange("year", obj.year); + } else if (!validMonth) { + return unitOutOfRange("month", obj.month); + } else if (!validDay) { + return unitOutOfRange("day", obj.day); + } else return false; +} + +function hasInvalidTimeData(obj) { + const { hour, minute, second, millisecond } = obj; + const validHour = + integerBetween(hour, 0, 23) || + (hour === 24 && minute === 0 && second === 0 && millisecond === 0), + validMinute = integerBetween(minute, 0, 59), + validSecond = integerBetween(second, 0, 59), + validMillisecond = integerBetween(millisecond, 0, 999); + + if (!validHour) { + return unitOutOfRange("hour", hour); + } else if (!validMinute) { + return unitOutOfRange("minute", minute); + } else if (!validSecond) { + return unitOutOfRange("second", second); + } else if (!validMillisecond) { + return unitOutOfRange("millisecond", millisecond); + } else return false; +} + +const INVALID = "Invalid DateTime"; +const MAX_DATE = 8.64e15; + +function unsupportedZone(zone) { + return new Invalid("unsupported zone", `the zone "${zone.name}" is not supported`); +} + +// we cache week data on the DT object and this intermediates the cache +function possiblyCachedWeekData(dt) { + if (dt.weekData === null) { + dt.weekData = gregorianToWeek(dt.c); + } + return dt.weekData; +} + +// clone really means, "make a new object with these modifications". all "setters" really use this +// to create a new object while only changing some of the properties +function clone(inst, alts) { + const current = { + ts: inst.ts, + zone: inst.zone, + c: inst.c, + o: inst.o, + loc: inst.loc, + invalid: inst.invalid, + }; + return new DateTime({ ...current, ...alts, old: current }); +} + +// find the right offset a given local time. The o input is our guess, which determines which +// offset we'll pick in ambiguous cases (e.g. there are two 3 AMs b/c Fallback DST) +function fixOffset(localTS, o, tz) { + // Our UTC time is just a guess because our offset is just a guess + let utcGuess = localTS - o * 60 * 1000; + + // Test whether the zone matches the offset for this ts + const o2 = tz.offset(utcGuess); + + // If so, offset didn't change and we're done + if (o === o2) { + return [utcGuess, o]; + } + + // If not, change the ts by the difference in the offset + utcGuess -= (o2 - o) * 60 * 1000; + + // If that gives us the local time we want, we're done + const o3 = tz.offset(utcGuess); + if (o2 === o3) { + return [utcGuess, o2]; + } + + // If it's different, we're in a hole time. The offset has changed, but the we don't adjust the time + return [localTS - Math.min(o2, o3) * 60 * 1000, Math.max(o2, o3)]; +} + +// convert an epoch timestamp into a calendar object with the given offset +function tsToObj(ts, offset) { + ts += offset * 60 * 1000; + + const d = new Date(ts); + + return { + year: d.getUTCFullYear(), + month: d.getUTCMonth() + 1, + day: d.getUTCDate(), + hour: d.getUTCHours(), + minute: d.getUTCMinutes(), + second: d.getUTCSeconds(), + millisecond: d.getUTCMilliseconds(), + }; +} + +// convert a calendar object to a epoch timestamp +function objToTS(obj, offset, zone) { + return fixOffset(objToLocalTS(obj), offset, zone); +} + +// create a new DT instance by adding a duration, adjusting for DSTs +function adjustTime(inst, dur) { + const oPre = inst.o, + year = inst.c.year + Math.trunc(dur.years), + month = inst.c.month + Math.trunc(dur.months) + Math.trunc(dur.quarters) * 3, + c = { + ...inst.c, + year, + month, + day: + Math.min(inst.c.day, daysInMonth(year, month)) + + Math.trunc(dur.days) + + Math.trunc(dur.weeks) * 7, + }, + millisToAdd = Duration.fromObject({ + years: dur.years - Math.trunc(dur.years), + quarters: dur.quarters - Math.trunc(dur.quarters), + months: dur.months - Math.trunc(dur.months), + weeks: dur.weeks - Math.trunc(dur.weeks), + days: dur.days - Math.trunc(dur.days), + hours: dur.hours, + minutes: dur.minutes, + seconds: dur.seconds, + milliseconds: dur.milliseconds, + }).as("milliseconds"), + localTS = objToLocalTS(c); + + let [ts, o] = fixOffset(localTS, oPre, inst.zone); + + if (millisToAdd !== 0) { + ts += millisToAdd; + // that could have changed the offset by going over a DST, but we want to keep the ts the same + o = inst.zone.offset(ts); + } + + return { ts, o }; +} + +// helper useful in turning the results of parsing into real dates +// by handling the zone options +function parseDataToDateTime(parsed, parsedZone, opts, format, text, specificOffset) { + const { setZone, zone } = opts; + if (parsed && Object.keys(parsed).length !== 0) { + const interpretationZone = parsedZone || zone, + inst = DateTime.fromObject(parsed, { + ...opts, + zone: interpretationZone, + specificOffset, + }); + return setZone ? inst : inst.setZone(zone); + } else { + return DateTime.invalid( + new Invalid("unparsable", `the input "${text}" can't be parsed as ${format}`) + ); + } +} + +// if you want to output a technical format (e.g. RFC 2822), this helper +// helps handle the details +function toTechFormat(dt, format, allowZ = true) { + return dt.isValid + ? Formatter.create(Locale.create("en-US"), { + allowZ, + forceSimple: true, + }).formatDateTimeFromString(dt, format) + : null; +} + +function toISODate(o, extended) { + const longFormat = o.c.year > 9999 || o.c.year < 0; + let c = ""; + if (longFormat && o.c.year >= 0) c += "+"; + c += padStart(o.c.year, longFormat ? 6 : 4); + + if (extended) { + c += "-"; + c += padStart(o.c.month); + c += "-"; + c += padStart(o.c.day); + } else { + c += padStart(o.c.month); + c += padStart(o.c.day); + } + return c; +} + +function toISOTime(o, extended, suppressSeconds, suppressMilliseconds, includeOffset) { + let c = padStart(o.c.hour); + if (extended) { + c += ":"; + c += padStart(o.c.minute); + if (o.c.second !== 0 || !suppressSeconds) { + c += ":"; + } + } else { + c += padStart(o.c.minute); + } + + if (o.c.second !== 0 || !suppressSeconds) { + c += padStart(o.c.second); + + if (o.c.millisecond !== 0 || !suppressMilliseconds) { + c += "."; + c += padStart(o.c.millisecond, 3); + } + } + + if (includeOffset) { + if (o.isOffsetFixed && o.offset === 0) { + c += "Z"; + } else if (o.o < 0) { + c += "-"; + c += padStart(Math.trunc(-o.o / 60)); + c += ":"; + c += padStart(Math.trunc(-o.o % 60)); + } else { + c += "+"; + c += padStart(Math.trunc(o.o / 60)); + c += ":"; + c += padStart(Math.trunc(o.o % 60)); + } + } + return c; +} + +// defaults for unspecified units in the supported calendars +const defaultUnitValues = { + month: 1, + day: 1, + hour: 0, + minute: 0, + second: 0, + millisecond: 0, + }, + defaultWeekUnitValues = { + weekNumber: 1, + weekday: 1, + hour: 0, + minute: 0, + second: 0, + millisecond: 0, + }, + defaultOrdinalUnitValues = { + ordinal: 1, + hour: 0, + minute: 0, + second: 0, + millisecond: 0, + }; + +// Units in the supported calendars, sorted by bigness +const orderedUnits = ["year", "month", "day", "hour", "minute", "second", "millisecond"], + orderedWeekUnits = [ + "weekYear", + "weekNumber", + "weekday", + "hour", + "minute", + "second", + "millisecond", + ], + orderedOrdinalUnits = ["year", "ordinal", "hour", "minute", "second", "millisecond"]; + +// standardize case and plurality in units +function normalizeUnit(unit) { + const normalized = { + year: "year", + years: "year", + month: "month", + months: "month", + day: "day", + days: "day", + hour: "hour", + hours: "hour", + minute: "minute", + minutes: "minute", + quarter: "quarter", + quarters: "quarter", + second: "second", + seconds: "second", + millisecond: "millisecond", + milliseconds: "millisecond", + weekday: "weekday", + weekdays: "weekday", + weeknumber: "weekNumber", + weeksnumber: "weekNumber", + weeknumbers: "weekNumber", + weekyear: "weekYear", + weekyears: "weekYear", + ordinal: "ordinal", + }[unit.toLowerCase()]; + + if (!normalized) throw new InvalidUnitError(unit); + + return normalized; +} + +// this is a dumbed down version of fromObject() that runs about 60% faster +// but doesn't do any validation, makes a bunch of assumptions about what units +// are present, and so on. + +// this is a dumbed down version of fromObject() that runs about 60% faster +// but doesn't do any validation, makes a bunch of assumptions about what units +// are present, and so on. +function quickDT(obj, opts) { + const zone = normalizeZone(opts.zone, Settings.defaultZone), + loc = Locale.fromObject(opts), + tsNow = Settings.now(); + + let ts, o; + + // assume we have the higher-order units + if (!isUndefined(obj.year)) { + for (const u of orderedUnits) { + if (isUndefined(obj[u])) { + obj[u] = defaultUnitValues[u]; + } + } + + const invalid = hasInvalidGregorianData(obj) || hasInvalidTimeData(obj); + if (invalid) { + return DateTime.invalid(invalid); + } + + const offsetProvis = zone.offset(tsNow); + [ts, o] = objToTS(obj, offsetProvis, zone); + } else { + ts = tsNow; + } + + return new DateTime({ ts, zone, loc, o }); +} + +function diffRelative(start, end, opts) { + const round = isUndefined(opts.round) ? true : opts.round, + format = (c, unit) => { + c = roundTo(c, round || opts.calendary ? 0 : 2, true); + const formatter = end.loc.clone(opts).relFormatter(opts); + return formatter.format(c, unit); + }, + differ = (unit) => { + if (opts.calendary) { + if (!end.hasSame(start, unit)) { + return end.startOf(unit).diff(start.startOf(unit), unit).get(unit); + } else return 0; + } else { + return end.diff(start, unit).get(unit); + } + }; + + if (opts.unit) { + return format(differ(opts.unit), opts.unit); + } + + for (const unit of opts.units) { + const count = differ(unit); + if (Math.abs(count) >= 1) { + return format(count, unit); + } + } + return format(start > end ? -0 : 0, opts.units[opts.units.length - 1]); +} + +function lastOpts(argList) { + let opts = {}, + args; + if (argList.length > 0 && typeof argList[argList.length - 1] === "object") { + opts = argList[argList.length - 1]; + args = Array.from(argList).slice(0, argList.length - 1); + } else { + args = Array.from(argList); + } + return [opts, args]; +} + +/** + * A DateTime is an immutable data structure representing a specific date and time and accompanying methods. It contains class and instance methods for creating, parsing, interrogating, transforming, and formatting them. + * + * A DateTime comprises of: + * * A timestamp. Each DateTime instance refers to a specific millisecond of the Unix epoch. + * * A time zone. Each instance is considered in the context of a specific zone (by default the local system's zone). + * * Configuration properties that effect how output strings are formatted, such as `locale`, `numberingSystem`, and `outputCalendar`. + * + * Here is a brief overview of the most commonly used functionality it provides: + * + * * **Creation**: To create a DateTime from its components, use one of its factory class methods: {@link DateTime#local}, {@link DateTime#utc}, and (most flexibly) {@link DateTime#fromObject}. To create one from a standard string format, use {@link DateTime#fromISO}, {@link DateTime#fromHTTP}, and {@link DateTime#fromRFC2822}. To create one from a custom string format, use {@link DateTime#fromFormat}. To create one from a native JS date, use {@link DateTime#fromJSDate}. + * * **Gregorian calendar and time**: To examine the Gregorian properties of a DateTime individually (i.e as opposed to collectively through {@link DateTime#toObject}), use the {@link DateTime#year}, {@link DateTime#month}, + * {@link DateTime#day}, {@link DateTime#hour}, {@link DateTime#minute}, {@link DateTime#second}, {@link DateTime#millisecond} accessors. + * * **Week calendar**: For ISO week calendar attributes, see the {@link DateTime#weekYear}, {@link DateTime#weekNumber}, and {@link DateTime#weekday} accessors. + * * **Configuration** See the {@link DateTime#locale} and {@link DateTime#numberingSystem} accessors. + * * **Transformation**: To transform the DateTime into other DateTimes, use {@link DateTime#set}, {@link DateTime#reconfigure}, {@link DateTime#setZone}, {@link DateTime#setLocale}, {@link DateTime.plus}, {@link DateTime#minus}, {@link DateTime#endOf}, {@link DateTime#startOf}, {@link DateTime#toUTC}, and {@link DateTime#toLocal}. + * * **Output**: To convert the DateTime to other representations, use the {@link DateTime#toRelative}, {@link DateTime#toRelativeCalendar}, {@link DateTime#toJSON}, {@link DateTime#toISO}, {@link DateTime#toHTTP}, {@link DateTime#toObject}, {@link DateTime#toRFC2822}, {@link DateTime#toString}, {@link DateTime#toLocaleString}, {@link DateTime#toFormat}, {@link DateTime#toMillis} and {@link DateTime#toJSDate}. + * + * There's plenty others documented below. In addition, for more information on subtler topics like internationalization, time zones, alternative calendars, validity, and so on, see the external documentation. + */ +class DateTime { + /** + * @access private + */ + constructor(config) { + const zone = config.zone || Settings.defaultZone; + + let invalid = + config.invalid || + (Number.isNaN(config.ts) ? new Invalid("invalid input") : null) || + (!zone.isValid ? unsupportedZone(zone) : null); + /** + * @access private + */ + this.ts = isUndefined(config.ts) ? Settings.now() : config.ts; + + let c = null, + o = null; + if (!invalid) { + const unchanged = config.old && config.old.ts === this.ts && config.old.zone.equals(zone); + + if (unchanged) { + [c, o] = [config.old.c, config.old.o]; + } else { + const ot = zone.offset(this.ts); + c = tsToObj(this.ts, ot); + invalid = Number.isNaN(c.year) ? new Invalid("invalid input") : null; + c = invalid ? null : c; + o = invalid ? null : ot; + } + } + + /** + * @access private + */ + this._zone = zone; + /** + * @access private + */ + this.loc = config.loc || Locale.create(); + /** + * @access private + */ + this.invalid = invalid; + /** + * @access private + */ + this.weekData = null; + /** + * @access private + */ + this.c = c; + /** + * @access private + */ + this.o = o; + /** + * @access private + */ + this.isLuxonDateTime = true; + } + + // CONSTRUCT + + /** + * Create a DateTime for the current instant, in the system's time zone. + * + * Use Settings to override these default values if needed. + * @example DateTime.now().toISO() //~> now in the ISO format + * @return {DateTime} + */ + static now() { + return new DateTime({}); + } + + /** + * Create a local DateTime + * @param {number} [year] - The calendar year. If omitted (as in, call `local()` with no arguments), the current time will be used + * @param {number} [month=1] - The month, 1-indexed + * @param {number} [day=1] - The day of the month, 1-indexed + * @param {number} [hour=0] - The hour of the day, in 24-hour time + * @param {number} [minute=0] - The minute of the hour, meaning a number between 0 and 59 + * @param {number} [second=0] - The second of the minute, meaning a number between 0 and 59 + * @param {number} [millisecond=0] - The millisecond of the second, meaning a number between 0 and 999 + * @example DateTime.local() //~> now + * @example DateTime.local({ zone: "America/New_York" }) //~> now, in US east coast time + * @example DateTime.local(2017) //~> 2017-01-01T00:00:00 + * @example DateTime.local(2017, 3) //~> 2017-03-01T00:00:00 + * @example DateTime.local(2017, 3, 12, { locale: "fr" }) //~> 2017-03-12T00:00:00, with a French locale + * @example DateTime.local(2017, 3, 12, 5) //~> 2017-03-12T05:00:00 + * @example DateTime.local(2017, 3, 12, 5, { zone: "utc" }) //~> 2017-03-12T05:00:00, in UTC + * @example DateTime.local(2017, 3, 12, 5, 45) //~> 2017-03-12T05:45:00 + * @example DateTime.local(2017, 3, 12, 5, 45, 10) //~> 2017-03-12T05:45:10 + * @example DateTime.local(2017, 3, 12, 5, 45, 10, 765) //~> 2017-03-12T05:45:10.765 + * @return {DateTime} + */ + static local() { + const [opts, args] = lastOpts(arguments), + [year, month, day, hour, minute, second, millisecond] = args; + return quickDT({ year, month, day, hour, minute, second, millisecond }, opts); + } + + /** + * Create a DateTime in UTC + * @param {number} [year] - The calendar year. If omitted (as in, call `utc()` with no arguments), the current time will be used + * @param {number} [month=1] - The month, 1-indexed + * @param {number} [day=1] - The day of the month + * @param {number} [hour=0] - The hour of the day, in 24-hour time + * @param {number} [minute=0] - The minute of the hour, meaning a number between 0 and 59 + * @param {number} [second=0] - The second of the minute, meaning a number between 0 and 59 + * @param {number} [millisecond=0] - The millisecond of the second, meaning a number between 0 and 999 + * @param {Object} options - configuration options for the DateTime + * @param {string} [options.locale] - a locale to set on the resulting DateTime instance + * @param {string} [options.outputCalendar] - the output calendar to set on the resulting DateTime instance + * @param {string} [options.numberingSystem] - the numbering system to set on the resulting DateTime instance + * @example DateTime.utc() //~> now + * @example DateTime.utc(2017) //~> 2017-01-01T00:00:00Z + * @example DateTime.utc(2017, 3) //~> 2017-03-01T00:00:00Z + * @example DateTime.utc(2017, 3, 12) //~> 2017-03-12T00:00:00Z + * @example DateTime.utc(2017, 3, 12, 5) //~> 2017-03-12T05:00:00Z + * @example DateTime.utc(2017, 3, 12, 5, 45) //~> 2017-03-12T05:45:00Z + * @example DateTime.utc(2017, 3, 12, 5, 45, { locale: "fr" }) //~> 2017-03-12T05:45:00Z with a French locale + * @example DateTime.utc(2017, 3, 12, 5, 45, 10) //~> 2017-03-12T05:45:10Z + * @example DateTime.utc(2017, 3, 12, 5, 45, 10, 765, { locale: "fr" }) //~> 2017-03-12T05:45:10.765Z with a French locale + * @return {DateTime} + */ + static utc() { + const [opts, args] = lastOpts(arguments), + [year, month, day, hour, minute, second, millisecond] = args; + + opts.zone = FixedOffsetZone.utcInstance; + return quickDT({ year, month, day, hour, minute, second, millisecond }, opts); + } + + /** + * Create a DateTime from a JavaScript Date object. Uses the default zone. + * @param {Date} date - a JavaScript Date object + * @param {Object} options - configuration options for the DateTime + * @param {string|Zone} [options.zone='local'] - the zone to place the DateTime into + * @return {DateTime} + */ + static fromJSDate(date, options = {}) { + const ts = isDate(date) ? date.valueOf() : NaN; + if (Number.isNaN(ts)) { + return DateTime.invalid("invalid input"); + } + + const zoneToUse = normalizeZone(options.zone, Settings.defaultZone); + if (!zoneToUse.isValid) { + return DateTime.invalid(unsupportedZone(zoneToUse)); + } + + return new DateTime({ + ts: ts, + zone: zoneToUse, + loc: Locale.fromObject(options), + }); + } + + /** + * Create a DateTime from a number of milliseconds since the epoch (meaning since 1 January 1970 00:00:00 UTC). Uses the default zone. + * @param {number} milliseconds - a number of milliseconds since 1970 UTC + * @param {Object} options - configuration options for the DateTime + * @param {string|Zone} [options.zone='local'] - the zone to place the DateTime into + * @param {string} [options.locale] - a locale to set on the resulting DateTime instance + * @param {string} options.outputCalendar - the output calendar to set on the resulting DateTime instance + * @param {string} options.numberingSystem - the numbering system to set on the resulting DateTime instance + * @return {DateTime} + */ + static fromMillis(milliseconds, options = {}) { + if (!isNumber(milliseconds)) { + throw new InvalidArgumentError( + `fromMillis requires a numerical input, but received a ${typeof milliseconds} with value ${milliseconds}` + ); + } else if (milliseconds < -MAX_DATE || milliseconds > MAX_DATE) { + // this isn't perfect because because we can still end up out of range because of additional shifting, but it's a start + return DateTime.invalid("Timestamp out of range"); + } else { + return new DateTime({ + ts: milliseconds, + zone: normalizeZone(options.zone, Settings.defaultZone), + loc: Locale.fromObject(options), + }); + } + } + + /** + * Create a DateTime from a number of seconds since the epoch (meaning since 1 January 1970 00:00:00 UTC). Uses the default zone. + * @param {number} seconds - a number of seconds since 1970 UTC + * @param {Object} options - configuration options for the DateTime + * @param {string|Zone} [options.zone='local'] - the zone to place the DateTime into + * @param {string} [options.locale] - a locale to set on the resulting DateTime instance + * @param {string} options.outputCalendar - the output calendar to set on the resulting DateTime instance + * @param {string} options.numberingSystem - the numbering system to set on the resulting DateTime instance + * @return {DateTime} + */ + static fromSeconds(seconds, options = {}) { + if (!isNumber(seconds)) { + throw new InvalidArgumentError("fromSeconds requires a numerical input"); + } else { + return new DateTime({ + ts: seconds * 1000, + zone: normalizeZone(options.zone, Settings.defaultZone), + loc: Locale.fromObject(options), + }); + } + } + + /** + * Create a DateTime from a JavaScript object with keys like 'year' and 'hour' with reasonable defaults. + * @param {Object} obj - the object to create the DateTime from + * @param {number} obj.year - a year, such as 1987 + * @param {number} obj.month - a month, 1-12 + * @param {number} obj.day - a day of the month, 1-31, depending on the month + * @param {number} obj.ordinal - day of the year, 1-365 or 366 + * @param {number} obj.weekYear - an ISO week year + * @param {number} obj.weekNumber - an ISO week number, between 1 and 52 or 53, depending on the year + * @param {number} obj.weekday - an ISO weekday, 1-7, where 1 is Monday and 7 is Sunday + * @param {number} obj.hour - hour of the day, 0-23 + * @param {number} obj.minute - minute of the hour, 0-59 + * @param {number} obj.second - second of the minute, 0-59 + * @param {number} obj.millisecond - millisecond of the second, 0-999 + * @param {Object} opts - options for creating this DateTime + * @param {string|Zone} [opts.zone='local'] - interpret the numbers in the context of a particular zone. Can take any value taken as the first argument to setZone() + * @param {string} [opts.locale='system's locale'] - a locale to set on the resulting DateTime instance + * @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance + * @param {string} opts.numberingSystem - the numbering system to set on the resulting DateTime instance + * @example DateTime.fromObject({ year: 1982, month: 5, day: 25}).toISODate() //=> '1982-05-25' + * @example DateTime.fromObject({ year: 1982 }).toISODate() //=> '1982-01-01' + * @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }) //~> today at 10:26:06 + * @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }, { zone: 'utc' }), + * @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }, { zone: 'local' }) + * @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }, { zone: 'America/New_York' }) + * @example DateTime.fromObject({ weekYear: 2016, weekNumber: 2, weekday: 3 }).toISODate() //=> '2016-01-13' + * @return {DateTime} + */ + static fromObject(obj, opts = {}) { + obj = obj || {}; + const zoneToUse = normalizeZone(opts.zone, Settings.defaultZone); + if (!zoneToUse.isValid) { + return DateTime.invalid(unsupportedZone(zoneToUse)); + } + + const tsNow = Settings.now(), + offsetProvis = !isUndefined(opts.specificOffset) + ? opts.specificOffset + : zoneToUse.offset(tsNow), + normalized = normalizeObject(obj, normalizeUnit), + containsOrdinal = !isUndefined(normalized.ordinal), + containsGregorYear = !isUndefined(normalized.year), + containsGregorMD = !isUndefined(normalized.month) || !isUndefined(normalized.day), + containsGregor = containsGregorYear || containsGregorMD, + definiteWeekDef = normalized.weekYear || normalized.weekNumber, + loc = Locale.fromObject(opts); + + // cases: + // just a weekday -> this week's instance of that weekday, no worries + // (gregorian data or ordinal) + (weekYear or weekNumber) -> error + // (gregorian month or day) + ordinal -> error + // otherwise just use weeks or ordinals or gregorian, depending on what's specified + + if ((containsGregor || containsOrdinal) && definiteWeekDef) { + throw new ConflictingSpecificationError( + "Can't mix weekYear/weekNumber units with year/month/day or ordinals" + ); + } + + if (containsGregorMD && containsOrdinal) { + throw new ConflictingSpecificationError("Can't mix ordinal dates with month/day"); + } + + const useWeekData = definiteWeekDef || (normalized.weekday && !containsGregor); + + // configure ourselves to deal with gregorian dates or week stuff + let units, + defaultValues, + objNow = tsToObj(tsNow, offsetProvis); + if (useWeekData) { + units = orderedWeekUnits; + defaultValues = defaultWeekUnitValues; + objNow = gregorianToWeek(objNow); + } else if (containsOrdinal) { + units = orderedOrdinalUnits; + defaultValues = defaultOrdinalUnitValues; + objNow = gregorianToOrdinal(objNow); + } else { + units = orderedUnits; + defaultValues = defaultUnitValues; + } + + // set default values for missing stuff + let foundFirst = false; + for (const u of units) { + const v = normalized[u]; + if (!isUndefined(v)) { + foundFirst = true; + } else if (foundFirst) { + normalized[u] = defaultValues[u]; + } else { + normalized[u] = objNow[u]; + } + } + + // make sure the values we have are in range + const higherOrderInvalid = useWeekData + ? hasInvalidWeekData(normalized) + : containsOrdinal + ? hasInvalidOrdinalData(normalized) + : hasInvalidGregorianData(normalized), + invalid = higherOrderInvalid || hasInvalidTimeData(normalized); + + if (invalid) { + return DateTime.invalid(invalid); + } + + // compute the actual time + const gregorian = useWeekData + ? weekToGregorian(normalized) + : containsOrdinal + ? ordinalToGregorian(normalized) + : normalized, + [tsFinal, offsetFinal] = objToTS(gregorian, offsetProvis, zoneToUse), + inst = new DateTime({ + ts: tsFinal, + zone: zoneToUse, + o: offsetFinal, + loc, + }); + + // gregorian data + weekday serves only to validate + if (normalized.weekday && containsGregor && obj.weekday !== inst.weekday) { + return DateTime.invalid( + "mismatched weekday", + `you can't specify both a weekday of ${normalized.weekday} and a date of ${inst.toISO()}` + ); + } + + return inst; + } + + /** + * Create a DateTime from an ISO 8601 string + * @param {string} text - the ISO string + * @param {Object} opts - options to affect the creation + * @param {string|Zone} [opts.zone='local'] - use this zone if no offset is specified in the input string itself. Will also convert the time to this zone + * @param {boolean} [opts.setZone=false] - override the zone with a fixed-offset zone specified in the string itself, if it specifies one + * @param {string} [opts.locale='system's locale'] - a locale to set on the resulting DateTime instance + * @param {string} [opts.outputCalendar] - the output calendar to set on the resulting DateTime instance + * @param {string} [opts.numberingSystem] - the numbering system to set on the resulting DateTime instance + * @example DateTime.fromISO('2016-05-25T09:08:34.123') + * @example DateTime.fromISO('2016-05-25T09:08:34.123+06:00') + * @example DateTime.fromISO('2016-05-25T09:08:34.123+06:00', {setZone: true}) + * @example DateTime.fromISO('2016-05-25T09:08:34.123', {zone: 'utc'}) + * @example DateTime.fromISO('2016-W05-4') + * @return {DateTime} + */ + static fromISO(text, opts = {}) { + const [vals, parsedZone] = parseISODate(text); + return parseDataToDateTime(vals, parsedZone, opts, "ISO 8601", text); + } + + /** + * Create a DateTime from an RFC 2822 string + * @param {string} text - the RFC 2822 string + * @param {Object} opts - options to affect the creation + * @param {string|Zone} [opts.zone='local'] - convert the time to this zone. Since the offset is always specified in the string itself, this has no effect on the interpretation of string, merely the zone the resulting DateTime is expressed in. + * @param {boolean} [opts.setZone=false] - override the zone with a fixed-offset zone specified in the string itself, if it specifies one + * @param {string} [opts.locale='system's locale'] - a locale to set on the resulting DateTime instance + * @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance + * @param {string} opts.numberingSystem - the numbering system to set on the resulting DateTime instance + * @example DateTime.fromRFC2822('25 Nov 2016 13:23:12 GMT') + * @example DateTime.fromRFC2822('Fri, 25 Nov 2016 13:23:12 +0600') + * @example DateTime.fromRFC2822('25 Nov 2016 13:23 Z') + * @return {DateTime} + */ + static fromRFC2822(text, opts = {}) { + const [vals, parsedZone] = parseRFC2822Date(text); + return parseDataToDateTime(vals, parsedZone, opts, "RFC 2822", text); + } + + /** + * Create a DateTime from an HTTP header date + * @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1 + * @param {string} text - the HTTP header date + * @param {Object} opts - options to affect the creation + * @param {string|Zone} [opts.zone='local'] - convert the time to this zone. Since HTTP dates are always in UTC, this has no effect on the interpretation of string, merely the zone the resulting DateTime is expressed in. + * @param {boolean} [opts.setZone=false] - override the zone with the fixed-offset zone specified in the string. For HTTP dates, this is always UTC, so this option is equivalent to setting the `zone` option to 'utc', but this option is included for consistency with similar methods. + * @param {string} [opts.locale='system's locale'] - a locale to set on the resulting DateTime instance + * @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance + * @param {string} opts.numberingSystem - the numbering system to set on the resulting DateTime instance + * @example DateTime.fromHTTP('Sun, 06 Nov 1994 08:49:37 GMT') + * @example DateTime.fromHTTP('Sunday, 06-Nov-94 08:49:37 GMT') + * @example DateTime.fromHTTP('Sun Nov 6 08:49:37 1994') + * @return {DateTime} + */ + static fromHTTP(text, opts = {}) { + const [vals, parsedZone] = parseHTTPDate(text); + return parseDataToDateTime(vals, parsedZone, opts, "HTTP", opts); + } + + /** + * Create a DateTime from an input string and format string. + * Defaults to en-US if no locale has been specified, regardless of the system's locale. For a table of tokens and their interpretations, see [here](https://moment.github.io/luxon/#/parsing?id=table-of-tokens). + * @param {string} text - the string to parse + * @param {string} fmt - the format the string is expected to be in (see the link below for the formats) + * @param {Object} opts - options to affect the creation + * @param {string|Zone} [opts.zone='local'] - use this zone if no offset is specified in the input string itself. Will also convert the DateTime to this zone + * @param {boolean} [opts.setZone=false] - override the zone with a zone specified in the string itself, if it specifies one + * @param {string} [opts.locale='en-US'] - a locale string to use when parsing. Will also set the DateTime to this locale + * @param {string} opts.numberingSystem - the numbering system to use when parsing. Will also set the resulting DateTime to this numbering system + * @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance + * @return {DateTime} + */ + static fromFormat(text, fmt, opts = {}) { + if (isUndefined(text) || isUndefined(fmt)) { + throw new InvalidArgumentError("fromFormat requires an input string and a format"); + } + + const { locale = null, numberingSystem = null } = opts, + localeToUse = Locale.fromOpts({ + locale, + numberingSystem, + defaultToEN: true, + }), + [vals, parsedZone, specificOffset, invalid] = parseFromTokens(localeToUse, text, fmt); + if (invalid) { + return DateTime.invalid(invalid); + } else { + return parseDataToDateTime(vals, parsedZone, opts, `format ${fmt}`, text, specificOffset); + } + } + + /** + * @deprecated use fromFormat instead + */ + static fromString(text, fmt, opts = {}) { + return DateTime.fromFormat(text, fmt, opts); + } + + /** + * Create a DateTime from a SQL date, time, or datetime + * Defaults to en-US if no locale has been specified, regardless of the system's locale + * @param {string} text - the string to parse + * @param {Object} opts - options to affect the creation + * @param {string|Zone} [opts.zone='local'] - use this zone if no offset is specified in the input string itself. Will also convert the DateTime to this zone + * @param {boolean} [opts.setZone=false] - override the zone with a zone specified in the string itself, if it specifies one + * @param {string} [opts.locale='en-US'] - a locale string to use when parsing. Will also set the DateTime to this locale + * @param {string} opts.numberingSystem - the numbering system to use when parsing. Will also set the resulting DateTime to this numbering system + * @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance + * @example DateTime.fromSQL('2017-05-15') + * @example DateTime.fromSQL('2017-05-15 09:12:34') + * @example DateTime.fromSQL('2017-05-15 09:12:34.342') + * @example DateTime.fromSQL('2017-05-15 09:12:34.342+06:00') + * @example DateTime.fromSQL('2017-05-15 09:12:34.342 America/Los_Angeles') + * @example DateTime.fromSQL('2017-05-15 09:12:34.342 America/Los_Angeles', { setZone: true }) + * @example DateTime.fromSQL('2017-05-15 09:12:34.342', { zone: 'America/Los_Angeles' }) + * @example DateTime.fromSQL('09:12:34.342') + * @return {DateTime} + */ + static fromSQL(text, opts = {}) { + const [vals, parsedZone] = parseSQL(text); + return parseDataToDateTime(vals, parsedZone, opts, "SQL", text); + } + + /** + * Create an invalid DateTime. + * @param {string} reason - simple string of why this DateTime is invalid. Should not contain parameters or anything else data-dependent + * @param {string} [explanation=null] - longer explanation, may include parameters and other useful debugging information + * @return {DateTime} + */ + static invalid(reason, explanation = null) { + if (!reason) { + throw new InvalidArgumentError("need to specify a reason the DateTime is invalid"); + } + + const invalid = reason instanceof Invalid ? reason : new Invalid(reason, explanation); + + if (Settings.throwOnInvalid) { + throw new InvalidDateTimeError(invalid); + } else { + return new DateTime({ invalid }); + } + } + + /** + * Check if an object is a DateTime. Works across context boundaries + * @param {object} o + * @return {boolean} + */ + static isDateTime(o) { + return (o && o.isLuxonDateTime) || false; + } + + // INFO + + /** + * Get the value of unit. + * @param {string} unit - a unit such as 'minute' or 'day' + * @example DateTime.local(2017, 7, 4).get('month'); //=> 7 + * @example DateTime.local(2017, 7, 4).get('day'); //=> 4 + * @return {number} + */ + get(unit) { + return this[unit]; + } + + /** + * Returns whether the DateTime is valid. Invalid DateTimes occur when: + * * The DateTime was created from invalid calendar information, such as the 13th month or February 30 + * * The DateTime was created by an operation on another invalid date + * @type {boolean} + */ + get isValid() { + return this.invalid === null; + } + + /** + * Returns an error code if this DateTime is invalid, or null if the DateTime is valid + * @type {string} + */ + get invalidReason() { + return this.invalid ? this.invalid.reason : null; + } + + /** + * Returns an explanation of why this DateTime became invalid, or null if the DateTime is valid + * @type {string} + */ + get invalidExplanation() { + return this.invalid ? this.invalid.explanation : null; + } + + /** + * Get the locale of a DateTime, such 'en-GB'. The locale is used when formatting the DateTime + * + * @type {string} + */ + get locale() { + return this.isValid ? this.loc.locale : null; + } + + /** + * Get the numbering system of a DateTime, such 'beng'. The numbering system is used when formatting the DateTime + * + * @type {string} + */ + get numberingSystem() { + return this.isValid ? this.loc.numberingSystem : null; + } + + /** + * Get the output calendar of a DateTime, such 'islamic'. The output calendar is used when formatting the DateTime + * + * @type {string} + */ + get outputCalendar() { + return this.isValid ? this.loc.outputCalendar : null; + } + + /** + * Get the time zone associated with this DateTime. + * @type {Zone} + */ + get zone() { + return this._zone; + } + + /** + * Get the name of the time zone. + * @type {string} + */ + get zoneName() { + return this.isValid ? this.zone.name : null; + } + + /** + * Get the year + * @example DateTime.local(2017, 5, 25).year //=> 2017 + * @type {number} + */ + get year() { + return this.isValid ? this.c.year : NaN; + } + + /** + * Get the quarter + * @example DateTime.local(2017, 5, 25).quarter //=> 2 + * @type {number} + */ + get quarter() { + return this.isValid ? Math.ceil(this.c.month / 3) : NaN; + } + + /** + * Get the month (1-12). + * @example DateTime.local(2017, 5, 25).month //=> 5 + * @type {number} + */ + get month() { + return this.isValid ? this.c.month : NaN; + } + + /** + * Get the day of the month (1-30ish). + * @example DateTime.local(2017, 5, 25).day //=> 25 + * @type {number} + */ + get day() { + return this.isValid ? this.c.day : NaN; + } + + /** + * Get the hour of the day (0-23). + * @example DateTime.local(2017, 5, 25, 9).hour //=> 9 + * @type {number} + */ + get hour() { + return this.isValid ? this.c.hour : NaN; + } + + /** + * Get the minute of the hour (0-59). + * @example DateTime.local(2017, 5, 25, 9, 30).minute //=> 30 + * @type {number} + */ + get minute() { + return this.isValid ? this.c.minute : NaN; + } + + /** + * Get the second of the minute (0-59). + * @example DateTime.local(2017, 5, 25, 9, 30, 52).second //=> 52 + * @type {number} + */ + get second() { + return this.isValid ? this.c.second : NaN; + } + + /** + * Get the millisecond of the second (0-999). + * @example DateTime.local(2017, 5, 25, 9, 30, 52, 654).millisecond //=> 654 + * @type {number} + */ + get millisecond() { + return this.isValid ? this.c.millisecond : NaN; + } + + /** + * Get the week year + * @see https://en.wikipedia.org/wiki/ISO_week_date + * @example DateTime.local(2014, 12, 31).weekYear //=> 2015 + * @type {number} + */ + get weekYear() { + return this.isValid ? possiblyCachedWeekData(this).weekYear : NaN; + } + + /** + * Get the week number of the week year (1-52ish). + * @see https://en.wikipedia.org/wiki/ISO_week_date + * @example DateTime.local(2017, 5, 25).weekNumber //=> 21 + * @type {number} + */ + get weekNumber() { + return this.isValid ? possiblyCachedWeekData(this).weekNumber : NaN; + } + + /** + * Get the day of the week. + * 1 is Monday and 7 is Sunday + * @see https://en.wikipedia.org/wiki/ISO_week_date + * @example DateTime.local(2014, 11, 31).weekday //=> 4 + * @type {number} + */ + get weekday() { + return this.isValid ? possiblyCachedWeekData(this).weekday : NaN; + } + + /** + * Get the ordinal (meaning the day of the year) + * @example DateTime.local(2017, 5, 25).ordinal //=> 145 + * @type {number|DateTime} + */ + get ordinal() { + return this.isValid ? gregorianToOrdinal(this.c).ordinal : NaN; + } + + /** + * Get the human readable short month name, such as 'Oct'. + * Defaults to the system's locale if no locale has been specified + * @example DateTime.local(2017, 10, 30).monthShort //=> Oct + * @type {string} + */ + get monthShort() { + return this.isValid ? Info.months("short", { locObj: this.loc })[this.month - 1] : null; + } + + /** + * Get the human readable long month name, such as 'October'. + * Defaults to the system's locale if no locale has been specified + * @example DateTime.local(2017, 10, 30).monthLong //=> October + * @type {string} + */ + get monthLong() { + return this.isValid ? Info.months("long", { locObj: this.loc })[this.month - 1] : null; + } + + /** + * Get the human readable short weekday, such as 'Mon'. + * Defaults to the system's locale if no locale has been specified + * @example DateTime.local(2017, 10, 30).weekdayShort //=> Mon + * @type {string} + */ + get weekdayShort() { + return this.isValid ? Info.weekdays("short", { locObj: this.loc })[this.weekday - 1] : null; + } + + /** + * Get the human readable long weekday, such as 'Monday'. + * Defaults to the system's locale if no locale has been specified + * @example DateTime.local(2017, 10, 30).weekdayLong //=> Monday + * @type {string} + */ + get weekdayLong() { + return this.isValid ? Info.weekdays("long", { locObj: this.loc })[this.weekday - 1] : null; + } + + /** + * Get the UTC offset of this DateTime in minutes + * @example DateTime.now().offset //=> -240 + * @example DateTime.utc().offset //=> 0 + * @type {number} + */ + get offset() { + return this.isValid ? +this.o : NaN; + } + + /** + * Get the short human name for the zone's current offset, for example "EST" or "EDT". + * Defaults to the system's locale if no locale has been specified + * @type {string} + */ + get offsetNameShort() { + if (this.isValid) { + return this.zone.offsetName(this.ts, { + format: "short", + locale: this.locale, + }); + } else { + return null; + } + } + + /** + * Get the long human name for the zone's current offset, for example "Eastern Standard Time" or "Eastern Daylight Time". + * Defaults to the system's locale if no locale has been specified + * @type {string} + */ + get offsetNameLong() { + if (this.isValid) { + return this.zone.offsetName(this.ts, { + format: "long", + locale: this.locale, + }); + } else { + return null; + } + } + + /** + * Get whether this zone's offset ever changes, as in a DST. + * @type {boolean} + */ + get isOffsetFixed() { + return this.isValid ? this.zone.isUniversal : null; + } + + /** + * Get whether the DateTime is in a DST. + * @type {boolean} + */ + get isInDST() { + if (this.isOffsetFixed) { + return false; + } else { + return ( + this.offset > this.set({ month: 1 }).offset || this.offset > this.set({ month: 5 }).offset + ); + } + } + + /** + * Returns true if this DateTime is in a leap year, false otherwise + * @example DateTime.local(2016).isInLeapYear //=> true + * @example DateTime.local(2013).isInLeapYear //=> false + * @type {boolean} + */ + get isInLeapYear() { + return isLeapYear(this.year); + } + + /** + * Returns the number of days in this DateTime's month + * @example DateTime.local(2016, 2).daysInMonth //=> 29 + * @example DateTime.local(2016, 3).daysInMonth //=> 31 + * @type {number} + */ + get daysInMonth() { + return daysInMonth(this.year, this.month); + } + + /** + * Returns the number of days in this DateTime's year + * @example DateTime.local(2016).daysInYear //=> 366 + * @example DateTime.local(2013).daysInYear //=> 365 + * @type {number} + */ + get daysInYear() { + return this.isValid ? daysInYear(this.year) : NaN; + } + + /** + * Returns the number of weeks in this DateTime's year + * @see https://en.wikipedia.org/wiki/ISO_week_date + * @example DateTime.local(2004).weeksInWeekYear //=> 53 + * @example DateTime.local(2013).weeksInWeekYear //=> 52 + * @type {number} + */ + get weeksInWeekYear() { + return this.isValid ? weeksInWeekYear(this.weekYear) : NaN; + } + + /** + * Returns the resolved Intl options for this DateTime. + * This is useful in understanding the behavior of formatting methods + * @param {Object} opts - the same options as toLocaleString + * @return {Object} + */ + resolvedLocaleOptions(opts = {}) { + const { locale, numberingSystem, calendar } = Formatter.create( + this.loc.clone(opts), + opts + ).resolvedOptions(this); + return { locale, numberingSystem, outputCalendar: calendar }; + } + + // TRANSFORM + + /** + * "Set" the DateTime's zone to UTC. Returns a newly-constructed DateTime. + * + * Equivalent to {@link DateTime#setZone}('utc') + * @param {number} [offset=0] - optionally, an offset from UTC in minutes + * @param {Object} [opts={}] - options to pass to `setZone()` + * @return {DateTime} + */ + toUTC(offset = 0, opts = {}) { + return this.setZone(FixedOffsetZone.instance(offset), opts); + } + + /** + * "Set" the DateTime's zone to the host's local zone. Returns a newly-constructed DateTime. + * + * Equivalent to `setZone('local')` + * @return {DateTime} + */ + toLocal() { + return this.setZone(Settings.defaultZone); + } + + /** + * "Set" the DateTime's zone to specified zone. Returns a newly-constructed DateTime. + * + * By default, the setter keeps the underlying time the same (as in, the same timestamp), but the new instance will report different local times and consider DSTs when making computations, as with {@link DateTime#plus}. You may wish to use {@link DateTime#toLocal} and {@link DateTime#toUTC} which provide simple convenience wrappers for commonly used zones. + * @param {string|Zone} [zone='local'] - a zone identifier. As a string, that can be any IANA zone supported by the host environment, or a fixed-offset name of the form 'UTC+3', or the strings 'local' or 'utc'. You may also supply an instance of a {@link DateTime#Zone} class. + * @param {Object} opts - options + * @param {boolean} [opts.keepLocalTime=false] - If true, adjust the underlying time so that the local time stays the same, but in the target zone. You should rarely need this. + * @return {DateTime} + */ + setZone(zone, { keepLocalTime = false, keepCalendarTime = false } = {}) { + zone = normalizeZone(zone, Settings.defaultZone); + if (zone.equals(this.zone)) { + return this; + } else if (!zone.isValid) { + return DateTime.invalid(unsupportedZone(zone)); + } else { + let newTS = this.ts; + if (keepLocalTime || keepCalendarTime) { + const offsetGuess = zone.offset(this.ts); + const asObj = this.toObject(); + [newTS] = objToTS(asObj, offsetGuess, zone); + } + return clone(this, { ts: newTS, zone }); + } + } + + /** + * "Set" the locale, numberingSystem, or outputCalendar. Returns a newly-constructed DateTime. + * @param {Object} properties - the properties to set + * @example DateTime.local(2017, 5, 25).reconfigure({ locale: 'en-GB' }) + * @return {DateTime} + */ + reconfigure({ locale, numberingSystem, outputCalendar } = {}) { + const loc = this.loc.clone({ locale, numberingSystem, outputCalendar }); + return clone(this, { loc }); + } + + /** + * "Set" the locale. Returns a newly-constructed DateTime. + * Just a convenient alias for reconfigure({ locale }) + * @example DateTime.local(2017, 5, 25).setLocale('en-GB') + * @return {DateTime} + */ + setLocale(locale) { + return this.reconfigure({ locale }); + } + + /** + * "Set" the values of specified units. Returns a newly-constructed DateTime. + * You can only set units with this method; for "setting" metadata, see {@link DateTime#reconfigure} and {@link DateTime#setZone}. + * @param {Object} values - a mapping of units to numbers + * @example dt.set({ year: 2017 }) + * @example dt.set({ hour: 8, minute: 30 }) + * @example dt.set({ weekday: 5 }) + * @example dt.set({ year: 2005, ordinal: 234 }) + * @return {DateTime} + */ + set(values) { + if (!this.isValid) return this; + + const normalized = normalizeObject(values, normalizeUnit), + settingWeekStuff = + !isUndefined(normalized.weekYear) || + !isUndefined(normalized.weekNumber) || + !isUndefined(normalized.weekday), + containsOrdinal = !isUndefined(normalized.ordinal), + containsGregorYear = !isUndefined(normalized.year), + containsGregorMD = !isUndefined(normalized.month) || !isUndefined(normalized.day), + containsGregor = containsGregorYear || containsGregorMD, + definiteWeekDef = normalized.weekYear || normalized.weekNumber; + + if ((containsGregor || containsOrdinal) && definiteWeekDef) { + throw new ConflictingSpecificationError( + "Can't mix weekYear/weekNumber units with year/month/day or ordinals" + ); + } + + if (containsGregorMD && containsOrdinal) { + throw new ConflictingSpecificationError("Can't mix ordinal dates with month/day"); + } + + let mixed; + if (settingWeekStuff) { + mixed = weekToGregorian({ ...gregorianToWeek(this.c), ...normalized }); + } else if (!isUndefined(normalized.ordinal)) { + mixed = ordinalToGregorian({ ...gregorianToOrdinal(this.c), ...normalized }); + } else { + mixed = { ...this.toObject(), ...normalized }; + + // if we didn't set the day but we ended up on an overflow date, + // use the last day of the right month + if (isUndefined(normalized.day)) { + mixed.day = Math.min(daysInMonth(mixed.year, mixed.month), mixed.day); + } + } + + const [ts, o] = objToTS(mixed, this.o, this.zone); + return clone(this, { ts, o }); + } + + /** + * Add a period of time to this DateTime and return the resulting DateTime + * + * Adding hours, minutes, seconds, or milliseconds increases the timestamp by the right number of milliseconds. Adding days, months, or years shifts the calendar, accounting for DSTs and leap years along the way. Thus, `dt.plus({ hours: 24 })` may result in a different time than `dt.plus({ days: 1 })` if there's a DST shift in between. + * @param {Duration|Object|number} duration - The amount to add. Either a Luxon Duration, a number of milliseconds, the object argument to Duration.fromObject() + * @example DateTime.now().plus(123) //~> in 123 milliseconds + * @example DateTime.now().plus({ minutes: 15 }) //~> in 15 minutes + * @example DateTime.now().plus({ days: 1 }) //~> this time tomorrow + * @example DateTime.now().plus({ days: -1 }) //~> this time yesterday + * @example DateTime.now().plus({ hours: 3, minutes: 13 }) //~> in 3 hr, 13 min + * @example DateTime.now().plus(Duration.fromObject({ hours: 3, minutes: 13 })) //~> in 3 hr, 13 min + * @return {DateTime} + */ + plus(duration) { + if (!this.isValid) return this; + const dur = Duration.fromDurationLike(duration); + return clone(this, adjustTime(this, dur)); + } + + /** + * Subtract a period of time to this DateTime and return the resulting DateTime + * See {@link DateTime#plus} + * @param {Duration|Object|number} duration - The amount to subtract. Either a Luxon Duration, a number of milliseconds, the object argument to Duration.fromObject() + @return {DateTime} + */ + minus(duration) { + if (!this.isValid) return this; + const dur = Duration.fromDurationLike(duration).negate(); + return clone(this, adjustTime(this, dur)); + } + + /** + * "Set" this DateTime to the beginning of a unit of time. + * @param {string} unit - The unit to go to the beginning of. Can be 'year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', or 'millisecond'. + * @example DateTime.local(2014, 3, 3).startOf('month').toISODate(); //=> '2014-03-01' + * @example DateTime.local(2014, 3, 3).startOf('year').toISODate(); //=> '2014-01-01' + * @example DateTime.local(2014, 3, 3).startOf('week').toISODate(); //=> '2014-03-03', weeks always start on Mondays + * @example DateTime.local(2014, 3, 3, 5, 30).startOf('day').toISOTime(); //=> '00:00.000-05:00' + * @example DateTime.local(2014, 3, 3, 5, 30).startOf('hour').toISOTime(); //=> '05:00:00.000-05:00' + * @return {DateTime} + */ + startOf(unit) { + if (!this.isValid) return this; + const o = {}, + normalizedUnit = Duration.normalizeUnit(unit); + switch (normalizedUnit) { + case "years": + o.month = 1; + // falls through + case "quarters": + case "months": + o.day = 1; + // falls through + case "weeks": + case "days": + o.hour = 0; + // falls through + case "hours": + o.minute = 0; + // falls through + case "minutes": + o.second = 0; + // falls through + case "seconds": + o.millisecond = 0; + break; + // no default, invalid units throw in normalizeUnit() + } + + if (normalizedUnit === "weeks") { + o.weekday = 1; + } + + if (normalizedUnit === "quarters") { + const q = Math.ceil(this.month / 3); + o.month = (q - 1) * 3 + 1; + } + + return this.set(o); + } + + /** + * "Set" this DateTime to the end (meaning the last millisecond) of a unit of time + * @param {string} unit - The unit to go to the end of. Can be 'year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', or 'millisecond'. + * @example DateTime.local(2014, 3, 3).endOf('month').toISO(); //=> '2014-03-31T23:59:59.999-05:00' + * @example DateTime.local(2014, 3, 3).endOf('year').toISO(); //=> '2014-12-31T23:59:59.999-05:00' + * @example DateTime.local(2014, 3, 3).endOf('week').toISO(); // => '2014-03-09T23:59:59.999-05:00', weeks start on Mondays + * @example DateTime.local(2014, 3, 3, 5, 30).endOf('day').toISO(); //=> '2014-03-03T23:59:59.999-05:00' + * @example DateTime.local(2014, 3, 3, 5, 30).endOf('hour').toISO(); //=> '2014-03-03T05:59:59.999-05:00' + * @return {DateTime} + */ + endOf(unit) { + return this.isValid + ? this.plus({ [unit]: 1 }) + .startOf(unit) + .minus(1) + : this; + } + + // OUTPUT + + /** + * Returns a string representation of this DateTime formatted according to the specified format string. + * **You may not want this.** See {@link DateTime#toLocaleString} for a more flexible formatting tool. For a table of tokens and their interpretations, see [here](https://moment.github.io/luxon/#/formatting?id=table-of-tokens). + * Defaults to en-US if no locale has been specified, regardless of the system's locale. + * @param {string} fmt - the format string + * @param {Object} opts - opts to override the configuration options on this DateTime + * @example DateTime.now().toFormat('yyyy LLL dd') //=> '2017 Apr 22' + * @example DateTime.now().setLocale('fr').toFormat('yyyy LLL dd') //=> '2017 avr. 22' + * @example DateTime.now().toFormat('yyyy LLL dd', { locale: "fr" }) //=> '2017 avr. 22' + * @example DateTime.now().toFormat("HH 'hours and' mm 'minutes'") //=> '20 hours and 55 minutes' + * @return {string} + */ + toFormat(fmt, opts = {}) { + return this.isValid + ? Formatter.create(this.loc.redefaultToEN(opts)).formatDateTimeFromString(this, fmt) + : INVALID; + } + + /** + * Returns a localized string representing this date. Accepts the same options as the Intl.DateTimeFormat constructor and any presets defined by Luxon, such as `DateTime.DATE_FULL` or `DateTime.TIME_SIMPLE`. + * The exact behavior of this method is browser-specific, but in general it will return an appropriate representation + * of the DateTime in the assigned locale. + * Defaults to the system's locale if no locale has been specified + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat + * @param formatOpts {Object} - Intl.DateTimeFormat constructor options and configuration options + * @param {Object} opts - opts to override the configuration options on this DateTime + * @example DateTime.now().toLocaleString(); //=> 4/20/2017 + * @example DateTime.now().setLocale('en-gb').toLocaleString(); //=> '20/04/2017' + * @example DateTime.now().toLocaleString({ locale: 'en-gb' }); //=> '20/04/2017' + * @example DateTime.now().toLocaleString(DateTime.DATE_FULL); //=> 'April 20, 2017' + * @example DateTime.now().toLocaleString(DateTime.TIME_SIMPLE); //=> '11:32 AM' + * @example DateTime.now().toLocaleString(DateTime.DATETIME_SHORT); //=> '4/20/2017, 11:32 AM' + * @example DateTime.now().toLocaleString({ weekday: 'long', month: 'long', day: '2-digit' }); //=> 'Thursday, April 20' + * @example DateTime.now().toLocaleString({ weekday: 'short', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }); //=> 'Thu, Apr 20, 11:27 AM' + * @example DateTime.now().toLocaleString({ hour: '2-digit', minute: '2-digit', hourCycle: 'h23' }); //=> '11:32' + * @return {string} + */ + toLocaleString(formatOpts = DATE_SHORT, opts = {}) { + return this.isValid + ? Formatter.create(this.loc.clone(opts), formatOpts).formatDateTime(this) + : INVALID; + } + + /** + * Returns an array of format "parts", meaning individual tokens along with metadata. This is allows callers to post-process individual sections of the formatted output. + * Defaults to the system's locale if no locale has been specified + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat/formatToParts + * @param opts {Object} - Intl.DateTimeFormat constructor options, same as `toLocaleString`. + * @example DateTime.now().toLocaleParts(); //=> [ + * //=> { type: 'day', value: '25' }, + * //=> { type: 'literal', value: '/' }, + * //=> { type: 'month', value: '05' }, + * //=> { type: 'literal', value: '/' }, + * //=> { type: 'year', value: '1982' } + * //=> ] + */ + toLocaleParts(opts = {}) { + return this.isValid + ? Formatter.create(this.loc.clone(opts), opts).formatDateTimeParts(this) + : []; + } + + /** + * Returns an ISO 8601-compliant string representation of this DateTime + * @param {Object} opts - options + * @param {boolean} [opts.suppressMilliseconds=false] - exclude milliseconds from the format if they're 0 + * @param {boolean} [opts.suppressSeconds=false] - exclude seconds from the format if they're 0 + * @param {boolean} [opts.includeOffset=true] - include the offset, such as 'Z' or '-04:00' + * @param {string} [opts.format='extended'] - choose between the basic and extended format + * @example DateTime.utc(1983, 5, 25).toISO() //=> '1982-05-25T00:00:00.000Z' + * @example DateTime.now().toISO() //=> '2017-04-22T20:47:05.335-04:00' + * @example DateTime.now().toISO({ includeOffset: false }) //=> '2017-04-22T20:47:05.335' + * @example DateTime.now().toISO({ format: 'basic' }) //=> '20170422T204705.335-0400' + * @return {string} + */ + toISO({ + format = "extended", + suppressSeconds = false, + suppressMilliseconds = false, + includeOffset = true, + } = {}) { + if (!this.isValid) { + return null; + } + + const ext = format === "extended"; + + let c = toISODate(this, ext); + c += "T"; + c += toISOTime(this, ext, suppressSeconds, suppressMilliseconds, includeOffset); + return c; + } + + /** + * Returns an ISO 8601-compliant string representation of this DateTime's date component + * @param {Object} opts - options + * @param {string} [opts.format='extended'] - choose between the basic and extended format + * @example DateTime.utc(1982, 5, 25).toISODate() //=> '1982-05-25' + * @example DateTime.utc(1982, 5, 25).toISODate({ format: 'basic' }) //=> '19820525' + * @return {string} + */ + toISODate({ format = "extended" } = {}) { + if (!this.isValid) { + return null; + } + + return toISODate(this, format === "extended"); + } + + /** + * Returns an ISO 8601-compliant string representation of this DateTime's week date + * @example DateTime.utc(1982, 5, 25).toISOWeekDate() //=> '1982-W21-2' + * @return {string} + */ + toISOWeekDate() { + return toTechFormat(this, "kkkk-'W'WW-c"); + } + + /** + * Returns an ISO 8601-compliant string representation of this DateTime's time component + * @param {Object} opts - options + * @param {boolean} [opts.suppressMilliseconds=false] - exclude milliseconds from the format if they're 0 + * @param {boolean} [opts.suppressSeconds=false] - exclude seconds from the format if they're 0 + * @param {boolean} [opts.includeOffset=true] - include the offset, such as 'Z' or '-04:00' + * @param {boolean} [opts.includePrefix=false] - include the `T` prefix + * @param {string} [opts.format='extended'] - choose between the basic and extended format + * @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime() //=> '07:34:19.361Z' + * @example DateTime.utc().set({ hour: 7, minute: 34, seconds: 0, milliseconds: 0 }).toISOTime({ suppressSeconds: true }) //=> '07:34Z' + * @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime({ format: 'basic' }) //=> '073419.361Z' + * @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime({ includePrefix: true }) //=> 'T07:34:19.361Z' + * @return {string} + */ + toISOTime({ + suppressMilliseconds = false, + suppressSeconds = false, + includeOffset = true, + includePrefix = false, + format = "extended", + } = {}) { + if (!this.isValid) { + return null; + } + + let c = includePrefix ? "T" : ""; + return ( + c + + toISOTime(this, format === "extended", suppressSeconds, suppressMilliseconds, includeOffset) + ); + } + + /** + * Returns an RFC 2822-compatible string representation of this DateTime + * @example DateTime.utc(2014, 7, 13).toRFC2822() //=> 'Sun, 13 Jul 2014 00:00:00 +0000' + * @example DateTime.local(2014, 7, 13).toRFC2822() //=> 'Sun, 13 Jul 2014 00:00:00 -0400' + * @return {string} + */ + toRFC2822() { + return toTechFormat(this, "EEE, dd LLL yyyy HH:mm:ss ZZZ", false); + } + + /** + * Returns a string representation of this DateTime appropriate for use in HTTP headers. The output is always expressed in GMT. + * Specifically, the string conforms to RFC 1123. + * @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1 + * @example DateTime.utc(2014, 7, 13).toHTTP() //=> 'Sun, 13 Jul 2014 00:00:00 GMT' + * @example DateTime.utc(2014, 7, 13, 19).toHTTP() //=> 'Sun, 13 Jul 2014 19:00:00 GMT' + * @return {string} + */ + toHTTP() { + return toTechFormat(this.toUTC(), "EEE, dd LLL yyyy HH:mm:ss 'GMT'"); + } + + /** + * Returns a string representation of this DateTime appropriate for use in SQL Date + * @example DateTime.utc(2014, 7, 13).toSQLDate() //=> '2014-07-13' + * @return {string} + */ + toSQLDate() { + if (!this.isValid) { + return null; + } + return toISODate(this, true); + } + + /** + * Returns a string representation of this DateTime appropriate for use in SQL Time + * @param {Object} opts - options + * @param {boolean} [opts.includeZone=false] - include the zone, such as 'America/New_York'. Overrides includeOffset. + * @param {boolean} [opts.includeOffset=true] - include the offset, such as 'Z' or '-04:00' + * @example DateTime.utc().toSQL() //=> '05:15:16.345' + * @example DateTime.now().toSQL() //=> '05:15:16.345 -04:00' + * @example DateTime.now().toSQL({ includeOffset: false }) //=> '05:15:16.345' + * @example DateTime.now().toSQL({ includeZone: false }) //=> '05:15:16.345 America/New_York' + * @return {string} + */ + toSQLTime({ includeOffset = true, includeZone = false } = {}) { + let fmt = "HH:mm:ss.SSS"; + + if (includeZone || includeOffset) { + fmt += " "; + if (includeZone) { + fmt += "z"; + } else if (includeOffset) { + fmt += "ZZ"; + } + } + + return toTechFormat(this, fmt, true); + } + + /** + * Returns a string representation of this DateTime appropriate for use in SQL DateTime + * @param {Object} opts - options + * @param {boolean} [opts.includeZone=false] - include the zone, such as 'America/New_York'. Overrides includeOffset. + * @param {boolean} [opts.includeOffset=true] - include the offset, such as 'Z' or '-04:00' + * @example DateTime.utc(2014, 7, 13).toSQL() //=> '2014-07-13 00:00:00.000 Z' + * @example DateTime.local(2014, 7, 13).toSQL() //=> '2014-07-13 00:00:00.000 -04:00' + * @example DateTime.local(2014, 7, 13).toSQL({ includeOffset: false }) //=> '2014-07-13 00:00:00.000' + * @example DateTime.local(2014, 7, 13).toSQL({ includeZone: true }) //=> '2014-07-13 00:00:00.000 America/New_York' + * @return {string} + */ + toSQL(opts = {}) { + if (!this.isValid) { + return null; + } + + return `${this.toSQLDate()} ${this.toSQLTime(opts)}`; + } + + /** + * Returns a string representation of this DateTime appropriate for debugging + * @return {string} + */ + toString() { + return this.isValid ? this.toISO() : INVALID; + } + + /** + * Returns the epoch milliseconds of this DateTime. Alias of {@link DateTime#toMillis} + * @return {number} + */ + valueOf() { + return this.toMillis(); + } + + /** + * Returns the epoch milliseconds of this DateTime. + * @return {number} + */ + toMillis() { + return this.isValid ? this.ts : NaN; + } + + /** + * Returns the epoch seconds of this DateTime. + * @return {number} + */ + toSeconds() { + return this.isValid ? this.ts / 1000 : NaN; + } + + /** + * Returns an ISO 8601 representation of this DateTime appropriate for use in JSON. + * @return {string} + */ + toJSON() { + return this.toISO(); + } + + /** + * Returns a BSON serializable equivalent to this DateTime. + * @return {Date} + */ + toBSON() { + return this.toJSDate(); + } + + /** + * Returns a JavaScript object with this DateTime's year, month, day, and so on. + * @param opts - options for generating the object + * @param {boolean} [opts.includeConfig=false] - include configuration attributes in the output + * @example DateTime.now().toObject() //=> { year: 2017, month: 4, day: 22, hour: 20, minute: 49, second: 42, millisecond: 268 } + * @return {Object} + */ + toObject(opts = {}) { + if (!this.isValid) return {}; + + const base = { ...this.c }; + + if (opts.includeConfig) { + base.outputCalendar = this.outputCalendar; + base.numberingSystem = this.loc.numberingSystem; + base.locale = this.loc.locale; + } + return base; + } + + /** + * Returns a JavaScript Date equivalent to this DateTime. + * @return {Date} + */ + toJSDate() { + return new Date(this.isValid ? this.ts : NaN); + } + + // COMPARE + + /** + * Return the difference between two DateTimes as a Duration. + * @param {DateTime} otherDateTime - the DateTime to compare this one to + * @param {string|string[]} [unit=['milliseconds']] - the unit or array of units (such as 'hours' or 'days') to include in the duration. + * @param {Object} opts - options that affect the creation of the Duration + * @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use + * @example + * var i1 = DateTime.fromISO('1982-05-25T09:45'), + * i2 = DateTime.fromISO('1983-10-14T10:30'); + * i2.diff(i1).toObject() //=> { milliseconds: 43807500000 } + * i2.diff(i1, 'hours').toObject() //=> { hours: 12168.75 } + * i2.diff(i1, ['months', 'days']).toObject() //=> { months: 16, days: 19.03125 } + * i2.diff(i1, ['months', 'days', 'hours']).toObject() //=> { months: 16, days: 19, hours: 0.75 } + * @return {Duration} + */ + diff(otherDateTime, unit = "milliseconds", opts = {}) { + if (!this.isValid || !otherDateTime.isValid) { + return Duration.invalid("created by diffing an invalid DateTime"); + } + + const durOpts = { locale: this.locale, numberingSystem: this.numberingSystem, ...opts }; + + const units = maybeArray(unit).map(Duration.normalizeUnit), + otherIsLater = otherDateTime.valueOf() > this.valueOf(), + earlier = otherIsLater ? this : otherDateTime, + later = otherIsLater ? otherDateTime : this, + diffed = diff(earlier, later, units, durOpts); + + return otherIsLater ? diffed.negate() : diffed; + } + + /** + * Return the difference between this DateTime and right now. + * See {@link DateTime#diff} + * @param {string|string[]} [unit=['milliseconds']] - the unit or units units (such as 'hours' or 'days') to include in the duration + * @param {Object} opts - options that affect the creation of the Duration + * @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use + * @return {Duration} + */ + diffNow(unit = "milliseconds", opts = {}) { + return this.diff(DateTime.now(), unit, opts); + } + + /** + * Return an Interval spanning between this DateTime and another DateTime + * @param {DateTime} otherDateTime - the other end point of the Interval + * @return {Interval} + */ + until(otherDateTime) { + return this.isValid ? Interval.fromDateTimes(this, otherDateTime) : this; + } + + /** + * Return whether this DateTime is in the same unit of time as another DateTime. + * Higher-order units must also be identical for this function to return `true`. + * Note that time zones are **ignored** in this comparison, which compares the **local** calendar time. Use {@link DateTime#setZone} to convert one of the dates if needed. + * @param {DateTime} otherDateTime - the other DateTime + * @param {string} unit - the unit of time to check sameness on + * @example DateTime.now().hasSame(otherDT, 'day'); //~> true if otherDT is in the same current calendar day + * @return {boolean} + */ + hasSame(otherDateTime, unit) { + if (!this.isValid) return false; + + const inputMs = otherDateTime.valueOf(); + const adjustedToZone = this.setZone(otherDateTime.zone, { keepLocalTime: true }); + return adjustedToZone.startOf(unit) <= inputMs && inputMs <= adjustedToZone.endOf(unit); + } + + /** + * Equality check + * Two DateTimes are equal iff they represent the same millisecond, have the same zone and location, and are both valid. + * To compare just the millisecond values, use `+dt1 === +dt2`. + * @param {DateTime} other - the other DateTime + * @return {boolean} + */ + equals(other) { + return ( + this.isValid && + other.isValid && + this.valueOf() === other.valueOf() && + this.zone.equals(other.zone) && + this.loc.equals(other.loc) + ); + } + + /** + * Returns a string representation of a this time relative to now, such as "in two days". Can only internationalize if your + * platform supports Intl.RelativeTimeFormat. Rounds down by default. + * @param {Object} options - options that affect the output + * @param {DateTime} [options.base=DateTime.now()] - the DateTime to use as the basis to which this time is compared. Defaults to now. + * @param {string} [options.style="long"] - the style of units, must be "long", "short", or "narrow" + * @param {string|string[]} options.unit - use a specific unit or array of units; if omitted, or an array, the method will pick the best unit. Use an array or one of "years", "quarters", "months", "weeks", "days", "hours", "minutes", or "seconds" + * @param {boolean} [options.round=true] - whether to round the numbers in the output. + * @param {number} [options.padding=0] - padding in milliseconds. This allows you to round up the result if it fits inside the threshold. Don't use in combination with {round: false} because the decimal output will include the padding. + * @param {string} options.locale - override the locale of this DateTime + * @param {string} options.numberingSystem - override the numberingSystem of this DateTime. The Intl system may choose not to honor this + * @example DateTime.now().plus({ days: 1 }).toRelative() //=> "in 1 day" + * @example DateTime.now().setLocale("es").toRelative({ days: 1 }) //=> "dentro de 1 día" + * @example DateTime.now().plus({ days: 1 }).toRelative({ locale: "fr" }) //=> "dans 23 heures" + * @example DateTime.now().minus({ days: 2 }).toRelative() //=> "2 days ago" + * @example DateTime.now().minus({ days: 2 }).toRelative({ unit: "hours" }) //=> "48 hours ago" + * @example DateTime.now().minus({ hours: 36 }).toRelative({ round: false }) //=> "1.5 days ago" + */ + toRelative(options = {}) { + if (!this.isValid) return null; + const base = options.base || DateTime.fromObject({}, { zone: this.zone }), + padding = options.padding ? (this < base ? -options.padding : options.padding) : 0; + let units = ["years", "months", "days", "hours", "minutes", "seconds"]; + let unit = options.unit; + if (Array.isArray(options.unit)) { + units = options.unit; + unit = undefined; + } + return diffRelative(base, this.plus(padding), { + ...options, + numeric: "always", + units, + unit, + }); + } + + /** + * Returns a string representation of this date relative to today, such as "yesterday" or "next month". + * Only internationalizes on platforms that supports Intl.RelativeTimeFormat. + * @param {Object} options - options that affect the output + * @param {DateTime} [options.base=DateTime.now()] - the DateTime to use as the basis to which this time is compared. Defaults to now. + * @param {string} options.locale - override the locale of this DateTime + * @param {string} options.unit - use a specific unit; if omitted, the method will pick the unit. Use one of "years", "quarters", "months", "weeks", or "days" + * @param {string} options.numberingSystem - override the numberingSystem of this DateTime. The Intl system may choose not to honor this + * @example DateTime.now().plus({ days: 1 }).toRelativeCalendar() //=> "tomorrow" + * @example DateTime.now().setLocale("es").plus({ days: 1 }).toRelative() //=> ""mañana" + * @example DateTime.now().plus({ days: 1 }).toRelativeCalendar({ locale: "fr" }) //=> "demain" + * @example DateTime.now().minus({ days: 2 }).toRelativeCalendar() //=> "2 days ago" + */ + toRelativeCalendar(options = {}) { + if (!this.isValid) return null; + + return diffRelative(options.base || DateTime.fromObject({}, { zone: this.zone }), this, { + ...options, + numeric: "auto", + units: ["years", "months", "days"], + calendary: true, + }); + } + + /** + * Return the min of several date times + * @param {...DateTime} dateTimes - the DateTimes from which to choose the minimum + * @return {DateTime} the min DateTime, or undefined if called with no argument + */ + static min(...dateTimes) { + if (!dateTimes.every(DateTime.isDateTime)) { + throw new InvalidArgumentError("min requires all arguments be DateTimes"); + } + return bestBy(dateTimes, (i) => i.valueOf(), Math.min); + } + + /** + * Return the max of several date times + * @param {...DateTime} dateTimes - the DateTimes from which to choose the maximum + * @return {DateTime} the max DateTime, or undefined if called with no argument + */ + static max(...dateTimes) { + if (!dateTimes.every(DateTime.isDateTime)) { + throw new InvalidArgumentError("max requires all arguments be DateTimes"); + } + return bestBy(dateTimes, (i) => i.valueOf(), Math.max); + } + + // MISC + + /** + * Explain how a string would be parsed by fromFormat() + * @param {string} text - the string to parse + * @param {string} fmt - the format the string is expected to be in (see description) + * @param {Object} options - options taken by fromFormat() + * @return {Object} + */ + static fromFormatExplain(text, fmt, options = {}) { + const { locale = null, numberingSystem = null } = options, + localeToUse = Locale.fromOpts({ + locale, + numberingSystem, + defaultToEN: true, + }); + return explainFromTokens(localeToUse, text, fmt); + } + + /** + * @deprecated use fromFormatExplain instead + */ + static fromStringExplain(text, fmt, options = {}) { + return DateTime.fromFormatExplain(text, fmt, options); + } + + // FORMAT PRESETS + + /** + * {@link DateTime#toLocaleString} format like 10/14/1983 + * @type {Object} + */ + static get DATE_SHORT() { + return DATE_SHORT; + } + + /** + * {@link DateTime#toLocaleString} format like 'Oct 14, 1983' + * @type {Object} + */ + static get DATE_MED() { + return DATE_MED; + } + + /** + * {@link DateTime#toLocaleString} format like 'Fri, Oct 14, 1983' + * @type {Object} + */ + static get DATE_MED_WITH_WEEKDAY() { + return DATE_MED_WITH_WEEKDAY; + } + + /** + * {@link DateTime#toLocaleString} format like 'October 14, 1983' + * @type {Object} + */ + static get DATE_FULL() { + return DATE_FULL; + } + + /** + * {@link DateTime#toLocaleString} format like 'Tuesday, October 14, 1983' + * @type {Object} + */ + static get DATE_HUGE() { + return DATE_HUGE; + } + + /** + * {@link DateTime#toLocaleString} format like '09:30 AM'. Only 12-hour if the locale is. + * @type {Object} + */ + static get TIME_SIMPLE() { + return TIME_SIMPLE; + } + + /** + * {@link DateTime#toLocaleString} format like '09:30:23 AM'. Only 12-hour if the locale is. + * @type {Object} + */ + static get TIME_WITH_SECONDS() { + return TIME_WITH_SECONDS; + } + + /** + * {@link DateTime#toLocaleString} format like '09:30:23 AM EDT'. Only 12-hour if the locale is. + * @type {Object} + */ + static get TIME_WITH_SHORT_OFFSET() { + return TIME_WITH_SHORT_OFFSET; + } + + /** + * {@link DateTime#toLocaleString} format like '09:30:23 AM Eastern Daylight Time'. Only 12-hour if the locale is. + * @type {Object} + */ + static get TIME_WITH_LONG_OFFSET() { + return TIME_WITH_LONG_OFFSET; + } + + /** + * {@link DateTime#toLocaleString} format like '09:30', always 24-hour. + * @type {Object} + */ + static get TIME_24_SIMPLE() { + return TIME_24_SIMPLE; + } + + /** + * {@link DateTime#toLocaleString} format like '09:30:23', always 24-hour. + * @type {Object} + */ + static get TIME_24_WITH_SECONDS() { + return TIME_24_WITH_SECONDS; + } + + /** + * {@link DateTime#toLocaleString} format like '09:30:23 EDT', always 24-hour. + * @type {Object} + */ + static get TIME_24_WITH_SHORT_OFFSET() { + return TIME_24_WITH_SHORT_OFFSET; + } + + /** + * {@link DateTime#toLocaleString} format like '09:30:23 Eastern Daylight Time', always 24-hour. + * @type {Object} + */ + static get TIME_24_WITH_LONG_OFFSET() { + return TIME_24_WITH_LONG_OFFSET; + } + + /** + * {@link DateTime#toLocaleString} format like '10/14/1983, 9:30 AM'. Only 12-hour if the locale is. + * @type {Object} + */ + static get DATETIME_SHORT() { + return DATETIME_SHORT; + } + + /** + * {@link DateTime#toLocaleString} format like '10/14/1983, 9:30:33 AM'. Only 12-hour if the locale is. + * @type {Object} + */ + static get DATETIME_SHORT_WITH_SECONDS() { + return DATETIME_SHORT_WITH_SECONDS; + } + + /** + * {@link DateTime#toLocaleString} format like 'Oct 14, 1983, 9:30 AM'. Only 12-hour if the locale is. + * @type {Object} + */ + static get DATETIME_MED() { + return DATETIME_MED; + } + + /** + * {@link DateTime#toLocaleString} format like 'Oct 14, 1983, 9:30:33 AM'. Only 12-hour if the locale is. + * @type {Object} + */ + static get DATETIME_MED_WITH_SECONDS() { + return DATETIME_MED_WITH_SECONDS; + } + + /** + * {@link DateTime#toLocaleString} format like 'Fri, 14 Oct 1983, 9:30 AM'. Only 12-hour if the locale is. + * @type {Object} + */ + static get DATETIME_MED_WITH_WEEKDAY() { + return DATETIME_MED_WITH_WEEKDAY; + } + + /** + * {@link DateTime#toLocaleString} format like 'October 14, 1983, 9:30 AM EDT'. Only 12-hour if the locale is. + * @type {Object} + */ + static get DATETIME_FULL() { + return DATETIME_FULL; + } + + /** + * {@link DateTime#toLocaleString} format like 'October 14, 1983, 9:30:33 AM EDT'. Only 12-hour if the locale is. + * @type {Object} + */ + static get DATETIME_FULL_WITH_SECONDS() { + return DATETIME_FULL_WITH_SECONDS; + } + + /** + * {@link DateTime#toLocaleString} format like 'Friday, October 14, 1983, 9:30 AM Eastern Daylight Time'. Only 12-hour if the locale is. + * @type {Object} + */ + static get DATETIME_HUGE() { + return DATETIME_HUGE; + } + + /** + * {@link DateTime#toLocaleString} format like 'Friday, October 14, 1983, 9:30:33 AM Eastern Daylight Time'. Only 12-hour if the locale is. + * @type {Object} + */ + static get DATETIME_HUGE_WITH_SECONDS() { + return DATETIME_HUGE_WITH_SECONDS; + } +} + +/** + * @private + */ +function friendlyDateTime(dateTimeish) { + if (DateTime.isDateTime(dateTimeish)) { + return dateTimeish; + } else if (dateTimeish && dateTimeish.valueOf && isNumber(dateTimeish.valueOf())) { + return DateTime.fromJSDate(dateTimeish); + } else if (dateTimeish && typeof dateTimeish === "object") { + return DateTime.fromObject(dateTimeish); + } else { + throw new InvalidArgumentError( + `Unknown datetime argument: ${dateTimeish}, of type ${typeof dateTimeish}` + ); + } +} + +const VERSION = "2.3.0"; + +export { DateTime, Duration, FixedOffsetZone, IANAZone, Info, Interval, InvalidZone, Settings, SystemZone, VERSION, Zone }; +//# sourceMappingURL=luxon.js.map diff --git a/assets/js/luxon/luxon.es6.min.js b/assets/js/luxon/luxon.es6.min.js new file mode 100644 index 0000000..2f331dc --- /dev/null +++ b/assets/js/luxon/luxon.es6.min.js @@ -0,0 +1 @@ +class e extends Error{}class r extends e{constructor(e){super("Invalid DateTime: "+e.toMessage())}}class n extends e{constructor(e){super("Invalid Interval: "+e.toMessage())}}class s extends e{constructor(e){super("Invalid Duration: "+e.toMessage())}}class N extends e{}class i extends e{constructor(e){super("Invalid unit "+e)}}class o extends e{}class a extends e{constructor(){super("Zone is an abstract class")}}var t="numeric",u="short",l="long";const c={year:t,month:t,day:t},h={year:t,month:u,day:t},d={year:t,month:u,day:t,weekday:u},m={year:t,month:l,day:t},f={year:t,month:l,day:t,weekday:l},y={hour:t,minute:t},g={hour:t,minute:t,second:t},w={hour:t,minute:t,second:t,timeZoneName:u},v={hour:t,minute:t,second:t,timeZoneName:l},p={hour:t,minute:t,hourCycle:"h23"},T={hour:t,minute:t,second:t,hourCycle:"h23"},S={hour:t,minute:t,second:t,hourCycle:"h23",timeZoneName:u},O={hour:t,minute:t,second:t,hourCycle:"h23",timeZoneName:l},b={year:t,month:t,day:t,hour:t,minute:t},k={year:t,month:t,day:t,hour:t,minute:t,second:t},M={year:t,month:u,day:t,hour:t,minute:t},D={year:t,month:u,day:t,hour:t,minute:t,second:t},E={year:t,month:u,day:t,weekday:u,hour:t,minute:t},V={year:t,month:l,day:t,hour:t,minute:t,timeZoneName:u},I={year:t,month:l,day:t,hour:t,minute:t,second:t,timeZoneName:u},x={year:t,month:l,day:t,weekday:l,hour:t,minute:t,timeZoneName:l},C={year:t,month:l,day:t,weekday:l,hour:t,minute:t,second:t,timeZoneName:l};function F(e){return void 0===e}function L(e){return"number"==typeof e}function Z(e){return"number"==typeof e&&e%1==0}function z(){try{return"undefined"!=typeof Intl&&!!Intl.RelativeTimeFormat}catch(e){return!1}}function q(e,r,n){if(0!==e.length)return e.reduce((e,t)=>{t=[r(t),t];return e&&n(e[0],t[0])===e[0]?e:t},null)[1]}function A(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function j(e,t,r){return Z(e)&&t<=e&&e<=r}function _(e,t=2){let r;return r=e<0?"-"+(""+-e).padStart(t,"0"):(""+e).padStart(t,"0"),r}function U(e){if(!F(e)&&null!==e&&""!==e)return parseInt(e,10)}function $(e){if(!F(e)&&null!==e&&""!==e)return parseFloat(e)}function H(e){if(!F(e)&&null!==e&&""!==e){e=1e3*parseFloat("0."+e);return Math.floor(e)}}function W(e,t,r=!1){const n=10**t,s=r?Math.trunc:Math.round;return s(e*n)/n}function R(e){return e%4==0&&(e%100!=0||e%400==0)}function J(e){return R(e)?366:365}function P(e,t){var r,n=(r=t-1)-(n=12)*Math.floor(r/n)+1;return 2==n?R(e+(t-n)/12)?29:28:[31,null,31,30,31,30,31,31,30,31,30,31][n-1]}function Y(e){let t=Date.UTC(e.year,e.month-1,e.day,e.hour,e.minute,e.second,e.millisecond);return e.year<100&&0<=e.year&&(t=new Date(t),t.setUTCFullYear(t.getUTCFullYear()-1900)),+t}function G(e){var t=(e+Math.floor(e/4)-Math.floor(e/100)+Math.floor(e/400))%7,e=e-1,e=(e+Math.floor(e/4)-Math.floor(e/100)+Math.floor(e/400))%7;return 4==t||3==e?53:52}function B(e){return 99"timezonename"===e.type.toLowerCase());return t?t.value:null}function K(e,t){let r=parseInt(e,10);Number.isNaN(r)&&(r=0);t=parseInt(t,10)||0,t=r<0||Object.is(r,-0)?-t:t;return 60*r+t}function X(e){var t=Number(e);if("boolean"==typeof e||""===e||Number.isNaN(t))throw new o("Invalid unit value "+e);return t}function ee(e,t){const r={};for(const s in e){var n;!A(e,s)||null!=(n=e[s])&&(r[t(s)]=X(n))}return r}function te(e,t){var r=Math.trunc(Math.abs(e/60)),n=Math.trunc(Math.abs(e%60)),s=0<=e?"+":"-";switch(t){case"short":return s+_(r,2)+":"+_(n,2);case"narrow":return s+r+(0(e[t]=r[t],e),{});var r}var ne=/[A-Za-z_+-]{1,256}(:?\/[A-Za-z0-9_+-]{1,256}(\/[A-Za-z0-9_+-]{1,256})?)?/;const se=["January","February","March","April","May","June","July","August","September","October","November","December"],ie=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],ae=["J","F","M","A","M","J","J","A","S","O","N","D"];function oe(e){switch(e){case"narrow":return[...ae];case"short":return[...ie];case"long":return[...se];case"numeric":return["1","2","3","4","5","6","7","8","9","10","11","12"];case"2-digit":return["01","02","03","04","05","06","07","08","09","10","11","12"];default:return null}}const ue=["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],le=["Mon","Tue","Wed","Thu","Fri","Sat","Sun"],ce=["M","T","W","T","F","S","S"];function he(e){switch(e){case"narrow":return[...ce];case"short":return[...le];case"long":return[...ue];case"numeric":return["1","2","3","4","5","6","7"];default:return null}}const de=["AM","PM"],me=["Before Christ","Anno Domini"],fe=["BC","AD"],ye=["B","A"];function ge(e){switch(e){case"narrow":return[...ye];case"short":return[...fe];case"long":return[...me];default:return null}}function we(e,t){let r="";for(const n of e)n.literal?r+=n.val:r+=t(n.val);return r}const ve={D:c,DD:h,DDD:m,DDDD:f,t:y,tt:g,ttt:w,tttt:v,T:p,TT:T,TTT:S,TTTT:O,f:b,ff:M,fff:V,ffff:x,F:k,FF:D,FFF:I,FFFF:C};class pe{static create(e,t={}){return new pe(e,t)}static parseFormat(t){let r=null,n="",s=!1;const i=[];for(let e=0;ethis.loc.extract(r,e,t),i=e=>r.isOffsetFixed&&0===r.offset&&e.allowZ?"Z":r.isValid?r.zone.formatOffset(r.ts,e.format):"",a=()=>n?function(e){return de[e.hour<12?0:1]}(r):s({hour:"numeric",hourCycle:"h12"},"dayperiod"),o=(e,t)=>n?function(e,t){return oe(t)[e.month-1]}(r,e):s(t?{month:e}:{month:e,day:"numeric"},"month"),u=(e,t)=>n?function(e,t){return he(t)[e.weekday-1]}(r,e):s(t?{weekday:e}:{weekday:e,month:"long",day:"numeric"},"weekday"),l=e=>{var t=pe.macroTokenToFormatOpts(e);return t?this.formatWithSystemDefault(r,t):e},c=e=>n?function(e,t){return ge(t)[e.year<0?0:1]}(r,e):s({era:e},"era");return we(pe.parseFormat(e),e=>{switch(e){case"S":return this.num(r.millisecond);case"u":case"SSS":return this.num(r.millisecond,3);case"s":return this.num(r.second);case"ss":return this.num(r.second,2);case"uu":return this.num(Math.floor(r.millisecond/10),2);case"uuu":return this.num(Math.floor(r.millisecond/100));case"m":return this.num(r.minute);case"mm":return this.num(r.minute,2);case"h":return this.num(r.hour%12==0?12:r.hour%12);case"hh":return this.num(r.hour%12==0?12:r.hour%12,2);case"H":return this.num(r.hour);case"HH":return this.num(r.hour,2);case"Z":return i({format:"narrow",allowZ:this.opts.allowZ});case"ZZ":return i({format:"short",allowZ:this.opts.allowZ});case"ZZZ":return i({format:"techie",allowZ:this.opts.allowZ});case"ZZZZ":return r.zone.offsetName(r.ts,{format:"short",locale:this.loc.locale});case"ZZZZZ":return r.zone.offsetName(r.ts,{format:"long",locale:this.loc.locale});case"z":return r.zoneName;case"a":return a();case"d":return t?s({day:"numeric"},"day"):this.num(r.day);case"dd":return t?s({day:"2-digit"},"day"):this.num(r.day,2);case"c":return this.num(r.weekday);case"ccc":return u("short",!0);case"cccc":return u("long",!0);case"ccccc":return u("narrow",!0);case"E":return this.num(r.weekday);case"EEE":return u("short",!1);case"EEEE":return u("long",!1);case"EEEEE":return u("narrow",!1);case"L":return t?s({month:"numeric",day:"numeric"},"month"):this.num(r.month);case"LL":return t?s({month:"2-digit",day:"numeric"},"month"):this.num(r.month,2);case"LLL":return o("short",!0);case"LLLL":return o("long",!0);case"LLLLL":return o("narrow",!0);case"M":return t?s({month:"numeric"},"month"):this.num(r.month);case"MM":return t?s({month:"2-digit"},"month"):this.num(r.month,2);case"MMM":return o("short",!1);case"MMMM":return o("long",!1);case"MMMMM":return o("narrow",!1);case"y":return t?s({year:"numeric"},"year"):this.num(r.year);case"yy":return t?s({year:"2-digit"},"year"):this.num(r.year.toString().slice(-2),2);case"yyyy":return t?s({year:"numeric"},"year"):this.num(r.year,4);case"yyyyyy":return t?s({year:"numeric"},"year"):this.num(r.year,6);case"G":return c("short");case"GG":return c("long");case"GGGGG":return c("narrow");case"kk":return this.num(r.weekYear.toString().slice(-2),2);case"kkkk":return this.num(r.weekYear,4);case"W":return this.num(r.weekNumber);case"WW":return this.num(r.weekNumber,2);case"o":return this.num(r.ordinal);case"ooo":return this.num(r.ordinal,3);case"q":return this.num(r.quarter);case"qq":return this.num(r.quarter,2);case"X":return this.num(Math.floor(r.ts/1e3));case"x":return this.num(r.ts);default:return l(e)}})}formatDurationFromString(e,t){const r=e=>{switch(e[0]){case"S":return"millisecond";case"s":return"second";case"m":return"minute";case"h":return"hour";case"d":return"day";case"M":return"month";case"y":return"year";default:return null}},n=pe.parseFormat(t),s=n.reduce((e,{literal:t,val:r})=>t?e:e.concat(r),[]),i=e.shiftTo(...s.map(r).filter(e=>e));return we(n,(a=i,e=>{var t=r(e);return t?this.num(a.get(t),e.length):e}));var a}}class Te{constructor(e,t){this.reason=e,this.explanation=t}toMessage(){return this.explanation?this.reason+": "+this.explanation:this.reason}}class Se{get type(){throw new a}get name(){throw new a}get isUniversal(){throw new a}offsetName(e,t){throw new a}formatOffset(e,t){throw new a}offset(e){throw new a}equals(e){throw new a}get isValid(){throw new a}}let Oe=null;class be extends Se{static get instance(){return null===Oe&&(Oe=new be),Oe}get type(){return"system"}get name(){return(new Intl.DateTimeFormat).resolvedOptions().timeZone}get isUniversal(){return!1}offsetName(e,{format:t,locale:r}){return Q(e,t,r)}formatOffset(e,t){return te(this.offset(e),t)}offset(e){return-new Date(e).getTimezoneOffset()}equals(e){return"system"===e.type}get isValid(){return!0}}const ke=RegExp(`^${ne.source}$`);let Me={};const Ne={year:0,month:1,day:2,hour:3,minute:4,second:5};let De={};class Ee extends Se{static create(e){return De[e]||(De[e]=new Ee(e)),De[e]}static resetCache(){De={},Me={}}static isValidSpecifier(e){return!(!e||!e.match(ke))}static isValidZone(e){if(!e)return!1;try{return new Intl.DateTimeFormat("en-US",{timeZone:e}).format(),!0}catch(e){return!1}}constructor(e){super(),this.zoneName=e,this.valid=Ee.isValidZone(e)}get type(){return"iana"}get name(){return this.zoneName}get isUniversal(){return!1}offsetName(e,{format:t,locale:r}){return Q(e,t,r,this.name)}formatOffset(e,t){return te(this.offset(e),t)}offset(e){var t=new Date(e);if(isNaN(t))return NaN;var r=(o=this.name,Me[o]||(Me[o]=new Intl.DateTimeFormat("en-US",{hour12:!1,timeZone:o,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"})),Me[o]),[n,s,i,a,e,o]=(r.formatToParts?function(e,t){const r=e.formatToParts(t),n=[];for(let e=0;eDate.now(),Le="system",Ze=null,ze=null,qe=null,Ae;class je{static get now(){return Fe}static set now(e){Fe=e}static set defaultZone(e){Le=e}static get defaultZone(){return Ce(Le,be.instance)}static get defaultLocale(){return Ze}static set defaultLocale(e){Ze=e}static get defaultNumberingSystem(){return ze}static set defaultNumberingSystem(e){ze=e}static get defaultOutputCalendar(){return qe}static set defaultOutputCalendar(e){qe=e}static get throwOnInvalid(){return Ae}static set throwOnInvalid(e){Ae=e}static resetCaches(){Be.resetCache(),Ee.resetCache()}}let _e={};let Ue={};function $e(e,t={}){var r=JSON.stringify([e,t]);let n=Ue[r];return n||(n=new Intl.DateTimeFormat(e,t),Ue[r]=n),n}let He={};let We={};let Re=null;function Je(e,t,r,n,s){r=e.listingMode(r);return"error"===r?null:("en"===r?n:s)(t)}class Pe{constructor(e,t,r){this.padTo=r.padTo||0,this.floor=r.floor||!1;const{padTo:n,floor:s,...i}=r;if(!t||0{const t=n?{month:r,day:"numeric"}:{month:r},e=n?"format":"standalone";return this.monthsCache[e][r]||(this.monthsCache[e][r]=function(t){const r=[];for(let e=1;e<=12;e++){var n=Jr.utc(2016,e,1);r.push(t(n))}return r}(e=>this.extract(e,t,"month"))),this.monthsCache[e][r]})}weekdays(r,n=!1,e=!0){return Je(this,r,e,he,()=>{const t=n?{weekday:r,year:"numeric",month:"long",day:"numeric"}:{weekday:r},e=n?"format":"standalone";return this.weekdaysCache[e][r]||(this.weekdaysCache[e][r]=function(t){const r=[];for(let e=1;e<=7;e++){var n=Jr.utc(2016,11,13+e);r.push(t(n))}return r}(e=>this.extract(e,t,"weekday"))),this.weekdaysCache[e][r]})}meridiems(e=!0){return Je(this,void 0,e,()=>de,()=>{if(!this.meridiemCache){const t={hour:"numeric",hourCycle:"h12"};this.meridiemCache=[Jr.utc(2016,11,13,9),Jr.utc(2016,11,13,19)].map(e=>this.extract(e,t,"dayperiod"))}return this.meridiemCache})}eras(e,t=!0){return Je(this,e,t,ge,()=>{const t={era:e};return this.eraCache[e]||(this.eraCache[e]=[Jr.utc(-40,1,1),Jr.utc(2017,1,1)].map(e=>this.extract(e,t,"era"))),this.eraCache[e]})}extract(e,t,r){const n=this.dtFormatter(e,t),s=n.formatToParts(),i=s.find(e=>e.type.toLowerCase()===r);return i?i.value:null}numberFormatter(e={}){return new Pe(this.intl,e.forceSimple||this.fastNumbers,e)}dtFormatter(e,t={}){return new Ye(e,this.intl,t)}relFormatter(e={}){return new Ge(this.intl,this.isEnglish(),e)}listFormatter(e={}){return function(e,t={}){var r=JSON.stringify([e,t]);let n=_e[r];return n||(n=new Intl.ListFormat(e,t),_e[r]=n),n}(this.intl,e)}isEnglish(){return"en"===this.locale||"en-us"===this.locale.toLowerCase()||new Intl.DateTimeFormat(this.intl).resolvedOptions().locale.startsWith("en-us")}equals(e){return this.locale===e.locale&&this.numberingSystem===e.numberingSystem&&this.outputCalendar===e.outputCalendar}}function Qe(...e){e=e.reduce((e,t)=>e+t.source,"");return RegExp(`^${e}$`)}function Ke(...e){return i=>e.reduce(([e,t,r],n)=>{var[s,n,r]=n(i,r);return[{...e,...s},t||n,r]},[{},null,1]).slice(0,2)}function Xe(e,...t){if(null==e)return[null,null];for(var[r,n]of t){r=r.exec(e);if(r)return n(r)}return[null,null]}function et(...s){return(e,t)=>{const r={};let n;for(n=0;nvoid 0!==e&&(t||e&&c)?-e:e;return[{years:t($(r)),months:t($(n)),weeks:t($(s)),days:t($(i)),hours:t($(a)),minutes:t($(o)),seconds:t($(u),"-0"===u),milliseconds:t(H(l),e)}]}const dt={GMT:0,EDT:-240,EST:-300,CDT:-300,CST:-360,MDT:-360,MST:-420,PDT:-420,PST:-480};function mt(e,t,r,n,s,i,a){const o={year:2===t.length?B(U(t)):U(t),month:ie.indexOf(r)+1,day:U(n),hour:U(s),minute:U(i)};return a&&(o.second=U(a)),e&&(o.weekday=3{var t=this.values[e];return F(t)?null:this.loc.numberFormatter({style:"unit",unitDisplay:"long",...r,unit:e.slice(0,-1)}).format(t)}).filter(e=>e);return this.loc.listFormatter({type:"conjunction",style:r.listStyle||"narrow",...r}).format(e)}toObject(){return this.isValid?{...this.values}:{}}toISO(){if(!this.isValid)return null;let e="P";return 0!==this.years&&(e+=this.years+"Y"),0===this.months&&0===this.quarters||(e+=this.months+3*this.quarters+"M"),0!==this.weeks&&(e+=this.weeks+"W"),0!==this.days&&(e+=this.days+"D"),0===this.hours&&0===this.minutes&&0===this.seconds&&0===this.milliseconds||(e+="T"),0!==this.hours&&(e+=this.hours+"H"),0!==this.minutes&&(e+=this.minutes+"M"),0===this.seconds&&0===this.milliseconds||(e+=W(this.seconds+this.milliseconds/1e3,3)+"S"),"P"===e&&(e+="T0S"),e}toISOTime(e={}){if(!this.isValid)return null;var t=this.toMillis();if(t<0||864e5<=t)return null;e={suppressMilliseconds:!1,suppressSeconds:!1,includePrefix:!1,format:"extended",...e};const r=this.shiftTo("hours","minutes","seconds","milliseconds");let n="basic"===e.format?"hhmm":"hh:mm";e.suppressSeconds&&0===r.seconds&&0===r.milliseconds||(n+="basic"===e.format?"ss":":ss",e.suppressMilliseconds&&0===r.milliseconds||(n+=".SSS"));let s=r.toFormat(n);return e.includePrefix&&(s="T"+s),s}toJSON(){return this.toISO()}toString(){return this.toISO()}toMillis(){return this.as("milliseconds")}valueOf(){return this.toMillis()}plus(e){if(!this.isValid)return this;const t=Ht.fromDurationLike(e),r={};for(const n of jt)(A(t.values,n)||A(this.values,n))&&(r[n]=t.get(n)+this.get(n));return Ut(this,{values:r},!0)}minus(e){if(!this.isValid)return this;const t=Ht.fromDurationLike(e);return this.plus(t.negate())}mapUnits(e){if(!this.isValid)return this;const t={};for(const r of Object.keys(this.values))t[r]=X(e(this.values[r],r));return Ut(this,{values:t},!0)}get(e){return this[Ht.normalizeUnit(e)]}set(e){return this.isValid?Ut(this,{values:{...this.values,...ee(e,Ht.normalizeUnit)}}):this}reconfigure({locale:e,numberingSystem:t,conversionAccuracy:r}={}){const n=this.loc.clone({locale:e,numberingSystem:t}),s={loc:n};return r&&(s.conversionAccuracy=r),Ut(this,s)}as(e){return this.isValid?this.shiftTo(e).get(e):NaN}normalize(){if(!this.isValid)return this;var r,n,e=this.toObject();return r=this.matrix,n=e,_t.reduce((e,t)=>F(n[t])?e:(e&&$t(r,n,e,n,t),t),null),Ut(this,{values:e},!0)}shiftTo(...e){if(!this.isValid)return this;if(0===e.length)return this;e=e.map(e=>Ht.normalizeUnit(e));const t={},r={},n=this.toObject();let s;for(const a of jt)if(0<=e.indexOf(a)){s=a;let e=0;for(const o in r)e+=this.matrix[o][a]*r[o],r[o]=0;L(n[a])&&(e+=n[a]);var i=Math.trunc(e);t[a]=i,r[a]=(1e3*e-1e3*i)/1e3;for(const u in n)jt.indexOf(u)>jt.indexOf(a)&&$t(this.matrix,n,u,t,a)}else L(n[a])&&(r[a]=n[a]);for(const l in r)0!==r[l]&&(t[s]+=l===s?r[l]:r[l]/this.matrix[s][l]);return Ut(this,{values:t},!0).normalize()}negate(){if(!this.isValid)return this;const e={};for(const t of Object.keys(this.values))e[t]=-this.values[t];return Ut(this,{values:e},!0)}get years(){return this.isValid?this.values.years||0:NaN}get quarters(){return this.isValid?this.values.quarters||0:NaN}get months(){return this.isValid?this.values.months||0:NaN}get weeks(){return this.isValid?this.values.weeks||0:NaN}get days(){return this.isValid?this.values.days||0:NaN}get hours(){return this.isValid?this.values.hours||0:NaN}get minutes(){return this.isValid?this.values.minutes||0:NaN}get seconds(){return this.isValid?this.values.seconds||0:NaN}get milliseconds(){return this.isValid?this.values.milliseconds||0:NaN}get isValid(){return null===this.invalid}get invalidReason(){return this.invalid?this.invalid.reason:null}get invalidExplanation(){return this.invalid?this.invalid.explanation:null}equals(e){if(!this.isValid||!e.isValid)return!1;if(!this.loc.equals(e.loc))return!1;for(const n of jt)if(t=this.values[n],r=e.values[n],!(void 0===t||0===t?void 0===r||0===r:t===r))return!1;var t,r;return!0}}const Wt="Invalid Interval";class Rt{constructor(e){this.s=e.start,this.e=e.end,this.invalid=e.invalid||null,this.isLuxonInterval=!0}static invalid(e,t=null){if(!e)throw new o("need to specify a reason the Interval is invalid");t=e instanceof Te?e:new Te(e,t);if(je.throwOnInvalid)throw new n(t);return new Rt({invalid:t})}static fromDateTimes(e,t){var r=Pr(e),n=Pr(t),e=(e=n,(t=r)&&t.isValid?e&&e.isValid?ee}isBefore(e){return!!this.isValid&&this.e<=e}contains(e){return!!this.isValid&&(this.s<=e&&this.e>e)}set({start:e,end:t}={}){return this.isValid?Rt.fromDateTimes(e||this.s,t||this.e):this}splitAt(...e){if(!this.isValid)return[];const t=e.map(Pr).filter(e=>this.contains(e)).sort(),r=[];let n=this["s"],s=0;for(;n+this.e?this.e:i;r.push(Rt.fromDateTimes(n,i)),n=i,s+=1}return r}splitBy(e){const t=Ht.fromDurationLike(e);if(!this.isValid||!t.isValid||0===t.as("milliseconds"))return[];let r=this["s"],n=1,s;const i=[];for(;re*n));s=+a>+this.e?this.e:a,i.push(Rt.fromDateTimes(r,s)),r=s,n+=1}return i}divideEqually(e){return this.isValid?this.splitBy(this.length()/e).slice(0,e):[]}overlaps(e){return this.e>e.s&&this.s=e.e)}equals(e){return!(!this.isValid||!e.isValid)&&(this.s.equals(e.s)&&this.e.equals(e.e))}intersection(e){if(!this.isValid)return this;var t=(this.s>e.s?this:e).s,e=(this.ee.e?this:e).e;return Rt.fromDateTimes(t,e)}static merge(e){const[t,r]=e.sort((e,t)=>e.s-t.s).reduce(([e,t],r)=>t?t.overlaps(r)||t.abutsStart(r)?[e,t.union(r)]:[e.concat([t]),r]:[e,r],[[],null]);return r&&t.push(r),t}static xor(e){let t=null,r=0;const n=[],s=e.map(e=>[{time:e.s,type:"s"},{time:e.e,type:"e"}]),i=Array.prototype.concat(...s),a=i.sort((e,t)=>e.time-t.time);for(const o of a)r+="s"===o.type?1:-1,t=1===r?o.time:(t&&+t!=+o.time&&n.push(Rt.fromDateTimes(t,o.time)),null);return Rt.merge(n)}difference(...e){return Rt.xor([this].concat(e)).map(e=>this.intersection(e)).filter(e=>e&&!e.isEmpty())}toString(){return this.isValid?`[${this.s.toISO()} – ${this.e.toISO()})`:Wt}toISO(e){return this.isValid?this.s.toISO(e)+"/"+this.e.toISO(e):Wt}toISODate(){return this.isValid?this.s.toISODate()+"/"+this.e.toISODate():Wt}toISOTime(e){return this.isValid?this.s.toISOTime(e)+"/"+this.e.toISOTime(e):Wt}toFormat(e,{separator:t=" – "}={}){return this.isValid?""+this.s.toFormat(e)+t+this.e.toFormat(e):Wt}toDuration(e,t){return this.isValid?this.e.diff(this.s,e,t):Ht.invalid(this.invalidReason)}mapEndpoints(e){return Rt.fromDateTimes(e(this.s),e(this.e))}}class Jt{static hasDST(e=je.defaultZone){const t=Jr.now().setZone(e).set({month:12});return!e.isUniversal&&t.offset!==t.set({month:6}).offset}static isValidIANAZone(e){return Ee.isValidSpecifier(e)&&Ee.isValidZone(e)}static normalizeZone(e){return Ce(e,je.defaultZone)}static months(e="long",{locale:t=null,numberingSystem:r=null,locObj:n=null,outputCalendar:s="gregory"}={}){return(n||Be.create(t,r,s)).months(e)}static monthsFormat(e="long",{locale:t=null,numberingSystem:r=null,locObj:n=null,outputCalendar:s="gregory"}={}){return(n||Be.create(t,r,s)).months(e,!0)}static weekdays(e="long",{locale:t=null,numberingSystem:r=null,locObj:n=null}={}){return(n||Be.create(t,r,null)).weekdays(e)}static weekdaysFormat(e="long",{locale:t=null,numberingSystem:r=null,locObj:n=null}={}){return(n||Be.create(t,r,null)).weekdays(e,!0)}static meridiems({locale:e=null}={}){return Be.create(e).meridiems()}static eras(e="short",{locale:t=null}={}){return Be.create(t,null,"gregory").eras(e)}static features(){return{relative:z()}}}function Pt(e,t){var r=e=>e.toUTC(0,{keepLocalTime:!0}).startOf("day").valueOf(),e=r(t)-r(e);return Math.floor(Ht.fromMillis(e).as("days"))}function Yt(e,t,r,n){let[s,i,a,o]=function(t,r,e){var n,s;const i={};let a,o;for([n,s]of[["years",(e,t)=>t.year-e.year],["quarters",(e,t)=>t.quarter-e.quarter],["months",(e,t)=>t.month-e.month+12*(t.year-e.year)],["weeks",(e,t)=>{t=Pt(e,t);return(t-t%7)/7}],["days",Pt]])if(0<=e.indexOf(n)){a=n;let e=s(t,r);o=t.plus({[n]:e}),o>r?(t=t.plus({[n]:e-1}),--e):t=o,i[n]=e}return[t,i,o,a]}(e,t,r);e=t-s,r=r.filter(e=>0<=["hours","minutes","seconds","milliseconds"].indexOf(e));0===r.length&&(ae){return{regex:e,deser:([e])=>t(function(t){let r=parseInt(t,10);if(isNaN(r)){r="";for(let e=0;ee.findIndex(e=>sr(t)===sr(e))+r}}function ar(e,t){return{regex:e,deser:([,e,t])=>K(e,t),groups:t}}function or(e){return{regex:e,deser:([e])=>e}}const ur={year:{"2-digit":"yy",numeric:"yyyyy"},month:{numeric:"M","2-digit":"MM",short:"MMM",long:"MMMM"},day:{numeric:"d","2-digit":"dd"},weekday:{short:"EEE",long:"EEEE"},dayperiod:"a",dayPeriod:"a",hour:{numeric:"h","2-digit":"hh"},minute:{numeric:"m","2-digit":"mm"},second:{numeric:"s","2-digit":"ss"}};let lr=null;function cr(e,t){if(e.literal)return e;const r=pe.macroTokenToFormatOpts(e.val);if(!r)return e;const n=pe.create(t,r),s=n.formatDateTimeParts((lr=lr||Jr.fromMillis(1555555555555),lr)),i=s.map(e=>function(e,t){var{type:r,value:e}=e;if("literal"===r)return{literal:!0,val:e};t=t[r];let n=ur[r];return"object"==typeof n&&(n=n[t]),n?{literal:!1,val:n}:void 0}(e,r));return i.includes(void 0)?e:i}function hr(t,e,r){const n=(c=pe.parseFormat(r),a=t,Array.prototype.concat(...c.map(e=>cr(e,a)))),s=n.map(e=>function(t,r){const n=Kt(r),s=Kt(r,"{2}"),i=Kt(r,"{3}"),a=Kt(r,"{4}"),o=Kt(r,"{6}"),u=Kt(r,"{1,2}"),l=Kt(r,"{1,3}"),c=Kt(r,"{1,6}"),h=Kt(r,"{1,9}"),d=Kt(r,"{2,4}"),m=Kt(r,"{4,6}"),f=e=>({regex:RegExp(e.val.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")),deser:([e])=>e,literal:!0}),e=(e=>{if(t.literal)return f(e);switch(e.val){case"G":return ir(r.eras("short",!1),0);case"GG":return ir(r.eras("long",!1),0);case"y":return er(c);case"yy":return er(d,B);case"yyyy":return er(a);case"yyyyy":return er(m);case"yyyyyy":return er(o);case"M":return er(u);case"MM":return er(s);case"MMM":return ir(r.months("short",!0,!1),1);case"MMMM":return ir(r.months("long",!0,!1),1);case"L":return er(u);case"LL":return er(s);case"LLL":return ir(r.months("short",!1,!1),1);case"LLLL":return ir(r.months("long",!1,!1),1);case"d":return er(u);case"dd":return er(s);case"o":return er(l);case"ooo":return er(i);case"HH":return er(s);case"H":return er(u);case"hh":return er(s);case"h":return er(u);case"mm":return er(s);case"m":case"q":return er(u);case"qq":return er(s);case"s":return er(u);case"ss":return er(s);case"S":return er(l);case"SSS":return er(i);case"u":return or(h);case"uu":return or(u);case"uuu":return er(n);case"a":return ir(r.meridiems(),0);case"kkkk":return er(a);case"kk":return er(d,B);case"W":return er(u);case"WW":return er(s);case"E":case"c":return er(n);case"EEE":return ir(r.weekdays("short",!1,!1),1);case"EEEE":return ir(r.weekdays("long",!1,!1),1);case"ccc":return ir(r.weekdays("short",!0,!1),1);case"cccc":return ir(r.weekdays("long",!0,!1),1);case"Z":case"ZZ":return ar(new RegExp(`([+-]${u.source})(?::(${s.source}))?`),2);case"ZZZ":return ar(new RegExp(`([+-]${u.source})(${s.source})?`),2);case"z":return or(/[a-z_+-/]{1,256}?/i);default:return f(e)}})(t)||{invalidReason:Xt};return e.token=t,e}(e,t)),i=s.find(e=>e.invalidReason);var a;if(i)return{input:e,tokens:n,invalidReason:i.invalidReason};var[o,u]=[`^${(h=s).map(e=>e.regex).reduce((e,t)=>`${e}(${t.source})`,"")}$`,h],l=RegExp(o,"i"),[r,c]=function(e,t,r){const n=e.match(t);if(n){const s={};let e=1;for(const i in r)if(A(r,i)){const a=r[i],o=a.groups?a.groups+1:1;!a.literal&&a.token&&(s[a.token.val[0]]=a.deser(n.slice(e,e+o))),e+=o}return[n,s]}return[n,{}]}(e,l,u),[h,o,u]=c?function(n){let e=null,t;return F(n.z)||(e=Ee.create(n.z)),F(n.Z)||(e=e||new Ie(n.Z),t=n.Z),F(n.q)||(n.M=3*(n.q-1)+1),F(n.h)||(n.h<12&&1===n.a?n.h+=12:12===n.h&&0===n.a&&(n.h=0)),0===n.G&&n.y&&(n.y=-n.y),F(n.u)||(n.S=H(n.u)),[Object.keys(n).reduce((e,t)=>{var r=(e=>{switch(e){case"S":return"millisecond";case"s":return"second";case"m":return"minute";case"h":case"H":return"hour";case"d":return"day";case"o":return"ordinal";case"L":case"M":return"month";case"y":return"year";case"E":case"c":return"weekday";case"W":return"weekNumber";case"k":return"weekYear";case"q":return"quarter";default:return null}})(t);return r&&(e[r]=n[t]),e},{}),e,t]}(c):[null,null,void 0];if(A(c,"a")&&A(c,"H"))throw new N("Can't include meridiem when specifying 24-hour format");return{input:e,tokens:n,regex:l,rawMatches:r,matches:c,result:h,zone:o,specificOffset:u}}const dr=[0,31,59,90,120,151,181,212,243,273,304,334],mr=[0,31,60,91,121,152,182,213,244,274,305,335];function fr(e,t){return new Te("unit out of range",`you specified ${t} (of type ${typeof t}) as a ${e}, which is invalid`)}function yr(e,t,r){r=new Date(Date.UTC(e,t-1,r)).getUTCDay();return 0===r?7:r}function gr(e,t,r){return r+(R(e)?mr:dr)[t-1]}function wr(e,t){const r=R(e)?mr:dr,n=r.findIndex(e=>eG(t)?(a=t+1,i=1):a=t,{weekYear:a,weekNumber:i,weekday:n,...re(e)}}function pr(e){var{weekYear:t,weekNumber:r,weekday:n}=e,s=yr(t,1,4),i=J(t);let a=7*r+n-s-3,o;a<1?(o=t-1,a+=J(o)):a>i?(o=t+1,a-=J(t)):o=t;var{month:i,day:t}=wr(o,a);return{year:o,month:i,day:t,...re(e)}}function Tr(e){var{year:t,month:r,day:n}=e;return{year:t,ordinal:gr(t,r,n),...re(e)}}function Sr(e){var{year:t,ordinal:r}=e,{month:n,day:r}=wr(t,r);return{year:t,month:n,day:r,...re(e)}}function Or(e){var t=Z(e.year),r=j(e.month,1,12),n=j(e.day,1,P(e.year,e.month));return t?r?!n&&fr("day",e.day):fr("month",e.month):fr("year",e.year)}function br(e){var{hour:t,minute:r,second:n,millisecond:s}=e,i=j(t,0,23)||24===t&&0===r&&0===n&&0===s,a=j(r,0,59),o=j(n,0,59),e=j(s,0,999);return i?a?o?!e&&fr("millisecond",s):fr("second",n):fr("minute",r):fr("hour",t)}const kr="Invalid DateTime";function Mr(e){return new Te("unsupported zone",`the zone "${e.name}" is not supported`)}function Nr(e){return null===e.weekData&&(e.weekData=vr(e.c)),e.weekData}function Dr(e,t){e={ts:e.ts,zone:e.zone,c:e.c,o:e.o,loc:e.loc,invalid:e.invalid};return new Jr({...e,...t,old:e})}function Er(e,t,r){let n=e-60*t*1e3;var s=r.offset(n);if(t===s)return[n,t];n-=60*(s-t)*1e3;r=r.offset(n);return s===r?[n,s]:[e-60*Math.min(s,r)*1e3,Math.max(s,r)]}function Vr(e,t){e+=60*t*1e3;const r=new Date(e);return{year:r.getUTCFullYear(),month:r.getUTCMonth()+1,day:r.getUTCDate(),hour:r.getUTCHours(),minute:r.getUTCMinutes(),second:r.getUTCSeconds(),millisecond:r.getUTCMilliseconds()}}function Ir(e,t,r){return Er(Y(e),t,r)}function xr(e,t){var r=e.o,n=e.c.year+Math.trunc(t.years),s=e.c.month+Math.trunc(t.months)+3*Math.trunc(t.quarters),s={...e.c,year:n,month:s,day:Math.min(e.c.day,P(n,s))+Math.trunc(t.days)+7*Math.trunc(t.weeks)},t=Ht.fromObject({years:t.years-Math.trunc(t.years),quarters:t.quarters-Math.trunc(t.quarters),months:t.months-Math.trunc(t.months),weeks:t.weeks-Math.trunc(t.weeks),days:t.days-Math.trunc(t.days),hours:t.hours,minutes:t.minutes,seconds:t.seconds,milliseconds:t.milliseconds}).as("milliseconds");let[i,a]=Er(Y(s),r,e.zone);return 0!==t&&(i+=t,a=e.zone.offset(i)),{ts:i,o:a}}function Cr(e,t,r,n,s,i){var{setZone:a,zone:o}=r;if(e&&0!==Object.keys(e).length){const u=t||o,l=Jr.fromObject(e,{...r,zone:u,specificOffset:i});return a?l:l.setZone(o)}return Jr.invalid(new Te("unparsable",`the input "${s}" can't be parsed as `+n))}function Fr(e,t,r=!0){return e.isValid?pe.create(Be.create("en-US"),{allowZ:r,forceSimple:!0}).formatDateTimeFromString(e,t):null}function Lr(e,t){var r=9999{e=W(e,i||s.calendary?0:2,!0);const r=n.loc.clone(s).relFormatter(s);return r.format(e,t)},r=e=>s.calendary?n.hasSame(t,e)?0:n.startOf(e).diff(t.startOf(e),e).get(e):n.diff(t,e).get(e);if(s.unit)return e(r(s.unit),s.unit);for(const o of s.units){var a=r(o);if(1<=Math.abs(a))return e(a,o)}return e(nthis.set({month:1}).offset||this.offset>this.set({month:5}).offset)}get isInLeapYear(){return R(this.year)}get daysInMonth(){return P(this.year,this.month)}get daysInYear(){return this.isValid?J(this.year):NaN}get weeksInWeekYear(){return this.isValid?G(this.weekYear):NaN}resolvedLocaleOptions(e={}){var{locale:t,numberingSystem:r,calendar:e}=pe.create(this.loc.clone(e),e).resolvedOptions(this);return{locale:t,numberingSystem:r,outputCalendar:e}}toUTC(e=0,t={}){return this.setZone(Ie.instance(e),t)}toLocal(){return this.setZone(je.defaultZone)}setZone(t,{keepLocalTime:r=!1,keepCalendarTime:n=!1}={}){if((t=Ce(t,je.defaultZone)).equals(this.zone))return this;if(t.isValid){let e=this.ts;return(r||n)&&(r=t.offset(this.ts),n=this.toObject(),[e]=Ir(n,r,t)),Dr(this,{ts:e,zone:t})}return Jr.invalid(Mr(t))}reconfigure({locale:e,numberingSystem:t,outputCalendar:r}={}){r=this.loc.clone({locale:e,numberingSystem:t,outputCalendar:r});return Dr(this,{loc:r})}setLocale(e){return this.reconfigure({locale:e})}set(e){if(!this.isValid)return this;var t=ee(e,$r),r=!F(t.weekYear)||!F(t.weekNumber)||!F(t.weekday),n=!F(t.ordinal),s=!F(t.year),i=!F(t.month)||!F(t.day),e=t.weekYear||t.weekNumber;if((s||i||n)&&e)throw new N("Can't mix weekYear/weekNumber units with year/month/day or ordinals");if(i&&n)throw new N("Can't mix ordinal dates with month/day");let a;r?a=pr({...vr(this.c),...t}):F(t.ordinal)?(a={...this.toObject(),...t},F(t.day)&&(a.day=Math.min(P(a.year,a.month),a.day))):a=Sr({...Tr(this.c),...t});var[r,t]=Ir(a,this.o,this.zone);return Dr(this,{ts:r,o:t})}plus(e){return this.isValid?Dr(this,xr(this,Ht.fromDurationLike(e))):this}minus(e){return this.isValid?Dr(this,xr(this,Ht.fromDurationLike(e).negate())):this}startOf(e){if(!this.isValid)return this;const t={},r=Ht.normalizeUnit(e);switch(r){case"years":t.month=1;case"quarters":case"months":t.day=1;case"weeks":case"days":t.hour=0;case"hours":t.minute=0;case"minutes":t.second=0;case"seconds":t.millisecond=0}return"weeks"===r&&(t.weekday=1),"quarters"===r&&(e=Math.ceil(this.month/3),t.month=3*(e-1)+1),this.set(t)}endOf(e){return this.isValid?this.plus({[e]:1}).startOf(e).minus(1):this}toFormat(e,t={}){return this.isValid?pe.create(this.loc.redefaultToEN(t)).formatDateTimeFromString(this,e):kr}toLocaleString(e=c,t={}){return this.isValid?pe.create(this.loc.clone(t),e).formatDateTime(this):kr}toLocaleParts(e={}){return this.isValid?pe.create(this.loc.clone(e),e).formatDateTimeParts(this):[]}toISO({format:e="extended",suppressSeconds:t=!1,suppressMilliseconds:r=!1,includeOffset:n=!0}={}){if(!this.isValid)return null;var s="extended"===e,e=Lr(this,s);return e+="T",e+=Zr(this,s,t,r,n)}toISODate({format:e="extended"}={}){return this.isValid?Lr(this,"extended"===e):null}toISOWeekDate(){return Fr(this,"kkkk-'W'WW-c")}toISOTime({suppressMilliseconds:e=!1,suppressSeconds:t=!1,includeOffset:r=!0,includePrefix:n=!1,format:s="extended"}={}){return this.isValid?(n?"T":"")+Zr(this,"extended"===s,t,e,r):null}toRFC2822(){return Fr(this,"EEE, dd LLL yyyy HH:mm:ss ZZZ",!1)}toHTTP(){return Fr(this.toUTC(),"EEE, dd LLL yyyy HH:mm:ss 'GMT'")}toSQLDate(){return this.isValid?Lr(this,!0):null}toSQLTime({includeOffset:e=!0,includeZone:t=!1}={}){let r="HH:mm:ss.SSS";return(t||e)&&(r+=" ",t?r+="z":e&&(r+="ZZ")),Fr(this,r,!0)}toSQL(e={}){return this.isValid?this.toSQLDate()+" "+this.toSQLTime(e):null}toString(){return this.isValid?this.toISO():kr}valueOf(){return this.toMillis()}toMillis(){return this.isValid?this.ts:NaN}toSeconds(){return this.isValid?this.ts/1e3:NaN}toJSON(){return this.toISO()}toBSON(){return this.toJSDate()}toObject(e={}){if(!this.isValid)return{};const t={...this.c};return e.includeConfig&&(t.outputCalendar=this.outputCalendar,t.numberingSystem=this.loc.numberingSystem,t.locale=this.loc.locale),t}toJSDate(){return new Date(this.isValid?this.ts:NaN)}diff(e,t="milliseconds",r={}){if(!this.isValid||!e.isValid)return Ht.invalid("created by diffing an invalid DateTime");r={locale:this.locale,numberingSystem:this.numberingSystem,...r};const n=(t=t,(Array.isArray(t)?t:[t]).map(Ht.normalizeUnit)),s=e.valueOf()>this.valueOf(),i=s?this:e,a=s?e:this,o=Yt(i,a,n,r);return s?o.negate():o}diffNow(e="milliseconds",t={}){return this.diff(Jr.now(),e,t)}until(e){return this.isValid?Rt.fromDateTimes(this,e):this}hasSame(e,t){if(!this.isValid)return!1;var r=e.valueOf();const n=this.setZone(e.zone,{keepLocalTime:!0});return n.startOf(t)<=r&&r<=n.endOf(t)}equals(e){return this.isValid&&e.isValid&&this.valueOf()===e.valueOf()&&this.zone.equals(e.zone)&&this.loc.equals(e.loc)}toRelative(e={}){if(!this.isValid)return null;var t=e.base||Jr.fromObject({},{zone:this.zone}),r=e.padding?thise.valueOf(),Math.min)}static max(...e){if(!e.every(Jr.isDateTime))throw new o("max requires all arguments be DateTimes");return q(e,e=>e.valueOf(),Math.max)}static fromFormatExplain(e,t,r={}){var{locale:n=null,numberingSystem:r=null}=r;return hr(Be.fromOpts({locale:n,numberingSystem:r,defaultToEN:!0}),e,t)}static fromStringExplain(e,t,r={}){return Jr.fromFormatExplain(e,t,r)}static get DATE_SHORT(){return c}static get DATE_MED(){return h}static get DATE_MED_WITH_WEEKDAY(){return d}static get DATE_FULL(){return m}static get DATE_HUGE(){return f}static get TIME_SIMPLE(){return y}static get TIME_WITH_SECONDS(){return g}static get TIME_WITH_SHORT_OFFSET(){return w}static get TIME_WITH_LONG_OFFSET(){return v}static get TIME_24_SIMPLE(){return p}static get TIME_24_WITH_SECONDS(){return T}static get TIME_24_WITH_SHORT_OFFSET(){return S}static get TIME_24_WITH_LONG_OFFSET(){return O}static get DATETIME_SHORT(){return b}static get DATETIME_SHORT_WITH_SECONDS(){return k}static get DATETIME_MED(){return M}static get DATETIME_MED_WITH_SECONDS(){return D}static get DATETIME_MED_WITH_WEEKDAY(){return E}static get DATETIME_FULL(){return V}static get DATETIME_FULL_WITH_SECONDS(){return I}static get DATETIME_HUGE(){return x}static get DATETIME_HUGE_WITH_SECONDS(){return C}}function Pr(e){if(Jr.isDateTime(e))return e;if(e&&e.valueOf&&L(e.valueOf()))return Jr.fromJSDate(e);if(e&&"object"==typeof e)return Jr.fromObject(e);throw new o(`Unknown datetime argument: ${e}, of type `+typeof e)}tt="2.3.0";export{Jr as DateTime,Ht as Duration,Ie as FixedOffsetZone,Ee as IANAZone,Jt as Info,Rt as Interval,xe as InvalidZone,je as Settings,be as SystemZone,tt as VERSION,Se as Zone}; \ No newline at end of file diff --git a/assets/js/luxon/luxon.js b/assets/js/luxon/luxon.js new file mode 100644 index 0000000..dd778a5 --- /dev/null +++ b/assets/js/luxon/luxon.js @@ -0,0 +1,8478 @@ +var luxon = (function (exports) { + 'use strict'; + + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; + } + + function _extends() { + _extends = Object.assign || function (target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + + return target; + }; + + return _extends.apply(this, arguments); + } + + function _inheritsLoose(subClass, superClass) { + subClass.prototype = Object.create(superClass.prototype); + subClass.prototype.constructor = subClass; + + _setPrototypeOf(subClass, superClass); + } + + function _getPrototypeOf(o) { + _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { + return o.__proto__ || Object.getPrototypeOf(o); + }; + return _getPrototypeOf(o); + } + + function _setPrototypeOf(o, p) { + _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + + return _setPrototypeOf(o, p); + } + + function _isNativeReflectConstruct() { + if (typeof Reflect === "undefined" || !Reflect.construct) return false; + if (Reflect.construct.sham) return false; + if (typeof Proxy === "function") return true; + + try { + Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); + return true; + } catch (e) { + return false; + } + } + + function _construct(Parent, args, Class) { + if (_isNativeReflectConstruct()) { + _construct = Reflect.construct; + } else { + _construct = function _construct(Parent, args, Class) { + var a = [null]; + a.push.apply(a, args); + var Constructor = Function.bind.apply(Parent, a); + var instance = new Constructor(); + if (Class) _setPrototypeOf(instance, Class.prototype); + return instance; + }; + } + + return _construct.apply(null, arguments); + } + + function _isNativeFunction(fn) { + return Function.toString.call(fn).indexOf("[native code]") !== -1; + } + + function _wrapNativeSuper(Class) { + var _cache = typeof Map === "function" ? new Map() : undefined; + + _wrapNativeSuper = function _wrapNativeSuper(Class) { + if (Class === null || !_isNativeFunction(Class)) return Class; + + if (typeof Class !== "function") { + throw new TypeError("Super expression must either be null or a function"); + } + + if (typeof _cache !== "undefined") { + if (_cache.has(Class)) return _cache.get(Class); + + _cache.set(Class, Wrapper); + } + + function Wrapper() { + return _construct(Class, arguments, _getPrototypeOf(this).constructor); + } + + Wrapper.prototype = Object.create(Class.prototype, { + constructor: { + value: Wrapper, + enumerable: false, + writable: true, + configurable: true + } + }); + return _setPrototypeOf(Wrapper, Class); + }; + + return _wrapNativeSuper(Class); + } + + function _objectWithoutPropertiesLoose(source, excluded) { + if (source == null) return {}; + var target = {}; + var sourceKeys = Object.keys(source); + var key, i; + + for (i = 0; i < sourceKeys.length; i++) { + key = sourceKeys[i]; + if (excluded.indexOf(key) >= 0) continue; + target[key] = source[key]; + } + + return target; + } + + function _unsupportedIterableToArray(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); + } + + function _arrayLikeToArray(arr, len) { + if (len == null || len > arr.length) len = arr.length; + + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + + return arr2; + } + + function _createForOfIteratorHelperLoose(o, allowArrayLike) { + var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; + if (it) return (it = it.call(o)).next.bind(it); + + if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { + if (it) o = it; + var i = 0; + return function () { + if (i >= o.length) return { + done: true + }; + return { + done: false, + value: o[i++] + }; + }; + } + + throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + // these aren't really private, but nor are they really useful to document + + /** + * @private + */ + var LuxonError = /*#__PURE__*/function (_Error) { + _inheritsLoose(LuxonError, _Error); + + function LuxonError() { + return _Error.apply(this, arguments) || this; + } + + return LuxonError; + }( /*#__PURE__*/_wrapNativeSuper(Error)); + /** + * @private + */ + + + var InvalidDateTimeError = /*#__PURE__*/function (_LuxonError) { + _inheritsLoose(InvalidDateTimeError, _LuxonError); + + function InvalidDateTimeError(reason) { + return _LuxonError.call(this, "Invalid DateTime: " + reason.toMessage()) || this; + } + + return InvalidDateTimeError; + }(LuxonError); + /** + * @private + */ + + var InvalidIntervalError = /*#__PURE__*/function (_LuxonError2) { + _inheritsLoose(InvalidIntervalError, _LuxonError2); + + function InvalidIntervalError(reason) { + return _LuxonError2.call(this, "Invalid Interval: " + reason.toMessage()) || this; + } + + return InvalidIntervalError; + }(LuxonError); + /** + * @private + */ + + var InvalidDurationError = /*#__PURE__*/function (_LuxonError3) { + _inheritsLoose(InvalidDurationError, _LuxonError3); + + function InvalidDurationError(reason) { + return _LuxonError3.call(this, "Invalid Duration: " + reason.toMessage()) || this; + } + + return InvalidDurationError; + }(LuxonError); + /** + * @private + */ + + var ConflictingSpecificationError = /*#__PURE__*/function (_LuxonError4) { + _inheritsLoose(ConflictingSpecificationError, _LuxonError4); + + function ConflictingSpecificationError() { + return _LuxonError4.apply(this, arguments) || this; + } + + return ConflictingSpecificationError; + }(LuxonError); + /** + * @private + */ + + var InvalidUnitError = /*#__PURE__*/function (_LuxonError5) { + _inheritsLoose(InvalidUnitError, _LuxonError5); + + function InvalidUnitError(unit) { + return _LuxonError5.call(this, "Invalid unit " + unit) || this; + } + + return InvalidUnitError; + }(LuxonError); + /** + * @private + */ + + var InvalidArgumentError = /*#__PURE__*/function (_LuxonError6) { + _inheritsLoose(InvalidArgumentError, _LuxonError6); + + function InvalidArgumentError() { + return _LuxonError6.apply(this, arguments) || this; + } + + return InvalidArgumentError; + }(LuxonError); + /** + * @private + */ + + var ZoneIsAbstractError = /*#__PURE__*/function (_LuxonError7) { + _inheritsLoose(ZoneIsAbstractError, _LuxonError7); + + function ZoneIsAbstractError() { + return _LuxonError7.call(this, "Zone is an abstract class") || this; + } + + return ZoneIsAbstractError; + }(LuxonError); + + /** + * @private + */ + var n = "numeric", + s = "short", + l = "long"; + var DATE_SHORT = { + year: n, + month: n, + day: n + }; + var DATE_MED = { + year: n, + month: s, + day: n + }; + var DATE_MED_WITH_WEEKDAY = { + year: n, + month: s, + day: n, + weekday: s + }; + var DATE_FULL = { + year: n, + month: l, + day: n + }; + var DATE_HUGE = { + year: n, + month: l, + day: n, + weekday: l + }; + var TIME_SIMPLE = { + hour: n, + minute: n + }; + var TIME_WITH_SECONDS = { + hour: n, + minute: n, + second: n + }; + var TIME_WITH_SHORT_OFFSET = { + hour: n, + minute: n, + second: n, + timeZoneName: s + }; + var TIME_WITH_LONG_OFFSET = { + hour: n, + minute: n, + second: n, + timeZoneName: l + }; + var TIME_24_SIMPLE = { + hour: n, + minute: n, + hourCycle: "h23" + }; + var TIME_24_WITH_SECONDS = { + hour: n, + minute: n, + second: n, + hourCycle: "h23" + }; + var TIME_24_WITH_SHORT_OFFSET = { + hour: n, + minute: n, + second: n, + hourCycle: "h23", + timeZoneName: s + }; + var TIME_24_WITH_LONG_OFFSET = { + hour: n, + minute: n, + second: n, + hourCycle: "h23", + timeZoneName: l + }; + var DATETIME_SHORT = { + year: n, + month: n, + day: n, + hour: n, + minute: n + }; + var DATETIME_SHORT_WITH_SECONDS = { + year: n, + month: n, + day: n, + hour: n, + minute: n, + second: n + }; + var DATETIME_MED = { + year: n, + month: s, + day: n, + hour: n, + minute: n + }; + var DATETIME_MED_WITH_SECONDS = { + year: n, + month: s, + day: n, + hour: n, + minute: n, + second: n + }; + var DATETIME_MED_WITH_WEEKDAY = { + year: n, + month: s, + day: n, + weekday: s, + hour: n, + minute: n + }; + var DATETIME_FULL = { + year: n, + month: l, + day: n, + hour: n, + minute: n, + timeZoneName: s + }; + var DATETIME_FULL_WITH_SECONDS = { + year: n, + month: l, + day: n, + hour: n, + minute: n, + second: n, + timeZoneName: s + }; + var DATETIME_HUGE = { + year: n, + month: l, + day: n, + weekday: l, + hour: n, + minute: n, + timeZoneName: l + }; + var DATETIME_HUGE_WITH_SECONDS = { + year: n, + month: l, + day: n, + weekday: l, + hour: n, + minute: n, + second: n, + timeZoneName: l + }; + + /** + * @private + */ + // TYPES + + function isUndefined(o) { + return typeof o === "undefined"; + } + function isNumber(o) { + return typeof o === "number"; + } + function isInteger(o) { + return typeof o === "number" && o % 1 === 0; + } + function isString(o) { + return typeof o === "string"; + } + function isDate(o) { + return Object.prototype.toString.call(o) === "[object Date]"; + } // CAPABILITIES + + function hasRelative() { + try { + return typeof Intl !== "undefined" && !!Intl.RelativeTimeFormat; + } catch (e) { + return false; + } + } // OBJECTS AND ARRAYS + + function maybeArray(thing) { + return Array.isArray(thing) ? thing : [thing]; + } + function bestBy(arr, by, compare) { + if (arr.length === 0) { + return undefined; + } + + return arr.reduce(function (best, next) { + var pair = [by(next), next]; + + if (!best) { + return pair; + } else if (compare(best[0], pair[0]) === best[0]) { + return best; + } else { + return pair; + } + }, null)[1]; + } + function pick(obj, keys) { + return keys.reduce(function (a, k) { + a[k] = obj[k]; + return a; + }, {}); + } + function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); + } // NUMBERS AND STRINGS + + function integerBetween(thing, bottom, top) { + return isInteger(thing) && thing >= bottom && thing <= top; + } // x % n but takes the sign of n instead of x + + function floorMod(x, n) { + return x - n * Math.floor(x / n); + } + function padStart(input, n) { + if (n === void 0) { + n = 2; + } + + var isNeg = input < 0; + var padded; + + if (isNeg) { + padded = "-" + ("" + -input).padStart(n, "0"); + } else { + padded = ("" + input).padStart(n, "0"); + } + + return padded; + } + function parseInteger(string) { + if (isUndefined(string) || string === null || string === "") { + return undefined; + } else { + return parseInt(string, 10); + } + } + function parseFloating(string) { + if (isUndefined(string) || string === null || string === "") { + return undefined; + } else { + return parseFloat(string); + } + } + function parseMillis(fraction) { + // Return undefined (instead of 0) in these cases, where fraction is not set + if (isUndefined(fraction) || fraction === null || fraction === "") { + return undefined; + } else { + var f = parseFloat("0." + fraction) * 1000; + return Math.floor(f); + } + } + function roundTo(number, digits, towardZero) { + if (towardZero === void 0) { + towardZero = false; + } + + var factor = Math.pow(10, digits), + rounder = towardZero ? Math.trunc : Math.round; + return rounder(number * factor) / factor; + } // DATE BASICS + + function isLeapYear(year) { + return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0); + } + function daysInYear(year) { + return isLeapYear(year) ? 366 : 365; + } + function daysInMonth(year, month) { + var modMonth = floorMod(month - 1, 12) + 1, + modYear = year + (month - modMonth) / 12; + + if (modMonth === 2) { + return isLeapYear(modYear) ? 29 : 28; + } else { + return [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][modMonth - 1]; + } + } // covert a calendar object to a local timestamp (epoch, but with the offset baked in) + + function objToLocalTS(obj) { + var d = Date.UTC(obj.year, obj.month - 1, obj.day, obj.hour, obj.minute, obj.second, obj.millisecond); // for legacy reasons, years between 0 and 99 are interpreted as 19XX; revert that + + if (obj.year < 100 && obj.year >= 0) { + d = new Date(d); + d.setUTCFullYear(d.getUTCFullYear() - 1900); + } + + return +d; + } + function weeksInWeekYear(weekYear) { + var p1 = (weekYear + Math.floor(weekYear / 4) - Math.floor(weekYear / 100) + Math.floor(weekYear / 400)) % 7, + last = weekYear - 1, + p2 = (last + Math.floor(last / 4) - Math.floor(last / 100) + Math.floor(last / 400)) % 7; + return p1 === 4 || p2 === 3 ? 53 : 52; + } + function untruncateYear(year) { + if (year > 99) { + return year; + } else return year > 60 ? 1900 + year : 2000 + year; + } // PARSING + + function parseZoneInfo(ts, offsetFormat, locale, timeZone) { + if (timeZone === void 0) { + timeZone = null; + } + + var date = new Date(ts), + intlOpts = { + hourCycle: "h23", + year: "numeric", + month: "2-digit", + day: "2-digit", + hour: "2-digit", + minute: "2-digit" + }; + + if (timeZone) { + intlOpts.timeZone = timeZone; + } + + var modified = _extends({ + timeZoneName: offsetFormat + }, intlOpts); + + var parsed = new Intl.DateTimeFormat(locale, modified).formatToParts(date).find(function (m) { + return m.type.toLowerCase() === "timezonename"; + }); + return parsed ? parsed.value : null; + } // signedOffset('-5', '30') -> -330 + + function signedOffset(offHourStr, offMinuteStr) { + var offHour = parseInt(offHourStr, 10); // don't || this because we want to preserve -0 + + if (Number.isNaN(offHour)) { + offHour = 0; + } + + var offMin = parseInt(offMinuteStr, 10) || 0, + offMinSigned = offHour < 0 || Object.is(offHour, -0) ? -offMin : offMin; + return offHour * 60 + offMinSigned; + } // COERCION + + function asNumber(value) { + var numericValue = Number(value); + if (typeof value === "boolean" || value === "" || Number.isNaN(numericValue)) throw new InvalidArgumentError("Invalid unit value " + value); + return numericValue; + } + function normalizeObject(obj, normalizer) { + var normalized = {}; + + for (var u in obj) { + if (hasOwnProperty(obj, u)) { + var v = obj[u]; + if (v === undefined || v === null) continue; + normalized[normalizer(u)] = asNumber(v); + } + } + + return normalized; + } + function formatOffset(offset, format) { + var hours = Math.trunc(Math.abs(offset / 60)), + minutes = Math.trunc(Math.abs(offset % 60)), + sign = offset >= 0 ? "+" : "-"; + + switch (format) { + case "short": + return "" + sign + padStart(hours, 2) + ":" + padStart(minutes, 2); + + case "narrow": + return "" + sign + hours + (minutes > 0 ? ":" + minutes : ""); + + case "techie": + return "" + sign + padStart(hours, 2) + padStart(minutes, 2); + + default: + throw new RangeError("Value format " + format + " is out of range for property format"); + } + } + function timeObject(obj) { + return pick(obj, ["hour", "minute", "second", "millisecond"]); + } + var ianaRegex = /[A-Za-z_+-]{1,256}(:?\/[A-Za-z0-9_+-]{1,256}(\/[A-Za-z0-9_+-]{1,256})?)?/; + + /** + * @private + */ + + + var monthsLong = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; + var monthsShort = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; + var monthsNarrow = ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"]; + function months(length) { + switch (length) { + case "narrow": + return [].concat(monthsNarrow); + + case "short": + return [].concat(monthsShort); + + case "long": + return [].concat(monthsLong); + + case "numeric": + return ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"]; + + case "2-digit": + return ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"]; + + default: + return null; + } + } + var weekdaysLong = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]; + var weekdaysShort = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]; + var weekdaysNarrow = ["M", "T", "W", "T", "F", "S", "S"]; + function weekdays(length) { + switch (length) { + case "narrow": + return [].concat(weekdaysNarrow); + + case "short": + return [].concat(weekdaysShort); + + case "long": + return [].concat(weekdaysLong); + + case "numeric": + return ["1", "2", "3", "4", "5", "6", "7"]; + + default: + return null; + } + } + var meridiems = ["AM", "PM"]; + var erasLong = ["Before Christ", "Anno Domini"]; + var erasShort = ["BC", "AD"]; + var erasNarrow = ["B", "A"]; + function eras(length) { + switch (length) { + case "narrow": + return [].concat(erasNarrow); + + case "short": + return [].concat(erasShort); + + case "long": + return [].concat(erasLong); + + default: + return null; + } + } + function meridiemForDateTime(dt) { + return meridiems[dt.hour < 12 ? 0 : 1]; + } + function weekdayForDateTime(dt, length) { + return weekdays(length)[dt.weekday - 1]; + } + function monthForDateTime(dt, length) { + return months(length)[dt.month - 1]; + } + function eraForDateTime(dt, length) { + return eras(length)[dt.year < 0 ? 0 : 1]; + } + function formatRelativeTime(unit, count, numeric, narrow) { + if (numeric === void 0) { + numeric = "always"; + } + + if (narrow === void 0) { + narrow = false; + } + + var units = { + years: ["year", "yr."], + quarters: ["quarter", "qtr."], + months: ["month", "mo."], + weeks: ["week", "wk."], + days: ["day", "day", "days"], + hours: ["hour", "hr."], + minutes: ["minute", "min."], + seconds: ["second", "sec."] + }; + var lastable = ["hours", "minutes", "seconds"].indexOf(unit) === -1; + + if (numeric === "auto" && lastable) { + var isDay = unit === "days"; + + switch (count) { + case 1: + return isDay ? "tomorrow" : "next " + units[unit][0]; + + case -1: + return isDay ? "yesterday" : "last " + units[unit][0]; + + case 0: + return isDay ? "today" : "this " + units[unit][0]; + + } + } + + var isInPast = Object.is(count, -0) || count < 0, + fmtValue = Math.abs(count), + singular = fmtValue === 1, + lilUnits = units[unit], + fmtUnit = narrow ? singular ? lilUnits[1] : lilUnits[2] || lilUnits[1] : singular ? units[unit][0] : unit; + return isInPast ? fmtValue + " " + fmtUnit + " ago" : "in " + fmtValue + " " + fmtUnit; + } + + function stringifyTokens(splits, tokenToString) { + var s = ""; + + for (var _iterator = _createForOfIteratorHelperLoose(splits), _step; !(_step = _iterator()).done;) { + var token = _step.value; + + if (token.literal) { + s += token.val; + } else { + s += tokenToString(token.val); + } + } + + return s; + } + + var _macroTokenToFormatOpts = { + D: DATE_SHORT, + DD: DATE_MED, + DDD: DATE_FULL, + DDDD: DATE_HUGE, + t: TIME_SIMPLE, + tt: TIME_WITH_SECONDS, + ttt: TIME_WITH_SHORT_OFFSET, + tttt: TIME_WITH_LONG_OFFSET, + T: TIME_24_SIMPLE, + TT: TIME_24_WITH_SECONDS, + TTT: TIME_24_WITH_SHORT_OFFSET, + TTTT: TIME_24_WITH_LONG_OFFSET, + f: DATETIME_SHORT, + ff: DATETIME_MED, + fff: DATETIME_FULL, + ffff: DATETIME_HUGE, + F: DATETIME_SHORT_WITH_SECONDS, + FF: DATETIME_MED_WITH_SECONDS, + FFF: DATETIME_FULL_WITH_SECONDS, + FFFF: DATETIME_HUGE_WITH_SECONDS + }; + /** + * @private + */ + + var Formatter = /*#__PURE__*/function () { + Formatter.create = function create(locale, opts) { + if (opts === void 0) { + opts = {}; + } + + return new Formatter(locale, opts); + }; + + Formatter.parseFormat = function parseFormat(fmt) { + var current = null, + currentFull = "", + bracketed = false; + var splits = []; + + for (var i = 0; i < fmt.length; i++) { + var c = fmt.charAt(i); + + if (c === "'") { + if (currentFull.length > 0) { + splits.push({ + literal: bracketed, + val: currentFull + }); + } + + current = null; + currentFull = ""; + bracketed = !bracketed; + } else if (bracketed) { + currentFull += c; + } else if (c === current) { + currentFull += c; + } else { + if (currentFull.length > 0) { + splits.push({ + literal: false, + val: currentFull + }); + } + + currentFull = c; + current = c; + } + } + + if (currentFull.length > 0) { + splits.push({ + literal: bracketed, + val: currentFull + }); + } + + return splits; + }; + + Formatter.macroTokenToFormatOpts = function macroTokenToFormatOpts(token) { + return _macroTokenToFormatOpts[token]; + }; + + function Formatter(locale, formatOpts) { + this.opts = formatOpts; + this.loc = locale; + this.systemLoc = null; + } + + var _proto = Formatter.prototype; + + _proto.formatWithSystemDefault = function formatWithSystemDefault(dt, opts) { + if (this.systemLoc === null) { + this.systemLoc = this.loc.redefaultToSystem(); + } + + var df = this.systemLoc.dtFormatter(dt, _extends({}, this.opts, opts)); + return df.format(); + }; + + _proto.formatDateTime = function formatDateTime(dt, opts) { + if (opts === void 0) { + opts = {}; + } + + var df = this.loc.dtFormatter(dt, _extends({}, this.opts, opts)); + return df.format(); + }; + + _proto.formatDateTimeParts = function formatDateTimeParts(dt, opts) { + if (opts === void 0) { + opts = {}; + } + + var df = this.loc.dtFormatter(dt, _extends({}, this.opts, opts)); + return df.formatToParts(); + }; + + _proto.resolvedOptions = function resolvedOptions(dt, opts) { + if (opts === void 0) { + opts = {}; + } + + var df = this.loc.dtFormatter(dt, _extends({}, this.opts, opts)); + return df.resolvedOptions(); + }; + + _proto.num = function num(n, p) { + if (p === void 0) { + p = 0; + } + + // we get some perf out of doing this here, annoyingly + if (this.opts.forceSimple) { + return padStart(n, p); + } + + var opts = _extends({}, this.opts); + + if (p > 0) { + opts.padTo = p; + } + + return this.loc.numberFormatter(opts).format(n); + }; + + _proto.formatDateTimeFromString = function formatDateTimeFromString(dt, fmt) { + var _this = this; + + var knownEnglish = this.loc.listingMode() === "en", + useDateTimeFormatter = this.loc.outputCalendar && this.loc.outputCalendar !== "gregory", + string = function string(opts, extract) { + return _this.loc.extract(dt, opts, extract); + }, + formatOffset = function formatOffset(opts) { + if (dt.isOffsetFixed && dt.offset === 0 && opts.allowZ) { + return "Z"; + } + + return dt.isValid ? dt.zone.formatOffset(dt.ts, opts.format) : ""; + }, + meridiem = function meridiem() { + return knownEnglish ? meridiemForDateTime(dt) : string({ + hour: "numeric", + hourCycle: "h12" + }, "dayperiod"); + }, + month = function month(length, standalone) { + return knownEnglish ? monthForDateTime(dt, length) : string(standalone ? { + month: length + } : { + month: length, + day: "numeric" + }, "month"); + }, + weekday = function weekday(length, standalone) { + return knownEnglish ? weekdayForDateTime(dt, length) : string(standalone ? { + weekday: length + } : { + weekday: length, + month: "long", + day: "numeric" + }, "weekday"); + }, + maybeMacro = function maybeMacro(token) { + var formatOpts = Formatter.macroTokenToFormatOpts(token); + + if (formatOpts) { + return _this.formatWithSystemDefault(dt, formatOpts); + } else { + return token; + } + }, + era = function era(length) { + return knownEnglish ? eraForDateTime(dt, length) : string({ + era: length + }, "era"); + }, + tokenToString = function tokenToString(token) { + // Where possible: http://cldr.unicode.org/translation/date-time-1/date-time#TOC-Standalone-vs.-Format-Styles + switch (token) { + // ms + case "S": + return _this.num(dt.millisecond); + + case "u": // falls through + + case "SSS": + return _this.num(dt.millisecond, 3); + // seconds + + case "s": + return _this.num(dt.second); + + case "ss": + return _this.num(dt.second, 2); + // fractional seconds + + case "uu": + return _this.num(Math.floor(dt.millisecond / 10), 2); + + case "uuu": + return _this.num(Math.floor(dt.millisecond / 100)); + // minutes + + case "m": + return _this.num(dt.minute); + + case "mm": + return _this.num(dt.minute, 2); + // hours + + case "h": + return _this.num(dt.hour % 12 === 0 ? 12 : dt.hour % 12); + + case "hh": + return _this.num(dt.hour % 12 === 0 ? 12 : dt.hour % 12, 2); + + case "H": + return _this.num(dt.hour); + + case "HH": + return _this.num(dt.hour, 2); + // offset + + case "Z": + // like +6 + return formatOffset({ + format: "narrow", + allowZ: _this.opts.allowZ + }); + + case "ZZ": + // like +06:00 + return formatOffset({ + format: "short", + allowZ: _this.opts.allowZ + }); + + case "ZZZ": + // like +0600 + return formatOffset({ + format: "techie", + allowZ: _this.opts.allowZ + }); + + case "ZZZZ": + // like EST + return dt.zone.offsetName(dt.ts, { + format: "short", + locale: _this.loc.locale + }); + + case "ZZZZZ": + // like Eastern Standard Time + return dt.zone.offsetName(dt.ts, { + format: "long", + locale: _this.loc.locale + }); + // zone + + case "z": + // like America/New_York + return dt.zoneName; + // meridiems + + case "a": + return meridiem(); + // dates + + case "d": + return useDateTimeFormatter ? string({ + day: "numeric" + }, "day") : _this.num(dt.day); + + case "dd": + return useDateTimeFormatter ? string({ + day: "2-digit" + }, "day") : _this.num(dt.day, 2); + // weekdays - standalone + + case "c": + // like 1 + return _this.num(dt.weekday); + + case "ccc": + // like 'Tues' + return weekday("short", true); + + case "cccc": + // like 'Tuesday' + return weekday("long", true); + + case "ccccc": + // like 'T' + return weekday("narrow", true); + // weekdays - format + + case "E": + // like 1 + return _this.num(dt.weekday); + + case "EEE": + // like 'Tues' + return weekday("short", false); + + case "EEEE": + // like 'Tuesday' + return weekday("long", false); + + case "EEEEE": + // like 'T' + return weekday("narrow", false); + // months - standalone + + case "L": + // like 1 + return useDateTimeFormatter ? string({ + month: "numeric", + day: "numeric" + }, "month") : _this.num(dt.month); + + case "LL": + // like 01, doesn't seem to work + return useDateTimeFormatter ? string({ + month: "2-digit", + day: "numeric" + }, "month") : _this.num(dt.month, 2); + + case "LLL": + // like Jan + return month("short", true); + + case "LLLL": + // like January + return month("long", true); + + case "LLLLL": + // like J + return month("narrow", true); + // months - format + + case "M": + // like 1 + return useDateTimeFormatter ? string({ + month: "numeric" + }, "month") : _this.num(dt.month); + + case "MM": + // like 01 + return useDateTimeFormatter ? string({ + month: "2-digit" + }, "month") : _this.num(dt.month, 2); + + case "MMM": + // like Jan + return month("short", false); + + case "MMMM": + // like January + return month("long", false); + + case "MMMMM": + // like J + return month("narrow", false); + // years + + case "y": + // like 2014 + return useDateTimeFormatter ? string({ + year: "numeric" + }, "year") : _this.num(dt.year); + + case "yy": + // like 14 + return useDateTimeFormatter ? string({ + year: "2-digit" + }, "year") : _this.num(dt.year.toString().slice(-2), 2); + + case "yyyy": + // like 0012 + return useDateTimeFormatter ? string({ + year: "numeric" + }, "year") : _this.num(dt.year, 4); + + case "yyyyyy": + // like 000012 + return useDateTimeFormatter ? string({ + year: "numeric" + }, "year") : _this.num(dt.year, 6); + // eras + + case "G": + // like AD + return era("short"); + + case "GG": + // like Anno Domini + return era("long"); + + case "GGGGG": + return era("narrow"); + + case "kk": + return _this.num(dt.weekYear.toString().slice(-2), 2); + + case "kkkk": + return _this.num(dt.weekYear, 4); + + case "W": + return _this.num(dt.weekNumber); + + case "WW": + return _this.num(dt.weekNumber, 2); + + case "o": + return _this.num(dt.ordinal); + + case "ooo": + return _this.num(dt.ordinal, 3); + + case "q": + // like 1 + return _this.num(dt.quarter); + + case "qq": + // like 01 + return _this.num(dt.quarter, 2); + + case "X": + return _this.num(Math.floor(dt.ts / 1000)); + + case "x": + return _this.num(dt.ts); + + default: + return maybeMacro(token); + } + }; + + return stringifyTokens(Formatter.parseFormat(fmt), tokenToString); + }; + + _proto.formatDurationFromString = function formatDurationFromString(dur, fmt) { + var _this2 = this; + + var tokenToField = function tokenToField(token) { + switch (token[0]) { + case "S": + return "millisecond"; + + case "s": + return "second"; + + case "m": + return "minute"; + + case "h": + return "hour"; + + case "d": + return "day"; + + case "M": + return "month"; + + case "y": + return "year"; + + default: + return null; + } + }, + tokenToString = function tokenToString(lildur) { + return function (token) { + var mapped = tokenToField(token); + + if (mapped) { + return _this2.num(lildur.get(mapped), token.length); + } else { + return token; + } + }; + }, + tokens = Formatter.parseFormat(fmt), + realTokens = tokens.reduce(function (found, _ref) { + var literal = _ref.literal, + val = _ref.val; + return literal ? found : found.concat(val); + }, []), + collapsed = dur.shiftTo.apply(dur, realTokens.map(tokenToField).filter(function (t) { + return t; + })); + + return stringifyTokens(tokens, tokenToString(collapsed)); + }; + + return Formatter; + }(); + + var Invalid = /*#__PURE__*/function () { + function Invalid(reason, explanation) { + this.reason = reason; + this.explanation = explanation; + } + + var _proto = Invalid.prototype; + + _proto.toMessage = function toMessage() { + if (this.explanation) { + return this.reason + ": " + this.explanation; + } else { + return this.reason; + } + }; + + return Invalid; + }(); + + /** + * @interface + */ + + var Zone = /*#__PURE__*/function () { + function Zone() {} + + var _proto = Zone.prototype; + + /** + * Returns the offset's common name (such as EST) at the specified timestamp + * @abstract + * @param {number} ts - Epoch milliseconds for which to get the name + * @param {Object} opts - Options to affect the format + * @param {string} opts.format - What style of offset to return. Accepts 'long' or 'short'. + * @param {string} opts.locale - What locale to return the offset name in. + * @return {string} + */ + _proto.offsetName = function offsetName(ts, opts) { + throw new ZoneIsAbstractError(); + } + /** + * Returns the offset's value as a string + * @abstract + * @param {number} ts - Epoch milliseconds for which to get the offset + * @param {string} format - What style of offset to return. + * Accepts 'narrow', 'short', or 'techie'. Returning '+6', '+06:00', or '+0600' respectively + * @return {string} + */ + ; + + _proto.formatOffset = function formatOffset(ts, format) { + throw new ZoneIsAbstractError(); + } + /** + * Return the offset in minutes for this zone at the specified timestamp. + * @abstract + * @param {number} ts - Epoch milliseconds for which to compute the offset + * @return {number} + */ + ; + + _proto.offset = function offset(ts) { + throw new ZoneIsAbstractError(); + } + /** + * Return whether this Zone is equal to another zone + * @abstract + * @param {Zone} otherZone - the zone to compare + * @return {boolean} + */ + ; + + _proto.equals = function equals(otherZone) { + throw new ZoneIsAbstractError(); + } + /** + * Return whether this Zone is valid. + * @abstract + * @type {boolean} + */ + ; + + _createClass(Zone, [{ + key: "type", + get: + /** + * The type of zone + * @abstract + * @type {string} + */ + function get() { + throw new ZoneIsAbstractError(); + } + /** + * The name of this zone. + * @abstract + * @type {string} + */ + + }, { + key: "name", + get: function get() { + throw new ZoneIsAbstractError(); + } + /** + * Returns whether the offset is known to be fixed for the whole year. + * @abstract + * @type {boolean} + */ + + }, { + key: "isUniversal", + get: function get() { + throw new ZoneIsAbstractError(); + } + }, { + key: "isValid", + get: function get() { + throw new ZoneIsAbstractError(); + } + }]); + + return Zone; + }(); + + var singleton$1 = null; + /** + * Represents the local zone for this JavaScript environment. + * @implements {Zone} + */ + + var SystemZone = /*#__PURE__*/function (_Zone) { + _inheritsLoose(SystemZone, _Zone); + + function SystemZone() { + return _Zone.apply(this, arguments) || this; + } + + var _proto = SystemZone.prototype; + + /** @override **/ + _proto.offsetName = function offsetName(ts, _ref) { + var format = _ref.format, + locale = _ref.locale; + return parseZoneInfo(ts, format, locale); + } + /** @override **/ + ; + + _proto.formatOffset = function formatOffset$1(ts, format) { + return formatOffset(this.offset(ts), format); + } + /** @override **/ + ; + + _proto.offset = function offset(ts) { + return -new Date(ts).getTimezoneOffset(); + } + /** @override **/ + ; + + _proto.equals = function equals(otherZone) { + return otherZone.type === "system"; + } + /** @override **/ + ; + + _createClass(SystemZone, [{ + key: "type", + get: + /** @override **/ + function get() { + return "system"; + } + /** @override **/ + + }, { + key: "name", + get: function get() { + return new Intl.DateTimeFormat().resolvedOptions().timeZone; + } + /** @override **/ + + }, { + key: "isUniversal", + get: function get() { + return false; + } + }, { + key: "isValid", + get: function get() { + return true; + } + }], [{ + key: "instance", + get: + /** + * Get a singleton instance of the local zone + * @return {SystemZone} + */ + function get() { + if (singleton$1 === null) { + singleton$1 = new SystemZone(); + } + + return singleton$1; + } + }]); + + return SystemZone; + }(Zone); + + var matchingRegex = RegExp("^" + ianaRegex.source + "$"); + var dtfCache = {}; + + function makeDTF(zone) { + if (!dtfCache[zone]) { + dtfCache[zone] = new Intl.DateTimeFormat("en-US", { + hour12: false, + timeZone: zone, + year: "numeric", + month: "2-digit", + day: "2-digit", + hour: "2-digit", + minute: "2-digit", + second: "2-digit" + }); + } + + return dtfCache[zone]; + } + + var typeToPos = { + year: 0, + month: 1, + day: 2, + hour: 3, + minute: 4, + second: 5 + }; + + function hackyOffset(dtf, date) { + var formatted = dtf.format(date).replace(/\u200E/g, ""), + parsed = /(\d+)\/(\d+)\/(\d+),? (\d+):(\d+):(\d+)/.exec(formatted), + fMonth = parsed[1], + fDay = parsed[2], + fYear = parsed[3], + fHour = parsed[4], + fMinute = parsed[5], + fSecond = parsed[6]; + return [fYear, fMonth, fDay, fHour, fMinute, fSecond]; + } + + function partsOffset(dtf, date) { + var formatted = dtf.formatToParts(date), + filled = []; + + for (var i = 0; i < formatted.length; i++) { + var _formatted$i = formatted[i], + type = _formatted$i.type, + value = _formatted$i.value, + pos = typeToPos[type]; + + if (!isUndefined(pos)) { + filled[pos] = parseInt(value, 10); + } + } + + return filled; + } + + var ianaZoneCache = {}; + /** + * A zone identified by an IANA identifier, like America/New_York + * @implements {Zone} + */ + + var IANAZone = /*#__PURE__*/function (_Zone) { + _inheritsLoose(IANAZone, _Zone); + + /** + * @param {string} name - Zone name + * @return {IANAZone} + */ + IANAZone.create = function create(name) { + if (!ianaZoneCache[name]) { + ianaZoneCache[name] = new IANAZone(name); + } + + return ianaZoneCache[name]; + } + /** + * Reset local caches. Should only be necessary in testing scenarios. + * @return {void} + */ + ; + + IANAZone.resetCache = function resetCache() { + ianaZoneCache = {}; + dtfCache = {}; + } + /** + * Returns whether the provided string is a valid specifier. This only checks the string's format, not that the specifier identifies a known zone; see isValidZone for that. + * @param {string} s - The string to check validity on + * @example IANAZone.isValidSpecifier("America/New_York") //=> true + * @example IANAZone.isValidSpecifier("Fantasia/Castle") //=> true + * @example IANAZone.isValidSpecifier("Sport~~blorp") //=> false + * @return {boolean} + */ + ; + + IANAZone.isValidSpecifier = function isValidSpecifier(s) { + return !!(s && s.match(matchingRegex)); + } + /** + * Returns whether the provided string identifies a real zone + * @param {string} zone - The string to check + * @example IANAZone.isValidZone("America/New_York") //=> true + * @example IANAZone.isValidZone("Fantasia/Castle") //=> false + * @example IANAZone.isValidZone("Sport~~blorp") //=> false + * @return {boolean} + */ + ; + + IANAZone.isValidZone = function isValidZone(zone) { + if (!zone) { + return false; + } + + try { + new Intl.DateTimeFormat("en-US", { + timeZone: zone + }).format(); + return true; + } catch (e) { + return false; + } + }; + + function IANAZone(name) { + var _this; + + _this = _Zone.call(this) || this; + /** @private **/ + + _this.zoneName = name; + /** @private **/ + + _this.valid = IANAZone.isValidZone(name); + return _this; + } + /** @override **/ + + + var _proto = IANAZone.prototype; + + /** @override **/ + _proto.offsetName = function offsetName(ts, _ref) { + var format = _ref.format, + locale = _ref.locale; + return parseZoneInfo(ts, format, locale, this.name); + } + /** @override **/ + ; + + _proto.formatOffset = function formatOffset$1(ts, format) { + return formatOffset(this.offset(ts), format); + } + /** @override **/ + ; + + _proto.offset = function offset(ts) { + var date = new Date(ts); + if (isNaN(date)) return NaN; + + var dtf = makeDTF(this.name), + _ref2 = dtf.formatToParts ? partsOffset(dtf, date) : hackyOffset(dtf, date), + year = _ref2[0], + month = _ref2[1], + day = _ref2[2], + hour = _ref2[3], + minute = _ref2[4], + second = _ref2[5]; // because we're using hour12 and https://bugs.chromium.org/p/chromium/issues/detail?id=1025564&can=2&q=%2224%3A00%22%20datetimeformat + + + var adjustedHour = hour === 24 ? 0 : hour; + var asUTC = objToLocalTS({ + year: year, + month: month, + day: day, + hour: adjustedHour, + minute: minute, + second: second, + millisecond: 0 + }); + var asTS = +date; + var over = asTS % 1000; + asTS -= over >= 0 ? over : 1000 + over; + return (asUTC - asTS) / (60 * 1000); + } + /** @override **/ + ; + + _proto.equals = function equals(otherZone) { + return otherZone.type === "iana" && otherZone.name === this.name; + } + /** @override **/ + ; + + _createClass(IANAZone, [{ + key: "type", + get: function get() { + return "iana"; + } + /** @override **/ + + }, { + key: "name", + get: function get() { + return this.zoneName; + } + /** @override **/ + + }, { + key: "isUniversal", + get: function get() { + return false; + } + }, { + key: "isValid", + get: function get() { + return this.valid; + } + }]); + + return IANAZone; + }(Zone); + + var singleton = null; + /** + * A zone with a fixed offset (meaning no DST) + * @implements {Zone} + */ + + var FixedOffsetZone = /*#__PURE__*/function (_Zone) { + _inheritsLoose(FixedOffsetZone, _Zone); + + /** + * Get an instance with a specified offset + * @param {number} offset - The offset in minutes + * @return {FixedOffsetZone} + */ + FixedOffsetZone.instance = function instance(offset) { + return offset === 0 ? FixedOffsetZone.utcInstance : new FixedOffsetZone(offset); + } + /** + * Get an instance of FixedOffsetZone from a UTC offset string, like "UTC+6" + * @param {string} s - The offset string to parse + * @example FixedOffsetZone.parseSpecifier("UTC+6") + * @example FixedOffsetZone.parseSpecifier("UTC+06") + * @example FixedOffsetZone.parseSpecifier("UTC-6:00") + * @return {FixedOffsetZone} + */ + ; + + FixedOffsetZone.parseSpecifier = function parseSpecifier(s) { + if (s) { + var r = s.match(/^utc(?:([+-]\d{1,2})(?::(\d{2}))?)?$/i); + + if (r) { + return new FixedOffsetZone(signedOffset(r[1], r[2])); + } + } + + return null; + }; + + function FixedOffsetZone(offset) { + var _this; + + _this = _Zone.call(this) || this; + /** @private **/ + + _this.fixed = offset; + return _this; + } + /** @override **/ + + + var _proto = FixedOffsetZone.prototype; + + /** @override **/ + _proto.offsetName = function offsetName() { + return this.name; + } + /** @override **/ + ; + + _proto.formatOffset = function formatOffset$1(ts, format) { + return formatOffset(this.fixed, format); + } + /** @override **/ + ; + + /** @override **/ + _proto.offset = function offset() { + return this.fixed; + } + /** @override **/ + ; + + _proto.equals = function equals(otherZone) { + return otherZone.type === "fixed" && otherZone.fixed === this.fixed; + } + /** @override **/ + ; + + _createClass(FixedOffsetZone, [{ + key: "type", + get: function get() { + return "fixed"; + } + /** @override **/ + + }, { + key: "name", + get: function get() { + return this.fixed === 0 ? "UTC" : "UTC" + formatOffset(this.fixed, "narrow"); + } + }, { + key: "isUniversal", + get: function get() { + return true; + } + }, { + key: "isValid", + get: function get() { + return true; + } + }], [{ + key: "utcInstance", + get: + /** + * Get a singleton instance of UTC + * @return {FixedOffsetZone} + */ + function get() { + if (singleton === null) { + singleton = new FixedOffsetZone(0); + } + + return singleton; + } + }]); + + return FixedOffsetZone; + }(Zone); + + /** + * A zone that failed to parse. You should never need to instantiate this. + * @implements {Zone} + */ + + var InvalidZone = /*#__PURE__*/function (_Zone) { + _inheritsLoose(InvalidZone, _Zone); + + function InvalidZone(zoneName) { + var _this; + + _this = _Zone.call(this) || this; + /** @private */ + + _this.zoneName = zoneName; + return _this; + } + /** @override **/ + + + var _proto = InvalidZone.prototype; + + /** @override **/ + _proto.offsetName = function offsetName() { + return null; + } + /** @override **/ + ; + + _proto.formatOffset = function formatOffset() { + return ""; + } + /** @override **/ + ; + + _proto.offset = function offset() { + return NaN; + } + /** @override **/ + ; + + _proto.equals = function equals() { + return false; + } + /** @override **/ + ; + + _createClass(InvalidZone, [{ + key: "type", + get: function get() { + return "invalid"; + } + /** @override **/ + + }, { + key: "name", + get: function get() { + return this.zoneName; + } + /** @override **/ + + }, { + key: "isUniversal", + get: function get() { + return false; + } + }, { + key: "isValid", + get: function get() { + return false; + } + }]); + + return InvalidZone; + }(Zone); + + /** + * @private + */ + function normalizeZone(input, defaultZone) { + + if (isUndefined(input) || input === null) { + return defaultZone; + } else if (input instanceof Zone) { + return input; + } else if (isString(input)) { + var lowered = input.toLowerCase(); + if (lowered === "local" || lowered === "system") return defaultZone;else if (lowered === "utc" || lowered === "gmt") return FixedOffsetZone.utcInstance;else if (IANAZone.isValidSpecifier(lowered)) return IANAZone.create(input);else return FixedOffsetZone.parseSpecifier(lowered) || new InvalidZone(input); + } else if (isNumber(input)) { + return FixedOffsetZone.instance(input); + } else if (typeof input === "object" && input.offset && typeof input.offset === "number") { + // This is dumb, but the instanceof check above doesn't seem to really work + // so we're duck checking it + return input; + } else { + return new InvalidZone(input); + } + } + + var now = function now() { + return Date.now(); + }, + defaultZone = "system", + defaultLocale = null, + defaultNumberingSystem = null, + defaultOutputCalendar = null, + throwOnInvalid; + /** + * Settings contains static getters and setters that control Luxon's overall behavior. Luxon is a simple library with few options, but the ones it does have live here. + */ + + + var Settings = /*#__PURE__*/function () { + function Settings() {} + + /** + * Reset Luxon's global caches. Should only be necessary in testing scenarios. + * @return {void} + */ + Settings.resetCaches = function resetCaches() { + Locale.resetCache(); + IANAZone.resetCache(); + }; + + _createClass(Settings, null, [{ + key: "now", + get: + /** + * Get the callback for returning the current timestamp. + * @type {function} + */ + function get() { + return now; + } + /** + * Set the callback for returning the current timestamp. + * The function should return a number, which will be interpreted as an Epoch millisecond count + * @type {function} + * @example Settings.now = () => Date.now() + 3000 // pretend it is 3 seconds in the future + * @example Settings.now = () => 0 // always pretend it's Jan 1, 1970 at midnight in UTC time + */ + , + set: function set(n) { + now = n; + } + /** + * Set the default time zone to create DateTimes in. Does not affect existing instances. + * Use the value "system" to reset this value to the system's time zone. + * @type {string} + */ + + }, { + key: "defaultZone", + get: + /** + * Get the default time zone object currently used to create DateTimes. Does not affect existing instances. + * The default value is the system's time zone (the one set on the machine that runs this code). + * @type {Zone} + */ + function get() { + return normalizeZone(defaultZone, SystemZone.instance); + } + /** + * Get the default locale to create DateTimes with. Does not affect existing instances. + * @type {string} + */ + , + set: function set(zone) { + defaultZone = zone; + } + }, { + key: "defaultLocale", + get: function get() { + return defaultLocale; + } + /** + * Set the default locale to create DateTimes with. Does not affect existing instances. + * @type {string} + */ + , + set: function set(locale) { + defaultLocale = locale; + } + /** + * Get the default numbering system to create DateTimes with. Does not affect existing instances. + * @type {string} + */ + + }, { + key: "defaultNumberingSystem", + get: function get() { + return defaultNumberingSystem; + } + /** + * Set the default numbering system to create DateTimes with. Does not affect existing instances. + * @type {string} + */ + , + set: function set(numberingSystem) { + defaultNumberingSystem = numberingSystem; + } + /** + * Get the default output calendar to create DateTimes with. Does not affect existing instances. + * @type {string} + */ + + }, { + key: "defaultOutputCalendar", + get: function get() { + return defaultOutputCalendar; + } + /** + * Set the default output calendar to create DateTimes with. Does not affect existing instances. + * @type {string} + */ + , + set: function set(outputCalendar) { + defaultOutputCalendar = outputCalendar; + } + /** + * Get whether Luxon will throw when it encounters invalid DateTimes, Durations, or Intervals + * @type {boolean} + */ + + }, { + key: "throwOnInvalid", + get: function get() { + return throwOnInvalid; + } + /** + * Set whether Luxon will throw when it encounters invalid DateTimes, Durations, or Intervals + * @type {boolean} + */ + , + set: function set(t) { + throwOnInvalid = t; + } + }]); + + return Settings; + }(); + + var _excluded = ["base"], + _excluded2 = ["padTo", "floor"]; + + var intlLFCache = {}; + + function getCachedLF(locString, opts) { + if (opts === void 0) { + opts = {}; + } + + var key = JSON.stringify([locString, opts]); + var dtf = intlLFCache[key]; + + if (!dtf) { + dtf = new Intl.ListFormat(locString, opts); + intlLFCache[key] = dtf; + } + + return dtf; + } + + var intlDTCache = {}; + + function getCachedDTF(locString, opts) { + if (opts === void 0) { + opts = {}; + } + + var key = JSON.stringify([locString, opts]); + var dtf = intlDTCache[key]; + + if (!dtf) { + dtf = new Intl.DateTimeFormat(locString, opts); + intlDTCache[key] = dtf; + } + + return dtf; + } + + var intlNumCache = {}; + + function getCachedINF(locString, opts) { + if (opts === void 0) { + opts = {}; + } + + var key = JSON.stringify([locString, opts]); + var inf = intlNumCache[key]; + + if (!inf) { + inf = new Intl.NumberFormat(locString, opts); + intlNumCache[key] = inf; + } + + return inf; + } + + var intlRelCache = {}; + + function getCachedRTF(locString, opts) { + if (opts === void 0) { + opts = {}; + } + + var _opts = opts; + _opts.base; + var cacheKeyOpts = _objectWithoutPropertiesLoose(_opts, _excluded); // exclude `base` from the options + + + var key = JSON.stringify([locString, cacheKeyOpts]); + var inf = intlRelCache[key]; + + if (!inf) { + inf = new Intl.RelativeTimeFormat(locString, opts); + intlRelCache[key] = inf; + } + + return inf; + } + + var sysLocaleCache = null; + + function systemLocale() { + if (sysLocaleCache) { + return sysLocaleCache; + } else { + sysLocaleCache = new Intl.DateTimeFormat().resolvedOptions().locale; + return sysLocaleCache; + } + } + + function parseLocaleString(localeStr) { + // I really want to avoid writing a BCP 47 parser + // see, e.g. https://github.com/wooorm/bcp-47 + // Instead, we'll do this: + // a) if the string has no -u extensions, just leave it alone + // b) if it does, use Intl to resolve everything + // c) if Intl fails, try again without the -u + var uIndex = localeStr.indexOf("-u-"); + + if (uIndex === -1) { + return [localeStr]; + } else { + var options; + var smaller = localeStr.substring(0, uIndex); + + try { + options = getCachedDTF(localeStr).resolvedOptions(); + } catch (e) { + options = getCachedDTF(smaller).resolvedOptions(); + } + + var _options = options, + numberingSystem = _options.numberingSystem, + calendar = _options.calendar; // return the smaller one so that we can append the calendar and numbering overrides to it + + return [smaller, numberingSystem, calendar]; + } + } + + function intlConfigString(localeStr, numberingSystem, outputCalendar) { + if (outputCalendar || numberingSystem) { + localeStr += "-u"; + + if (outputCalendar) { + localeStr += "-ca-" + outputCalendar; + } + + if (numberingSystem) { + localeStr += "-nu-" + numberingSystem; + } + + return localeStr; + } else { + return localeStr; + } + } + + function mapMonths(f) { + var ms = []; + + for (var i = 1; i <= 12; i++) { + var dt = DateTime.utc(2016, i, 1); + ms.push(f(dt)); + } + + return ms; + } + + function mapWeekdays(f) { + var ms = []; + + for (var i = 1; i <= 7; i++) { + var dt = DateTime.utc(2016, 11, 13 + i); + ms.push(f(dt)); + } + + return ms; + } + + function listStuff(loc, length, defaultOK, englishFn, intlFn) { + var mode = loc.listingMode(defaultOK); + + if (mode === "error") { + return null; + } else if (mode === "en") { + return englishFn(length); + } else { + return intlFn(length); + } + } + + function supportsFastNumbers(loc) { + if (loc.numberingSystem && loc.numberingSystem !== "latn") { + return false; + } else { + return loc.numberingSystem === "latn" || !loc.locale || loc.locale.startsWith("en") || new Intl.DateTimeFormat(loc.intl).resolvedOptions().numberingSystem === "latn"; + } + } + /** + * @private + */ + + + var PolyNumberFormatter = /*#__PURE__*/function () { + function PolyNumberFormatter(intl, forceSimple, opts) { + this.padTo = opts.padTo || 0; + this.floor = opts.floor || false; + + opts.padTo; + opts.floor; + var otherOpts = _objectWithoutPropertiesLoose(opts, _excluded2); + + if (!forceSimple || Object.keys(otherOpts).length > 0) { + var intlOpts = _extends({ + useGrouping: false + }, opts); + + if (opts.padTo > 0) intlOpts.minimumIntegerDigits = opts.padTo; + this.inf = getCachedINF(intl, intlOpts); + } + } + + var _proto = PolyNumberFormatter.prototype; + + _proto.format = function format(i) { + if (this.inf) { + var fixed = this.floor ? Math.floor(i) : i; + return this.inf.format(fixed); + } else { + // to match the browser's numberformatter defaults + var _fixed = this.floor ? Math.floor(i) : roundTo(i, 3); + + return padStart(_fixed, this.padTo); + } + }; + + return PolyNumberFormatter; + }(); + /** + * @private + */ + + + var PolyDateFormatter = /*#__PURE__*/function () { + function PolyDateFormatter(dt, intl, opts) { + this.opts = opts; + var z; + + if (dt.zone.isUniversal) { + // UTC-8 or Etc/UTC-8 are not part of tzdata, only Etc/GMT+8 and the like. + // That is why fixed-offset TZ is set to that unless it is: + // 1. Representing offset 0 when UTC is used to maintain previous behavior and does not become GMT. + // 2. Unsupported by the browser: + // - some do not support Etc/ + // - < Etc/GMT-14, > Etc/GMT+12, and 30-minute or 45-minute offsets are not part of tzdata + var gmtOffset = -1 * (dt.offset / 60); + var offsetZ = gmtOffset >= 0 ? "Etc/GMT+" + gmtOffset : "Etc/GMT" + gmtOffset; + + if (dt.offset !== 0 && IANAZone.create(offsetZ).valid) { + z = offsetZ; + this.dt = dt; + } else { + // Not all fixed-offset zones like Etc/+4:30 are present in tzdata. + // So we have to make do. Two cases: + // 1. The format options tell us to show the zone. We can't do that, so the best + // we can do is format the date in UTC. + // 2. The format options don't tell us to show the zone. Then we can adjust them + // the time and tell the formatter to show it to us in UTC, so that the time is right + // and the bad zone doesn't show up. + z = "UTC"; + + if (opts.timeZoneName) { + this.dt = dt; + } else { + this.dt = dt.offset === 0 ? dt : DateTime.fromMillis(dt.ts + dt.offset * 60 * 1000); + } + } + } else if (dt.zone.type === "system") { + this.dt = dt; + } else { + this.dt = dt; + z = dt.zone.name; + } + + var intlOpts = _extends({}, this.opts); + + if (z) { + intlOpts.timeZone = z; + } + + this.dtf = getCachedDTF(intl, intlOpts); + } + + var _proto2 = PolyDateFormatter.prototype; + + _proto2.format = function format() { + return this.dtf.format(this.dt.toJSDate()); + }; + + _proto2.formatToParts = function formatToParts() { + return this.dtf.formatToParts(this.dt.toJSDate()); + }; + + _proto2.resolvedOptions = function resolvedOptions() { + return this.dtf.resolvedOptions(); + }; + + return PolyDateFormatter; + }(); + /** + * @private + */ + + + var PolyRelFormatter = /*#__PURE__*/function () { + function PolyRelFormatter(intl, isEnglish, opts) { + this.opts = _extends({ + style: "long" + }, opts); + + if (!isEnglish && hasRelative()) { + this.rtf = getCachedRTF(intl, opts); + } + } + + var _proto3 = PolyRelFormatter.prototype; + + _proto3.format = function format(count, unit) { + if (this.rtf) { + return this.rtf.format(count, unit); + } else { + return formatRelativeTime(unit, count, this.opts.numeric, this.opts.style !== "long"); + } + }; + + _proto3.formatToParts = function formatToParts(count, unit) { + if (this.rtf) { + return this.rtf.formatToParts(count, unit); + } else { + return []; + } + }; + + return PolyRelFormatter; + }(); + /** + * @private + */ + + + var Locale = /*#__PURE__*/function () { + Locale.fromOpts = function fromOpts(opts) { + return Locale.create(opts.locale, opts.numberingSystem, opts.outputCalendar, opts.defaultToEN); + }; + + Locale.create = function create(locale, numberingSystem, outputCalendar, defaultToEN) { + if (defaultToEN === void 0) { + defaultToEN = false; + } + + var specifiedLocale = locale || Settings.defaultLocale; // the system locale is useful for human readable strings but annoying for parsing/formatting known formats + + var localeR = specifiedLocale || (defaultToEN ? "en-US" : systemLocale()); + var numberingSystemR = numberingSystem || Settings.defaultNumberingSystem; + var outputCalendarR = outputCalendar || Settings.defaultOutputCalendar; + return new Locale(localeR, numberingSystemR, outputCalendarR, specifiedLocale); + }; + + Locale.resetCache = function resetCache() { + sysLocaleCache = null; + intlDTCache = {}; + intlNumCache = {}; + intlRelCache = {}; + }; + + Locale.fromObject = function fromObject(_temp) { + var _ref = _temp === void 0 ? {} : _temp, + locale = _ref.locale, + numberingSystem = _ref.numberingSystem, + outputCalendar = _ref.outputCalendar; + + return Locale.create(locale, numberingSystem, outputCalendar); + }; + + function Locale(locale, numbering, outputCalendar, specifiedLocale) { + var _parseLocaleString = parseLocaleString(locale), + parsedLocale = _parseLocaleString[0], + parsedNumberingSystem = _parseLocaleString[1], + parsedOutputCalendar = _parseLocaleString[2]; + + this.locale = parsedLocale; + this.numberingSystem = numbering || parsedNumberingSystem || null; + this.outputCalendar = outputCalendar || parsedOutputCalendar || null; + this.intl = intlConfigString(this.locale, this.numberingSystem, this.outputCalendar); + this.weekdaysCache = { + format: {}, + standalone: {} + }; + this.monthsCache = { + format: {}, + standalone: {} + }; + this.meridiemCache = null; + this.eraCache = {}; + this.specifiedLocale = specifiedLocale; + this.fastNumbersCached = null; + } + + var _proto4 = Locale.prototype; + + _proto4.listingMode = function listingMode() { + var isActuallyEn = this.isEnglish(); + var hasNoWeirdness = (this.numberingSystem === null || this.numberingSystem === "latn") && (this.outputCalendar === null || this.outputCalendar === "gregory"); + return isActuallyEn && hasNoWeirdness ? "en" : "intl"; + }; + + _proto4.clone = function clone(alts) { + if (!alts || Object.getOwnPropertyNames(alts).length === 0) { + return this; + } else { + return Locale.create(alts.locale || this.specifiedLocale, alts.numberingSystem || this.numberingSystem, alts.outputCalendar || this.outputCalendar, alts.defaultToEN || false); + } + }; + + _proto4.redefaultToEN = function redefaultToEN(alts) { + if (alts === void 0) { + alts = {}; + } + + return this.clone(_extends({}, alts, { + defaultToEN: true + })); + }; + + _proto4.redefaultToSystem = function redefaultToSystem(alts) { + if (alts === void 0) { + alts = {}; + } + + return this.clone(_extends({}, alts, { + defaultToEN: false + })); + }; + + _proto4.months = function months$1(length, format, defaultOK) { + var _this = this; + + if (format === void 0) { + format = false; + } + + if (defaultOK === void 0) { + defaultOK = true; + } + + return listStuff(this, length, defaultOK, months, function () { + var intl = format ? { + month: length, + day: "numeric" + } : { + month: length + }, + formatStr = format ? "format" : "standalone"; + + if (!_this.monthsCache[formatStr][length]) { + _this.monthsCache[formatStr][length] = mapMonths(function (dt) { + return _this.extract(dt, intl, "month"); + }); + } + + return _this.monthsCache[formatStr][length]; + }); + }; + + _proto4.weekdays = function weekdays$1(length, format, defaultOK) { + var _this2 = this; + + if (format === void 0) { + format = false; + } + + if (defaultOK === void 0) { + defaultOK = true; + } + + return listStuff(this, length, defaultOK, weekdays, function () { + var intl = format ? { + weekday: length, + year: "numeric", + month: "long", + day: "numeric" + } : { + weekday: length + }, + formatStr = format ? "format" : "standalone"; + + if (!_this2.weekdaysCache[formatStr][length]) { + _this2.weekdaysCache[formatStr][length] = mapWeekdays(function (dt) { + return _this2.extract(dt, intl, "weekday"); + }); + } + + return _this2.weekdaysCache[formatStr][length]; + }); + }; + + _proto4.meridiems = function meridiems$1(defaultOK) { + var _this3 = this; + + if (defaultOK === void 0) { + defaultOK = true; + } + + return listStuff(this, undefined, defaultOK, function () { + return meridiems; + }, function () { + // In theory there could be aribitrary day periods. We're gonna assume there are exactly two + // for AM and PM. This is probably wrong, but it's makes parsing way easier. + if (!_this3.meridiemCache) { + var intl = { + hour: "numeric", + hourCycle: "h12" + }; + _this3.meridiemCache = [DateTime.utc(2016, 11, 13, 9), DateTime.utc(2016, 11, 13, 19)].map(function (dt) { + return _this3.extract(dt, intl, "dayperiod"); + }); + } + + return _this3.meridiemCache; + }); + }; + + _proto4.eras = function eras$1(length, defaultOK) { + var _this4 = this; + + if (defaultOK === void 0) { + defaultOK = true; + } + + return listStuff(this, length, defaultOK, eras, function () { + var intl = { + era: length + }; // This is problematic. Different calendars are going to define eras totally differently. What I need is the minimum set of dates + // to definitely enumerate them. + + if (!_this4.eraCache[length]) { + _this4.eraCache[length] = [DateTime.utc(-40, 1, 1), DateTime.utc(2017, 1, 1)].map(function (dt) { + return _this4.extract(dt, intl, "era"); + }); + } + + return _this4.eraCache[length]; + }); + }; + + _proto4.extract = function extract(dt, intlOpts, field) { + var df = this.dtFormatter(dt, intlOpts), + results = df.formatToParts(), + matching = results.find(function (m) { + return m.type.toLowerCase() === field; + }); + return matching ? matching.value : null; + }; + + _proto4.numberFormatter = function numberFormatter(opts) { + if (opts === void 0) { + opts = {}; + } + + // this forcesimple option is never used (the only caller short-circuits on it, but it seems safer to leave) + // (in contrast, the rest of the condition is used heavily) + return new PolyNumberFormatter(this.intl, opts.forceSimple || this.fastNumbers, opts); + }; + + _proto4.dtFormatter = function dtFormatter(dt, intlOpts) { + if (intlOpts === void 0) { + intlOpts = {}; + } + + return new PolyDateFormatter(dt, this.intl, intlOpts); + }; + + _proto4.relFormatter = function relFormatter(opts) { + if (opts === void 0) { + opts = {}; + } + + return new PolyRelFormatter(this.intl, this.isEnglish(), opts); + }; + + _proto4.listFormatter = function listFormatter(opts) { + if (opts === void 0) { + opts = {}; + } + + return getCachedLF(this.intl, opts); + }; + + _proto4.isEnglish = function isEnglish() { + return this.locale === "en" || this.locale.toLowerCase() === "en-us" || new Intl.DateTimeFormat(this.intl).resolvedOptions().locale.startsWith("en-us"); + }; + + _proto4.equals = function equals(other) { + return this.locale === other.locale && this.numberingSystem === other.numberingSystem && this.outputCalendar === other.outputCalendar; + }; + + _createClass(Locale, [{ + key: "fastNumbers", + get: function get() { + if (this.fastNumbersCached == null) { + this.fastNumbersCached = supportsFastNumbers(this); + } + + return this.fastNumbersCached; + } + }]); + + return Locale; + }(); + + /* + * This file handles parsing for well-specified formats. Here's how it works: + * Two things go into parsing: a regex to match with and an extractor to take apart the groups in the match. + * An extractor is just a function that takes a regex match array and returns a { year: ..., month: ... } object + * parse() does the work of executing the regex and applying the extractor. It takes multiple regex/extractor pairs to try in sequence. + * Extractors can take a "cursor" representing the offset in the match to look at. This makes it easy to combine extractors. + * combineExtractors() does the work of combining them, keeping track of the cursor through multiple extractions. + * Some extractions are super dumb and simpleParse and fromStrings help DRY them. + */ + + function combineRegexes() { + for (var _len = arguments.length, regexes = new Array(_len), _key = 0; _key < _len; _key++) { + regexes[_key] = arguments[_key]; + } + + var full = regexes.reduce(function (f, r) { + return f + r.source; + }, ""); + return RegExp("^" + full + "$"); + } + + function combineExtractors() { + for (var _len2 = arguments.length, extractors = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + extractors[_key2] = arguments[_key2]; + } + + return function (m) { + return extractors.reduce(function (_ref, ex) { + var mergedVals = _ref[0], + mergedZone = _ref[1], + cursor = _ref[2]; + + var _ex = ex(m, cursor), + val = _ex[0], + zone = _ex[1], + next = _ex[2]; + + return [_extends({}, mergedVals, val), mergedZone || zone, next]; + }, [{}, null, 1]).slice(0, 2); + }; + } + + function parse(s) { + if (s == null) { + return [null, null]; + } + + for (var _len3 = arguments.length, patterns = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { + patterns[_key3 - 1] = arguments[_key3]; + } + + for (var _i = 0, _patterns = patterns; _i < _patterns.length; _i++) { + var _patterns$_i = _patterns[_i], + regex = _patterns$_i[0], + extractor = _patterns$_i[1]; + var m = regex.exec(s); + + if (m) { + return extractor(m); + } + } + + return [null, null]; + } + + function simpleParse() { + for (var _len4 = arguments.length, keys = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { + keys[_key4] = arguments[_key4]; + } + + return function (match, cursor) { + var ret = {}; + var i; + + for (i = 0; i < keys.length; i++) { + ret[keys[i]] = parseInteger(match[cursor + i]); + } + + return [ret, null, cursor + i]; + }; + } // ISO and SQL parsing + + + var offsetRegex = /(?:(Z)|([+-]\d\d)(?::?(\d\d))?)/, + isoTimeBaseRegex = /(\d\d)(?::?(\d\d)(?::?(\d\d)(?:[.,](\d{1,30}))?)?)?/, + isoTimeRegex = RegExp("" + isoTimeBaseRegex.source + offsetRegex.source + "?"), + isoTimeExtensionRegex = RegExp("(?:T" + isoTimeRegex.source + ")?"), + isoYmdRegex = /([+-]\d{6}|\d{4})(?:-?(\d\d)(?:-?(\d\d))?)?/, + isoWeekRegex = /(\d{4})-?W(\d\d)(?:-?(\d))?/, + isoOrdinalRegex = /(\d{4})-?(\d{3})/, + extractISOWeekData = simpleParse("weekYear", "weekNumber", "weekDay"), + extractISOOrdinalData = simpleParse("year", "ordinal"), + sqlYmdRegex = /(\d{4})-(\d\d)-(\d\d)/, + // dumbed-down version of the ISO one + sqlTimeRegex = RegExp(isoTimeBaseRegex.source + " ?(?:" + offsetRegex.source + "|(" + ianaRegex.source + "))?"), + sqlTimeExtensionRegex = RegExp("(?: " + sqlTimeRegex.source + ")?"); + + function int(match, pos, fallback) { + var m = match[pos]; + return isUndefined(m) ? fallback : parseInteger(m); + } + + function extractISOYmd(match, cursor) { + var item = { + year: int(match, cursor), + month: int(match, cursor + 1, 1), + day: int(match, cursor + 2, 1) + }; + return [item, null, cursor + 3]; + } + + function extractISOTime(match, cursor) { + var item = { + hours: int(match, cursor, 0), + minutes: int(match, cursor + 1, 0), + seconds: int(match, cursor + 2, 0), + milliseconds: parseMillis(match[cursor + 3]) + }; + return [item, null, cursor + 4]; + } + + function extractISOOffset(match, cursor) { + var local = !match[cursor] && !match[cursor + 1], + fullOffset = signedOffset(match[cursor + 1], match[cursor + 2]), + zone = local ? null : FixedOffsetZone.instance(fullOffset); + return [{}, zone, cursor + 3]; + } + + function extractIANAZone(match, cursor) { + var zone = match[cursor] ? IANAZone.create(match[cursor]) : null; + return [{}, zone, cursor + 1]; + } // ISO time parsing + + + var isoTimeOnly = RegExp("^T?" + isoTimeBaseRegex.source + "$"); // ISO duration parsing + + var isoDuration = /^-?P(?:(?:(-?\d{1,9}(?:\.\d{1,9})?)Y)?(?:(-?\d{1,9}(?:\.\d{1,9})?)M)?(?:(-?\d{1,9}(?:\.\d{1,9})?)W)?(?:(-?\d{1,9}(?:\.\d{1,9})?)D)?(?:T(?:(-?\d{1,9}(?:\.\d{1,9})?)H)?(?:(-?\d{1,9}(?:\.\d{1,9})?)M)?(?:(-?\d{1,20})(?:[.,](-?\d{1,9}))?S)?)?)$/; + + function extractISODuration(match) { + var s = match[0], + yearStr = match[1], + monthStr = match[2], + weekStr = match[3], + dayStr = match[4], + hourStr = match[5], + minuteStr = match[6], + secondStr = match[7], + millisecondsStr = match[8]; + var hasNegativePrefix = s[0] === "-"; + var negativeSeconds = secondStr && secondStr[0] === "-"; + + var maybeNegate = function maybeNegate(num, force) { + if (force === void 0) { + force = false; + } + + return num !== undefined && (force || num && hasNegativePrefix) ? -num : num; + }; + + return [{ + years: maybeNegate(parseFloating(yearStr)), + months: maybeNegate(parseFloating(monthStr)), + weeks: maybeNegate(parseFloating(weekStr)), + days: maybeNegate(parseFloating(dayStr)), + hours: maybeNegate(parseFloating(hourStr)), + minutes: maybeNegate(parseFloating(minuteStr)), + seconds: maybeNegate(parseFloating(secondStr), secondStr === "-0"), + milliseconds: maybeNegate(parseMillis(millisecondsStr), negativeSeconds) + }]; + } // These are a little braindead. EDT *should* tell us that we're in, say, America/New_York + // and not just that we're in -240 *right now*. But since I don't think these are used that often + // I'm just going to ignore that + + + var obsOffsets = { + GMT: 0, + EDT: -4 * 60, + EST: -5 * 60, + CDT: -5 * 60, + CST: -6 * 60, + MDT: -6 * 60, + MST: -7 * 60, + PDT: -7 * 60, + PST: -8 * 60 + }; + + function fromStrings(weekdayStr, yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) { + var result = { + year: yearStr.length === 2 ? untruncateYear(parseInteger(yearStr)) : parseInteger(yearStr), + month: monthsShort.indexOf(monthStr) + 1, + day: parseInteger(dayStr), + hour: parseInteger(hourStr), + minute: parseInteger(minuteStr) + }; + if (secondStr) result.second = parseInteger(secondStr); + + if (weekdayStr) { + result.weekday = weekdayStr.length > 3 ? weekdaysLong.indexOf(weekdayStr) + 1 : weekdaysShort.indexOf(weekdayStr) + 1; + } + + return result; + } // RFC 2822/5322 + + + var rfc2822 = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|(?:([+-]\d\d)(\d\d)))$/; + + function extractRFC2822(match) { + var weekdayStr = match[1], + dayStr = match[2], + monthStr = match[3], + yearStr = match[4], + hourStr = match[5], + minuteStr = match[6], + secondStr = match[7], + obsOffset = match[8], + milOffset = match[9], + offHourStr = match[10], + offMinuteStr = match[11], + result = fromStrings(weekdayStr, yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr); + var offset; + + if (obsOffset) { + offset = obsOffsets[obsOffset]; + } else if (milOffset) { + offset = 0; + } else { + offset = signedOffset(offHourStr, offMinuteStr); + } + + return [result, new FixedOffsetZone(offset)]; + } + + function preprocessRFC2822(s) { + // Remove comments and folding whitespace and replace multiple-spaces with a single space + return s.replace(/\([^)]*\)|[\n\t]/g, " ").replace(/(\s\s+)/g, " ").trim(); + } // http date + + + var rfc1123 = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun), (\d\d) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{4}) (\d\d):(\d\d):(\d\d) GMT$/, + rfc850 = /^(Monday|Tuesday|Wedsday|Thursday|Friday|Saturday|Sunday), (\d\d)-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(\d\d) (\d\d):(\d\d):(\d\d) GMT$/, + ascii = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ( \d|\d\d) (\d\d):(\d\d):(\d\d) (\d{4})$/; + + function extractRFC1123Or850(match) { + var weekdayStr = match[1], + dayStr = match[2], + monthStr = match[3], + yearStr = match[4], + hourStr = match[5], + minuteStr = match[6], + secondStr = match[7], + result = fromStrings(weekdayStr, yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr); + return [result, FixedOffsetZone.utcInstance]; + } + + function extractASCII(match) { + var weekdayStr = match[1], + monthStr = match[2], + dayStr = match[3], + hourStr = match[4], + minuteStr = match[5], + secondStr = match[6], + yearStr = match[7], + result = fromStrings(weekdayStr, yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr); + return [result, FixedOffsetZone.utcInstance]; + } + + var isoYmdWithTimeExtensionRegex = combineRegexes(isoYmdRegex, isoTimeExtensionRegex); + var isoWeekWithTimeExtensionRegex = combineRegexes(isoWeekRegex, isoTimeExtensionRegex); + var isoOrdinalWithTimeExtensionRegex = combineRegexes(isoOrdinalRegex, isoTimeExtensionRegex); + var isoTimeCombinedRegex = combineRegexes(isoTimeRegex); + var extractISOYmdTimeAndOffset = combineExtractors(extractISOYmd, extractISOTime, extractISOOffset); + var extractISOWeekTimeAndOffset = combineExtractors(extractISOWeekData, extractISOTime, extractISOOffset); + var extractISOOrdinalDateAndTime = combineExtractors(extractISOOrdinalData, extractISOTime, extractISOOffset); + var extractISOTimeAndOffset = combineExtractors(extractISOTime, extractISOOffset); + /** + * @private + */ + + function parseISODate(s) { + return parse(s, [isoYmdWithTimeExtensionRegex, extractISOYmdTimeAndOffset], [isoWeekWithTimeExtensionRegex, extractISOWeekTimeAndOffset], [isoOrdinalWithTimeExtensionRegex, extractISOOrdinalDateAndTime], [isoTimeCombinedRegex, extractISOTimeAndOffset]); + } + function parseRFC2822Date(s) { + return parse(preprocessRFC2822(s), [rfc2822, extractRFC2822]); + } + function parseHTTPDate(s) { + return parse(s, [rfc1123, extractRFC1123Or850], [rfc850, extractRFC1123Or850], [ascii, extractASCII]); + } + function parseISODuration(s) { + return parse(s, [isoDuration, extractISODuration]); + } + var extractISOTimeOnly = combineExtractors(extractISOTime); + function parseISOTimeOnly(s) { + return parse(s, [isoTimeOnly, extractISOTimeOnly]); + } + var sqlYmdWithTimeExtensionRegex = combineRegexes(sqlYmdRegex, sqlTimeExtensionRegex); + var sqlTimeCombinedRegex = combineRegexes(sqlTimeRegex); + var extractISOYmdTimeOffsetAndIANAZone = combineExtractors(extractISOYmd, extractISOTime, extractISOOffset, extractIANAZone); + var extractISOTimeOffsetAndIANAZone = combineExtractors(extractISOTime, extractISOOffset, extractIANAZone); + function parseSQL(s) { + return parse(s, [sqlYmdWithTimeExtensionRegex, extractISOYmdTimeOffsetAndIANAZone], [sqlTimeCombinedRegex, extractISOTimeOffsetAndIANAZone]); + } + + var INVALID$2 = "Invalid Duration"; // unit conversion constants + + var lowOrderMatrix = { + weeks: { + days: 7, + hours: 7 * 24, + minutes: 7 * 24 * 60, + seconds: 7 * 24 * 60 * 60, + milliseconds: 7 * 24 * 60 * 60 * 1000 + }, + days: { + hours: 24, + minutes: 24 * 60, + seconds: 24 * 60 * 60, + milliseconds: 24 * 60 * 60 * 1000 + }, + hours: { + minutes: 60, + seconds: 60 * 60, + milliseconds: 60 * 60 * 1000 + }, + minutes: { + seconds: 60, + milliseconds: 60 * 1000 + }, + seconds: { + milliseconds: 1000 + } + }, + casualMatrix = _extends({ + years: { + quarters: 4, + months: 12, + weeks: 52, + days: 365, + hours: 365 * 24, + minutes: 365 * 24 * 60, + seconds: 365 * 24 * 60 * 60, + milliseconds: 365 * 24 * 60 * 60 * 1000 + }, + quarters: { + months: 3, + weeks: 13, + days: 91, + hours: 91 * 24, + minutes: 91 * 24 * 60, + seconds: 91 * 24 * 60 * 60, + milliseconds: 91 * 24 * 60 * 60 * 1000 + }, + months: { + weeks: 4, + days: 30, + hours: 30 * 24, + minutes: 30 * 24 * 60, + seconds: 30 * 24 * 60 * 60, + milliseconds: 30 * 24 * 60 * 60 * 1000 + } + }, lowOrderMatrix), + daysInYearAccurate = 146097.0 / 400, + daysInMonthAccurate = 146097.0 / 4800, + accurateMatrix = _extends({ + years: { + quarters: 4, + months: 12, + weeks: daysInYearAccurate / 7, + days: daysInYearAccurate, + hours: daysInYearAccurate * 24, + minutes: daysInYearAccurate * 24 * 60, + seconds: daysInYearAccurate * 24 * 60 * 60, + milliseconds: daysInYearAccurate * 24 * 60 * 60 * 1000 + }, + quarters: { + months: 3, + weeks: daysInYearAccurate / 28, + days: daysInYearAccurate / 4, + hours: daysInYearAccurate * 24 / 4, + minutes: daysInYearAccurate * 24 * 60 / 4, + seconds: daysInYearAccurate * 24 * 60 * 60 / 4, + milliseconds: daysInYearAccurate * 24 * 60 * 60 * 1000 / 4 + }, + months: { + weeks: daysInMonthAccurate / 7, + days: daysInMonthAccurate, + hours: daysInMonthAccurate * 24, + minutes: daysInMonthAccurate * 24 * 60, + seconds: daysInMonthAccurate * 24 * 60 * 60, + milliseconds: daysInMonthAccurate * 24 * 60 * 60 * 1000 + } + }, lowOrderMatrix); // units ordered by size + + var orderedUnits$1 = ["years", "quarters", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds"]; + var reverseUnits = orderedUnits$1.slice(0).reverse(); // clone really means "create another instance just like this one, but with these changes" + + function clone$1(dur, alts, clear) { + if (clear === void 0) { + clear = false; + } + + // deep merge for vals + var conf = { + values: clear ? alts.values : _extends({}, dur.values, alts.values || {}), + loc: dur.loc.clone(alts.loc), + conversionAccuracy: alts.conversionAccuracy || dur.conversionAccuracy + }; + return new Duration(conf); + } + + function antiTrunc(n) { + return n < 0 ? Math.floor(n) : Math.ceil(n); + } // NB: mutates parameters + + + function convert(matrix, fromMap, fromUnit, toMap, toUnit) { + var conv = matrix[toUnit][fromUnit], + raw = fromMap[fromUnit] / conv, + sameSign = Math.sign(raw) === Math.sign(toMap[toUnit]), + // ok, so this is wild, but see the matrix in the tests + added = !sameSign && toMap[toUnit] !== 0 && Math.abs(raw) <= 1 ? antiTrunc(raw) : Math.trunc(raw); + toMap[toUnit] += added; + fromMap[fromUnit] -= added * conv; + } // NB: mutates parameters + + + function normalizeValues(matrix, vals) { + reverseUnits.reduce(function (previous, current) { + if (!isUndefined(vals[current])) { + if (previous) { + convert(matrix, vals, previous, vals, current); + } + + return current; + } else { + return previous; + } + }, null); + } + /** + * A Duration object represents a period of time, like "2 months" or "1 day, 1 hour". Conceptually, it's just a map of units to their quantities, accompanied by some additional configuration and methods for creating, parsing, interrogating, transforming, and formatting them. They can be used on their own or in conjunction with other Luxon types; for example, you can use {@link DateTime#plus} to add a Duration object to a DateTime, producing another DateTime. + * + * Here is a brief overview of commonly used methods and getters in Duration: + * + * * **Creation** To create a Duration, use {@link Duration#fromMillis}, {@link Duration#fromObject}, or {@link Duration#fromISO}. + * * **Unit values** See the {@link Duration#years}, {@link Duration.months}, {@link Duration#weeks}, {@link Duration#days}, {@link Duration#hours}, {@link Duration#minutes}, {@link Duration#seconds}, {@link Duration#milliseconds} accessors. + * * **Configuration** See {@link Duration#locale} and {@link Duration#numberingSystem} accessors. + * * **Transformation** To create new Durations out of old ones use {@link Duration#plus}, {@link Duration#minus}, {@link Duration#normalize}, {@link Duration#set}, {@link Duration#reconfigure}, {@link Duration#shiftTo}, and {@link Duration#negate}. + * * **Output** To convert the Duration into other representations, see {@link Duration#as}, {@link Duration#toISO}, {@link Duration#toFormat}, and {@link Duration#toJSON} + * + * There's are more methods documented below. In addition, for more information on subtler topics like internationalization and validity, see the external documentation. + */ + + + var Duration = /*#__PURE__*/function () { + /** + * @private + */ + function Duration(config) { + var accurate = config.conversionAccuracy === "longterm" || false; + /** + * @access private + */ + + this.values = config.values; + /** + * @access private + */ + + this.loc = config.loc || Locale.create(); + /** + * @access private + */ + + this.conversionAccuracy = accurate ? "longterm" : "casual"; + /** + * @access private + */ + + this.invalid = config.invalid || null; + /** + * @access private + */ + + this.matrix = accurate ? accurateMatrix : casualMatrix; + /** + * @access private + */ + + this.isLuxonDuration = true; + } + /** + * Create Duration from a number of milliseconds. + * @param {number} count of milliseconds + * @param {Object} opts - options for parsing + * @param {string} [opts.locale='en-US'] - the locale to use + * @param {string} opts.numberingSystem - the numbering system to use + * @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use + * @return {Duration} + */ + + + Duration.fromMillis = function fromMillis(count, opts) { + return Duration.fromObject({ + milliseconds: count + }, opts); + } + /** + * Create a Duration from a JavaScript object with keys like 'years' and 'hours'. + * If this object is empty then a zero milliseconds duration is returned. + * @param {Object} obj - the object to create the DateTime from + * @param {number} obj.years + * @param {number} obj.quarters + * @param {number} obj.months + * @param {number} obj.weeks + * @param {number} obj.days + * @param {number} obj.hours + * @param {number} obj.minutes + * @param {number} obj.seconds + * @param {number} obj.milliseconds + * @param {Object} [opts=[]] - options for creating this Duration + * @param {string} [opts.locale='en-US'] - the locale to use + * @param {string} opts.numberingSystem - the numbering system to use + * @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use + * @return {Duration} + */ + ; + + Duration.fromObject = function fromObject(obj, opts) { + if (opts === void 0) { + opts = {}; + } + + if (obj == null || typeof obj !== "object") { + throw new InvalidArgumentError("Duration.fromObject: argument expected to be an object, got " + (obj === null ? "null" : typeof obj)); + } + + return new Duration({ + values: normalizeObject(obj, Duration.normalizeUnit), + loc: Locale.fromObject(opts), + conversionAccuracy: opts.conversionAccuracy + }); + } + /** + * Create a Duration from DurationLike. + * + * @param {Object | number | Duration} durationLike + * One of: + * - object with keys like 'years' and 'hours'. + * - number representing milliseconds + * - Duration instance + * @return {Duration} + */ + ; + + Duration.fromDurationLike = function fromDurationLike(durationLike) { + if (isNumber(durationLike)) { + return Duration.fromMillis(durationLike); + } else if (Duration.isDuration(durationLike)) { + return durationLike; + } else if (typeof durationLike === "object") { + return Duration.fromObject(durationLike); + } else { + throw new InvalidArgumentError("Unknown duration argument " + durationLike + " of type " + typeof durationLike); + } + } + /** + * Create a Duration from an ISO 8601 duration string. + * @param {string} text - text to parse + * @param {Object} opts - options for parsing + * @param {string} [opts.locale='en-US'] - the locale to use + * @param {string} opts.numberingSystem - the numbering system to use + * @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use + * @see https://en.wikipedia.org/wiki/ISO_8601#Durations + * @example Duration.fromISO('P3Y6M1W4DT12H30M5S').toObject() //=> { years: 3, months: 6, weeks: 1, days: 4, hours: 12, minutes: 30, seconds: 5 } + * @example Duration.fromISO('PT23H').toObject() //=> { hours: 23 } + * @example Duration.fromISO('P5Y3M').toObject() //=> { years: 5, months: 3 } + * @return {Duration} + */ + ; + + Duration.fromISO = function fromISO(text, opts) { + var _parseISODuration = parseISODuration(text), + parsed = _parseISODuration[0]; + + if (parsed) { + return Duration.fromObject(parsed, opts); + } else { + return Duration.invalid("unparsable", "the input \"" + text + "\" can't be parsed as ISO 8601"); + } + } + /** + * Create a Duration from an ISO 8601 time string. + * @param {string} text - text to parse + * @param {Object} opts - options for parsing + * @param {string} [opts.locale='en-US'] - the locale to use + * @param {string} opts.numberingSystem - the numbering system to use + * @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use + * @see https://en.wikipedia.org/wiki/ISO_8601#Times + * @example Duration.fromISOTime('11:22:33.444').toObject() //=> { hours: 11, minutes: 22, seconds: 33, milliseconds: 444 } + * @example Duration.fromISOTime('11:00').toObject() //=> { hours: 11, minutes: 0, seconds: 0 } + * @example Duration.fromISOTime('T11:00').toObject() //=> { hours: 11, minutes: 0, seconds: 0 } + * @example Duration.fromISOTime('1100').toObject() //=> { hours: 11, minutes: 0, seconds: 0 } + * @example Duration.fromISOTime('T1100').toObject() //=> { hours: 11, minutes: 0, seconds: 0 } + * @return {Duration} + */ + ; + + Duration.fromISOTime = function fromISOTime(text, opts) { + var _parseISOTimeOnly = parseISOTimeOnly(text), + parsed = _parseISOTimeOnly[0]; + + if (parsed) { + return Duration.fromObject(parsed, opts); + } else { + return Duration.invalid("unparsable", "the input \"" + text + "\" can't be parsed as ISO 8601"); + } + } + /** + * Create an invalid Duration. + * @param {string} reason - simple string of why this datetime is invalid. Should not contain parameters or anything else data-dependent + * @param {string} [explanation=null] - longer explanation, may include parameters and other useful debugging information + * @return {Duration} + */ + ; + + Duration.invalid = function invalid(reason, explanation) { + if (explanation === void 0) { + explanation = null; + } + + if (!reason) { + throw new InvalidArgumentError("need to specify a reason the Duration is invalid"); + } + + var invalid = reason instanceof Invalid ? reason : new Invalid(reason, explanation); + + if (Settings.throwOnInvalid) { + throw new InvalidDurationError(invalid); + } else { + return new Duration({ + invalid: invalid + }); + } + } + /** + * @private + */ + ; + + Duration.normalizeUnit = function normalizeUnit(unit) { + var normalized = { + year: "years", + years: "years", + quarter: "quarters", + quarters: "quarters", + month: "months", + months: "months", + week: "weeks", + weeks: "weeks", + day: "days", + days: "days", + hour: "hours", + hours: "hours", + minute: "minutes", + minutes: "minutes", + second: "seconds", + seconds: "seconds", + millisecond: "milliseconds", + milliseconds: "milliseconds" + }[unit ? unit.toLowerCase() : unit]; + if (!normalized) throw new InvalidUnitError(unit); + return normalized; + } + /** + * Check if an object is a Duration. Works across context boundaries + * @param {object} o + * @return {boolean} + */ + ; + + Duration.isDuration = function isDuration(o) { + return o && o.isLuxonDuration || false; + } + /** + * Get the locale of a Duration, such 'en-GB' + * @type {string} + */ + ; + + var _proto = Duration.prototype; + + /** + * Returns a string representation of this Duration formatted according to the specified format string. You may use these tokens: + * * `S` for milliseconds + * * `s` for seconds + * * `m` for minutes + * * `h` for hours + * * `d` for days + * * `M` for months + * * `y` for years + * Notes: + * * Add padding by repeating the token, e.g. "yy" pads the years to two digits, "hhhh" pads the hours out to four digits + * * The duration will be converted to the set of units in the format string using {@link Duration#shiftTo} and the Durations's conversion accuracy setting. + * @param {string} fmt - the format string + * @param {Object} opts - options + * @param {boolean} [opts.floor=true] - floor numerical values + * @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toFormat("y d s") //=> "1 6 2" + * @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toFormat("yy dd sss") //=> "01 06 002" + * @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toFormat("M S") //=> "12 518402000" + * @return {string} + */ + _proto.toFormat = function toFormat(fmt, opts) { + if (opts === void 0) { + opts = {}; + } + + // reverse-compat since 1.2; we always round down now, never up, and we do it by default + var fmtOpts = _extends({}, opts, { + floor: opts.round !== false && opts.floor !== false + }); + + return this.isValid ? Formatter.create(this.loc, fmtOpts).formatDurationFromString(this, fmt) : INVALID$2; + } + /** + * Returns a string representation of a Duration with all units included + * To modify its behavior use the `listStyle` and any Intl.NumberFormat option, though `unitDisplay` is especially relevant. See {@link Intl.NumberFormat}. + * @param opts - On option object to override the formatting. Accepts the same keys as the options parameter of the native `Int.NumberFormat` constructor, as well as `listStyle`. + * @example + * ```js + * var dur = Duration.fromObject({ days: 1, hours: 5, minutes: 6 }) + * dur.toHuman() //=> '1 day, 5 hours, 6 minutes' + * dur.toHuman({ listStyle: "long" }) //=> '1 day, 5 hours, and 6 minutes' + * dur.toHuman({ unitDisplay: "short" }) //=> '1 day, 5 hr, 6 min' + * ``` + */ + ; + + _proto.toHuman = function toHuman(opts) { + var _this = this; + + if (opts === void 0) { + opts = {}; + } + + var l = orderedUnits$1.map(function (unit) { + var val = _this.values[unit]; + + if (isUndefined(val)) { + return null; + } + + return _this.loc.numberFormatter(_extends({ + style: "unit", + unitDisplay: "long" + }, opts, { + unit: unit.slice(0, -1) + })).format(val); + }).filter(function (n) { + return n; + }); + return this.loc.listFormatter(_extends({ + type: "conjunction", + style: opts.listStyle || "narrow" + }, opts)).format(l); + } + /** + * Returns a JavaScript object with this Duration's values. + * @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toObject() //=> { years: 1, days: 6, seconds: 2 } + * @return {Object} + */ + ; + + _proto.toObject = function toObject() { + if (!this.isValid) return {}; + return _extends({}, this.values); + } + /** + * Returns an ISO 8601-compliant string representation of this Duration. + * @see https://en.wikipedia.org/wiki/ISO_8601#Durations + * @example Duration.fromObject({ years: 3, seconds: 45 }).toISO() //=> 'P3YT45S' + * @example Duration.fromObject({ months: 4, seconds: 45 }).toISO() //=> 'P4MT45S' + * @example Duration.fromObject({ months: 5 }).toISO() //=> 'P5M' + * @example Duration.fromObject({ minutes: 5 }).toISO() //=> 'PT5M' + * @example Duration.fromObject({ milliseconds: 6 }).toISO() //=> 'PT0.006S' + * @return {string} + */ + ; + + _proto.toISO = function toISO() { + // we could use the formatter, but this is an easier way to get the minimum string + if (!this.isValid) return null; + var s = "P"; + if (this.years !== 0) s += this.years + "Y"; + if (this.months !== 0 || this.quarters !== 0) s += this.months + this.quarters * 3 + "M"; + if (this.weeks !== 0) s += this.weeks + "W"; + if (this.days !== 0) s += this.days + "D"; + if (this.hours !== 0 || this.minutes !== 0 || this.seconds !== 0 || this.milliseconds !== 0) s += "T"; + if (this.hours !== 0) s += this.hours + "H"; + if (this.minutes !== 0) s += this.minutes + "M"; + if (this.seconds !== 0 || this.milliseconds !== 0) // this will handle "floating point madness" by removing extra decimal places + // https://stackoverflow.com/questions/588004/is-floating-point-math-broken + s += roundTo(this.seconds + this.milliseconds / 1000, 3) + "S"; + if (s === "P") s += "T0S"; + return s; + } + /** + * Returns an ISO 8601-compliant string representation of this Duration, formatted as a time of day. + * Note that this will return null if the duration is invalid, negative, or equal to or greater than 24 hours. + * @see https://en.wikipedia.org/wiki/ISO_8601#Times + * @param {Object} opts - options + * @param {boolean} [opts.suppressMilliseconds=false] - exclude milliseconds from the format if they're 0 + * @param {boolean} [opts.suppressSeconds=false] - exclude seconds from the format if they're 0 + * @param {boolean} [opts.includePrefix=false] - include the `T` prefix + * @param {string} [opts.format='extended'] - choose between the basic and extended format + * @example Duration.fromObject({ hours: 11 }).toISOTime() //=> '11:00:00.000' + * @example Duration.fromObject({ hours: 11 }).toISOTime({ suppressMilliseconds: true }) //=> '11:00:00' + * @example Duration.fromObject({ hours: 11 }).toISOTime({ suppressSeconds: true }) //=> '11:00' + * @example Duration.fromObject({ hours: 11 }).toISOTime({ includePrefix: true }) //=> 'T11:00:00.000' + * @example Duration.fromObject({ hours: 11 }).toISOTime({ format: 'basic' }) //=> '110000.000' + * @return {string} + */ + ; + + _proto.toISOTime = function toISOTime(opts) { + if (opts === void 0) { + opts = {}; + } + + if (!this.isValid) return null; + var millis = this.toMillis(); + if (millis < 0 || millis >= 86400000) return null; + opts = _extends({ + suppressMilliseconds: false, + suppressSeconds: false, + includePrefix: false, + format: "extended" + }, opts); + var value = this.shiftTo("hours", "minutes", "seconds", "milliseconds"); + var fmt = opts.format === "basic" ? "hhmm" : "hh:mm"; + + if (!opts.suppressSeconds || value.seconds !== 0 || value.milliseconds !== 0) { + fmt += opts.format === "basic" ? "ss" : ":ss"; + + if (!opts.suppressMilliseconds || value.milliseconds !== 0) { + fmt += ".SSS"; + } + } + + var str = value.toFormat(fmt); + + if (opts.includePrefix) { + str = "T" + str; + } + + return str; + } + /** + * Returns an ISO 8601 representation of this Duration appropriate for use in JSON. + * @return {string} + */ + ; + + _proto.toJSON = function toJSON() { + return this.toISO(); + } + /** + * Returns an ISO 8601 representation of this Duration appropriate for use in debugging. + * @return {string} + */ + ; + + _proto.toString = function toString() { + return this.toISO(); + } + /** + * Returns an milliseconds value of this Duration. + * @return {number} + */ + ; + + _proto.toMillis = function toMillis() { + return this.as("milliseconds"); + } + /** + * Returns an milliseconds value of this Duration. Alias of {@link toMillis} + * @return {number} + */ + ; + + _proto.valueOf = function valueOf() { + return this.toMillis(); + } + /** + * Make this Duration longer by the specified amount. Return a newly-constructed Duration. + * @param {Duration|Object|number} duration - The amount to add. Either a Luxon Duration, a number of milliseconds, the object argument to Duration.fromObject() + * @return {Duration} + */ + ; + + _proto.plus = function plus(duration) { + if (!this.isValid) return this; + var dur = Duration.fromDurationLike(duration), + result = {}; + + for (var _iterator = _createForOfIteratorHelperLoose(orderedUnits$1), _step; !(_step = _iterator()).done;) { + var k = _step.value; + + if (hasOwnProperty(dur.values, k) || hasOwnProperty(this.values, k)) { + result[k] = dur.get(k) + this.get(k); + } + } + + return clone$1(this, { + values: result + }, true); + } + /** + * Make this Duration shorter by the specified amount. Return a newly-constructed Duration. + * @param {Duration|Object|number} duration - The amount to subtract. Either a Luxon Duration, a number of milliseconds, the object argument to Duration.fromObject() + * @return {Duration} + */ + ; + + _proto.minus = function minus(duration) { + if (!this.isValid) return this; + var dur = Duration.fromDurationLike(duration); + return this.plus(dur.negate()); + } + /** + * Scale this Duration by the specified amount. Return a newly-constructed Duration. + * @param {function} fn - The function to apply to each unit. Arity is 1 or 2: the value of the unit and, optionally, the unit name. Must return a number. + * @example Duration.fromObject({ hours: 1, minutes: 30 }).mapUnits(x => x * 2) //=> { hours: 2, minutes: 60 } + * @example Duration.fromObject({ hours: 1, minutes: 30 }).mapUnits((x, u) => u === "hour" ? x * 2 : x) //=> { hours: 2, minutes: 30 } + * @return {Duration} + */ + ; + + _proto.mapUnits = function mapUnits(fn) { + if (!this.isValid) return this; + var result = {}; + + for (var _i = 0, _Object$keys = Object.keys(this.values); _i < _Object$keys.length; _i++) { + var k = _Object$keys[_i]; + result[k] = asNumber(fn(this.values[k], k)); + } + + return clone$1(this, { + values: result + }, true); + } + /** + * Get the value of unit. + * @param {string} unit - a unit such as 'minute' or 'day' + * @example Duration.fromObject({years: 2, days: 3}).get('years') //=> 2 + * @example Duration.fromObject({years: 2, days: 3}).get('months') //=> 0 + * @example Duration.fromObject({years: 2, days: 3}).get('days') //=> 3 + * @return {number} + */ + ; + + _proto.get = function get(unit) { + return this[Duration.normalizeUnit(unit)]; + } + /** + * "Set" the values of specified units. Return a newly-constructed Duration. + * @param {Object} values - a mapping of units to numbers + * @example dur.set({ years: 2017 }) + * @example dur.set({ hours: 8, minutes: 30 }) + * @return {Duration} + */ + ; + + _proto.set = function set(values) { + if (!this.isValid) return this; + + var mixed = _extends({}, this.values, normalizeObject(values, Duration.normalizeUnit)); + + return clone$1(this, { + values: mixed + }); + } + /** + * "Set" the locale and/or numberingSystem. Returns a newly-constructed Duration. + * @example dur.reconfigure({ locale: 'en-GB' }) + * @return {Duration} + */ + ; + + _proto.reconfigure = function reconfigure(_temp) { + var _ref = _temp === void 0 ? {} : _temp, + locale = _ref.locale, + numberingSystem = _ref.numberingSystem, + conversionAccuracy = _ref.conversionAccuracy; + + var loc = this.loc.clone({ + locale: locale, + numberingSystem: numberingSystem + }), + opts = { + loc: loc + }; + + if (conversionAccuracy) { + opts.conversionAccuracy = conversionAccuracy; + } + + return clone$1(this, opts); + } + /** + * Return the length of the duration in the specified unit. + * @param {string} unit - a unit such as 'minutes' or 'days' + * @example Duration.fromObject({years: 1}).as('days') //=> 365 + * @example Duration.fromObject({years: 1}).as('months') //=> 12 + * @example Duration.fromObject({hours: 60}).as('days') //=> 2.5 + * @return {number} + */ + ; + + _proto.as = function as(unit) { + return this.isValid ? this.shiftTo(unit).get(unit) : NaN; + } + /** + * Reduce this Duration to its canonical representation in its current units. + * @example Duration.fromObject({ years: 2, days: 5000 }).normalize().toObject() //=> { years: 15, days: 255 } + * @example Duration.fromObject({ hours: 12, minutes: -45 }).normalize().toObject() //=> { hours: 11, minutes: 15 } + * @return {Duration} + */ + ; + + _proto.normalize = function normalize() { + if (!this.isValid) return this; + var vals = this.toObject(); + normalizeValues(this.matrix, vals); + return clone$1(this, { + values: vals + }, true); + } + /** + * Convert this Duration into its representation in a different set of units. + * @example Duration.fromObject({ hours: 1, seconds: 30 }).shiftTo('minutes', 'milliseconds').toObject() //=> { minutes: 60, milliseconds: 30000 } + * @return {Duration} + */ + ; + + _proto.shiftTo = function shiftTo() { + for (var _len = arguments.length, units = new Array(_len), _key = 0; _key < _len; _key++) { + units[_key] = arguments[_key]; + } + + if (!this.isValid) return this; + + if (units.length === 0) { + return this; + } + + units = units.map(function (u) { + return Duration.normalizeUnit(u); + }); + var built = {}, + accumulated = {}, + vals = this.toObject(); + var lastUnit; + + for (var _iterator2 = _createForOfIteratorHelperLoose(orderedUnits$1), _step2; !(_step2 = _iterator2()).done;) { + var k = _step2.value; + + if (units.indexOf(k) >= 0) { + lastUnit = k; + var own = 0; // anything we haven't boiled down yet should get boiled to this unit + + for (var ak in accumulated) { + own += this.matrix[ak][k] * accumulated[ak]; + accumulated[ak] = 0; + } // plus anything that's already in this unit + + + if (isNumber(vals[k])) { + own += vals[k]; + } + + var i = Math.trunc(own); + built[k] = i; + accumulated[k] = (own * 1000 - i * 1000) / 1000; // plus anything further down the chain that should be rolled up in to this + + for (var down in vals) { + if (orderedUnits$1.indexOf(down) > orderedUnits$1.indexOf(k)) { + convert(this.matrix, vals, down, built, k); + } + } // otherwise, keep it in the wings to boil it later + + } else if (isNumber(vals[k])) { + accumulated[k] = vals[k]; + } + } // anything leftover becomes the decimal for the last unit + // lastUnit must be defined since units is not empty + + + for (var key in accumulated) { + if (accumulated[key] !== 0) { + built[lastUnit] += key === lastUnit ? accumulated[key] : accumulated[key] / this.matrix[lastUnit][key]; + } + } + + return clone$1(this, { + values: built + }, true).normalize(); + } + /** + * Return the negative of this Duration. + * @example Duration.fromObject({ hours: 1, seconds: 30 }).negate().toObject() //=> { hours: -1, seconds: -30 } + * @return {Duration} + */ + ; + + _proto.negate = function negate() { + if (!this.isValid) return this; + var negated = {}; + + for (var _i2 = 0, _Object$keys2 = Object.keys(this.values); _i2 < _Object$keys2.length; _i2++) { + var k = _Object$keys2[_i2]; + negated[k] = -this.values[k]; + } + + return clone$1(this, { + values: negated + }, true); + } + /** + * Get the years. + * @type {number} + */ + ; + + /** + * Equality check + * Two Durations are equal iff they have the same units and the same values for each unit. + * @param {Duration} other + * @return {boolean} + */ + _proto.equals = function equals(other) { + if (!this.isValid || !other.isValid) { + return false; + } + + if (!this.loc.equals(other.loc)) { + return false; + } + + function eq(v1, v2) { + // Consider 0 and undefined as equal + if (v1 === undefined || v1 === 0) return v2 === undefined || v2 === 0; + return v1 === v2; + } + + for (var _iterator3 = _createForOfIteratorHelperLoose(orderedUnits$1), _step3; !(_step3 = _iterator3()).done;) { + var u = _step3.value; + + if (!eq(this.values[u], other.values[u])) { + return false; + } + } + + return true; + }; + + _createClass(Duration, [{ + key: "locale", + get: function get() { + return this.isValid ? this.loc.locale : null; + } + /** + * Get the numbering system of a Duration, such 'beng'. The numbering system is used when formatting the Duration + * + * @type {string} + */ + + }, { + key: "numberingSystem", + get: function get() { + return this.isValid ? this.loc.numberingSystem : null; + } + }, { + key: "years", + get: function get() { + return this.isValid ? this.values.years || 0 : NaN; + } + /** + * Get the quarters. + * @type {number} + */ + + }, { + key: "quarters", + get: function get() { + return this.isValid ? this.values.quarters || 0 : NaN; + } + /** + * Get the months. + * @type {number} + */ + + }, { + key: "months", + get: function get() { + return this.isValid ? this.values.months || 0 : NaN; + } + /** + * Get the weeks + * @type {number} + */ + + }, { + key: "weeks", + get: function get() { + return this.isValid ? this.values.weeks || 0 : NaN; + } + /** + * Get the days. + * @type {number} + */ + + }, { + key: "days", + get: function get() { + return this.isValid ? this.values.days || 0 : NaN; + } + /** + * Get the hours. + * @type {number} + */ + + }, { + key: "hours", + get: function get() { + return this.isValid ? this.values.hours || 0 : NaN; + } + /** + * Get the minutes. + * @type {number} + */ + + }, { + key: "minutes", + get: function get() { + return this.isValid ? this.values.minutes || 0 : NaN; + } + /** + * Get the seconds. + * @return {number} + */ + + }, { + key: "seconds", + get: function get() { + return this.isValid ? this.values.seconds || 0 : NaN; + } + /** + * Get the milliseconds. + * @return {number} + */ + + }, { + key: "milliseconds", + get: function get() { + return this.isValid ? this.values.milliseconds || 0 : NaN; + } + /** + * Returns whether the Duration is invalid. Invalid durations are returned by diff operations + * on invalid DateTimes or Intervals. + * @return {boolean} + */ + + }, { + key: "isValid", + get: function get() { + return this.invalid === null; + } + /** + * Returns an error code if this Duration became invalid, or null if the Duration is valid + * @return {string} + */ + + }, { + key: "invalidReason", + get: function get() { + return this.invalid ? this.invalid.reason : null; + } + /** + * Returns an explanation of why this Duration became invalid, or null if the Duration is valid + * @type {string} + */ + + }, { + key: "invalidExplanation", + get: function get() { + return this.invalid ? this.invalid.explanation : null; + } + }]); + + return Duration; + }(); + + var INVALID$1 = "Invalid Interval"; // checks if the start is equal to or before the end + + function validateStartEnd(start, end) { + if (!start || !start.isValid) { + return Interval.invalid("missing or invalid start"); + } else if (!end || !end.isValid) { + return Interval.invalid("missing or invalid end"); + } else if (end < start) { + return Interval.invalid("end before start", "The end of an interval must be after its start, but you had start=" + start.toISO() + " and end=" + end.toISO()); + } else { + return null; + } + } + /** + * An Interval object represents a half-open interval of time, where each endpoint is a {@link DateTime}. Conceptually, it's a container for those two endpoints, accompanied by methods for creating, parsing, interrogating, comparing, transforming, and formatting them. + * + * Here is a brief overview of the most commonly used methods and getters in Interval: + * + * * **Creation** To create an Interval, use {@link Interval#fromDateTimes}, {@link Interval#after}, {@link Interval#before}, or {@link Interval#fromISO}. + * * **Accessors** Use {@link Interval#start} and {@link Interval#end} to get the start and end. + * * **Interrogation** To analyze the Interval, use {@link Interval#count}, {@link Interval#length}, {@link Interval#hasSame}, {@link Interval#contains}, {@link Interval#isAfter}, or {@link Interval#isBefore}. + * * **Transformation** To create other Intervals out of this one, use {@link Interval#set}, {@link Interval#splitAt}, {@link Interval#splitBy}, {@link Interval#divideEqually}, {@link Interval#merge}, {@link Interval#xor}, {@link Interval#union}, {@link Interval#intersection}, or {@link Interval#difference}. + * * **Comparison** To compare this Interval to another one, use {@link Interval#equals}, {@link Interval#overlaps}, {@link Interval#abutsStart}, {@link Interval#abutsEnd}, {@link Interval#engulfs} + * * **Output** To convert the Interval into other representations, see {@link Interval#toString}, {@link Interval#toISO}, {@link Interval#toISODate}, {@link Interval#toISOTime}, {@link Interval#toFormat}, and {@link Interval#toDuration}. + */ + + + var Interval = /*#__PURE__*/function () { + /** + * @private + */ + function Interval(config) { + /** + * @access private + */ + this.s = config.start; + /** + * @access private + */ + + this.e = config.end; + /** + * @access private + */ + + this.invalid = config.invalid || null; + /** + * @access private + */ + + this.isLuxonInterval = true; + } + /** + * Create an invalid Interval. + * @param {string} reason - simple string of why this Interval is invalid. Should not contain parameters or anything else data-dependent + * @param {string} [explanation=null] - longer explanation, may include parameters and other useful debugging information + * @return {Interval} + */ + + + Interval.invalid = function invalid(reason, explanation) { + if (explanation === void 0) { + explanation = null; + } + + if (!reason) { + throw new InvalidArgumentError("need to specify a reason the Interval is invalid"); + } + + var invalid = reason instanceof Invalid ? reason : new Invalid(reason, explanation); + + if (Settings.throwOnInvalid) { + throw new InvalidIntervalError(invalid); + } else { + return new Interval({ + invalid: invalid + }); + } + } + /** + * Create an Interval from a start DateTime and an end DateTime. Inclusive of the start but not the end. + * @param {DateTime|Date|Object} start + * @param {DateTime|Date|Object} end + * @return {Interval} + */ + ; + + Interval.fromDateTimes = function fromDateTimes(start, end) { + var builtStart = friendlyDateTime(start), + builtEnd = friendlyDateTime(end); + var validateError = validateStartEnd(builtStart, builtEnd); + + if (validateError == null) { + return new Interval({ + start: builtStart, + end: builtEnd + }); + } else { + return validateError; + } + } + /** + * Create an Interval from a start DateTime and a Duration to extend to. + * @param {DateTime|Date|Object} start + * @param {Duration|Object|number} duration - the length of the Interval. + * @return {Interval} + */ + ; + + Interval.after = function after(start, duration) { + var dur = Duration.fromDurationLike(duration), + dt = friendlyDateTime(start); + return Interval.fromDateTimes(dt, dt.plus(dur)); + } + /** + * Create an Interval from an end DateTime and a Duration to extend backwards to. + * @param {DateTime|Date|Object} end + * @param {Duration|Object|number} duration - the length of the Interval. + * @return {Interval} + */ + ; + + Interval.before = function before(end, duration) { + var dur = Duration.fromDurationLike(duration), + dt = friendlyDateTime(end); + return Interval.fromDateTimes(dt.minus(dur), dt); + } + /** + * Create an Interval from an ISO 8601 string. + * Accepts `/`, `/`, and `/` formats. + * @param {string} text - the ISO string to parse + * @param {Object} [opts] - options to pass {@link DateTime#fromISO} and optionally {@link Duration#fromISO} + * @see https://en.wikipedia.org/wiki/ISO_8601#Time_intervals + * @return {Interval} + */ + ; + + Interval.fromISO = function fromISO(text, opts) { + var _split = (text || "").split("/", 2), + s = _split[0], + e = _split[1]; + + if (s && e) { + var start, startIsValid; + + try { + start = DateTime.fromISO(s, opts); + startIsValid = start.isValid; + } catch (e) { + startIsValid = false; + } + + var end, endIsValid; + + try { + end = DateTime.fromISO(e, opts); + endIsValid = end.isValid; + } catch (e) { + endIsValid = false; + } + + if (startIsValid && endIsValid) { + return Interval.fromDateTimes(start, end); + } + + if (startIsValid) { + var dur = Duration.fromISO(e, opts); + + if (dur.isValid) { + return Interval.after(start, dur); + } + } else if (endIsValid) { + var _dur = Duration.fromISO(s, opts); + + if (_dur.isValid) { + return Interval.before(end, _dur); + } + } + } + + return Interval.invalid("unparsable", "the input \"" + text + "\" can't be parsed as ISO 8601"); + } + /** + * Check if an object is an Interval. Works across context boundaries + * @param {object} o + * @return {boolean} + */ + ; + + Interval.isInterval = function isInterval(o) { + return o && o.isLuxonInterval || false; + } + /** + * Returns the start of the Interval + * @type {DateTime} + */ + ; + + var _proto = Interval.prototype; + + /** + * Returns the length of the Interval in the specified unit. + * @param {string} unit - the unit (such as 'hours' or 'days') to return the length in. + * @return {number} + */ + _proto.length = function length(unit) { + if (unit === void 0) { + unit = "milliseconds"; + } + + return this.isValid ? this.toDuration.apply(this, [unit]).get(unit) : NaN; + } + /** + * Returns the count of minutes, hours, days, months, or years included in the Interval, even in part. + * Unlike {@link Interval#length} this counts sections of the calendar, not periods of time, e.g. specifying 'day' + * asks 'what dates are included in this interval?', not 'how many days long is this interval?' + * @param {string} [unit='milliseconds'] - the unit of time to count. + * @return {number} + */ + ; + + _proto.count = function count(unit) { + if (unit === void 0) { + unit = "milliseconds"; + } + + if (!this.isValid) return NaN; + var start = this.start.startOf(unit), + end = this.end.startOf(unit); + return Math.floor(end.diff(start, unit).get(unit)) + 1; + } + /** + * Returns whether this Interval's start and end are both in the same unit of time + * @param {string} unit - the unit of time to check sameness on + * @return {boolean} + */ + ; + + _proto.hasSame = function hasSame(unit) { + return this.isValid ? this.isEmpty() || this.e.minus(1).hasSame(this.s, unit) : false; + } + /** + * Return whether this Interval has the same start and end DateTimes. + * @return {boolean} + */ + ; + + _proto.isEmpty = function isEmpty() { + return this.s.valueOf() === this.e.valueOf(); + } + /** + * Return whether this Interval's start is after the specified DateTime. + * @param {DateTime} dateTime + * @return {boolean} + */ + ; + + _proto.isAfter = function isAfter(dateTime) { + if (!this.isValid) return false; + return this.s > dateTime; + } + /** + * Return whether this Interval's end is before the specified DateTime. + * @param {DateTime} dateTime + * @return {boolean} + */ + ; + + _proto.isBefore = function isBefore(dateTime) { + if (!this.isValid) return false; + return this.e <= dateTime; + } + /** + * Return whether this Interval contains the specified DateTime. + * @param {DateTime} dateTime + * @return {boolean} + */ + ; + + _proto.contains = function contains(dateTime) { + if (!this.isValid) return false; + return this.s <= dateTime && this.e > dateTime; + } + /** + * "Sets" the start and/or end dates. Returns a newly-constructed Interval. + * @param {Object} values - the values to set + * @param {DateTime} values.start - the starting DateTime + * @param {DateTime} values.end - the ending DateTime + * @return {Interval} + */ + ; + + _proto.set = function set(_temp) { + var _ref = _temp === void 0 ? {} : _temp, + start = _ref.start, + end = _ref.end; + + if (!this.isValid) return this; + return Interval.fromDateTimes(start || this.s, end || this.e); + } + /** + * Split this Interval at each of the specified DateTimes + * @param {...DateTime} dateTimes - the unit of time to count. + * @return {Array} + */ + ; + + _proto.splitAt = function splitAt() { + var _this = this; + + if (!this.isValid) return []; + + for (var _len = arguments.length, dateTimes = new Array(_len), _key = 0; _key < _len; _key++) { + dateTimes[_key] = arguments[_key]; + } + + var sorted = dateTimes.map(friendlyDateTime).filter(function (d) { + return _this.contains(d); + }).sort(), + results = []; + var s = this.s, + i = 0; + + while (s < this.e) { + var added = sorted[i] || this.e, + next = +added > +this.e ? this.e : added; + results.push(Interval.fromDateTimes(s, next)); + s = next; + i += 1; + } + + return results; + } + /** + * Split this Interval into smaller Intervals, each of the specified length. + * Left over time is grouped into a smaller interval + * @param {Duration|Object|number} duration - The length of each resulting interval. + * @return {Array} + */ + ; + + _proto.splitBy = function splitBy(duration) { + var dur = Duration.fromDurationLike(duration); + + if (!this.isValid || !dur.isValid || dur.as("milliseconds") === 0) { + return []; + } + + var s = this.s, + idx = 1, + next; + var results = []; + + while (s < this.e) { + var added = this.start.plus(dur.mapUnits(function (x) { + return x * idx; + })); + next = +added > +this.e ? this.e : added; + results.push(Interval.fromDateTimes(s, next)); + s = next; + idx += 1; + } + + return results; + } + /** + * Split this Interval into the specified number of smaller intervals. + * @param {number} numberOfParts - The number of Intervals to divide the Interval into. + * @return {Array} + */ + ; + + _proto.divideEqually = function divideEqually(numberOfParts) { + if (!this.isValid) return []; + return this.splitBy(this.length() / numberOfParts).slice(0, numberOfParts); + } + /** + * Return whether this Interval overlaps with the specified Interval + * @param {Interval} other + * @return {boolean} + */ + ; + + _proto.overlaps = function overlaps(other) { + return this.e > other.s && this.s < other.e; + } + /** + * Return whether this Interval's end is adjacent to the specified Interval's start. + * @param {Interval} other + * @return {boolean} + */ + ; + + _proto.abutsStart = function abutsStart(other) { + if (!this.isValid) return false; + return +this.e === +other.s; + } + /** + * Return whether this Interval's start is adjacent to the specified Interval's end. + * @param {Interval} other + * @return {boolean} + */ + ; + + _proto.abutsEnd = function abutsEnd(other) { + if (!this.isValid) return false; + return +other.e === +this.s; + } + /** + * Return whether this Interval engulfs the start and end of the specified Interval. + * @param {Interval} other + * @return {boolean} + */ + ; + + _proto.engulfs = function engulfs(other) { + if (!this.isValid) return false; + return this.s <= other.s && this.e >= other.e; + } + /** + * Return whether this Interval has the same start and end as the specified Interval. + * @param {Interval} other + * @return {boolean} + */ + ; + + _proto.equals = function equals(other) { + if (!this.isValid || !other.isValid) { + return false; + } + + return this.s.equals(other.s) && this.e.equals(other.e); + } + /** + * Return an Interval representing the intersection of this Interval and the specified Interval. + * Specifically, the resulting Interval has the maximum start time and the minimum end time of the two Intervals. + * Returns null if the intersection is empty, meaning, the intervals don't intersect. + * @param {Interval} other + * @return {Interval} + */ + ; + + _proto.intersection = function intersection(other) { + if (!this.isValid) return this; + var s = this.s > other.s ? this.s : other.s, + e = this.e < other.e ? this.e : other.e; + + if (s >= e) { + return null; + } else { + return Interval.fromDateTimes(s, e); + } + } + /** + * Return an Interval representing the union of this Interval and the specified Interval. + * Specifically, the resulting Interval has the minimum start time and the maximum end time of the two Intervals. + * @param {Interval} other + * @return {Interval} + */ + ; + + _proto.union = function union(other) { + if (!this.isValid) return this; + var s = this.s < other.s ? this.s : other.s, + e = this.e > other.e ? this.e : other.e; + return Interval.fromDateTimes(s, e); + } + /** + * Merge an array of Intervals into a equivalent minimal set of Intervals. + * Combines overlapping and adjacent Intervals. + * @param {Array} intervals + * @return {Array} + */ + ; + + Interval.merge = function merge(intervals) { + var _intervals$sort$reduc = intervals.sort(function (a, b) { + return a.s - b.s; + }).reduce(function (_ref2, item) { + var sofar = _ref2[0], + current = _ref2[1]; + + if (!current) { + return [sofar, item]; + } else if (current.overlaps(item) || current.abutsStart(item)) { + return [sofar, current.union(item)]; + } else { + return [sofar.concat([current]), item]; + } + }, [[], null]), + found = _intervals$sort$reduc[0], + final = _intervals$sort$reduc[1]; + + if (final) { + found.push(final); + } + + return found; + } + /** + * Return an array of Intervals representing the spans of time that only appear in one of the specified Intervals. + * @param {Array} intervals + * @return {Array} + */ + ; + + Interval.xor = function xor(intervals) { + var _Array$prototype; + + var start = null, + currentCount = 0; + + var results = [], + ends = intervals.map(function (i) { + return [{ + time: i.s, + type: "s" + }, { + time: i.e, + type: "e" + }]; + }), + flattened = (_Array$prototype = Array.prototype).concat.apply(_Array$prototype, ends), + arr = flattened.sort(function (a, b) { + return a.time - b.time; + }); + + for (var _iterator = _createForOfIteratorHelperLoose(arr), _step; !(_step = _iterator()).done;) { + var i = _step.value; + currentCount += i.type === "s" ? 1 : -1; + + if (currentCount === 1) { + start = i.time; + } else { + if (start && +start !== +i.time) { + results.push(Interval.fromDateTimes(start, i.time)); + } + + start = null; + } + } + + return Interval.merge(results); + } + /** + * Return an Interval representing the span of time in this Interval that doesn't overlap with any of the specified Intervals. + * @param {...Interval} intervals + * @return {Array} + */ + ; + + _proto.difference = function difference() { + var _this2 = this; + + for (var _len2 = arguments.length, intervals = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + intervals[_key2] = arguments[_key2]; + } + + return Interval.xor([this].concat(intervals)).map(function (i) { + return _this2.intersection(i); + }).filter(function (i) { + return i && !i.isEmpty(); + }); + } + /** + * Returns a string representation of this Interval appropriate for debugging. + * @return {string} + */ + ; + + _proto.toString = function toString() { + if (!this.isValid) return INVALID$1; + return "[" + this.s.toISO() + " \u2013 " + this.e.toISO() + ")"; + } + /** + * Returns an ISO 8601-compliant string representation of this Interval. + * @see https://en.wikipedia.org/wiki/ISO_8601#Time_intervals + * @param {Object} opts - The same options as {@link DateTime#toISO} + * @return {string} + */ + ; + + _proto.toISO = function toISO(opts) { + if (!this.isValid) return INVALID$1; + return this.s.toISO(opts) + "/" + this.e.toISO(opts); + } + /** + * Returns an ISO 8601-compliant string representation of date of this Interval. + * The time components are ignored. + * @see https://en.wikipedia.org/wiki/ISO_8601#Time_intervals + * @return {string} + */ + ; + + _proto.toISODate = function toISODate() { + if (!this.isValid) return INVALID$1; + return this.s.toISODate() + "/" + this.e.toISODate(); + } + /** + * Returns an ISO 8601-compliant string representation of time of this Interval. + * The date components are ignored. + * @see https://en.wikipedia.org/wiki/ISO_8601#Time_intervals + * @param {Object} opts - The same options as {@link DateTime#toISO} + * @return {string} + */ + ; + + _proto.toISOTime = function toISOTime(opts) { + if (!this.isValid) return INVALID$1; + return this.s.toISOTime(opts) + "/" + this.e.toISOTime(opts); + } + /** + * Returns a string representation of this Interval formatted according to the specified format string. + * @param {string} dateFormat - the format string. This string formats the start and end time. See {@link DateTime#toFormat} for details. + * @param {Object} opts - options + * @param {string} [opts.separator = ' – '] - a separator to place between the start and end representations + * @return {string} + */ + ; + + _proto.toFormat = function toFormat(dateFormat, _temp2) { + var _ref3 = _temp2 === void 0 ? {} : _temp2, + _ref3$separator = _ref3.separator, + separator = _ref3$separator === void 0 ? " – " : _ref3$separator; + + if (!this.isValid) return INVALID$1; + return "" + this.s.toFormat(dateFormat) + separator + this.e.toFormat(dateFormat); + } + /** + * Return a Duration representing the time spanned by this interval. + * @param {string|string[]} [unit=['milliseconds']] - the unit or units (such as 'hours' or 'days') to include in the duration. + * @param {Object} opts - options that affect the creation of the Duration + * @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use + * @example Interval.fromDateTimes(dt1, dt2).toDuration().toObject() //=> { milliseconds: 88489257 } + * @example Interval.fromDateTimes(dt1, dt2).toDuration('days').toObject() //=> { days: 1.0241812152777778 } + * @example Interval.fromDateTimes(dt1, dt2).toDuration(['hours', 'minutes']).toObject() //=> { hours: 24, minutes: 34.82095 } + * @example Interval.fromDateTimes(dt1, dt2).toDuration(['hours', 'minutes', 'seconds']).toObject() //=> { hours: 24, minutes: 34, seconds: 49.257 } + * @example Interval.fromDateTimes(dt1, dt2).toDuration('seconds').toObject() //=> { seconds: 88489.257 } + * @return {Duration} + */ + ; + + _proto.toDuration = function toDuration(unit, opts) { + if (!this.isValid) { + return Duration.invalid(this.invalidReason); + } + + return this.e.diff(this.s, unit, opts); + } + /** + * Run mapFn on the interval start and end, returning a new Interval from the resulting DateTimes + * @param {function} mapFn + * @return {Interval} + * @example Interval.fromDateTimes(dt1, dt2).mapEndpoints(endpoint => endpoint.toUTC()) + * @example Interval.fromDateTimes(dt1, dt2).mapEndpoints(endpoint => endpoint.plus({ hours: 2 })) + */ + ; + + _proto.mapEndpoints = function mapEndpoints(mapFn) { + return Interval.fromDateTimes(mapFn(this.s), mapFn(this.e)); + }; + + _createClass(Interval, [{ + key: "start", + get: function get() { + return this.isValid ? this.s : null; + } + /** + * Returns the end of the Interval + * @type {DateTime} + */ + + }, { + key: "end", + get: function get() { + return this.isValid ? this.e : null; + } + /** + * Returns whether this Interval's end is at least its start, meaning that the Interval isn't 'backwards'. + * @type {boolean} + */ + + }, { + key: "isValid", + get: function get() { + return this.invalidReason === null; + } + /** + * Returns an error code if this Interval is invalid, or null if the Interval is valid + * @type {string} + */ + + }, { + key: "invalidReason", + get: function get() { + return this.invalid ? this.invalid.reason : null; + } + /** + * Returns an explanation of why this Interval became invalid, or null if the Interval is valid + * @type {string} + */ + + }, { + key: "invalidExplanation", + get: function get() { + return this.invalid ? this.invalid.explanation : null; + } + }]); + + return Interval; + }(); + + /** + * The Info class contains static methods for retrieving general time and date related data. For example, it has methods for finding out if a time zone has a DST, for listing the months in any supported locale, and for discovering which of Luxon features are available in the current environment. + */ + + var Info = /*#__PURE__*/function () { + function Info() {} + + /** + * Return whether the specified zone contains a DST. + * @param {string|Zone} [zone='local'] - Zone to check. Defaults to the environment's local zone. + * @return {boolean} + */ + Info.hasDST = function hasDST(zone) { + if (zone === void 0) { + zone = Settings.defaultZone; + } + + var proto = DateTime.now().setZone(zone).set({ + month: 12 + }); + return !zone.isUniversal && proto.offset !== proto.set({ + month: 6 + }).offset; + } + /** + * Return whether the specified zone is a valid IANA specifier. + * @param {string} zone - Zone to check + * @return {boolean} + */ + ; + + Info.isValidIANAZone = function isValidIANAZone(zone) { + return IANAZone.isValidSpecifier(zone) && IANAZone.isValidZone(zone); + } + /** + * Converts the input into a {@link Zone} instance. + * + * * If `input` is already a Zone instance, it is returned unchanged. + * * If `input` is a string containing a valid time zone name, a Zone instance + * with that name is returned. + * * If `input` is a string that doesn't refer to a known time zone, a Zone + * instance with {@link Zone#isValid} == false is returned. + * * If `input is a number, a Zone instance with the specified fixed offset + * in minutes is returned. + * * If `input` is `null` or `undefined`, the default zone is returned. + * @param {string|Zone|number} [input] - the value to be converted + * @return {Zone} + */ + ; + + Info.normalizeZone = function normalizeZone$1(input) { + return normalizeZone(input, Settings.defaultZone); + } + /** + * Return an array of standalone month names. + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat + * @param {string} [length='long'] - the length of the month representation, such as "numeric", "2-digit", "narrow", "short", "long" + * @param {Object} opts - options + * @param {string} [opts.locale] - the locale code + * @param {string} [opts.numberingSystem=null] - the numbering system + * @param {string} [opts.locObj=null] - an existing locale object to use + * @param {string} [opts.outputCalendar='gregory'] - the calendar + * @example Info.months()[0] //=> 'January' + * @example Info.months('short')[0] //=> 'Jan' + * @example Info.months('numeric')[0] //=> '1' + * @example Info.months('short', { locale: 'fr-CA' } )[0] //=> 'janv.' + * @example Info.months('numeric', { locale: 'ar' })[0] //=> '١' + * @example Info.months('long', { outputCalendar: 'islamic' })[0] //=> 'Rabiʻ I' + * @return {Array} + */ + ; + + Info.months = function months(length, _temp) { + if (length === void 0) { + length = "long"; + } + + var _ref = _temp === void 0 ? {} : _temp, + _ref$locale = _ref.locale, + locale = _ref$locale === void 0 ? null : _ref$locale, + _ref$numberingSystem = _ref.numberingSystem, + numberingSystem = _ref$numberingSystem === void 0 ? null : _ref$numberingSystem, + _ref$locObj = _ref.locObj, + locObj = _ref$locObj === void 0 ? null : _ref$locObj, + _ref$outputCalendar = _ref.outputCalendar, + outputCalendar = _ref$outputCalendar === void 0 ? "gregory" : _ref$outputCalendar; + + return (locObj || Locale.create(locale, numberingSystem, outputCalendar)).months(length); + } + /** + * Return an array of format month names. + * Format months differ from standalone months in that they're meant to appear next to the day of the month. In some languages, that + * changes the string. + * See {@link Info#months} + * @param {string} [length='long'] - the length of the month representation, such as "numeric", "2-digit", "narrow", "short", "long" + * @param {Object} opts - options + * @param {string} [opts.locale] - the locale code + * @param {string} [opts.numberingSystem=null] - the numbering system + * @param {string} [opts.locObj=null] - an existing locale object to use + * @param {string} [opts.outputCalendar='gregory'] - the calendar + * @return {Array} + */ + ; + + Info.monthsFormat = function monthsFormat(length, _temp2) { + if (length === void 0) { + length = "long"; + } + + var _ref2 = _temp2 === void 0 ? {} : _temp2, + _ref2$locale = _ref2.locale, + locale = _ref2$locale === void 0 ? null : _ref2$locale, + _ref2$numberingSystem = _ref2.numberingSystem, + numberingSystem = _ref2$numberingSystem === void 0 ? null : _ref2$numberingSystem, + _ref2$locObj = _ref2.locObj, + locObj = _ref2$locObj === void 0 ? null : _ref2$locObj, + _ref2$outputCalendar = _ref2.outputCalendar, + outputCalendar = _ref2$outputCalendar === void 0 ? "gregory" : _ref2$outputCalendar; + + return (locObj || Locale.create(locale, numberingSystem, outputCalendar)).months(length, true); + } + /** + * Return an array of standalone week names. + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat + * @param {string} [length='long'] - the length of the weekday representation, such as "narrow", "short", "long". + * @param {Object} opts - options + * @param {string} [opts.locale] - the locale code + * @param {string} [opts.numberingSystem=null] - the numbering system + * @param {string} [opts.locObj=null] - an existing locale object to use + * @example Info.weekdays()[0] //=> 'Monday' + * @example Info.weekdays('short')[0] //=> 'Mon' + * @example Info.weekdays('short', { locale: 'fr-CA' })[0] //=> 'lun.' + * @example Info.weekdays('short', { locale: 'ar' })[0] //=> 'الاثنين' + * @return {Array} + */ + ; + + Info.weekdays = function weekdays(length, _temp3) { + if (length === void 0) { + length = "long"; + } + + var _ref3 = _temp3 === void 0 ? {} : _temp3, + _ref3$locale = _ref3.locale, + locale = _ref3$locale === void 0 ? null : _ref3$locale, + _ref3$numberingSystem = _ref3.numberingSystem, + numberingSystem = _ref3$numberingSystem === void 0 ? null : _ref3$numberingSystem, + _ref3$locObj = _ref3.locObj, + locObj = _ref3$locObj === void 0 ? null : _ref3$locObj; + + return (locObj || Locale.create(locale, numberingSystem, null)).weekdays(length); + } + /** + * Return an array of format week names. + * Format weekdays differ from standalone weekdays in that they're meant to appear next to more date information. In some languages, that + * changes the string. + * See {@link Info#weekdays} + * @param {string} [length='long'] - the length of the month representation, such as "narrow", "short", "long". + * @param {Object} opts - options + * @param {string} [opts.locale=null] - the locale code + * @param {string} [opts.numberingSystem=null] - the numbering system + * @param {string} [opts.locObj=null] - an existing locale object to use + * @return {Array} + */ + ; + + Info.weekdaysFormat = function weekdaysFormat(length, _temp4) { + if (length === void 0) { + length = "long"; + } + + var _ref4 = _temp4 === void 0 ? {} : _temp4, + _ref4$locale = _ref4.locale, + locale = _ref4$locale === void 0 ? null : _ref4$locale, + _ref4$numberingSystem = _ref4.numberingSystem, + numberingSystem = _ref4$numberingSystem === void 0 ? null : _ref4$numberingSystem, + _ref4$locObj = _ref4.locObj, + locObj = _ref4$locObj === void 0 ? null : _ref4$locObj; + + return (locObj || Locale.create(locale, numberingSystem, null)).weekdays(length, true); + } + /** + * Return an array of meridiems. + * @param {Object} opts - options + * @param {string} [opts.locale] - the locale code + * @example Info.meridiems() //=> [ 'AM', 'PM' ] + * @example Info.meridiems({ locale: 'my' }) //=> [ 'နံနက်', 'ညနေ' ] + * @return {Array} + */ + ; + + Info.meridiems = function meridiems(_temp5) { + var _ref5 = _temp5 === void 0 ? {} : _temp5, + _ref5$locale = _ref5.locale, + locale = _ref5$locale === void 0 ? null : _ref5$locale; + + return Locale.create(locale).meridiems(); + } + /** + * Return an array of eras, such as ['BC', 'AD']. The locale can be specified, but the calendar system is always Gregorian. + * @param {string} [length='short'] - the length of the era representation, such as "short" or "long". + * @param {Object} opts - options + * @param {string} [opts.locale] - the locale code + * @example Info.eras() //=> [ 'BC', 'AD' ] + * @example Info.eras('long') //=> [ 'Before Christ', 'Anno Domini' ] + * @example Info.eras('long', { locale: 'fr' }) //=> [ 'avant Jésus-Christ', 'après Jésus-Christ' ] + * @return {Array} + */ + ; + + Info.eras = function eras(length, _temp6) { + if (length === void 0) { + length = "short"; + } + + var _ref6 = _temp6 === void 0 ? {} : _temp6, + _ref6$locale = _ref6.locale, + locale = _ref6$locale === void 0 ? null : _ref6$locale; + + return Locale.create(locale, null, "gregory").eras(length); + } + /** + * Return the set of available features in this environment. + * Some features of Luxon are not available in all environments. For example, on older browsers, relative time formatting support is not available. Use this function to figure out if that's the case. + * Keys: + * * `relative`: whether this environment supports relative time formatting + * @example Info.features() //=> { relative: false } + * @return {Object} + */ + ; + + Info.features = function features() { + return { + relative: hasRelative() + }; + }; + + return Info; + }(); + + function dayDiff(earlier, later) { + var utcDayStart = function utcDayStart(dt) { + return dt.toUTC(0, { + keepLocalTime: true + }).startOf("day").valueOf(); + }, + ms = utcDayStart(later) - utcDayStart(earlier); + + return Math.floor(Duration.fromMillis(ms).as("days")); + } + + function highOrderDiffs(cursor, later, units) { + var differs = [["years", function (a, b) { + return b.year - a.year; + }], ["quarters", function (a, b) { + return b.quarter - a.quarter; + }], ["months", function (a, b) { + return b.month - a.month + (b.year - a.year) * 12; + }], ["weeks", function (a, b) { + var days = dayDiff(a, b); + return (days - days % 7) / 7; + }], ["days", dayDiff]]; + var results = {}; + var lowestOrder, highWater; + + for (var _i = 0, _differs = differs; _i < _differs.length; _i++) { + var _differs$_i = _differs[_i], + unit = _differs$_i[0], + differ = _differs$_i[1]; + + if (units.indexOf(unit) >= 0) { + var _cursor$plus; + + lowestOrder = unit; + var delta = differ(cursor, later); + highWater = cursor.plus((_cursor$plus = {}, _cursor$plus[unit] = delta, _cursor$plus)); + + if (highWater > later) { + var _cursor$plus2; + + cursor = cursor.plus((_cursor$plus2 = {}, _cursor$plus2[unit] = delta - 1, _cursor$plus2)); + delta -= 1; + } else { + cursor = highWater; + } + + results[unit] = delta; + } + } + + return [cursor, results, highWater, lowestOrder]; + } + + function _diff (earlier, later, units, opts) { + var _highOrderDiffs = highOrderDiffs(earlier, later, units), + cursor = _highOrderDiffs[0], + results = _highOrderDiffs[1], + highWater = _highOrderDiffs[2], + lowestOrder = _highOrderDiffs[3]; + + var remainingMillis = later - cursor; + var lowerOrderUnits = units.filter(function (u) { + return ["hours", "minutes", "seconds", "milliseconds"].indexOf(u) >= 0; + }); + + if (lowerOrderUnits.length === 0) { + if (highWater < later) { + var _cursor$plus3; + + highWater = cursor.plus((_cursor$plus3 = {}, _cursor$plus3[lowestOrder] = 1, _cursor$plus3)); + } + + if (highWater !== cursor) { + results[lowestOrder] = (results[lowestOrder] || 0) + remainingMillis / (highWater - cursor); + } + } + + var duration = Duration.fromObject(results, opts); + + if (lowerOrderUnits.length > 0) { + var _Duration$fromMillis; + + return (_Duration$fromMillis = Duration.fromMillis(remainingMillis, opts)).shiftTo.apply(_Duration$fromMillis, lowerOrderUnits).plus(duration); + } else { + return duration; + } + } + + var numberingSystems = { + arab: "[\u0660-\u0669]", + arabext: "[\u06F0-\u06F9]", + bali: "[\u1B50-\u1B59]", + beng: "[\u09E6-\u09EF]", + deva: "[\u0966-\u096F]", + fullwide: "[\uFF10-\uFF19]", + gujr: "[\u0AE6-\u0AEF]", + hanidec: "[〇|一|二|三|四|五|六|七|八|九]", + khmr: "[\u17E0-\u17E9]", + knda: "[\u0CE6-\u0CEF]", + laoo: "[\u0ED0-\u0ED9]", + limb: "[\u1946-\u194F]", + mlym: "[\u0D66-\u0D6F]", + mong: "[\u1810-\u1819]", + mymr: "[\u1040-\u1049]", + orya: "[\u0B66-\u0B6F]", + tamldec: "[\u0BE6-\u0BEF]", + telu: "[\u0C66-\u0C6F]", + thai: "[\u0E50-\u0E59]", + tibt: "[\u0F20-\u0F29]", + latn: "\\d" + }; + var numberingSystemsUTF16 = { + arab: [1632, 1641], + arabext: [1776, 1785], + bali: [6992, 7001], + beng: [2534, 2543], + deva: [2406, 2415], + fullwide: [65296, 65303], + gujr: [2790, 2799], + khmr: [6112, 6121], + knda: [3302, 3311], + laoo: [3792, 3801], + limb: [6470, 6479], + mlym: [3430, 3439], + mong: [6160, 6169], + mymr: [4160, 4169], + orya: [2918, 2927], + tamldec: [3046, 3055], + telu: [3174, 3183], + thai: [3664, 3673], + tibt: [3872, 3881] + }; + var hanidecChars = numberingSystems.hanidec.replace(/[\[|\]]/g, "").split(""); + function parseDigits(str) { + var value = parseInt(str, 10); + + if (isNaN(value)) { + value = ""; + + for (var i = 0; i < str.length; i++) { + var code = str.charCodeAt(i); + + if (str[i].search(numberingSystems.hanidec) !== -1) { + value += hanidecChars.indexOf(str[i]); + } else { + for (var key in numberingSystemsUTF16) { + var _numberingSystemsUTF = numberingSystemsUTF16[key], + min = _numberingSystemsUTF[0], + max = _numberingSystemsUTF[1]; + + if (code >= min && code <= max) { + value += code - min; + } + } + } + } + + return parseInt(value, 10); + } else { + return value; + } + } + function digitRegex(_ref, append) { + var numberingSystem = _ref.numberingSystem; + + if (append === void 0) { + append = ""; + } + + return new RegExp("" + numberingSystems[numberingSystem || "latn"] + append); + } + + var MISSING_FTP = "missing Intl.DateTimeFormat.formatToParts support"; + + function intUnit(regex, post) { + if (post === void 0) { + post = function post(i) { + return i; + }; + } + + return { + regex: regex, + deser: function deser(_ref) { + var s = _ref[0]; + return post(parseDigits(s)); + } + }; + } + + var NBSP = String.fromCharCode(160); + var spaceOrNBSP = "( |" + NBSP + ")"; + var spaceOrNBSPRegExp = new RegExp(spaceOrNBSP, "g"); + + function fixListRegex(s) { + // make dots optional and also make them literal + // make space and non breakable space characters interchangeable + return s.replace(/\./g, "\\.?").replace(spaceOrNBSPRegExp, spaceOrNBSP); + } + + function stripInsensitivities(s) { + return s.replace(/\./g, "") // ignore dots that were made optional + .replace(spaceOrNBSPRegExp, " ") // interchange space and nbsp + .toLowerCase(); + } + + function oneOf(strings, startIndex) { + if (strings === null) { + return null; + } else { + return { + regex: RegExp(strings.map(fixListRegex).join("|")), + deser: function deser(_ref2) { + var s = _ref2[0]; + return strings.findIndex(function (i) { + return stripInsensitivities(s) === stripInsensitivities(i); + }) + startIndex; + } + }; + } + } + + function offset(regex, groups) { + return { + regex: regex, + deser: function deser(_ref3) { + var h = _ref3[1], + m = _ref3[2]; + return signedOffset(h, m); + }, + groups: groups + }; + } + + function simple(regex) { + return { + regex: regex, + deser: function deser(_ref4) { + var s = _ref4[0]; + return s; + } + }; + } + + function escapeToken(value) { + return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"); + } + + function unitForToken(token, loc) { + var one = digitRegex(loc), + two = digitRegex(loc, "{2}"), + three = digitRegex(loc, "{3}"), + four = digitRegex(loc, "{4}"), + six = digitRegex(loc, "{6}"), + oneOrTwo = digitRegex(loc, "{1,2}"), + oneToThree = digitRegex(loc, "{1,3}"), + oneToSix = digitRegex(loc, "{1,6}"), + oneToNine = digitRegex(loc, "{1,9}"), + twoToFour = digitRegex(loc, "{2,4}"), + fourToSix = digitRegex(loc, "{4,6}"), + literal = function literal(t) { + return { + regex: RegExp(escapeToken(t.val)), + deser: function deser(_ref5) { + var s = _ref5[0]; + return s; + }, + literal: true + }; + }, + unitate = function unitate(t) { + if (token.literal) { + return literal(t); + } + + switch (t.val) { + // era + case "G": + return oneOf(loc.eras("short", false), 0); + + case "GG": + return oneOf(loc.eras("long", false), 0); + // years + + case "y": + return intUnit(oneToSix); + + case "yy": + return intUnit(twoToFour, untruncateYear); + + case "yyyy": + return intUnit(four); + + case "yyyyy": + return intUnit(fourToSix); + + case "yyyyyy": + return intUnit(six); + // months + + case "M": + return intUnit(oneOrTwo); + + case "MM": + return intUnit(two); + + case "MMM": + return oneOf(loc.months("short", true, false), 1); + + case "MMMM": + return oneOf(loc.months("long", true, false), 1); + + case "L": + return intUnit(oneOrTwo); + + case "LL": + return intUnit(two); + + case "LLL": + return oneOf(loc.months("short", false, false), 1); + + case "LLLL": + return oneOf(loc.months("long", false, false), 1); + // dates + + case "d": + return intUnit(oneOrTwo); + + case "dd": + return intUnit(two); + // ordinals + + case "o": + return intUnit(oneToThree); + + case "ooo": + return intUnit(three); + // time + + case "HH": + return intUnit(two); + + case "H": + return intUnit(oneOrTwo); + + case "hh": + return intUnit(two); + + case "h": + return intUnit(oneOrTwo); + + case "mm": + return intUnit(two); + + case "m": + return intUnit(oneOrTwo); + + case "q": + return intUnit(oneOrTwo); + + case "qq": + return intUnit(two); + + case "s": + return intUnit(oneOrTwo); + + case "ss": + return intUnit(two); + + case "S": + return intUnit(oneToThree); + + case "SSS": + return intUnit(three); + + case "u": + return simple(oneToNine); + + case "uu": + return simple(oneOrTwo); + + case "uuu": + return intUnit(one); + // meridiem + + case "a": + return oneOf(loc.meridiems(), 0); + // weekYear (k) + + case "kkkk": + return intUnit(four); + + case "kk": + return intUnit(twoToFour, untruncateYear); + // weekNumber (W) + + case "W": + return intUnit(oneOrTwo); + + case "WW": + return intUnit(two); + // weekdays + + case "E": + case "c": + return intUnit(one); + + case "EEE": + return oneOf(loc.weekdays("short", false, false), 1); + + case "EEEE": + return oneOf(loc.weekdays("long", false, false), 1); + + case "ccc": + return oneOf(loc.weekdays("short", true, false), 1); + + case "cccc": + return oneOf(loc.weekdays("long", true, false), 1); + // offset/zone + + case "Z": + case "ZZ": + return offset(new RegExp("([+-]" + oneOrTwo.source + ")(?::(" + two.source + "))?"), 2); + + case "ZZZ": + return offset(new RegExp("([+-]" + oneOrTwo.source + ")(" + two.source + ")?"), 2); + // we don't support ZZZZ (PST) or ZZZZZ (Pacific Standard Time) in parsing + // because we don't have any way to figure out what they are + + case "z": + return simple(/[a-z_+-/]{1,256}?/i); + + default: + return literal(t); + } + }; + + var unit = unitate(token) || { + invalidReason: MISSING_FTP + }; + unit.token = token; + return unit; + } + + var partTypeStyleToTokenVal = { + year: { + "2-digit": "yy", + numeric: "yyyyy" + }, + month: { + numeric: "M", + "2-digit": "MM", + short: "MMM", + long: "MMMM" + }, + day: { + numeric: "d", + "2-digit": "dd" + }, + weekday: { + short: "EEE", + long: "EEEE" + }, + dayperiod: "a", + dayPeriod: "a", + hour: { + numeric: "h", + "2-digit": "hh" + }, + minute: { + numeric: "m", + "2-digit": "mm" + }, + second: { + numeric: "s", + "2-digit": "ss" + } + }; + + function tokenForPart(part, locale, formatOpts) { + var type = part.type, + value = part.value; + + if (type === "literal") { + return { + literal: true, + val: value + }; + } + + var style = formatOpts[type]; + var val = partTypeStyleToTokenVal[type]; + + if (typeof val === "object") { + val = val[style]; + } + + if (val) { + return { + literal: false, + val: val + }; + } + + return undefined; + } + + function buildRegex(units) { + var re = units.map(function (u) { + return u.regex; + }).reduce(function (f, r) { + return f + "(" + r.source + ")"; + }, ""); + return ["^" + re + "$", units]; + } + + function match(input, regex, handlers) { + var matches = input.match(regex); + + if (matches) { + var all = {}; + var matchIndex = 1; + + for (var i in handlers) { + if (hasOwnProperty(handlers, i)) { + var h = handlers[i], + groups = h.groups ? h.groups + 1 : 1; + + if (!h.literal && h.token) { + all[h.token.val[0]] = h.deser(matches.slice(matchIndex, matchIndex + groups)); + } + + matchIndex += groups; + } + } + + return [matches, all]; + } else { + return [matches, {}]; + } + } + + function dateTimeFromMatches(matches) { + var toField = function toField(token) { + switch (token) { + case "S": + return "millisecond"; + + case "s": + return "second"; + + case "m": + return "minute"; + + case "h": + case "H": + return "hour"; + + case "d": + return "day"; + + case "o": + return "ordinal"; + + case "L": + case "M": + return "month"; + + case "y": + return "year"; + + case "E": + case "c": + return "weekday"; + + case "W": + return "weekNumber"; + + case "k": + return "weekYear"; + + case "q": + return "quarter"; + + default: + return null; + } + }; + + var zone = null; + var specificOffset; + + if (!isUndefined(matches.z)) { + zone = IANAZone.create(matches.z); + } + + if (!isUndefined(matches.Z)) { + if (!zone) { + zone = new FixedOffsetZone(matches.Z); + } + + specificOffset = matches.Z; + } + + if (!isUndefined(matches.q)) { + matches.M = (matches.q - 1) * 3 + 1; + } + + if (!isUndefined(matches.h)) { + if (matches.h < 12 && matches.a === 1) { + matches.h += 12; + } else if (matches.h === 12 && matches.a === 0) { + matches.h = 0; + } + } + + if (matches.G === 0 && matches.y) { + matches.y = -matches.y; + } + + if (!isUndefined(matches.u)) { + matches.S = parseMillis(matches.u); + } + + var vals = Object.keys(matches).reduce(function (r, k) { + var f = toField(k); + + if (f) { + r[f] = matches[k]; + } + + return r; + }, {}); + return [vals, zone, specificOffset]; + } + + var dummyDateTimeCache = null; + + function getDummyDateTime() { + if (!dummyDateTimeCache) { + dummyDateTimeCache = DateTime.fromMillis(1555555555555); + } + + return dummyDateTimeCache; + } + + function maybeExpandMacroToken(token, locale) { + if (token.literal) { + return token; + } + + var formatOpts = Formatter.macroTokenToFormatOpts(token.val); + + if (!formatOpts) { + return token; + } + + var formatter = Formatter.create(locale, formatOpts); + var parts = formatter.formatDateTimeParts(getDummyDateTime()); + var tokens = parts.map(function (p) { + return tokenForPart(p, locale, formatOpts); + }); + + if (tokens.includes(undefined)) { + return token; + } + + return tokens; + } + + function expandMacroTokens(tokens, locale) { + var _Array$prototype; + + return (_Array$prototype = Array.prototype).concat.apply(_Array$prototype, tokens.map(function (t) { + return maybeExpandMacroToken(t, locale); + })); + } + /** + * @private + */ + + + function explainFromTokens(locale, input, format) { + var tokens = expandMacroTokens(Formatter.parseFormat(format), locale), + units = tokens.map(function (t) { + return unitForToken(t, locale); + }), + disqualifyingUnit = units.find(function (t) { + return t.invalidReason; + }); + + if (disqualifyingUnit) { + return { + input: input, + tokens: tokens, + invalidReason: disqualifyingUnit.invalidReason + }; + } else { + var _buildRegex = buildRegex(units), + regexString = _buildRegex[0], + handlers = _buildRegex[1], + regex = RegExp(regexString, "i"), + _match = match(input, regex, handlers), + rawMatches = _match[0], + matches = _match[1], + _ref6 = matches ? dateTimeFromMatches(matches) : [null, null, undefined], + result = _ref6[0], + zone = _ref6[1], + specificOffset = _ref6[2]; + + if (hasOwnProperty(matches, "a") && hasOwnProperty(matches, "H")) { + throw new ConflictingSpecificationError("Can't include meridiem when specifying 24-hour format"); + } + + return { + input: input, + tokens: tokens, + regex: regex, + rawMatches: rawMatches, + matches: matches, + result: result, + zone: zone, + specificOffset: specificOffset + }; + } + } + function parseFromTokens(locale, input, format) { + var _explainFromTokens = explainFromTokens(locale, input, format), + result = _explainFromTokens.result, + zone = _explainFromTokens.zone, + specificOffset = _explainFromTokens.specificOffset, + invalidReason = _explainFromTokens.invalidReason; + + return [result, zone, specificOffset, invalidReason]; + } + + var nonLeapLadder = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334], + leapLadder = [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335]; + + function unitOutOfRange(unit, value) { + return new Invalid("unit out of range", "you specified " + value + " (of type " + typeof value + ") as a " + unit + ", which is invalid"); + } + + function dayOfWeek(year, month, day) { + var js = new Date(Date.UTC(year, month - 1, day)).getUTCDay(); + return js === 0 ? 7 : js; + } + + function computeOrdinal(year, month, day) { + return day + (isLeapYear(year) ? leapLadder : nonLeapLadder)[month - 1]; + } + + function uncomputeOrdinal(year, ordinal) { + var table = isLeapYear(year) ? leapLadder : nonLeapLadder, + month0 = table.findIndex(function (i) { + return i < ordinal; + }), + day = ordinal - table[month0]; + return { + month: month0 + 1, + day: day + }; + } + /** + * @private + */ + + + function gregorianToWeek(gregObj) { + var year = gregObj.year, + month = gregObj.month, + day = gregObj.day, + ordinal = computeOrdinal(year, month, day), + weekday = dayOfWeek(year, month, day); + var weekNumber = Math.floor((ordinal - weekday + 10) / 7), + weekYear; + + if (weekNumber < 1) { + weekYear = year - 1; + weekNumber = weeksInWeekYear(weekYear); + } else if (weekNumber > weeksInWeekYear(year)) { + weekYear = year + 1; + weekNumber = 1; + } else { + weekYear = year; + } + + return _extends({ + weekYear: weekYear, + weekNumber: weekNumber, + weekday: weekday + }, timeObject(gregObj)); + } + function weekToGregorian(weekData) { + var weekYear = weekData.weekYear, + weekNumber = weekData.weekNumber, + weekday = weekData.weekday, + weekdayOfJan4 = dayOfWeek(weekYear, 1, 4), + yearInDays = daysInYear(weekYear); + var ordinal = weekNumber * 7 + weekday - weekdayOfJan4 - 3, + year; + + if (ordinal < 1) { + year = weekYear - 1; + ordinal += daysInYear(year); + } else if (ordinal > yearInDays) { + year = weekYear + 1; + ordinal -= daysInYear(weekYear); + } else { + year = weekYear; + } + + var _uncomputeOrdinal = uncomputeOrdinal(year, ordinal), + month = _uncomputeOrdinal.month, + day = _uncomputeOrdinal.day; + + return _extends({ + year: year, + month: month, + day: day + }, timeObject(weekData)); + } + function gregorianToOrdinal(gregData) { + var year = gregData.year, + month = gregData.month, + day = gregData.day; + var ordinal = computeOrdinal(year, month, day); + return _extends({ + year: year, + ordinal: ordinal + }, timeObject(gregData)); + } + function ordinalToGregorian(ordinalData) { + var year = ordinalData.year, + ordinal = ordinalData.ordinal; + + var _uncomputeOrdinal2 = uncomputeOrdinal(year, ordinal), + month = _uncomputeOrdinal2.month, + day = _uncomputeOrdinal2.day; + + return _extends({ + year: year, + month: month, + day: day + }, timeObject(ordinalData)); + } + function hasInvalidWeekData(obj) { + var validYear = isInteger(obj.weekYear), + validWeek = integerBetween(obj.weekNumber, 1, weeksInWeekYear(obj.weekYear)), + validWeekday = integerBetween(obj.weekday, 1, 7); + + if (!validYear) { + return unitOutOfRange("weekYear", obj.weekYear); + } else if (!validWeek) { + return unitOutOfRange("week", obj.week); + } else if (!validWeekday) { + return unitOutOfRange("weekday", obj.weekday); + } else return false; + } + function hasInvalidOrdinalData(obj) { + var validYear = isInteger(obj.year), + validOrdinal = integerBetween(obj.ordinal, 1, daysInYear(obj.year)); + + if (!validYear) { + return unitOutOfRange("year", obj.year); + } else if (!validOrdinal) { + return unitOutOfRange("ordinal", obj.ordinal); + } else return false; + } + function hasInvalidGregorianData(obj) { + var validYear = isInteger(obj.year), + validMonth = integerBetween(obj.month, 1, 12), + validDay = integerBetween(obj.day, 1, daysInMonth(obj.year, obj.month)); + + if (!validYear) { + return unitOutOfRange("year", obj.year); + } else if (!validMonth) { + return unitOutOfRange("month", obj.month); + } else if (!validDay) { + return unitOutOfRange("day", obj.day); + } else return false; + } + function hasInvalidTimeData(obj) { + var hour = obj.hour, + minute = obj.minute, + second = obj.second, + millisecond = obj.millisecond; + var validHour = integerBetween(hour, 0, 23) || hour === 24 && minute === 0 && second === 0 && millisecond === 0, + validMinute = integerBetween(minute, 0, 59), + validSecond = integerBetween(second, 0, 59), + validMillisecond = integerBetween(millisecond, 0, 999); + + if (!validHour) { + return unitOutOfRange("hour", hour); + } else if (!validMinute) { + return unitOutOfRange("minute", minute); + } else if (!validSecond) { + return unitOutOfRange("second", second); + } else if (!validMillisecond) { + return unitOutOfRange("millisecond", millisecond); + } else return false; + } + + var INVALID = "Invalid DateTime"; + var MAX_DATE = 8.64e15; + + function unsupportedZone(zone) { + return new Invalid("unsupported zone", "the zone \"" + zone.name + "\" is not supported"); + } // we cache week data on the DT object and this intermediates the cache + + + function possiblyCachedWeekData(dt) { + if (dt.weekData === null) { + dt.weekData = gregorianToWeek(dt.c); + } + + return dt.weekData; + } // clone really means, "make a new object with these modifications". all "setters" really use this + // to create a new object while only changing some of the properties + + + function clone(inst, alts) { + var current = { + ts: inst.ts, + zone: inst.zone, + c: inst.c, + o: inst.o, + loc: inst.loc, + invalid: inst.invalid + }; + return new DateTime(_extends({}, current, alts, { + old: current + })); + } // find the right offset a given local time. The o input is our guess, which determines which + // offset we'll pick in ambiguous cases (e.g. there are two 3 AMs b/c Fallback DST) + + + function fixOffset(localTS, o, tz) { + // Our UTC time is just a guess because our offset is just a guess + var utcGuess = localTS - o * 60 * 1000; // Test whether the zone matches the offset for this ts + + var o2 = tz.offset(utcGuess); // If so, offset didn't change and we're done + + if (o === o2) { + return [utcGuess, o]; + } // If not, change the ts by the difference in the offset + + + utcGuess -= (o2 - o) * 60 * 1000; // If that gives us the local time we want, we're done + + var o3 = tz.offset(utcGuess); + + if (o2 === o3) { + return [utcGuess, o2]; + } // If it's different, we're in a hole time. The offset has changed, but the we don't adjust the time + + + return [localTS - Math.min(o2, o3) * 60 * 1000, Math.max(o2, o3)]; + } // convert an epoch timestamp into a calendar object with the given offset + + + function tsToObj(ts, offset) { + ts += offset * 60 * 1000; + var d = new Date(ts); + return { + year: d.getUTCFullYear(), + month: d.getUTCMonth() + 1, + day: d.getUTCDate(), + hour: d.getUTCHours(), + minute: d.getUTCMinutes(), + second: d.getUTCSeconds(), + millisecond: d.getUTCMilliseconds() + }; + } // convert a calendar object to a epoch timestamp + + + function objToTS(obj, offset, zone) { + return fixOffset(objToLocalTS(obj), offset, zone); + } // create a new DT instance by adding a duration, adjusting for DSTs + + + function adjustTime(inst, dur) { + var oPre = inst.o, + year = inst.c.year + Math.trunc(dur.years), + month = inst.c.month + Math.trunc(dur.months) + Math.trunc(dur.quarters) * 3, + c = _extends({}, inst.c, { + year: year, + month: month, + day: Math.min(inst.c.day, daysInMonth(year, month)) + Math.trunc(dur.days) + Math.trunc(dur.weeks) * 7 + }), + millisToAdd = Duration.fromObject({ + years: dur.years - Math.trunc(dur.years), + quarters: dur.quarters - Math.trunc(dur.quarters), + months: dur.months - Math.trunc(dur.months), + weeks: dur.weeks - Math.trunc(dur.weeks), + days: dur.days - Math.trunc(dur.days), + hours: dur.hours, + minutes: dur.minutes, + seconds: dur.seconds, + milliseconds: dur.milliseconds + }).as("milliseconds"), + localTS = objToLocalTS(c); + + var _fixOffset = fixOffset(localTS, oPre, inst.zone), + ts = _fixOffset[0], + o = _fixOffset[1]; + + if (millisToAdd !== 0) { + ts += millisToAdd; // that could have changed the offset by going over a DST, but we want to keep the ts the same + + o = inst.zone.offset(ts); + } + + return { + ts: ts, + o: o + }; + } // helper useful in turning the results of parsing into real dates + // by handling the zone options + + + function parseDataToDateTime(parsed, parsedZone, opts, format, text, specificOffset) { + var setZone = opts.setZone, + zone = opts.zone; + + if (parsed && Object.keys(parsed).length !== 0) { + var interpretationZone = parsedZone || zone, + inst = DateTime.fromObject(parsed, _extends({}, opts, { + zone: interpretationZone, + specificOffset: specificOffset + })); + return setZone ? inst : inst.setZone(zone); + } else { + return DateTime.invalid(new Invalid("unparsable", "the input \"" + text + "\" can't be parsed as " + format)); + } + } // if you want to output a technical format (e.g. RFC 2822), this helper + // helps handle the details + + + function toTechFormat(dt, format, allowZ) { + if (allowZ === void 0) { + allowZ = true; + } + + return dt.isValid ? Formatter.create(Locale.create("en-US"), { + allowZ: allowZ, + forceSimple: true + }).formatDateTimeFromString(dt, format) : null; + } + + function _toISODate(o, extended) { + var longFormat = o.c.year > 9999 || o.c.year < 0; + var c = ""; + if (longFormat && o.c.year >= 0) c += "+"; + c += padStart(o.c.year, longFormat ? 6 : 4); + + if (extended) { + c += "-"; + c += padStart(o.c.month); + c += "-"; + c += padStart(o.c.day); + } else { + c += padStart(o.c.month); + c += padStart(o.c.day); + } + + return c; + } + + function _toISOTime(o, extended, suppressSeconds, suppressMilliseconds, includeOffset) { + var c = padStart(o.c.hour); + + if (extended) { + c += ":"; + c += padStart(o.c.minute); + + if (o.c.second !== 0 || !suppressSeconds) { + c += ":"; + } + } else { + c += padStart(o.c.minute); + } + + if (o.c.second !== 0 || !suppressSeconds) { + c += padStart(o.c.second); + + if (o.c.millisecond !== 0 || !suppressMilliseconds) { + c += "."; + c += padStart(o.c.millisecond, 3); + } + } + + if (includeOffset) { + if (o.isOffsetFixed && o.offset === 0) { + c += "Z"; + } else if (o.o < 0) { + c += "-"; + c += padStart(Math.trunc(-o.o / 60)); + c += ":"; + c += padStart(Math.trunc(-o.o % 60)); + } else { + c += "+"; + c += padStart(Math.trunc(o.o / 60)); + c += ":"; + c += padStart(Math.trunc(o.o % 60)); + } + } + + return c; + } // defaults for unspecified units in the supported calendars + + + var defaultUnitValues = { + month: 1, + day: 1, + hour: 0, + minute: 0, + second: 0, + millisecond: 0 + }, + defaultWeekUnitValues = { + weekNumber: 1, + weekday: 1, + hour: 0, + minute: 0, + second: 0, + millisecond: 0 + }, + defaultOrdinalUnitValues = { + ordinal: 1, + hour: 0, + minute: 0, + second: 0, + millisecond: 0 + }; // Units in the supported calendars, sorted by bigness + + var orderedUnits = ["year", "month", "day", "hour", "minute", "second", "millisecond"], + orderedWeekUnits = ["weekYear", "weekNumber", "weekday", "hour", "minute", "second", "millisecond"], + orderedOrdinalUnits = ["year", "ordinal", "hour", "minute", "second", "millisecond"]; // standardize case and plurality in units + + function normalizeUnit(unit) { + var normalized = { + year: "year", + years: "year", + month: "month", + months: "month", + day: "day", + days: "day", + hour: "hour", + hours: "hour", + minute: "minute", + minutes: "minute", + quarter: "quarter", + quarters: "quarter", + second: "second", + seconds: "second", + millisecond: "millisecond", + milliseconds: "millisecond", + weekday: "weekday", + weekdays: "weekday", + weeknumber: "weekNumber", + weeksnumber: "weekNumber", + weeknumbers: "weekNumber", + weekyear: "weekYear", + weekyears: "weekYear", + ordinal: "ordinal" + }[unit.toLowerCase()]; + if (!normalized) throw new InvalidUnitError(unit); + return normalized; + } // this is a dumbed down version of fromObject() that runs about 60% faster + // but doesn't do any validation, makes a bunch of assumptions about what units + // are present, and so on. + // this is a dumbed down version of fromObject() that runs about 60% faster + // but doesn't do any validation, makes a bunch of assumptions about what units + // are present, and so on. + + + function quickDT(obj, opts) { + var zone = normalizeZone(opts.zone, Settings.defaultZone), + loc = Locale.fromObject(opts), + tsNow = Settings.now(); + var ts, o; // assume we have the higher-order units + + if (!isUndefined(obj.year)) { + for (var _iterator = _createForOfIteratorHelperLoose(orderedUnits), _step; !(_step = _iterator()).done;) { + var u = _step.value; + + if (isUndefined(obj[u])) { + obj[u] = defaultUnitValues[u]; + } + } + + var invalid = hasInvalidGregorianData(obj) || hasInvalidTimeData(obj); + + if (invalid) { + return DateTime.invalid(invalid); + } + + var offsetProvis = zone.offset(tsNow); + + var _objToTS = objToTS(obj, offsetProvis, zone); + + ts = _objToTS[0]; + o = _objToTS[1]; + } else { + ts = tsNow; + } + + return new DateTime({ + ts: ts, + zone: zone, + loc: loc, + o: o + }); + } + + function diffRelative(start, end, opts) { + var round = isUndefined(opts.round) ? true : opts.round, + format = function format(c, unit) { + c = roundTo(c, round || opts.calendary ? 0 : 2, true); + var formatter = end.loc.clone(opts).relFormatter(opts); + return formatter.format(c, unit); + }, + differ = function differ(unit) { + if (opts.calendary) { + if (!end.hasSame(start, unit)) { + return end.startOf(unit).diff(start.startOf(unit), unit).get(unit); + } else return 0; + } else { + return end.diff(start, unit).get(unit); + } + }; + + if (opts.unit) { + return format(differ(opts.unit), opts.unit); + } + + for (var _iterator2 = _createForOfIteratorHelperLoose(opts.units), _step2; !(_step2 = _iterator2()).done;) { + var unit = _step2.value; + var count = differ(unit); + + if (Math.abs(count) >= 1) { + return format(count, unit); + } + } + + return format(start > end ? -0 : 0, opts.units[opts.units.length - 1]); + } + + function lastOpts(argList) { + var opts = {}, + args; + + if (argList.length > 0 && typeof argList[argList.length - 1] === "object") { + opts = argList[argList.length - 1]; + args = Array.from(argList).slice(0, argList.length - 1); + } else { + args = Array.from(argList); + } + + return [opts, args]; + } + /** + * A DateTime is an immutable data structure representing a specific date and time and accompanying methods. It contains class and instance methods for creating, parsing, interrogating, transforming, and formatting them. + * + * A DateTime comprises of: + * * A timestamp. Each DateTime instance refers to a specific millisecond of the Unix epoch. + * * A time zone. Each instance is considered in the context of a specific zone (by default the local system's zone). + * * Configuration properties that effect how output strings are formatted, such as `locale`, `numberingSystem`, and `outputCalendar`. + * + * Here is a brief overview of the most commonly used functionality it provides: + * + * * **Creation**: To create a DateTime from its components, use one of its factory class methods: {@link DateTime#local}, {@link DateTime#utc}, and (most flexibly) {@link DateTime#fromObject}. To create one from a standard string format, use {@link DateTime#fromISO}, {@link DateTime#fromHTTP}, and {@link DateTime#fromRFC2822}. To create one from a custom string format, use {@link DateTime#fromFormat}. To create one from a native JS date, use {@link DateTime#fromJSDate}. + * * **Gregorian calendar and time**: To examine the Gregorian properties of a DateTime individually (i.e as opposed to collectively through {@link DateTime#toObject}), use the {@link DateTime#year}, {@link DateTime#month}, + * {@link DateTime#day}, {@link DateTime#hour}, {@link DateTime#minute}, {@link DateTime#second}, {@link DateTime#millisecond} accessors. + * * **Week calendar**: For ISO week calendar attributes, see the {@link DateTime#weekYear}, {@link DateTime#weekNumber}, and {@link DateTime#weekday} accessors. + * * **Configuration** See the {@link DateTime#locale} and {@link DateTime#numberingSystem} accessors. + * * **Transformation**: To transform the DateTime into other DateTimes, use {@link DateTime#set}, {@link DateTime#reconfigure}, {@link DateTime#setZone}, {@link DateTime#setLocale}, {@link DateTime.plus}, {@link DateTime#minus}, {@link DateTime#endOf}, {@link DateTime#startOf}, {@link DateTime#toUTC}, and {@link DateTime#toLocal}. + * * **Output**: To convert the DateTime to other representations, use the {@link DateTime#toRelative}, {@link DateTime#toRelativeCalendar}, {@link DateTime#toJSON}, {@link DateTime#toISO}, {@link DateTime#toHTTP}, {@link DateTime#toObject}, {@link DateTime#toRFC2822}, {@link DateTime#toString}, {@link DateTime#toLocaleString}, {@link DateTime#toFormat}, {@link DateTime#toMillis} and {@link DateTime#toJSDate}. + * + * There's plenty others documented below. In addition, for more information on subtler topics like internationalization, time zones, alternative calendars, validity, and so on, see the external documentation. + */ + + + var DateTime = /*#__PURE__*/function () { + /** + * @access private + */ + function DateTime(config) { + var zone = config.zone || Settings.defaultZone; + var invalid = config.invalid || (Number.isNaN(config.ts) ? new Invalid("invalid input") : null) || (!zone.isValid ? unsupportedZone(zone) : null); + /** + * @access private + */ + + this.ts = isUndefined(config.ts) ? Settings.now() : config.ts; + var c = null, + o = null; + + if (!invalid) { + var unchanged = config.old && config.old.ts === this.ts && config.old.zone.equals(zone); + + if (unchanged) { + var _ref = [config.old.c, config.old.o]; + c = _ref[0]; + o = _ref[1]; + } else { + var ot = zone.offset(this.ts); + c = tsToObj(this.ts, ot); + invalid = Number.isNaN(c.year) ? new Invalid("invalid input") : null; + c = invalid ? null : c; + o = invalid ? null : ot; + } + } + /** + * @access private + */ + + + this._zone = zone; + /** + * @access private + */ + + this.loc = config.loc || Locale.create(); + /** + * @access private + */ + + this.invalid = invalid; + /** + * @access private + */ + + this.weekData = null; + /** + * @access private + */ + + this.c = c; + /** + * @access private + */ + + this.o = o; + /** + * @access private + */ + + this.isLuxonDateTime = true; + } // CONSTRUCT + + /** + * Create a DateTime for the current instant, in the system's time zone. + * + * Use Settings to override these default values if needed. + * @example DateTime.now().toISO() //~> now in the ISO format + * @return {DateTime} + */ + + + DateTime.now = function now() { + return new DateTime({}); + } + /** + * Create a local DateTime + * @param {number} [year] - The calendar year. If omitted (as in, call `local()` with no arguments), the current time will be used + * @param {number} [month=1] - The month, 1-indexed + * @param {number} [day=1] - The day of the month, 1-indexed + * @param {number} [hour=0] - The hour of the day, in 24-hour time + * @param {number} [minute=0] - The minute of the hour, meaning a number between 0 and 59 + * @param {number} [second=0] - The second of the minute, meaning a number between 0 and 59 + * @param {number} [millisecond=0] - The millisecond of the second, meaning a number between 0 and 999 + * @example DateTime.local() //~> now + * @example DateTime.local({ zone: "America/New_York" }) //~> now, in US east coast time + * @example DateTime.local(2017) //~> 2017-01-01T00:00:00 + * @example DateTime.local(2017, 3) //~> 2017-03-01T00:00:00 + * @example DateTime.local(2017, 3, 12, { locale: "fr" }) //~> 2017-03-12T00:00:00, with a French locale + * @example DateTime.local(2017, 3, 12, 5) //~> 2017-03-12T05:00:00 + * @example DateTime.local(2017, 3, 12, 5, { zone: "utc" }) //~> 2017-03-12T05:00:00, in UTC + * @example DateTime.local(2017, 3, 12, 5, 45) //~> 2017-03-12T05:45:00 + * @example DateTime.local(2017, 3, 12, 5, 45, 10) //~> 2017-03-12T05:45:10 + * @example DateTime.local(2017, 3, 12, 5, 45, 10, 765) //~> 2017-03-12T05:45:10.765 + * @return {DateTime} + */ + ; + + DateTime.local = function local() { + var _lastOpts = lastOpts(arguments), + opts = _lastOpts[0], + args = _lastOpts[1], + year = args[0], + month = args[1], + day = args[2], + hour = args[3], + minute = args[4], + second = args[5], + millisecond = args[6]; + + return quickDT({ + year: year, + month: month, + day: day, + hour: hour, + minute: minute, + second: second, + millisecond: millisecond + }, opts); + } + /** + * Create a DateTime in UTC + * @param {number} [year] - The calendar year. If omitted (as in, call `utc()` with no arguments), the current time will be used + * @param {number} [month=1] - The month, 1-indexed + * @param {number} [day=1] - The day of the month + * @param {number} [hour=0] - The hour of the day, in 24-hour time + * @param {number} [minute=0] - The minute of the hour, meaning a number between 0 and 59 + * @param {number} [second=0] - The second of the minute, meaning a number between 0 and 59 + * @param {number} [millisecond=0] - The millisecond of the second, meaning a number between 0 and 999 + * @param {Object} options - configuration options for the DateTime + * @param {string} [options.locale] - a locale to set on the resulting DateTime instance + * @param {string} [options.outputCalendar] - the output calendar to set on the resulting DateTime instance + * @param {string} [options.numberingSystem] - the numbering system to set on the resulting DateTime instance + * @example DateTime.utc() //~> now + * @example DateTime.utc(2017) //~> 2017-01-01T00:00:00Z + * @example DateTime.utc(2017, 3) //~> 2017-03-01T00:00:00Z + * @example DateTime.utc(2017, 3, 12) //~> 2017-03-12T00:00:00Z + * @example DateTime.utc(2017, 3, 12, 5) //~> 2017-03-12T05:00:00Z + * @example DateTime.utc(2017, 3, 12, 5, 45) //~> 2017-03-12T05:45:00Z + * @example DateTime.utc(2017, 3, 12, 5, 45, { locale: "fr" }) //~> 2017-03-12T05:45:00Z with a French locale + * @example DateTime.utc(2017, 3, 12, 5, 45, 10) //~> 2017-03-12T05:45:10Z + * @example DateTime.utc(2017, 3, 12, 5, 45, 10, 765, { locale: "fr" }) //~> 2017-03-12T05:45:10.765Z with a French locale + * @return {DateTime} + */ + ; + + DateTime.utc = function utc() { + var _lastOpts2 = lastOpts(arguments), + opts = _lastOpts2[0], + args = _lastOpts2[1], + year = args[0], + month = args[1], + day = args[2], + hour = args[3], + minute = args[4], + second = args[5], + millisecond = args[6]; + + opts.zone = FixedOffsetZone.utcInstance; + return quickDT({ + year: year, + month: month, + day: day, + hour: hour, + minute: minute, + second: second, + millisecond: millisecond + }, opts); + } + /** + * Create a DateTime from a JavaScript Date object. Uses the default zone. + * @param {Date} date - a JavaScript Date object + * @param {Object} options - configuration options for the DateTime + * @param {string|Zone} [options.zone='local'] - the zone to place the DateTime into + * @return {DateTime} + */ + ; + + DateTime.fromJSDate = function fromJSDate(date, options) { + if (options === void 0) { + options = {}; + } + + var ts = isDate(date) ? date.valueOf() : NaN; + + if (Number.isNaN(ts)) { + return DateTime.invalid("invalid input"); + } + + var zoneToUse = normalizeZone(options.zone, Settings.defaultZone); + + if (!zoneToUse.isValid) { + return DateTime.invalid(unsupportedZone(zoneToUse)); + } + + return new DateTime({ + ts: ts, + zone: zoneToUse, + loc: Locale.fromObject(options) + }); + } + /** + * Create a DateTime from a number of milliseconds since the epoch (meaning since 1 January 1970 00:00:00 UTC). Uses the default zone. + * @param {number} milliseconds - a number of milliseconds since 1970 UTC + * @param {Object} options - configuration options for the DateTime + * @param {string|Zone} [options.zone='local'] - the zone to place the DateTime into + * @param {string} [options.locale] - a locale to set on the resulting DateTime instance + * @param {string} options.outputCalendar - the output calendar to set on the resulting DateTime instance + * @param {string} options.numberingSystem - the numbering system to set on the resulting DateTime instance + * @return {DateTime} + */ + ; + + DateTime.fromMillis = function fromMillis(milliseconds, options) { + if (options === void 0) { + options = {}; + } + + if (!isNumber(milliseconds)) { + throw new InvalidArgumentError("fromMillis requires a numerical input, but received a " + typeof milliseconds + " with value " + milliseconds); + } else if (milliseconds < -MAX_DATE || milliseconds > MAX_DATE) { + // this isn't perfect because because we can still end up out of range because of additional shifting, but it's a start + return DateTime.invalid("Timestamp out of range"); + } else { + return new DateTime({ + ts: milliseconds, + zone: normalizeZone(options.zone, Settings.defaultZone), + loc: Locale.fromObject(options) + }); + } + } + /** + * Create a DateTime from a number of seconds since the epoch (meaning since 1 January 1970 00:00:00 UTC). Uses the default zone. + * @param {number} seconds - a number of seconds since 1970 UTC + * @param {Object} options - configuration options for the DateTime + * @param {string|Zone} [options.zone='local'] - the zone to place the DateTime into + * @param {string} [options.locale] - a locale to set on the resulting DateTime instance + * @param {string} options.outputCalendar - the output calendar to set on the resulting DateTime instance + * @param {string} options.numberingSystem - the numbering system to set on the resulting DateTime instance + * @return {DateTime} + */ + ; + + DateTime.fromSeconds = function fromSeconds(seconds, options) { + if (options === void 0) { + options = {}; + } + + if (!isNumber(seconds)) { + throw new InvalidArgumentError("fromSeconds requires a numerical input"); + } else { + return new DateTime({ + ts: seconds * 1000, + zone: normalizeZone(options.zone, Settings.defaultZone), + loc: Locale.fromObject(options) + }); + } + } + /** + * Create a DateTime from a JavaScript object with keys like 'year' and 'hour' with reasonable defaults. + * @param {Object} obj - the object to create the DateTime from + * @param {number} obj.year - a year, such as 1987 + * @param {number} obj.month - a month, 1-12 + * @param {number} obj.day - a day of the month, 1-31, depending on the month + * @param {number} obj.ordinal - day of the year, 1-365 or 366 + * @param {number} obj.weekYear - an ISO week year + * @param {number} obj.weekNumber - an ISO week number, between 1 and 52 or 53, depending on the year + * @param {number} obj.weekday - an ISO weekday, 1-7, where 1 is Monday and 7 is Sunday + * @param {number} obj.hour - hour of the day, 0-23 + * @param {number} obj.minute - minute of the hour, 0-59 + * @param {number} obj.second - second of the minute, 0-59 + * @param {number} obj.millisecond - millisecond of the second, 0-999 + * @param {Object} opts - options for creating this DateTime + * @param {string|Zone} [opts.zone='local'] - interpret the numbers in the context of a particular zone. Can take any value taken as the first argument to setZone() + * @param {string} [opts.locale='system's locale'] - a locale to set on the resulting DateTime instance + * @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance + * @param {string} opts.numberingSystem - the numbering system to set on the resulting DateTime instance + * @example DateTime.fromObject({ year: 1982, month: 5, day: 25}).toISODate() //=> '1982-05-25' + * @example DateTime.fromObject({ year: 1982 }).toISODate() //=> '1982-01-01' + * @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }) //~> today at 10:26:06 + * @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }, { zone: 'utc' }), + * @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }, { zone: 'local' }) + * @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }, { zone: 'America/New_York' }) + * @example DateTime.fromObject({ weekYear: 2016, weekNumber: 2, weekday: 3 }).toISODate() //=> '2016-01-13' + * @return {DateTime} + */ + ; + + DateTime.fromObject = function fromObject(obj, opts) { + if (opts === void 0) { + opts = {}; + } + + obj = obj || {}; + var zoneToUse = normalizeZone(opts.zone, Settings.defaultZone); + + if (!zoneToUse.isValid) { + return DateTime.invalid(unsupportedZone(zoneToUse)); + } + + var tsNow = Settings.now(), + offsetProvis = !isUndefined(opts.specificOffset) ? opts.specificOffset : zoneToUse.offset(tsNow), + normalized = normalizeObject(obj, normalizeUnit), + containsOrdinal = !isUndefined(normalized.ordinal), + containsGregorYear = !isUndefined(normalized.year), + containsGregorMD = !isUndefined(normalized.month) || !isUndefined(normalized.day), + containsGregor = containsGregorYear || containsGregorMD, + definiteWeekDef = normalized.weekYear || normalized.weekNumber, + loc = Locale.fromObject(opts); // cases: + // just a weekday -> this week's instance of that weekday, no worries + // (gregorian data or ordinal) + (weekYear or weekNumber) -> error + // (gregorian month or day) + ordinal -> error + // otherwise just use weeks or ordinals or gregorian, depending on what's specified + + if ((containsGregor || containsOrdinal) && definiteWeekDef) { + throw new ConflictingSpecificationError("Can't mix weekYear/weekNumber units with year/month/day or ordinals"); + } + + if (containsGregorMD && containsOrdinal) { + throw new ConflictingSpecificationError("Can't mix ordinal dates with month/day"); + } + + var useWeekData = definiteWeekDef || normalized.weekday && !containsGregor; // configure ourselves to deal with gregorian dates or week stuff + + var units, + defaultValues, + objNow = tsToObj(tsNow, offsetProvis); + + if (useWeekData) { + units = orderedWeekUnits; + defaultValues = defaultWeekUnitValues; + objNow = gregorianToWeek(objNow); + } else if (containsOrdinal) { + units = orderedOrdinalUnits; + defaultValues = defaultOrdinalUnitValues; + objNow = gregorianToOrdinal(objNow); + } else { + units = orderedUnits; + defaultValues = defaultUnitValues; + } // set default values for missing stuff + + + var foundFirst = false; + + for (var _iterator3 = _createForOfIteratorHelperLoose(units), _step3; !(_step3 = _iterator3()).done;) { + var u = _step3.value; + var v = normalized[u]; + + if (!isUndefined(v)) { + foundFirst = true; + } else if (foundFirst) { + normalized[u] = defaultValues[u]; + } else { + normalized[u] = objNow[u]; + } + } // make sure the values we have are in range + + + var higherOrderInvalid = useWeekData ? hasInvalidWeekData(normalized) : containsOrdinal ? hasInvalidOrdinalData(normalized) : hasInvalidGregorianData(normalized), + invalid = higherOrderInvalid || hasInvalidTimeData(normalized); + + if (invalid) { + return DateTime.invalid(invalid); + } // compute the actual time + + + var gregorian = useWeekData ? weekToGregorian(normalized) : containsOrdinal ? ordinalToGregorian(normalized) : normalized, + _objToTS2 = objToTS(gregorian, offsetProvis, zoneToUse), + tsFinal = _objToTS2[0], + offsetFinal = _objToTS2[1], + inst = new DateTime({ + ts: tsFinal, + zone: zoneToUse, + o: offsetFinal, + loc: loc + }); // gregorian data + weekday serves only to validate + + + if (normalized.weekday && containsGregor && obj.weekday !== inst.weekday) { + return DateTime.invalid("mismatched weekday", "you can't specify both a weekday of " + normalized.weekday + " and a date of " + inst.toISO()); + } + + return inst; + } + /** + * Create a DateTime from an ISO 8601 string + * @param {string} text - the ISO string + * @param {Object} opts - options to affect the creation + * @param {string|Zone} [opts.zone='local'] - use this zone if no offset is specified in the input string itself. Will also convert the time to this zone + * @param {boolean} [opts.setZone=false] - override the zone with a fixed-offset zone specified in the string itself, if it specifies one + * @param {string} [opts.locale='system's locale'] - a locale to set on the resulting DateTime instance + * @param {string} [opts.outputCalendar] - the output calendar to set on the resulting DateTime instance + * @param {string} [opts.numberingSystem] - the numbering system to set on the resulting DateTime instance + * @example DateTime.fromISO('2016-05-25T09:08:34.123') + * @example DateTime.fromISO('2016-05-25T09:08:34.123+06:00') + * @example DateTime.fromISO('2016-05-25T09:08:34.123+06:00', {setZone: true}) + * @example DateTime.fromISO('2016-05-25T09:08:34.123', {zone: 'utc'}) + * @example DateTime.fromISO('2016-W05-4') + * @return {DateTime} + */ + ; + + DateTime.fromISO = function fromISO(text, opts) { + if (opts === void 0) { + opts = {}; + } + + var _parseISODate = parseISODate(text), + vals = _parseISODate[0], + parsedZone = _parseISODate[1]; + + return parseDataToDateTime(vals, parsedZone, opts, "ISO 8601", text); + } + /** + * Create a DateTime from an RFC 2822 string + * @param {string} text - the RFC 2822 string + * @param {Object} opts - options to affect the creation + * @param {string|Zone} [opts.zone='local'] - convert the time to this zone. Since the offset is always specified in the string itself, this has no effect on the interpretation of string, merely the zone the resulting DateTime is expressed in. + * @param {boolean} [opts.setZone=false] - override the zone with a fixed-offset zone specified in the string itself, if it specifies one + * @param {string} [opts.locale='system's locale'] - a locale to set on the resulting DateTime instance + * @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance + * @param {string} opts.numberingSystem - the numbering system to set on the resulting DateTime instance + * @example DateTime.fromRFC2822('25 Nov 2016 13:23:12 GMT') + * @example DateTime.fromRFC2822('Fri, 25 Nov 2016 13:23:12 +0600') + * @example DateTime.fromRFC2822('25 Nov 2016 13:23 Z') + * @return {DateTime} + */ + ; + + DateTime.fromRFC2822 = function fromRFC2822(text, opts) { + if (opts === void 0) { + opts = {}; + } + + var _parseRFC2822Date = parseRFC2822Date(text), + vals = _parseRFC2822Date[0], + parsedZone = _parseRFC2822Date[1]; + + return parseDataToDateTime(vals, parsedZone, opts, "RFC 2822", text); + } + /** + * Create a DateTime from an HTTP header date + * @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1 + * @param {string} text - the HTTP header date + * @param {Object} opts - options to affect the creation + * @param {string|Zone} [opts.zone='local'] - convert the time to this zone. Since HTTP dates are always in UTC, this has no effect on the interpretation of string, merely the zone the resulting DateTime is expressed in. + * @param {boolean} [opts.setZone=false] - override the zone with the fixed-offset zone specified in the string. For HTTP dates, this is always UTC, so this option is equivalent to setting the `zone` option to 'utc', but this option is included for consistency with similar methods. + * @param {string} [opts.locale='system's locale'] - a locale to set on the resulting DateTime instance + * @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance + * @param {string} opts.numberingSystem - the numbering system to set on the resulting DateTime instance + * @example DateTime.fromHTTP('Sun, 06 Nov 1994 08:49:37 GMT') + * @example DateTime.fromHTTP('Sunday, 06-Nov-94 08:49:37 GMT') + * @example DateTime.fromHTTP('Sun Nov 6 08:49:37 1994') + * @return {DateTime} + */ + ; + + DateTime.fromHTTP = function fromHTTP(text, opts) { + if (opts === void 0) { + opts = {}; + } + + var _parseHTTPDate = parseHTTPDate(text), + vals = _parseHTTPDate[0], + parsedZone = _parseHTTPDate[1]; + + return parseDataToDateTime(vals, parsedZone, opts, "HTTP", opts); + } + /** + * Create a DateTime from an input string and format string. + * Defaults to en-US if no locale has been specified, regardless of the system's locale. For a table of tokens and their interpretations, see [here](https://moment.github.io/luxon/#/parsing?id=table-of-tokens). + * @param {string} text - the string to parse + * @param {string} fmt - the format the string is expected to be in (see the link below for the formats) + * @param {Object} opts - options to affect the creation + * @param {string|Zone} [opts.zone='local'] - use this zone if no offset is specified in the input string itself. Will also convert the DateTime to this zone + * @param {boolean} [opts.setZone=false] - override the zone with a zone specified in the string itself, if it specifies one + * @param {string} [opts.locale='en-US'] - a locale string to use when parsing. Will also set the DateTime to this locale + * @param {string} opts.numberingSystem - the numbering system to use when parsing. Will also set the resulting DateTime to this numbering system + * @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance + * @return {DateTime} + */ + ; + + DateTime.fromFormat = function fromFormat(text, fmt, opts) { + if (opts === void 0) { + opts = {}; + } + + if (isUndefined(text) || isUndefined(fmt)) { + throw new InvalidArgumentError("fromFormat requires an input string and a format"); + } + + var _opts = opts, + _opts$locale = _opts.locale, + locale = _opts$locale === void 0 ? null : _opts$locale, + _opts$numberingSystem = _opts.numberingSystem, + numberingSystem = _opts$numberingSystem === void 0 ? null : _opts$numberingSystem, + localeToUse = Locale.fromOpts({ + locale: locale, + numberingSystem: numberingSystem, + defaultToEN: true + }), + _parseFromTokens = parseFromTokens(localeToUse, text, fmt), + vals = _parseFromTokens[0], + parsedZone = _parseFromTokens[1], + specificOffset = _parseFromTokens[2], + invalid = _parseFromTokens[3]; + + if (invalid) { + return DateTime.invalid(invalid); + } else { + return parseDataToDateTime(vals, parsedZone, opts, "format " + fmt, text, specificOffset); + } + } + /** + * @deprecated use fromFormat instead + */ + ; + + DateTime.fromString = function fromString(text, fmt, opts) { + if (opts === void 0) { + opts = {}; + } + + return DateTime.fromFormat(text, fmt, opts); + } + /** + * Create a DateTime from a SQL date, time, or datetime + * Defaults to en-US if no locale has been specified, regardless of the system's locale + * @param {string} text - the string to parse + * @param {Object} opts - options to affect the creation + * @param {string|Zone} [opts.zone='local'] - use this zone if no offset is specified in the input string itself. Will also convert the DateTime to this zone + * @param {boolean} [opts.setZone=false] - override the zone with a zone specified in the string itself, if it specifies one + * @param {string} [opts.locale='en-US'] - a locale string to use when parsing. Will also set the DateTime to this locale + * @param {string} opts.numberingSystem - the numbering system to use when parsing. Will also set the resulting DateTime to this numbering system + * @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance + * @example DateTime.fromSQL('2017-05-15') + * @example DateTime.fromSQL('2017-05-15 09:12:34') + * @example DateTime.fromSQL('2017-05-15 09:12:34.342') + * @example DateTime.fromSQL('2017-05-15 09:12:34.342+06:00') + * @example DateTime.fromSQL('2017-05-15 09:12:34.342 America/Los_Angeles') + * @example DateTime.fromSQL('2017-05-15 09:12:34.342 America/Los_Angeles', { setZone: true }) + * @example DateTime.fromSQL('2017-05-15 09:12:34.342', { zone: 'America/Los_Angeles' }) + * @example DateTime.fromSQL('09:12:34.342') + * @return {DateTime} + */ + ; + + DateTime.fromSQL = function fromSQL(text, opts) { + if (opts === void 0) { + opts = {}; + } + + var _parseSQL = parseSQL(text), + vals = _parseSQL[0], + parsedZone = _parseSQL[1]; + + return parseDataToDateTime(vals, parsedZone, opts, "SQL", text); + } + /** + * Create an invalid DateTime. + * @param {string} reason - simple string of why this DateTime is invalid. Should not contain parameters or anything else data-dependent + * @param {string} [explanation=null] - longer explanation, may include parameters and other useful debugging information + * @return {DateTime} + */ + ; + + DateTime.invalid = function invalid(reason, explanation) { + if (explanation === void 0) { + explanation = null; + } + + if (!reason) { + throw new InvalidArgumentError("need to specify a reason the DateTime is invalid"); + } + + var invalid = reason instanceof Invalid ? reason : new Invalid(reason, explanation); + + if (Settings.throwOnInvalid) { + throw new InvalidDateTimeError(invalid); + } else { + return new DateTime({ + invalid: invalid + }); + } + } + /** + * Check if an object is a DateTime. Works across context boundaries + * @param {object} o + * @return {boolean} + */ + ; + + DateTime.isDateTime = function isDateTime(o) { + return o && o.isLuxonDateTime || false; + } // INFO + + /** + * Get the value of unit. + * @param {string} unit - a unit such as 'minute' or 'day' + * @example DateTime.local(2017, 7, 4).get('month'); //=> 7 + * @example DateTime.local(2017, 7, 4).get('day'); //=> 4 + * @return {number} + */ + ; + + var _proto = DateTime.prototype; + + _proto.get = function get(unit) { + return this[unit]; + } + /** + * Returns whether the DateTime is valid. Invalid DateTimes occur when: + * * The DateTime was created from invalid calendar information, such as the 13th month or February 30 + * * The DateTime was created by an operation on another invalid date + * @type {boolean} + */ + ; + + /** + * Returns the resolved Intl options for this DateTime. + * This is useful in understanding the behavior of formatting methods + * @param {Object} opts - the same options as toLocaleString + * @return {Object} + */ + _proto.resolvedLocaleOptions = function resolvedLocaleOptions(opts) { + if (opts === void 0) { + opts = {}; + } + + var _Formatter$create$res = Formatter.create(this.loc.clone(opts), opts).resolvedOptions(this), + locale = _Formatter$create$res.locale, + numberingSystem = _Formatter$create$res.numberingSystem, + calendar = _Formatter$create$res.calendar; + + return { + locale: locale, + numberingSystem: numberingSystem, + outputCalendar: calendar + }; + } // TRANSFORM + + /** + * "Set" the DateTime's zone to UTC. Returns a newly-constructed DateTime. + * + * Equivalent to {@link DateTime#setZone}('utc') + * @param {number} [offset=0] - optionally, an offset from UTC in minutes + * @param {Object} [opts={}] - options to pass to `setZone()` + * @return {DateTime} + */ + ; + + _proto.toUTC = function toUTC(offset, opts) { + if (offset === void 0) { + offset = 0; + } + + if (opts === void 0) { + opts = {}; + } + + return this.setZone(FixedOffsetZone.instance(offset), opts); + } + /** + * "Set" the DateTime's zone to the host's local zone. Returns a newly-constructed DateTime. + * + * Equivalent to `setZone('local')` + * @return {DateTime} + */ + ; + + _proto.toLocal = function toLocal() { + return this.setZone(Settings.defaultZone); + } + /** + * "Set" the DateTime's zone to specified zone. Returns a newly-constructed DateTime. + * + * By default, the setter keeps the underlying time the same (as in, the same timestamp), but the new instance will report different local times and consider DSTs when making computations, as with {@link DateTime#plus}. You may wish to use {@link DateTime#toLocal} and {@link DateTime#toUTC} which provide simple convenience wrappers for commonly used zones. + * @param {string|Zone} [zone='local'] - a zone identifier. As a string, that can be any IANA zone supported by the host environment, or a fixed-offset name of the form 'UTC+3', or the strings 'local' or 'utc'. You may also supply an instance of a {@link DateTime#Zone} class. + * @param {Object} opts - options + * @param {boolean} [opts.keepLocalTime=false] - If true, adjust the underlying time so that the local time stays the same, but in the target zone. You should rarely need this. + * @return {DateTime} + */ + ; + + _proto.setZone = function setZone(zone, _temp) { + var _ref2 = _temp === void 0 ? {} : _temp, + _ref2$keepLocalTime = _ref2.keepLocalTime, + keepLocalTime = _ref2$keepLocalTime === void 0 ? false : _ref2$keepLocalTime, + _ref2$keepCalendarTim = _ref2.keepCalendarTime, + keepCalendarTime = _ref2$keepCalendarTim === void 0 ? false : _ref2$keepCalendarTim; + + zone = normalizeZone(zone, Settings.defaultZone); + + if (zone.equals(this.zone)) { + return this; + } else if (!zone.isValid) { + return DateTime.invalid(unsupportedZone(zone)); + } else { + var newTS = this.ts; + + if (keepLocalTime || keepCalendarTime) { + var offsetGuess = zone.offset(this.ts); + var asObj = this.toObject(); + + var _objToTS3 = objToTS(asObj, offsetGuess, zone); + + newTS = _objToTS3[0]; + } + + return clone(this, { + ts: newTS, + zone: zone + }); + } + } + /** + * "Set" the locale, numberingSystem, or outputCalendar. Returns a newly-constructed DateTime. + * @param {Object} properties - the properties to set + * @example DateTime.local(2017, 5, 25).reconfigure({ locale: 'en-GB' }) + * @return {DateTime} + */ + ; + + _proto.reconfigure = function reconfigure(_temp2) { + var _ref3 = _temp2 === void 0 ? {} : _temp2, + locale = _ref3.locale, + numberingSystem = _ref3.numberingSystem, + outputCalendar = _ref3.outputCalendar; + + var loc = this.loc.clone({ + locale: locale, + numberingSystem: numberingSystem, + outputCalendar: outputCalendar + }); + return clone(this, { + loc: loc + }); + } + /** + * "Set" the locale. Returns a newly-constructed DateTime. + * Just a convenient alias for reconfigure({ locale }) + * @example DateTime.local(2017, 5, 25).setLocale('en-GB') + * @return {DateTime} + */ + ; + + _proto.setLocale = function setLocale(locale) { + return this.reconfigure({ + locale: locale + }); + } + /** + * "Set" the values of specified units. Returns a newly-constructed DateTime. + * You can only set units with this method; for "setting" metadata, see {@link DateTime#reconfigure} and {@link DateTime#setZone}. + * @param {Object} values - a mapping of units to numbers + * @example dt.set({ year: 2017 }) + * @example dt.set({ hour: 8, minute: 30 }) + * @example dt.set({ weekday: 5 }) + * @example dt.set({ year: 2005, ordinal: 234 }) + * @return {DateTime} + */ + ; + + _proto.set = function set(values) { + if (!this.isValid) return this; + var normalized = normalizeObject(values, normalizeUnit), + settingWeekStuff = !isUndefined(normalized.weekYear) || !isUndefined(normalized.weekNumber) || !isUndefined(normalized.weekday), + containsOrdinal = !isUndefined(normalized.ordinal), + containsGregorYear = !isUndefined(normalized.year), + containsGregorMD = !isUndefined(normalized.month) || !isUndefined(normalized.day), + containsGregor = containsGregorYear || containsGregorMD, + definiteWeekDef = normalized.weekYear || normalized.weekNumber; + + if ((containsGregor || containsOrdinal) && definiteWeekDef) { + throw new ConflictingSpecificationError("Can't mix weekYear/weekNumber units with year/month/day or ordinals"); + } + + if (containsGregorMD && containsOrdinal) { + throw new ConflictingSpecificationError("Can't mix ordinal dates with month/day"); + } + + var mixed; + + if (settingWeekStuff) { + mixed = weekToGregorian(_extends({}, gregorianToWeek(this.c), normalized)); + } else if (!isUndefined(normalized.ordinal)) { + mixed = ordinalToGregorian(_extends({}, gregorianToOrdinal(this.c), normalized)); + } else { + mixed = _extends({}, this.toObject(), normalized); // if we didn't set the day but we ended up on an overflow date, + // use the last day of the right month + + if (isUndefined(normalized.day)) { + mixed.day = Math.min(daysInMonth(mixed.year, mixed.month), mixed.day); + } + } + + var _objToTS4 = objToTS(mixed, this.o, this.zone), + ts = _objToTS4[0], + o = _objToTS4[1]; + + return clone(this, { + ts: ts, + o: o + }); + } + /** + * Add a period of time to this DateTime and return the resulting DateTime + * + * Adding hours, minutes, seconds, or milliseconds increases the timestamp by the right number of milliseconds. Adding days, months, or years shifts the calendar, accounting for DSTs and leap years along the way. Thus, `dt.plus({ hours: 24 })` may result in a different time than `dt.plus({ days: 1 })` if there's a DST shift in between. + * @param {Duration|Object|number} duration - The amount to add. Either a Luxon Duration, a number of milliseconds, the object argument to Duration.fromObject() + * @example DateTime.now().plus(123) //~> in 123 milliseconds + * @example DateTime.now().plus({ minutes: 15 }) //~> in 15 minutes + * @example DateTime.now().plus({ days: 1 }) //~> this time tomorrow + * @example DateTime.now().plus({ days: -1 }) //~> this time yesterday + * @example DateTime.now().plus({ hours: 3, minutes: 13 }) //~> in 3 hr, 13 min + * @example DateTime.now().plus(Duration.fromObject({ hours: 3, minutes: 13 })) //~> in 3 hr, 13 min + * @return {DateTime} + */ + ; + + _proto.plus = function plus(duration) { + if (!this.isValid) return this; + var dur = Duration.fromDurationLike(duration); + return clone(this, adjustTime(this, dur)); + } + /** + * Subtract a period of time to this DateTime and return the resulting DateTime + * See {@link DateTime#plus} + * @param {Duration|Object|number} duration - The amount to subtract. Either a Luxon Duration, a number of milliseconds, the object argument to Duration.fromObject() + @return {DateTime} + */ + ; + + _proto.minus = function minus(duration) { + if (!this.isValid) return this; + var dur = Duration.fromDurationLike(duration).negate(); + return clone(this, adjustTime(this, dur)); + } + /** + * "Set" this DateTime to the beginning of a unit of time. + * @param {string} unit - The unit to go to the beginning of. Can be 'year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', or 'millisecond'. + * @example DateTime.local(2014, 3, 3).startOf('month').toISODate(); //=> '2014-03-01' + * @example DateTime.local(2014, 3, 3).startOf('year').toISODate(); //=> '2014-01-01' + * @example DateTime.local(2014, 3, 3).startOf('week').toISODate(); //=> '2014-03-03', weeks always start on Mondays + * @example DateTime.local(2014, 3, 3, 5, 30).startOf('day').toISOTime(); //=> '00:00.000-05:00' + * @example DateTime.local(2014, 3, 3, 5, 30).startOf('hour').toISOTime(); //=> '05:00:00.000-05:00' + * @return {DateTime} + */ + ; + + _proto.startOf = function startOf(unit) { + if (!this.isValid) return this; + var o = {}, + normalizedUnit = Duration.normalizeUnit(unit); + + switch (normalizedUnit) { + case "years": + o.month = 1; + // falls through + + case "quarters": + case "months": + o.day = 1; + // falls through + + case "weeks": + case "days": + o.hour = 0; + // falls through + + case "hours": + o.minute = 0; + // falls through + + case "minutes": + o.second = 0; + // falls through + + case "seconds": + o.millisecond = 0; + break; + // no default, invalid units throw in normalizeUnit() + } + + if (normalizedUnit === "weeks") { + o.weekday = 1; + } + + if (normalizedUnit === "quarters") { + var q = Math.ceil(this.month / 3); + o.month = (q - 1) * 3 + 1; + } + + return this.set(o); + } + /** + * "Set" this DateTime to the end (meaning the last millisecond) of a unit of time + * @param {string} unit - The unit to go to the end of. Can be 'year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', or 'millisecond'. + * @example DateTime.local(2014, 3, 3).endOf('month').toISO(); //=> '2014-03-31T23:59:59.999-05:00' + * @example DateTime.local(2014, 3, 3).endOf('year').toISO(); //=> '2014-12-31T23:59:59.999-05:00' + * @example DateTime.local(2014, 3, 3).endOf('week').toISO(); // => '2014-03-09T23:59:59.999-05:00', weeks start on Mondays + * @example DateTime.local(2014, 3, 3, 5, 30).endOf('day').toISO(); //=> '2014-03-03T23:59:59.999-05:00' + * @example DateTime.local(2014, 3, 3, 5, 30).endOf('hour').toISO(); //=> '2014-03-03T05:59:59.999-05:00' + * @return {DateTime} + */ + ; + + _proto.endOf = function endOf(unit) { + var _this$plus; + + return this.isValid ? this.plus((_this$plus = {}, _this$plus[unit] = 1, _this$plus)).startOf(unit).minus(1) : this; + } // OUTPUT + + /** + * Returns a string representation of this DateTime formatted according to the specified format string. + * **You may not want this.** See {@link DateTime#toLocaleString} for a more flexible formatting tool. For a table of tokens and their interpretations, see [here](https://moment.github.io/luxon/#/formatting?id=table-of-tokens). + * Defaults to en-US if no locale has been specified, regardless of the system's locale. + * @param {string} fmt - the format string + * @param {Object} opts - opts to override the configuration options on this DateTime + * @example DateTime.now().toFormat('yyyy LLL dd') //=> '2017 Apr 22' + * @example DateTime.now().setLocale('fr').toFormat('yyyy LLL dd') //=> '2017 avr. 22' + * @example DateTime.now().toFormat('yyyy LLL dd', { locale: "fr" }) //=> '2017 avr. 22' + * @example DateTime.now().toFormat("HH 'hours and' mm 'minutes'") //=> '20 hours and 55 minutes' + * @return {string} + */ + ; + + _proto.toFormat = function toFormat(fmt, opts) { + if (opts === void 0) { + opts = {}; + } + + return this.isValid ? Formatter.create(this.loc.redefaultToEN(opts)).formatDateTimeFromString(this, fmt) : INVALID; + } + /** + * Returns a localized string representing this date. Accepts the same options as the Intl.DateTimeFormat constructor and any presets defined by Luxon, such as `DateTime.DATE_FULL` or `DateTime.TIME_SIMPLE`. + * The exact behavior of this method is browser-specific, but in general it will return an appropriate representation + * of the DateTime in the assigned locale. + * Defaults to the system's locale if no locale has been specified + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat + * @param formatOpts {Object} - Intl.DateTimeFormat constructor options and configuration options + * @param {Object} opts - opts to override the configuration options on this DateTime + * @example DateTime.now().toLocaleString(); //=> 4/20/2017 + * @example DateTime.now().setLocale('en-gb').toLocaleString(); //=> '20/04/2017' + * @example DateTime.now().toLocaleString({ locale: 'en-gb' }); //=> '20/04/2017' + * @example DateTime.now().toLocaleString(DateTime.DATE_FULL); //=> 'April 20, 2017' + * @example DateTime.now().toLocaleString(DateTime.TIME_SIMPLE); //=> '11:32 AM' + * @example DateTime.now().toLocaleString(DateTime.DATETIME_SHORT); //=> '4/20/2017, 11:32 AM' + * @example DateTime.now().toLocaleString({ weekday: 'long', month: 'long', day: '2-digit' }); //=> 'Thursday, April 20' + * @example DateTime.now().toLocaleString({ weekday: 'short', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }); //=> 'Thu, Apr 20, 11:27 AM' + * @example DateTime.now().toLocaleString({ hour: '2-digit', minute: '2-digit', hourCycle: 'h23' }); //=> '11:32' + * @return {string} + */ + ; + + _proto.toLocaleString = function toLocaleString(formatOpts, opts) { + if (formatOpts === void 0) { + formatOpts = DATE_SHORT; + } + + if (opts === void 0) { + opts = {}; + } + + return this.isValid ? Formatter.create(this.loc.clone(opts), formatOpts).formatDateTime(this) : INVALID; + } + /** + * Returns an array of format "parts", meaning individual tokens along with metadata. This is allows callers to post-process individual sections of the formatted output. + * Defaults to the system's locale if no locale has been specified + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat/formatToParts + * @param opts {Object} - Intl.DateTimeFormat constructor options, same as `toLocaleString`. + * @example DateTime.now().toLocaleParts(); //=> [ + * //=> { type: 'day', value: '25' }, + * //=> { type: 'literal', value: '/' }, + * //=> { type: 'month', value: '05' }, + * //=> { type: 'literal', value: '/' }, + * //=> { type: 'year', value: '1982' } + * //=> ] + */ + ; + + _proto.toLocaleParts = function toLocaleParts(opts) { + if (opts === void 0) { + opts = {}; + } + + return this.isValid ? Formatter.create(this.loc.clone(opts), opts).formatDateTimeParts(this) : []; + } + /** + * Returns an ISO 8601-compliant string representation of this DateTime + * @param {Object} opts - options + * @param {boolean} [opts.suppressMilliseconds=false] - exclude milliseconds from the format if they're 0 + * @param {boolean} [opts.suppressSeconds=false] - exclude seconds from the format if they're 0 + * @param {boolean} [opts.includeOffset=true] - include the offset, such as 'Z' or '-04:00' + * @param {string} [opts.format='extended'] - choose between the basic and extended format + * @example DateTime.utc(1983, 5, 25).toISO() //=> '1982-05-25T00:00:00.000Z' + * @example DateTime.now().toISO() //=> '2017-04-22T20:47:05.335-04:00' + * @example DateTime.now().toISO({ includeOffset: false }) //=> '2017-04-22T20:47:05.335' + * @example DateTime.now().toISO({ format: 'basic' }) //=> '20170422T204705.335-0400' + * @return {string} + */ + ; + + _proto.toISO = function toISO(_temp3) { + var _ref4 = _temp3 === void 0 ? {} : _temp3, + _ref4$format = _ref4.format, + format = _ref4$format === void 0 ? "extended" : _ref4$format, + _ref4$suppressSeconds = _ref4.suppressSeconds, + suppressSeconds = _ref4$suppressSeconds === void 0 ? false : _ref4$suppressSeconds, + _ref4$suppressMillise = _ref4.suppressMilliseconds, + suppressMilliseconds = _ref4$suppressMillise === void 0 ? false : _ref4$suppressMillise, + _ref4$includeOffset = _ref4.includeOffset, + includeOffset = _ref4$includeOffset === void 0 ? true : _ref4$includeOffset; + + if (!this.isValid) { + return null; + } + + var ext = format === "extended"; + + var c = _toISODate(this, ext); + + c += "T"; + c += _toISOTime(this, ext, suppressSeconds, suppressMilliseconds, includeOffset); + return c; + } + /** + * Returns an ISO 8601-compliant string representation of this DateTime's date component + * @param {Object} opts - options + * @param {string} [opts.format='extended'] - choose between the basic and extended format + * @example DateTime.utc(1982, 5, 25).toISODate() //=> '1982-05-25' + * @example DateTime.utc(1982, 5, 25).toISODate({ format: 'basic' }) //=> '19820525' + * @return {string} + */ + ; + + _proto.toISODate = function toISODate(_temp4) { + var _ref5 = _temp4 === void 0 ? {} : _temp4, + _ref5$format = _ref5.format, + format = _ref5$format === void 0 ? "extended" : _ref5$format; + + if (!this.isValid) { + return null; + } + + return _toISODate(this, format === "extended"); + } + /** + * Returns an ISO 8601-compliant string representation of this DateTime's week date + * @example DateTime.utc(1982, 5, 25).toISOWeekDate() //=> '1982-W21-2' + * @return {string} + */ + ; + + _proto.toISOWeekDate = function toISOWeekDate() { + return toTechFormat(this, "kkkk-'W'WW-c"); + } + /** + * Returns an ISO 8601-compliant string representation of this DateTime's time component + * @param {Object} opts - options + * @param {boolean} [opts.suppressMilliseconds=false] - exclude milliseconds from the format if they're 0 + * @param {boolean} [opts.suppressSeconds=false] - exclude seconds from the format if they're 0 + * @param {boolean} [opts.includeOffset=true] - include the offset, such as 'Z' or '-04:00' + * @param {boolean} [opts.includePrefix=false] - include the `T` prefix + * @param {string} [opts.format='extended'] - choose between the basic and extended format + * @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime() //=> '07:34:19.361Z' + * @example DateTime.utc().set({ hour: 7, minute: 34, seconds: 0, milliseconds: 0 }).toISOTime({ suppressSeconds: true }) //=> '07:34Z' + * @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime({ format: 'basic' }) //=> '073419.361Z' + * @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime({ includePrefix: true }) //=> 'T07:34:19.361Z' + * @return {string} + */ + ; + + _proto.toISOTime = function toISOTime(_temp5) { + var _ref6 = _temp5 === void 0 ? {} : _temp5, + _ref6$suppressMillise = _ref6.suppressMilliseconds, + suppressMilliseconds = _ref6$suppressMillise === void 0 ? false : _ref6$suppressMillise, + _ref6$suppressSeconds = _ref6.suppressSeconds, + suppressSeconds = _ref6$suppressSeconds === void 0 ? false : _ref6$suppressSeconds, + _ref6$includeOffset = _ref6.includeOffset, + includeOffset = _ref6$includeOffset === void 0 ? true : _ref6$includeOffset, + _ref6$includePrefix = _ref6.includePrefix, + includePrefix = _ref6$includePrefix === void 0 ? false : _ref6$includePrefix, + _ref6$format = _ref6.format, + format = _ref6$format === void 0 ? "extended" : _ref6$format; + + if (!this.isValid) { + return null; + } + + var c = includePrefix ? "T" : ""; + return c + _toISOTime(this, format === "extended", suppressSeconds, suppressMilliseconds, includeOffset); + } + /** + * Returns an RFC 2822-compatible string representation of this DateTime + * @example DateTime.utc(2014, 7, 13).toRFC2822() //=> 'Sun, 13 Jul 2014 00:00:00 +0000' + * @example DateTime.local(2014, 7, 13).toRFC2822() //=> 'Sun, 13 Jul 2014 00:00:00 -0400' + * @return {string} + */ + ; + + _proto.toRFC2822 = function toRFC2822() { + return toTechFormat(this, "EEE, dd LLL yyyy HH:mm:ss ZZZ", false); + } + /** + * Returns a string representation of this DateTime appropriate for use in HTTP headers. The output is always expressed in GMT. + * Specifically, the string conforms to RFC 1123. + * @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1 + * @example DateTime.utc(2014, 7, 13).toHTTP() //=> 'Sun, 13 Jul 2014 00:00:00 GMT' + * @example DateTime.utc(2014, 7, 13, 19).toHTTP() //=> 'Sun, 13 Jul 2014 19:00:00 GMT' + * @return {string} + */ + ; + + _proto.toHTTP = function toHTTP() { + return toTechFormat(this.toUTC(), "EEE, dd LLL yyyy HH:mm:ss 'GMT'"); + } + /** + * Returns a string representation of this DateTime appropriate for use in SQL Date + * @example DateTime.utc(2014, 7, 13).toSQLDate() //=> '2014-07-13' + * @return {string} + */ + ; + + _proto.toSQLDate = function toSQLDate() { + if (!this.isValid) { + return null; + } + + return _toISODate(this, true); + } + /** + * Returns a string representation of this DateTime appropriate for use in SQL Time + * @param {Object} opts - options + * @param {boolean} [opts.includeZone=false] - include the zone, such as 'America/New_York'. Overrides includeOffset. + * @param {boolean} [opts.includeOffset=true] - include the offset, such as 'Z' or '-04:00' + * @example DateTime.utc().toSQL() //=> '05:15:16.345' + * @example DateTime.now().toSQL() //=> '05:15:16.345 -04:00' + * @example DateTime.now().toSQL({ includeOffset: false }) //=> '05:15:16.345' + * @example DateTime.now().toSQL({ includeZone: false }) //=> '05:15:16.345 America/New_York' + * @return {string} + */ + ; + + _proto.toSQLTime = function toSQLTime(_temp6) { + var _ref7 = _temp6 === void 0 ? {} : _temp6, + _ref7$includeOffset = _ref7.includeOffset, + includeOffset = _ref7$includeOffset === void 0 ? true : _ref7$includeOffset, + _ref7$includeZone = _ref7.includeZone, + includeZone = _ref7$includeZone === void 0 ? false : _ref7$includeZone; + + var fmt = "HH:mm:ss.SSS"; + + if (includeZone || includeOffset) { + fmt += " "; + + if (includeZone) { + fmt += "z"; + } else if (includeOffset) { + fmt += "ZZ"; + } + } + + return toTechFormat(this, fmt, true); + } + /** + * Returns a string representation of this DateTime appropriate for use in SQL DateTime + * @param {Object} opts - options + * @param {boolean} [opts.includeZone=false] - include the zone, such as 'America/New_York'. Overrides includeOffset. + * @param {boolean} [opts.includeOffset=true] - include the offset, such as 'Z' or '-04:00' + * @example DateTime.utc(2014, 7, 13).toSQL() //=> '2014-07-13 00:00:00.000 Z' + * @example DateTime.local(2014, 7, 13).toSQL() //=> '2014-07-13 00:00:00.000 -04:00' + * @example DateTime.local(2014, 7, 13).toSQL({ includeOffset: false }) //=> '2014-07-13 00:00:00.000' + * @example DateTime.local(2014, 7, 13).toSQL({ includeZone: true }) //=> '2014-07-13 00:00:00.000 America/New_York' + * @return {string} + */ + ; + + _proto.toSQL = function toSQL(opts) { + if (opts === void 0) { + opts = {}; + } + + if (!this.isValid) { + return null; + } + + return this.toSQLDate() + " " + this.toSQLTime(opts); + } + /** + * Returns a string representation of this DateTime appropriate for debugging + * @return {string} + */ + ; + + _proto.toString = function toString() { + return this.isValid ? this.toISO() : INVALID; + } + /** + * Returns the epoch milliseconds of this DateTime. Alias of {@link DateTime#toMillis} + * @return {number} + */ + ; + + _proto.valueOf = function valueOf() { + return this.toMillis(); + } + /** + * Returns the epoch milliseconds of this DateTime. + * @return {number} + */ + ; + + _proto.toMillis = function toMillis() { + return this.isValid ? this.ts : NaN; + } + /** + * Returns the epoch seconds of this DateTime. + * @return {number} + */ + ; + + _proto.toSeconds = function toSeconds() { + return this.isValid ? this.ts / 1000 : NaN; + } + /** + * Returns an ISO 8601 representation of this DateTime appropriate for use in JSON. + * @return {string} + */ + ; + + _proto.toJSON = function toJSON() { + return this.toISO(); + } + /** + * Returns a BSON serializable equivalent to this DateTime. + * @return {Date} + */ + ; + + _proto.toBSON = function toBSON() { + return this.toJSDate(); + } + /** + * Returns a JavaScript object with this DateTime's year, month, day, and so on. + * @param opts - options for generating the object + * @param {boolean} [opts.includeConfig=false] - include configuration attributes in the output + * @example DateTime.now().toObject() //=> { year: 2017, month: 4, day: 22, hour: 20, minute: 49, second: 42, millisecond: 268 } + * @return {Object} + */ + ; + + _proto.toObject = function toObject(opts) { + if (opts === void 0) { + opts = {}; + } + + if (!this.isValid) return {}; + + var base = _extends({}, this.c); + + if (opts.includeConfig) { + base.outputCalendar = this.outputCalendar; + base.numberingSystem = this.loc.numberingSystem; + base.locale = this.loc.locale; + } + + return base; + } + /** + * Returns a JavaScript Date equivalent to this DateTime. + * @return {Date} + */ + ; + + _proto.toJSDate = function toJSDate() { + return new Date(this.isValid ? this.ts : NaN); + } // COMPARE + + /** + * Return the difference between two DateTimes as a Duration. + * @param {DateTime} otherDateTime - the DateTime to compare this one to + * @param {string|string[]} [unit=['milliseconds']] - the unit or array of units (such as 'hours' or 'days') to include in the duration. + * @param {Object} opts - options that affect the creation of the Duration + * @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use + * @example + * var i1 = DateTime.fromISO('1982-05-25T09:45'), + * i2 = DateTime.fromISO('1983-10-14T10:30'); + * i2.diff(i1).toObject() //=> { milliseconds: 43807500000 } + * i2.diff(i1, 'hours').toObject() //=> { hours: 12168.75 } + * i2.diff(i1, ['months', 'days']).toObject() //=> { months: 16, days: 19.03125 } + * i2.diff(i1, ['months', 'days', 'hours']).toObject() //=> { months: 16, days: 19, hours: 0.75 } + * @return {Duration} + */ + ; + + _proto.diff = function diff(otherDateTime, unit, opts) { + if (unit === void 0) { + unit = "milliseconds"; + } + + if (opts === void 0) { + opts = {}; + } + + if (!this.isValid || !otherDateTime.isValid) { + return Duration.invalid("created by diffing an invalid DateTime"); + } + + var durOpts = _extends({ + locale: this.locale, + numberingSystem: this.numberingSystem + }, opts); + + var units = maybeArray(unit).map(Duration.normalizeUnit), + otherIsLater = otherDateTime.valueOf() > this.valueOf(), + earlier = otherIsLater ? this : otherDateTime, + later = otherIsLater ? otherDateTime : this, + diffed = _diff(earlier, later, units, durOpts); + + return otherIsLater ? diffed.negate() : diffed; + } + /** + * Return the difference between this DateTime and right now. + * See {@link DateTime#diff} + * @param {string|string[]} [unit=['milliseconds']] - the unit or units units (such as 'hours' or 'days') to include in the duration + * @param {Object} opts - options that affect the creation of the Duration + * @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use + * @return {Duration} + */ + ; + + _proto.diffNow = function diffNow(unit, opts) { + if (unit === void 0) { + unit = "milliseconds"; + } + + if (opts === void 0) { + opts = {}; + } + + return this.diff(DateTime.now(), unit, opts); + } + /** + * Return an Interval spanning between this DateTime and another DateTime + * @param {DateTime} otherDateTime - the other end point of the Interval + * @return {Interval} + */ + ; + + _proto.until = function until(otherDateTime) { + return this.isValid ? Interval.fromDateTimes(this, otherDateTime) : this; + } + /** + * Return whether this DateTime is in the same unit of time as another DateTime. + * Higher-order units must also be identical for this function to return `true`. + * Note that time zones are **ignored** in this comparison, which compares the **local** calendar time. Use {@link DateTime#setZone} to convert one of the dates if needed. + * @param {DateTime} otherDateTime - the other DateTime + * @param {string} unit - the unit of time to check sameness on + * @example DateTime.now().hasSame(otherDT, 'day'); //~> true if otherDT is in the same current calendar day + * @return {boolean} + */ + ; + + _proto.hasSame = function hasSame(otherDateTime, unit) { + if (!this.isValid) return false; + var inputMs = otherDateTime.valueOf(); + var adjustedToZone = this.setZone(otherDateTime.zone, { + keepLocalTime: true + }); + return adjustedToZone.startOf(unit) <= inputMs && inputMs <= adjustedToZone.endOf(unit); + } + /** + * Equality check + * Two DateTimes are equal iff they represent the same millisecond, have the same zone and location, and are both valid. + * To compare just the millisecond values, use `+dt1 === +dt2`. + * @param {DateTime} other - the other DateTime + * @return {boolean} + */ + ; + + _proto.equals = function equals(other) { + return this.isValid && other.isValid && this.valueOf() === other.valueOf() && this.zone.equals(other.zone) && this.loc.equals(other.loc); + } + /** + * Returns a string representation of a this time relative to now, such as "in two days". Can only internationalize if your + * platform supports Intl.RelativeTimeFormat. Rounds down by default. + * @param {Object} options - options that affect the output + * @param {DateTime} [options.base=DateTime.now()] - the DateTime to use as the basis to which this time is compared. Defaults to now. + * @param {string} [options.style="long"] - the style of units, must be "long", "short", or "narrow" + * @param {string|string[]} options.unit - use a specific unit or array of units; if omitted, or an array, the method will pick the best unit. Use an array or one of "years", "quarters", "months", "weeks", "days", "hours", "minutes", or "seconds" + * @param {boolean} [options.round=true] - whether to round the numbers in the output. + * @param {number} [options.padding=0] - padding in milliseconds. This allows you to round up the result if it fits inside the threshold. Don't use in combination with {round: false} because the decimal output will include the padding. + * @param {string} options.locale - override the locale of this DateTime + * @param {string} options.numberingSystem - override the numberingSystem of this DateTime. The Intl system may choose not to honor this + * @example DateTime.now().plus({ days: 1 }).toRelative() //=> "in 1 day" + * @example DateTime.now().setLocale("es").toRelative({ days: 1 }) //=> "dentro de 1 día" + * @example DateTime.now().plus({ days: 1 }).toRelative({ locale: "fr" }) //=> "dans 23 heures" + * @example DateTime.now().minus({ days: 2 }).toRelative() //=> "2 days ago" + * @example DateTime.now().minus({ days: 2 }).toRelative({ unit: "hours" }) //=> "48 hours ago" + * @example DateTime.now().minus({ hours: 36 }).toRelative({ round: false }) //=> "1.5 days ago" + */ + ; + + _proto.toRelative = function toRelative(options) { + if (options === void 0) { + options = {}; + } + + if (!this.isValid) return null; + var base = options.base || DateTime.fromObject({}, { + zone: this.zone + }), + padding = options.padding ? this < base ? -options.padding : options.padding : 0; + var units = ["years", "months", "days", "hours", "minutes", "seconds"]; + var unit = options.unit; + + if (Array.isArray(options.unit)) { + units = options.unit; + unit = undefined; + } + + return diffRelative(base, this.plus(padding), _extends({}, options, { + numeric: "always", + units: units, + unit: unit + })); + } + /** + * Returns a string representation of this date relative to today, such as "yesterday" or "next month". + * Only internationalizes on platforms that supports Intl.RelativeTimeFormat. + * @param {Object} options - options that affect the output + * @param {DateTime} [options.base=DateTime.now()] - the DateTime to use as the basis to which this time is compared. Defaults to now. + * @param {string} options.locale - override the locale of this DateTime + * @param {string} options.unit - use a specific unit; if omitted, the method will pick the unit. Use one of "years", "quarters", "months", "weeks", or "days" + * @param {string} options.numberingSystem - override the numberingSystem of this DateTime. The Intl system may choose not to honor this + * @example DateTime.now().plus({ days: 1 }).toRelativeCalendar() //=> "tomorrow" + * @example DateTime.now().setLocale("es").plus({ days: 1 }).toRelative() //=> ""mañana" + * @example DateTime.now().plus({ days: 1 }).toRelativeCalendar({ locale: "fr" }) //=> "demain" + * @example DateTime.now().minus({ days: 2 }).toRelativeCalendar() //=> "2 days ago" + */ + ; + + _proto.toRelativeCalendar = function toRelativeCalendar(options) { + if (options === void 0) { + options = {}; + } + + if (!this.isValid) return null; + return diffRelative(options.base || DateTime.fromObject({}, { + zone: this.zone + }), this, _extends({}, options, { + numeric: "auto", + units: ["years", "months", "days"], + calendary: true + })); + } + /** + * Return the min of several date times + * @param {...DateTime} dateTimes - the DateTimes from which to choose the minimum + * @return {DateTime} the min DateTime, or undefined if called with no argument + */ + ; + + DateTime.min = function min() { + for (var _len = arguments.length, dateTimes = new Array(_len), _key = 0; _key < _len; _key++) { + dateTimes[_key] = arguments[_key]; + } + + if (!dateTimes.every(DateTime.isDateTime)) { + throw new InvalidArgumentError("min requires all arguments be DateTimes"); + } + + return bestBy(dateTimes, function (i) { + return i.valueOf(); + }, Math.min); + } + /** + * Return the max of several date times + * @param {...DateTime} dateTimes - the DateTimes from which to choose the maximum + * @return {DateTime} the max DateTime, or undefined if called with no argument + */ + ; + + DateTime.max = function max() { + for (var _len2 = arguments.length, dateTimes = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + dateTimes[_key2] = arguments[_key2]; + } + + if (!dateTimes.every(DateTime.isDateTime)) { + throw new InvalidArgumentError("max requires all arguments be DateTimes"); + } + + return bestBy(dateTimes, function (i) { + return i.valueOf(); + }, Math.max); + } // MISC + + /** + * Explain how a string would be parsed by fromFormat() + * @param {string} text - the string to parse + * @param {string} fmt - the format the string is expected to be in (see description) + * @param {Object} options - options taken by fromFormat() + * @return {Object} + */ + ; + + DateTime.fromFormatExplain = function fromFormatExplain(text, fmt, options) { + if (options === void 0) { + options = {}; + } + + var _options = options, + _options$locale = _options.locale, + locale = _options$locale === void 0 ? null : _options$locale, + _options$numberingSys = _options.numberingSystem, + numberingSystem = _options$numberingSys === void 0 ? null : _options$numberingSys, + localeToUse = Locale.fromOpts({ + locale: locale, + numberingSystem: numberingSystem, + defaultToEN: true + }); + return explainFromTokens(localeToUse, text, fmt); + } + /** + * @deprecated use fromFormatExplain instead + */ + ; + + DateTime.fromStringExplain = function fromStringExplain(text, fmt, options) { + if (options === void 0) { + options = {}; + } + + return DateTime.fromFormatExplain(text, fmt, options); + } // FORMAT PRESETS + + /** + * {@link DateTime#toLocaleString} format like 10/14/1983 + * @type {Object} + */ + ; + + _createClass(DateTime, [{ + key: "isValid", + get: function get() { + return this.invalid === null; + } + /** + * Returns an error code if this DateTime is invalid, or null if the DateTime is valid + * @type {string} + */ + + }, { + key: "invalidReason", + get: function get() { + return this.invalid ? this.invalid.reason : null; + } + /** + * Returns an explanation of why this DateTime became invalid, or null if the DateTime is valid + * @type {string} + */ + + }, { + key: "invalidExplanation", + get: function get() { + return this.invalid ? this.invalid.explanation : null; + } + /** + * Get the locale of a DateTime, such 'en-GB'. The locale is used when formatting the DateTime + * + * @type {string} + */ + + }, { + key: "locale", + get: function get() { + return this.isValid ? this.loc.locale : null; + } + /** + * Get the numbering system of a DateTime, such 'beng'. The numbering system is used when formatting the DateTime + * + * @type {string} + */ + + }, { + key: "numberingSystem", + get: function get() { + return this.isValid ? this.loc.numberingSystem : null; + } + /** + * Get the output calendar of a DateTime, such 'islamic'. The output calendar is used when formatting the DateTime + * + * @type {string} + */ + + }, { + key: "outputCalendar", + get: function get() { + return this.isValid ? this.loc.outputCalendar : null; + } + /** + * Get the time zone associated with this DateTime. + * @type {Zone} + */ + + }, { + key: "zone", + get: function get() { + return this._zone; + } + /** + * Get the name of the time zone. + * @type {string} + */ + + }, { + key: "zoneName", + get: function get() { + return this.isValid ? this.zone.name : null; + } + /** + * Get the year + * @example DateTime.local(2017, 5, 25).year //=> 2017 + * @type {number} + */ + + }, { + key: "year", + get: function get() { + return this.isValid ? this.c.year : NaN; + } + /** + * Get the quarter + * @example DateTime.local(2017, 5, 25).quarter //=> 2 + * @type {number} + */ + + }, { + key: "quarter", + get: function get() { + return this.isValid ? Math.ceil(this.c.month / 3) : NaN; + } + /** + * Get the month (1-12). + * @example DateTime.local(2017, 5, 25).month //=> 5 + * @type {number} + */ + + }, { + key: "month", + get: function get() { + return this.isValid ? this.c.month : NaN; + } + /** + * Get the day of the month (1-30ish). + * @example DateTime.local(2017, 5, 25).day //=> 25 + * @type {number} + */ + + }, { + key: "day", + get: function get() { + return this.isValid ? this.c.day : NaN; + } + /** + * Get the hour of the day (0-23). + * @example DateTime.local(2017, 5, 25, 9).hour //=> 9 + * @type {number} + */ + + }, { + key: "hour", + get: function get() { + return this.isValid ? this.c.hour : NaN; + } + /** + * Get the minute of the hour (0-59). + * @example DateTime.local(2017, 5, 25, 9, 30).minute //=> 30 + * @type {number} + */ + + }, { + key: "minute", + get: function get() { + return this.isValid ? this.c.minute : NaN; + } + /** + * Get the second of the minute (0-59). + * @example DateTime.local(2017, 5, 25, 9, 30, 52).second //=> 52 + * @type {number} + */ + + }, { + key: "second", + get: function get() { + return this.isValid ? this.c.second : NaN; + } + /** + * Get the millisecond of the second (0-999). + * @example DateTime.local(2017, 5, 25, 9, 30, 52, 654).millisecond //=> 654 + * @type {number} + */ + + }, { + key: "millisecond", + get: function get() { + return this.isValid ? this.c.millisecond : NaN; + } + /** + * Get the week year + * @see https://en.wikipedia.org/wiki/ISO_week_date + * @example DateTime.local(2014, 12, 31).weekYear //=> 2015 + * @type {number} + */ + + }, { + key: "weekYear", + get: function get() { + return this.isValid ? possiblyCachedWeekData(this).weekYear : NaN; + } + /** + * Get the week number of the week year (1-52ish). + * @see https://en.wikipedia.org/wiki/ISO_week_date + * @example DateTime.local(2017, 5, 25).weekNumber //=> 21 + * @type {number} + */ + + }, { + key: "weekNumber", + get: function get() { + return this.isValid ? possiblyCachedWeekData(this).weekNumber : NaN; + } + /** + * Get the day of the week. + * 1 is Monday and 7 is Sunday + * @see https://en.wikipedia.org/wiki/ISO_week_date + * @example DateTime.local(2014, 11, 31).weekday //=> 4 + * @type {number} + */ + + }, { + key: "weekday", + get: function get() { + return this.isValid ? possiblyCachedWeekData(this).weekday : NaN; + } + /** + * Get the ordinal (meaning the day of the year) + * @example DateTime.local(2017, 5, 25).ordinal //=> 145 + * @type {number|DateTime} + */ + + }, { + key: "ordinal", + get: function get() { + return this.isValid ? gregorianToOrdinal(this.c).ordinal : NaN; + } + /** + * Get the human readable short month name, such as 'Oct'. + * Defaults to the system's locale if no locale has been specified + * @example DateTime.local(2017, 10, 30).monthShort //=> Oct + * @type {string} + */ + + }, { + key: "monthShort", + get: function get() { + return this.isValid ? Info.months("short", { + locObj: this.loc + })[this.month - 1] : null; + } + /** + * Get the human readable long month name, such as 'October'. + * Defaults to the system's locale if no locale has been specified + * @example DateTime.local(2017, 10, 30).monthLong //=> October + * @type {string} + */ + + }, { + key: "monthLong", + get: function get() { + return this.isValid ? Info.months("long", { + locObj: this.loc + })[this.month - 1] : null; + } + /** + * Get the human readable short weekday, such as 'Mon'. + * Defaults to the system's locale if no locale has been specified + * @example DateTime.local(2017, 10, 30).weekdayShort //=> Mon + * @type {string} + */ + + }, { + key: "weekdayShort", + get: function get() { + return this.isValid ? Info.weekdays("short", { + locObj: this.loc + })[this.weekday - 1] : null; + } + /** + * Get the human readable long weekday, such as 'Monday'. + * Defaults to the system's locale if no locale has been specified + * @example DateTime.local(2017, 10, 30).weekdayLong //=> Monday + * @type {string} + */ + + }, { + key: "weekdayLong", + get: function get() { + return this.isValid ? Info.weekdays("long", { + locObj: this.loc + })[this.weekday - 1] : null; + } + /** + * Get the UTC offset of this DateTime in minutes + * @example DateTime.now().offset //=> -240 + * @example DateTime.utc().offset //=> 0 + * @type {number} + */ + + }, { + key: "offset", + get: function get() { + return this.isValid ? +this.o : NaN; + } + /** + * Get the short human name for the zone's current offset, for example "EST" or "EDT". + * Defaults to the system's locale if no locale has been specified + * @type {string} + */ + + }, { + key: "offsetNameShort", + get: function get() { + if (this.isValid) { + return this.zone.offsetName(this.ts, { + format: "short", + locale: this.locale + }); + } else { + return null; + } + } + /** + * Get the long human name for the zone's current offset, for example "Eastern Standard Time" or "Eastern Daylight Time". + * Defaults to the system's locale if no locale has been specified + * @type {string} + */ + + }, { + key: "offsetNameLong", + get: function get() { + if (this.isValid) { + return this.zone.offsetName(this.ts, { + format: "long", + locale: this.locale + }); + } else { + return null; + } + } + /** + * Get whether this zone's offset ever changes, as in a DST. + * @type {boolean} + */ + + }, { + key: "isOffsetFixed", + get: function get() { + return this.isValid ? this.zone.isUniversal : null; + } + /** + * Get whether the DateTime is in a DST. + * @type {boolean} + */ + + }, { + key: "isInDST", + get: function get() { + if (this.isOffsetFixed) { + return false; + } else { + return this.offset > this.set({ + month: 1 + }).offset || this.offset > this.set({ + month: 5 + }).offset; + } + } + /** + * Returns true if this DateTime is in a leap year, false otherwise + * @example DateTime.local(2016).isInLeapYear //=> true + * @example DateTime.local(2013).isInLeapYear //=> false + * @type {boolean} + */ + + }, { + key: "isInLeapYear", + get: function get() { + return isLeapYear(this.year); + } + /** + * Returns the number of days in this DateTime's month + * @example DateTime.local(2016, 2).daysInMonth //=> 29 + * @example DateTime.local(2016, 3).daysInMonth //=> 31 + * @type {number} + */ + + }, { + key: "daysInMonth", + get: function get() { + return daysInMonth(this.year, this.month); + } + /** + * Returns the number of days in this DateTime's year + * @example DateTime.local(2016).daysInYear //=> 366 + * @example DateTime.local(2013).daysInYear //=> 365 + * @type {number} + */ + + }, { + key: "daysInYear", + get: function get() { + return this.isValid ? daysInYear(this.year) : NaN; + } + /** + * Returns the number of weeks in this DateTime's year + * @see https://en.wikipedia.org/wiki/ISO_week_date + * @example DateTime.local(2004).weeksInWeekYear //=> 53 + * @example DateTime.local(2013).weeksInWeekYear //=> 52 + * @type {number} + */ + + }, { + key: "weeksInWeekYear", + get: function get() { + return this.isValid ? weeksInWeekYear(this.weekYear) : NaN; + } + }], [{ + key: "DATE_SHORT", + get: function get() { + return DATE_SHORT; + } + /** + * {@link DateTime#toLocaleString} format like 'Oct 14, 1983' + * @type {Object} + */ + + }, { + key: "DATE_MED", + get: function get() { + return DATE_MED; + } + /** + * {@link DateTime#toLocaleString} format like 'Fri, Oct 14, 1983' + * @type {Object} + */ + + }, { + key: "DATE_MED_WITH_WEEKDAY", + get: function get() { + return DATE_MED_WITH_WEEKDAY; + } + /** + * {@link DateTime#toLocaleString} format like 'October 14, 1983' + * @type {Object} + */ + + }, { + key: "DATE_FULL", + get: function get() { + return DATE_FULL; + } + /** + * {@link DateTime#toLocaleString} format like 'Tuesday, October 14, 1983' + * @type {Object} + */ + + }, { + key: "DATE_HUGE", + get: function get() { + return DATE_HUGE; + } + /** + * {@link DateTime#toLocaleString} format like '09:30 AM'. Only 12-hour if the locale is. + * @type {Object} + */ + + }, { + key: "TIME_SIMPLE", + get: function get() { + return TIME_SIMPLE; + } + /** + * {@link DateTime#toLocaleString} format like '09:30:23 AM'. Only 12-hour if the locale is. + * @type {Object} + */ + + }, { + key: "TIME_WITH_SECONDS", + get: function get() { + return TIME_WITH_SECONDS; + } + /** + * {@link DateTime#toLocaleString} format like '09:30:23 AM EDT'. Only 12-hour if the locale is. + * @type {Object} + */ + + }, { + key: "TIME_WITH_SHORT_OFFSET", + get: function get() { + return TIME_WITH_SHORT_OFFSET; + } + /** + * {@link DateTime#toLocaleString} format like '09:30:23 AM Eastern Daylight Time'. Only 12-hour if the locale is. + * @type {Object} + */ + + }, { + key: "TIME_WITH_LONG_OFFSET", + get: function get() { + return TIME_WITH_LONG_OFFSET; + } + /** + * {@link DateTime#toLocaleString} format like '09:30', always 24-hour. + * @type {Object} + */ + + }, { + key: "TIME_24_SIMPLE", + get: function get() { + return TIME_24_SIMPLE; + } + /** + * {@link DateTime#toLocaleString} format like '09:30:23', always 24-hour. + * @type {Object} + */ + + }, { + key: "TIME_24_WITH_SECONDS", + get: function get() { + return TIME_24_WITH_SECONDS; + } + /** + * {@link DateTime#toLocaleString} format like '09:30:23 EDT', always 24-hour. + * @type {Object} + */ + + }, { + key: "TIME_24_WITH_SHORT_OFFSET", + get: function get() { + return TIME_24_WITH_SHORT_OFFSET; + } + /** + * {@link DateTime#toLocaleString} format like '09:30:23 Eastern Daylight Time', always 24-hour. + * @type {Object} + */ + + }, { + key: "TIME_24_WITH_LONG_OFFSET", + get: function get() { + return TIME_24_WITH_LONG_OFFSET; + } + /** + * {@link DateTime#toLocaleString} format like '10/14/1983, 9:30 AM'. Only 12-hour if the locale is. + * @type {Object} + */ + + }, { + key: "DATETIME_SHORT", + get: function get() { + return DATETIME_SHORT; + } + /** + * {@link DateTime#toLocaleString} format like '10/14/1983, 9:30:33 AM'. Only 12-hour if the locale is. + * @type {Object} + */ + + }, { + key: "DATETIME_SHORT_WITH_SECONDS", + get: function get() { + return DATETIME_SHORT_WITH_SECONDS; + } + /** + * {@link DateTime#toLocaleString} format like 'Oct 14, 1983, 9:30 AM'. Only 12-hour if the locale is. + * @type {Object} + */ + + }, { + key: "DATETIME_MED", + get: function get() { + return DATETIME_MED; + } + /** + * {@link DateTime#toLocaleString} format like 'Oct 14, 1983, 9:30:33 AM'. Only 12-hour if the locale is. + * @type {Object} + */ + + }, { + key: "DATETIME_MED_WITH_SECONDS", + get: function get() { + return DATETIME_MED_WITH_SECONDS; + } + /** + * {@link DateTime#toLocaleString} format like 'Fri, 14 Oct 1983, 9:30 AM'. Only 12-hour if the locale is. + * @type {Object} + */ + + }, { + key: "DATETIME_MED_WITH_WEEKDAY", + get: function get() { + return DATETIME_MED_WITH_WEEKDAY; + } + /** + * {@link DateTime#toLocaleString} format like 'October 14, 1983, 9:30 AM EDT'. Only 12-hour if the locale is. + * @type {Object} + */ + + }, { + key: "DATETIME_FULL", + get: function get() { + return DATETIME_FULL; + } + /** + * {@link DateTime#toLocaleString} format like 'October 14, 1983, 9:30:33 AM EDT'. Only 12-hour if the locale is. + * @type {Object} + */ + + }, { + key: "DATETIME_FULL_WITH_SECONDS", + get: function get() { + return DATETIME_FULL_WITH_SECONDS; + } + /** + * {@link DateTime#toLocaleString} format like 'Friday, October 14, 1983, 9:30 AM Eastern Daylight Time'. Only 12-hour if the locale is. + * @type {Object} + */ + + }, { + key: "DATETIME_HUGE", + get: function get() { + return DATETIME_HUGE; + } + /** + * {@link DateTime#toLocaleString} format like 'Friday, October 14, 1983, 9:30:33 AM Eastern Daylight Time'. Only 12-hour if the locale is. + * @type {Object} + */ + + }, { + key: "DATETIME_HUGE_WITH_SECONDS", + get: function get() { + return DATETIME_HUGE_WITH_SECONDS; + } + }]); + + return DateTime; + }(); + function friendlyDateTime(dateTimeish) { + if (DateTime.isDateTime(dateTimeish)) { + return dateTimeish; + } else if (dateTimeish && dateTimeish.valueOf && isNumber(dateTimeish.valueOf())) { + return DateTime.fromJSDate(dateTimeish); + } else if (dateTimeish && typeof dateTimeish === "object") { + return DateTime.fromObject(dateTimeish); + } else { + throw new InvalidArgumentError("Unknown datetime argument: " + dateTimeish + ", of type " + typeof dateTimeish); + } + } + + var VERSION = "2.3.0"; + + exports.DateTime = DateTime; + exports.Duration = Duration; + exports.FixedOffsetZone = FixedOffsetZone; + exports.IANAZone = IANAZone; + exports.Info = Info; + exports.Interval = Interval; + exports.InvalidZone = InvalidZone; + exports.Settings = Settings; + exports.SystemZone = SystemZone; + exports.VERSION = VERSION; + exports.Zone = Zone; + + Object.defineProperty(exports, '__esModule', { value: true }); + + return exports; + +})({}); +//# sourceMappingURL=luxon.js.map diff --git a/assets/js/luxon/luxon.min.js b/assets/js/luxon/luxon.min.js new file mode 100644 index 0000000..c9a4611 --- /dev/null +++ b/assets/js/luxon/luxon.min.js @@ -0,0 +1 @@ +var luxon=function(e){"use strict";function r(e,t){for(var n=0;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var n=function(e){function t(){return e.apply(this,arguments)||this}return i(t,e),t}(t(Error)),d=function(t){function e(e){return t.call(this,"Invalid DateTime: "+e.toMessage())||this}return i(e,t),e}(n),h=function(t){function e(e){return t.call(this,"Invalid Interval: "+e.toMessage())||this}return i(e,t),e}(n),y=function(t){function e(e){return t.call(this,"Invalid Duration: "+e.toMessage())||this}return i(e,t),e}(n),S=function(e){function t(){return e.apply(this,arguments)||this}return i(t,e),t}(n),v=function(t){function e(e){return t.call(this,"Invalid unit "+e)||this}return i(e,t),e}(n),p=function(e){function t(){return e.apply(this,arguments)||this}return i(t,e),t}(n),m=function(e){function t(){return e.call(this,"Zone is an abstract class")||this}return i(t,e),t}(n),g="numeric",w="short",T="long",b={year:g,month:g,day:g},O={year:g,month:w,day:g},M={year:g,month:w,day:g,weekday:w},N={year:g,month:T,day:g},D={year:g,month:T,day:g,weekday:T},E={hour:g,minute:g},V={hour:g,minute:g,second:g},I={hour:g,minute:g,second:g,timeZoneName:w},x={hour:g,minute:g,second:g,timeZoneName:T},C={hour:g,minute:g,hourCycle:"h23"},F={hour:g,minute:g,second:g,hourCycle:"h23"},L={hour:g,minute:g,second:g,hourCycle:"h23",timeZoneName:w},Z={hour:g,minute:g,second:g,hourCycle:"h23",timeZoneName:T},A={year:g,month:g,day:g,hour:g,minute:g},z={year:g,month:g,day:g,hour:g,minute:g,second:g},j={year:g,month:w,day:g,hour:g,minute:g},q={year:g,month:w,day:g,hour:g,minute:g,second:g},_={year:g,month:w,day:g,weekday:w,hour:g,minute:g},U={year:g,month:T,day:g,hour:g,minute:g,timeZoneName:w},R={year:g,month:T,day:g,hour:g,minute:g,second:g,timeZoneName:w},H={year:g,month:T,day:g,weekday:T,hour:g,minute:g,timeZoneName:T},P={year:g,month:T,day:g,weekday:T,hour:g,minute:g,second:g,timeZoneName:T};function W(e){return void 0===e}function J(e){return"number"==typeof e}function Y(e){return"number"==typeof e&&e%1==0}function G(){try{return"undefined"!=typeof Intl&&!!Intl.RelativeTimeFormat}catch(e){return!1}}function $(e,n,r){if(0!==e.length)return e.reduce(function(e,t){t=[n(t),t];return e&&r(e[0],t[0])===e[0]?e:t},null)[1]}function B(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function Q(e,t,n){return Y(e)&&t<=e&&e<=n}function K(e,t){void 0===t&&(t=2);t=e<0?"-"+(""+-e).padStart(t,"0"):(""+e).padStart(t,"0");return t}function X(e){if(!W(e)&&null!==e&&""!==e)return parseInt(e,10)}function ee(e){if(!W(e)&&null!==e&&""!==e)return parseFloat(e)}function te(e){if(!W(e)&&null!==e&&""!==e){e=1e3*parseFloat("0."+e);return Math.floor(e)}}function ne(e,t,n){void 0===n&&(n=!1);t=Math.pow(10,t);return(n?Math.trunc:Math.round)(e*t)/t}function re(e){return e%4==0&&(e%100!=0||e%400==0)}function ie(e){return re(e)?366:365}function oe(e,t){var n,r=(n=t-1)-(r=12)*Math.floor(n/r)+1;return 2==r?re(e+(t-r)/12)?29:28:[31,null,31,30,31,30,31,31,30,31,30,31][r-1]}function ue(e){var t=Date.UTC(e.year,e.month-1,e.day,e.hour,e.minute,e.second,e.millisecond);return e.year<100&&0<=e.year&&(t=new Date(t)).setUTCFullYear(t.getUTCFullYear()-1900),+t}function ae(e){var t=(e+Math.floor(e/4)-Math.floor(e/100)+Math.floor(e/400))%7,e=e-1,e=(e+Math.floor(e/4)-Math.floor(e/100)+Math.floor(e/400))%7;return 4==t||3==e?53:52}function se(e){return 99$t.indexOf(s)&&Kt(this.matrix,u,d,i,s)}else J(u[s])&&(o[s]=u[s])}for(r in o)0!==o[r]&&(i[l]+=r===l?o[r]:o[r]/this.matrix[l][r]);return Qt(this,{values:i},!0).normalize()},e.negate=function(){if(!this.isValid)return this;for(var e={},t=0,n=Object.keys(this.values);te},e.isBefore=function(e){return!!this.isValid&&this.e<=e},e.contains=function(e){return!!this.isValid&&(this.s<=e&&this.e>e)},e.set=function(e){var t=void 0===e?{}:e,e=t.start,t=t.end;return this.isValid?c.fromDateTimes(e||this.s,t||this.e):this},e.splitAt=function(){var t=this;if(!this.isValid)return[];for(var e=arguments.length,n=new Array(e),r=0;r+this.e?this.e:s;o.push(c.fromDateTimes(u,s)),u=s,a+=1}return o},e.splitBy=function(e){var t=Xt.fromDurationLike(e);if(!this.isValid||!t.isValid||0===t.as("milliseconds"))return[];for(var n=this.s,r=1,i=[];n+this.e?this.e:o;i.push(c.fromDateTimes(n,o)),n=o,r+=1}return i},e.divideEqually=function(e){return this.isValid?this.splitBy(this.length()/e).slice(0,e):[]},e.overlaps=function(e){return this.e>e.s&&this.s=e.e)},e.equals=function(e){return!(!this.isValid||!e.isValid)&&(this.s.equals(e.s)&&this.e.equals(e.e))},e.intersection=function(e){if(!this.isValid)return this;var t=(this.s>e.s?this:e).s,e=(this.ee.e?this:e).e;return c.fromDateTimes(t,e)},c.merge=function(e){var t=e.sort(function(e,t){return e.s-t.s}).reduce(function(e,t){var n=e[0],e=e[1];return e?e.overlaps(t)||e.abutsStart(t)?[n,e.union(t)]:[n.concat([e]),t]:[n,t]},[[],null]),e=t[0],t=t[1];return t&&e.push(t),e},c.xor=function(e){for(var t=null,n=0,r=[],i=e.map(function(e){return[{time:e.s,type:"s"},{time:e.e,type:"e"}]}),o=k((e=Array.prototype).concat.apply(e,i).sort(function(e,t){return e.time-t.time}));!(u=o()).done;)var u=u.value,t=1===(n+="s"===u.type?1:-1)?u.time:(t&&+t!=+u.time&&r.push(c.fromDateTimes(t,u.time)),null);return c.merge(r)},e.difference=function(){for(var t=this,e=arguments.length,n=new Array(e),r=0;rae(n)?(t=n+1,o=1):t=n,s({weekYear:t,weekNumber:o,weekday:i},me(e))}function xn(e){var t,n=e.weekYear,r=e.weekNumber,i=e.weekday,o=Dn(n,1,4),u=ie(n),o=7*r+i-o-3;o<1?o+=ie(t=n-1):uthis.valueOf(),r=on(n?this:e,n?e:this,t,r);return n?r.negate():r},e.diffNow=function(e,t){return void 0===e&&(e="milliseconds"),void 0===t&&(t={}),this.diff(w.now(),e,t)},e.until=function(e){return this.isValid?tn.fromDateTimes(this,e):this},e.hasSame=function(e,t){if(!this.isValid)return!1;var n=e.valueOf(),e=this.setZone(e.zone,{keepLocalTime:!0});return e.startOf(t)<=n&&n<=e.endOf(t)},e.equals=function(e){return this.isValid&&e.isValid&&this.valueOf()===e.valueOf()&&this.zone.equals(e.zone)&&this.loc.equals(e.loc)},e.toRelative=function(e){if(!this.isValid)return null;var t=(e=void 0===e?{}:e).base||w.fromObject({},{zone:this.zone}),n=e.padding?thisthis.set({month:1}).offset||this.offset>this.set({month:5}).offset)}},{key:"isInLeapYear",get:function(){return re(this.year)}},{key:"daysInMonth",get:function(){return oe(this.year,this.month)}},{key:"daysInYear",get:function(){return this.isValid?ie(this.year):NaN}},{key:"weeksInWeekYear",get:function(){return this.isValid?ae(this.weekYear):NaN}}],[{key:"DATE_SHORT",get:function(){return b}},{key:"DATE_MED",get:function(){return O}},{key:"DATE_MED_WITH_WEEKDAY",get:function(){return M}},{key:"DATE_FULL",get:function(){return N}},{key:"DATE_HUGE",get:function(){return D}},{key:"TIME_SIMPLE",get:function(){return E}},{key:"TIME_WITH_SECONDS",get:function(){return V}},{key:"TIME_WITH_SHORT_OFFSET",get:function(){return I}},{key:"TIME_WITH_LONG_OFFSET",get:function(){return x}},{key:"TIME_24_SIMPLE",get:function(){return C}},{key:"TIME_24_WITH_SECONDS",get:function(){return F}},{key:"TIME_24_WITH_SHORT_OFFSET",get:function(){return L}},{key:"TIME_24_WITH_LONG_OFFSET",get:function(){return Z}},{key:"DATETIME_SHORT",get:function(){return A}},{key:"DATETIME_SHORT_WITH_SECONDS",get:function(){return z}},{key:"DATETIME_MED",get:function(){return j}},{key:"DATETIME_MED_WITH_SECONDS",get:function(){return q}},{key:"DATETIME_MED_WITH_WEEKDAY",get:function(){return _}},{key:"DATETIME_FULL",get:function(){return U}},{key:"DATETIME_FULL_WITH_SECONDS",get:function(){return R}},{key:"DATETIME_HUGE",get:function(){return H}},{key:"DATETIME_HUGE_WITH_SECONDS",get:function(){return P}}]),w}();function or(e){if(ir.isDateTime(e))return e;if(e&&e.valueOf&&J(e.valueOf()))return ir.fromJSDate(e);if(e&&"object"==typeof e)return ir.fromObject(e);throw new p("Unknown datetime argument: "+e+", of type "+typeof e)}return e.DateTime=ir,e.Duration=Xt,e.FixedOffsetZone=Re,e.IANAZone=_e,e.Info=nn,e.Interval=tn,e.InvalidZone=He,e.Settings=Qe,e.SystemZone=Ze,e.VERSION="2.3.0",e.Zone=Fe,Object.defineProperty(e,"__esModule",{value:!0}),e}({}); \ No newline at end of file diff --git a/assets/js/preact/preact.min.js b/assets/js/preact/preact.min.js new file mode 100644 index 0000000..9b0c8dd --- /dev/null +++ b/assets/js/preact/preact.min.js @@ -0,0 +1,2 @@ +!function(){var n,l,u,t,i,o,r,f,e,c={},a=[],s=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;function h(n,l){for(var u in l)n[u]=l[u];return n}function v(n){var l=n.parentNode;l&&l.removeChild(n)}function y(l,u,t){var i,o,r,f={};for(r in u)"key"==r?i=u[r]:"ref"==r?o=u[r]:f[r]=u[r];if(arguments.length>2&&(f.children=arguments.length>3?n.call(arguments,2):t),"function"==typeof l&&null!=l.defaultProps)for(r in l.defaultProps)void 0===f[r]&&(f[r]=l.defaultProps[r]);return d(l,f,i,o,null)}function d(n,t,i,o,r){var f={type:n,props:t,key:i,ref:o,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==r?++u:r};return null!=l.vnode&&l.vnode(f),f}function p(n){return n.children}function _(n,l){this.props=n,this.context=l}function m(n,l){if(null==l)return n.__?m(n.__,n.__.__k.indexOf(n)+1):null;for(var u;l0?d(_.type,_.props,_.key,null,_.__v):_)){if(_.__=u,_.__b=u.__b+1,null===(y=w[h])||y&&_.key==y.key&&_.type===y.type)w[h]=void 0;else for(v=0;v2&&(f.children=arguments.length>3?n.call(arguments,2):t),d(l.type,f,i||l.key,o||l.ref,null)},createContext:function(n,l){var u={__c:l="__cC"+f++,__:n,Consumer:function(n,l){return n.children(l)},Provider:function(n){var u,t;return this.getChildContext||(u=[],(t={})[l]=this,this.getChildContext=function(){return t},this.shouldComponentUpdate=function(n){this.props.value!==n.value&&u.some(b)},this.sub=function(n){u.push(n);var l=n.componentWillUnmount;n.componentWillUnmount=function(){u.splice(u.indexOf(n),1),l&&l.call(n)}}),n.children}};return u.Provider.__=u.Consumer.contextType=u},toChildArray:function n(l,u){return u=u||[],null==l||"boolean"==typeof l||(Array.isArray(l)?l.some(function(l){n(l,u)}):u.push(l)),u},options:l},typeof module<"u"?module.exports=e:self.preact=e}(); +//# sourceMappingURL=preact.min.js.map diff --git a/assets/js/preact/preact.min.js.map b/assets/js/preact/preact.min.js.map new file mode 100644 index 0000000..7a5a1fc --- /dev/null +++ b/assets/js/preact/preact.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"preact.min.js","sources":["../src/util.js","../src/options.js","../src/create-element.js","../src/component.js","../src/create-context.js","../src/constants.js","../src/diff/children.js","../src/diff/props.js","../src/diff/index.js","../src/render.js","../src/diff/catch-error.js","../src/clone-element.js","../src/cjs.js"],"sourcesContent":["import { EMPTY_ARR } from \"./constants\";\n\n/**\n * Assign properties from `props` to `obj`\n * @template O, P The obj and props types\n * @param {O} obj The object to copy properties to\n * @param {P} props The object to copy properties from\n * @returns {O & P}\n */\nexport function assign(obj, props) {\n\t// @ts-ignore We change the type of `obj` to be `O & P`\n\tfor (let i in props) obj[i] = props[i];\n\treturn /** @type {O & P} */ (obj);\n}\n\n/**\n * Remove a child node from its parent if attached. This is a workaround for\n * IE11 which doesn't support `Element.prototype.remove()`. Using this function\n * is smaller than including a dedicated polyfill.\n * @param {Node} node The node to remove\n */\nexport function removeNode(node) {\n\tlet parentNode = node.parentNode;\n\tif (parentNode) parentNode.removeChild(node);\n}\n\nexport const slice = EMPTY_ARR.slice;\n","import { _catchError } from './diff/catch-error';\n\n/**\n * The `option` object can potentially contain callback functions\n * that are called during various stages of our renderer. This is the\n * foundation on which all our addons like `preact/debug`, `preact/compat`,\n * and `preact/hooks` are based on. See the `Options` type in `internal.d.ts`\n * for a full list of available option hooks (most editors/IDEs allow you to\n * ctrl+click or cmd+click on mac the type definition below).\n * @type {import('./internal').Options}\n */\nconst options = {\n\t_catchError\n};\n\nexport default options;\n","import { slice } from './util';\nimport options from './options';\n\nlet vnodeId = 0;\n\n/**\n * Create an virtual node (used for JSX)\n * @param {import('./internal').VNode[\"type\"]} type The node name or Component\n * constructor for this virtual node\n * @param {object | null | undefined} [props] The properties of the virtual node\n * @param {Array} [children] The children of the virtual node\n * @returns {import('./internal').VNode}\n */\nexport function createElement(type, props, children) {\n\tlet normalizedProps = {},\n\t\tkey,\n\t\tref,\n\t\ti;\n\tfor (i in props) {\n\t\tif (i == 'key') key = props[i];\n\t\telse if (i == 'ref') ref = props[i];\n\t\telse normalizedProps[i] = props[i];\n\t}\n\n\tif (arguments.length > 2) {\n\t\tnormalizedProps.children =\n\t\t\targuments.length > 3 ? slice.call(arguments, 2) : children;\n\t}\n\n\t// If a Component VNode, check for and apply defaultProps\n\t// Note: type may be undefined in development, must never error here.\n\tif (typeof type == 'function' && type.defaultProps != null) {\n\t\tfor (i in type.defaultProps) {\n\t\t\tif (normalizedProps[i] === undefined) {\n\t\t\t\tnormalizedProps[i] = type.defaultProps[i];\n\t\t\t}\n\t\t}\n\t}\n\n\treturn createVNode(type, normalizedProps, key, ref, null);\n}\n\n/**\n * Create a VNode (used internally by Preact)\n * @param {import('./internal').VNode[\"type\"]} type The node name or Component\n * Constructor for this virtual node\n * @param {object | string | number | null} props The properties of this virtual node.\n * If this virtual node represents a text node, this is the text of the node (string or number).\n * @param {string | number | null} key The key for this virtual node, used when\n * diffing it against its children\n * @param {import('./internal').VNode[\"ref\"]} ref The ref property that will\n * receive a reference to its created child\n * @returns {import('./internal').VNode}\n */\nexport function createVNode(type, props, key, ref, original) {\n\t// V8 seems to be better at detecting type shapes if the object is allocated from the same call site\n\t// Do not inline into createElement and coerceToVNode!\n\tconst vnode = {\n\t\ttype,\n\t\tprops,\n\t\tkey,\n\t\tref,\n\t\t_children: null,\n\t\t_parent: null,\n\t\t_depth: 0,\n\t\t_dom: null,\n\t\t// _nextDom must be initialized to undefined b/c it will eventually\n\t\t// be set to dom.nextSibling which can return `null` and it is important\n\t\t// to be able to distinguish between an uninitialized _nextDom and\n\t\t// a _nextDom that has been set to `null`\n\t\t_nextDom: undefined,\n\t\t_component: null,\n\t\t_hydrating: null,\n\t\tconstructor: undefined,\n\t\t_original: original == null ? ++vnodeId : original\n\t};\n\n\tif (options.vnode != null) options.vnode(vnode);\n\n\treturn vnode;\n}\n\nexport function createRef() {\n\treturn { current: null };\n}\n\nexport function Fragment(props) {\n\treturn props.children;\n}\n\n/**\n * Check if a the argument is a valid Preact VNode.\n * @param {*} vnode\n * @returns {vnode is import('./internal').VNode}\n */\nexport const isValidElement = vnode =>\n\tvnode != null && vnode.constructor === undefined;\n","import { assign } from './util';\nimport { diff, commitRoot } from './diff/index';\nimport options from './options';\nimport { Fragment } from './create-element';\n\n/**\n * Base Component class. Provides `setState()` and `forceUpdate()`, which\n * trigger rendering\n * @param {object} props The initial component props\n * @param {object} context The initial context from parent components'\n * getChildContext\n */\nexport function Component(props, context) {\n\tthis.props = props;\n\tthis.context = context;\n}\n\n/**\n * Update component state and schedule a re-render.\n * @this {import('./internal').Component}\n * @param {object | ((s: object, p: object) => object)} update A hash of state\n * properties to update with new values or a function that given the current\n * state and props returns a new partial state\n * @param {() => void} [callback] A function to be called once component state is\n * updated\n */\nComponent.prototype.setState = function(update, callback) {\n\t// only clone state when copying to nextState the first time.\n\tlet s;\n\tif (this._nextState != null && this._nextState !== this.state) {\n\t\ts = this._nextState;\n\t} else {\n\t\ts = this._nextState = assign({}, this.state);\n\t}\n\n\tif (typeof update == 'function') {\n\t\t// Some libraries like `immer` mark the current state as readonly,\n\t\t// preventing us from mutating it, so we need to clone it. See #2716\n\t\tupdate = update(assign({}, s), this.props);\n\t}\n\n\tif (update) {\n\t\tassign(s, update);\n\t}\n\n\t// Skip update if updater function returned null\n\tif (update == null) return;\n\n\tif (this._vnode) {\n\t\tif (callback) this._renderCallbacks.push(callback);\n\t\tenqueueRender(this);\n\t}\n};\n\n/**\n * Immediately perform a synchronous re-render of the component\n * @this {import('./internal').Component}\n * @param {() => void} [callback] A function to be called after component is\n * re-rendered\n */\nComponent.prototype.forceUpdate = function(callback) {\n\tif (this._vnode) {\n\t\t// Set render mode so that we can differentiate where the render request\n\t\t// is coming from. We need this because forceUpdate should never call\n\t\t// shouldComponentUpdate\n\t\tthis._force = true;\n\t\tif (callback) this._renderCallbacks.push(callback);\n\t\tenqueueRender(this);\n\t}\n};\n\n/**\n * Accepts `props` and `state`, and returns a new Virtual DOM tree to build.\n * Virtual DOM is generally constructed via [JSX](http://jasonformat.com/wtf-is-jsx).\n * @param {object} props Props (eg: JSX attributes) received from parent\n * element/component\n * @param {object} state The component's current state\n * @param {object} context Context object, as returned by the nearest\n * ancestor's `getChildContext()`\n * @returns {import('./index').ComponentChildren | void}\n */\nComponent.prototype.render = Fragment;\n\n/**\n * @param {import('./internal').VNode} vnode\n * @param {number | null} [childIndex]\n */\nexport function getDomSibling(vnode, childIndex) {\n\tif (childIndex == null) {\n\t\t// Use childIndex==null as a signal to resume the search from the vnode's sibling\n\t\treturn vnode._parent\n\t\t\t? getDomSibling(vnode._parent, vnode._parent._children.indexOf(vnode) + 1)\n\t\t\t: null;\n\t}\n\n\tlet sibling;\n\tfor (; childIndex < vnode._children.length; childIndex++) {\n\t\tsibling = vnode._children[childIndex];\n\n\t\tif (sibling != null && sibling._dom != null) {\n\t\t\t// Since updateParentDomPointers keeps _dom pointer correct,\n\t\t\t// we can rely on _dom to tell us if this subtree contains a\n\t\t\t// rendered DOM node, and what the first rendered DOM node is\n\t\t\treturn sibling._dom;\n\t\t}\n\t}\n\n\t// If we get here, we have not found a DOM node in this vnode's children.\n\t// We must resume from this vnode's sibling (in it's parent _children array)\n\t// Only climb up and search the parent if we aren't searching through a DOM\n\t// VNode (meaning we reached the DOM parent of the original vnode that began\n\t// the search)\n\treturn typeof vnode.type == 'function' ? getDomSibling(vnode) : null;\n}\n\n/**\n * Trigger in-place re-rendering of a component.\n * @param {import('./internal').Component} component The component to rerender\n */\nfunction renderComponent(component) {\n\tlet vnode = component._vnode,\n\t\toldDom = vnode._dom,\n\t\tparentDom = component._parentDom;\n\n\tif (parentDom) {\n\t\tlet commitQueue = [];\n\t\tconst oldVNode = assign({}, vnode);\n\t\toldVNode._original = vnode._original + 1;\n\n\t\tdiff(\n\t\t\tparentDom,\n\t\t\tvnode,\n\t\t\toldVNode,\n\t\t\tcomponent._globalContext,\n\t\t\tparentDom.ownerSVGElement !== undefined,\n\t\t\tvnode._hydrating != null ? [oldDom] : null,\n\t\t\tcommitQueue,\n\t\t\toldDom == null ? getDomSibling(vnode) : oldDom,\n\t\t\tvnode._hydrating\n\t\t);\n\t\tcommitRoot(commitQueue, vnode);\n\n\t\tif (vnode._dom != oldDom) {\n\t\t\tupdateParentDomPointers(vnode);\n\t\t}\n\t}\n}\n\n/**\n * @param {import('./internal').VNode} vnode\n */\nfunction updateParentDomPointers(vnode) {\n\tif ((vnode = vnode._parent) != null && vnode._component != null) {\n\t\tvnode._dom = vnode._component.base = null;\n\t\tfor (let i = 0; i < vnode._children.length; i++) {\n\t\t\tlet child = vnode._children[i];\n\t\t\tif (child != null && child._dom != null) {\n\t\t\t\tvnode._dom = vnode._component.base = child._dom;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn updateParentDomPointers(vnode);\n\t}\n}\n\n/**\n * The render queue\n * @type {Array}\n */\nlet rerenderQueue = [];\n\n/**\n * Asynchronously schedule a callback\n * @type {(cb: () => void) => void}\n */\n/* istanbul ignore next */\n// Note the following line isn't tree-shaken by rollup cuz of rollup/rollup#2566\nconst defer =\n\ttypeof Promise == 'function'\n\t\t? Promise.prototype.then.bind(Promise.resolve())\n\t\t: setTimeout;\n\n/*\n * The value of `Component.debounce` must asynchronously invoke the passed in callback. It is\n * important that contributors to Preact can consistently reason about what calls to `setState`, etc.\n * do, and when their effects will be applied. See the links below for some further reading on designing\n * asynchronous APIs.\n * * [Designing APIs for Asynchrony](https://blog.izs.me/2013/08/designing-apis-for-asynchrony)\n * * [Callbacks synchronous and asynchronous](https://blog.ometer.com/2011/07/24/callbacks-synchronous-and-asynchronous/)\n */\n\nlet prevDebounce;\n\n/**\n * Enqueue a rerender of a component\n * @param {import('./internal').Component} c The component to rerender\n */\nexport function enqueueRender(c) {\n\tif (\n\t\t(!c._dirty &&\n\t\t\t(c._dirty = true) &&\n\t\t\trerenderQueue.push(c) &&\n\t\t\t!process._rerenderCount++) ||\n\t\tprevDebounce !== options.debounceRendering\n\t) {\n\t\tprevDebounce = options.debounceRendering;\n\t\t(prevDebounce || defer)(process);\n\t}\n}\n\n/** Flush the render queue by rerendering all queued components */\nfunction process() {\n\tlet queue;\n\twhile ((process._rerenderCount = rerenderQueue.length)) {\n\t\tqueue = rerenderQueue.sort((a, b) => a._vnode._depth - b._vnode._depth);\n\t\trerenderQueue = [];\n\t\t// Don't update `renderCount` yet. Keep its value non-zero to prevent unnecessary\n\t\t// process() calls from getting scheduled while `queue` is still being consumed.\n\t\tqueue.some(c => {\n\t\t\tif (c._dirty) renderComponent(c);\n\t\t});\n\t}\n}\nprocess._rerenderCount = 0;\n","import { enqueueRender } from './component';\n\nexport let i = 0;\n\nexport function createContext(defaultValue, contextId) {\n\tcontextId = '__cC' + i++;\n\n\tconst context = {\n\t\t_id: contextId,\n\t\t_defaultValue: defaultValue,\n\t\t/** @type {import('./internal').FunctionComponent} */\n\t\tConsumer(props, contextValue) {\n\t\t\t// return props.children(\n\t\t\t// \tcontext[contextId] ? context[contextId].props.value : defaultValue\n\t\t\t// );\n\t\t\treturn props.children(contextValue);\n\t\t},\n\t\t/** @type {import('./internal').FunctionComponent} */\n\t\tProvider(props) {\n\t\t\tif (!this.getChildContext) {\n\t\t\t\tlet subs = [];\n\t\t\t\tlet ctx = {};\n\t\t\t\tctx[contextId] = this;\n\n\t\t\t\tthis.getChildContext = () => ctx;\n\n\t\t\t\tthis.shouldComponentUpdate = function(_props) {\n\t\t\t\t\tif (this.props.value !== _props.value) {\n\t\t\t\t\t\t// I think the forced value propagation here was only needed when `options.debounceRendering` was being bypassed:\n\t\t\t\t\t\t// https://github.com/preactjs/preact/commit/4d339fb803bea09e9f198abf38ca1bf8ea4b7771#diff-54682ce380935a717e41b8bfc54737f6R358\n\t\t\t\t\t\t// In those cases though, even with the value corrected, we're double-rendering all nodes.\n\t\t\t\t\t\t// It might be better to just tell folks not to use force-sync mode.\n\t\t\t\t\t\t// Currently, using `useContext()` in a class component will overwrite its `this.context` value.\n\t\t\t\t\t\t// subs.some(c => {\n\t\t\t\t\t\t// \tc.context = _props.value;\n\t\t\t\t\t\t// \tenqueueRender(c);\n\t\t\t\t\t\t// });\n\n\t\t\t\t\t\t// subs.some(c => {\n\t\t\t\t\t\t// \tc.context[contextId] = _props.value;\n\t\t\t\t\t\t// \tenqueueRender(c);\n\t\t\t\t\t\t// });\n\t\t\t\t\t\tsubs.some(enqueueRender);\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tthis.sub = c => {\n\t\t\t\t\tsubs.push(c);\n\t\t\t\t\tlet old = c.componentWillUnmount;\n\t\t\t\t\tc.componentWillUnmount = () => {\n\t\t\t\t\t\tsubs.splice(subs.indexOf(c), 1);\n\t\t\t\t\t\tif (old) old.call(c);\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn props.children;\n\t\t}\n\t};\n\n\t// Devtools needs access to the context object when it\n\t// encounters a Provider. This is necessary to support\n\t// setting `displayName` on the context object instead\n\t// of on the component itself. See:\n\t// https://reactjs.org/docs/context.html#contextdisplayname\n\n\treturn (context.Provider._contextRef = context.Consumer.contextType = context);\n}\n","export const EMPTY_OBJ = {};\nexport const EMPTY_ARR = [];\nexport const IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;\n","import { diff, unmount, applyRef } from './index';\nimport { createVNode, Fragment } from '../create-element';\nimport { EMPTY_OBJ, EMPTY_ARR } from '../constants';\nimport { getDomSibling } from '../component';\n\n/**\n * Diff the children of a virtual node\n * @param {import('../internal').PreactElement} parentDom The DOM element whose\n * children are being diffed\n * @param {import('../internal').ComponentChildren[]} renderResult\n * @param {import('../internal').VNode} newParentVNode The new virtual\n * node whose children should be diff'ed against oldParentVNode\n * @param {import('../internal').VNode} oldParentVNode The old virtual\n * node whose children should be diff'ed against newParentVNode\n * @param {object} globalContext The current context object - modified by getChildContext\n * @param {boolean} isSvg Whether or not this DOM node is an SVG node\n * @param {Array} excessDomChildren\n * @param {Array} commitQueue List of components\n * which have callbacks to invoke in commitRoot\n * @param {import('../internal').PreactElement} oldDom The current attached DOM\n * element any new dom elements should be placed around. Likely `null` on first\n * render (except when hydrating). Can be a sibling DOM element when diffing\n * Fragments that have siblings. In most cases, it starts out as `oldChildren[0]._dom`.\n * @param {boolean} isHydrating Whether or not we are in hydration\n */\nexport function diffChildren(\n\tparentDom,\n\trenderResult,\n\tnewParentVNode,\n\toldParentVNode,\n\tglobalContext,\n\tisSvg,\n\texcessDomChildren,\n\tcommitQueue,\n\toldDom,\n\tisHydrating\n) {\n\tlet i, j, oldVNode, childVNode, newDom, firstChildDom, refs;\n\n\t// This is a compression of oldParentVNode!=null && oldParentVNode != EMPTY_OBJ && oldParentVNode._children || EMPTY_ARR\n\t// as EMPTY_OBJ._children should be `undefined`.\n\tlet oldChildren = (oldParentVNode && oldParentVNode._children) || EMPTY_ARR;\n\n\tlet oldChildrenLength = oldChildren.length;\n\n\tnewParentVNode._children = [];\n\tfor (i = 0; i < renderResult.length; i++) {\n\t\tchildVNode = renderResult[i];\n\n\t\tif (childVNode == null || typeof childVNode == 'boolean') {\n\t\t\tchildVNode = newParentVNode._children[i] = null;\n\t\t}\n\t\t// If this newVNode is being reused (e.g.
{reuse}{reuse}
) in the same diff,\n\t\t// or we are rendering a component (e.g. setState) copy the oldVNodes so it can have\n\t\t// it's own DOM & etc. pointers\n\t\telse if (\n\t\t\ttypeof childVNode == 'string' ||\n\t\t\ttypeof childVNode == 'number' ||\n\t\t\t// eslint-disable-next-line valid-typeof\n\t\t\ttypeof childVNode == 'bigint'\n\t\t) {\n\t\t\tchildVNode = newParentVNode._children[i] = createVNode(\n\t\t\t\tnull,\n\t\t\t\tchildVNode,\n\t\t\t\tnull,\n\t\t\t\tnull,\n\t\t\t\tchildVNode\n\t\t\t);\n\t\t} else if (Array.isArray(childVNode)) {\n\t\t\tchildVNode = newParentVNode._children[i] = createVNode(\n\t\t\t\tFragment,\n\t\t\t\t{ children: childVNode },\n\t\t\t\tnull,\n\t\t\t\tnull,\n\t\t\t\tnull\n\t\t\t);\n\t\t} else if (childVNode._depth > 0) {\n\t\t\t// VNode is already in use, clone it. This can happen in the following\n\t\t\t// scenario:\n\t\t\t// const reuse =
\n\t\t\t//
{reuse}{reuse}
\n\t\t\tchildVNode = newParentVNode._children[i] = createVNode(\n\t\t\t\tchildVNode.type,\n\t\t\t\tchildVNode.props,\n\t\t\t\tchildVNode.key,\n\t\t\t\tnull,\n\t\t\t\tchildVNode._original\n\t\t\t);\n\t\t} else {\n\t\t\tchildVNode = newParentVNode._children[i] = childVNode;\n\t\t}\n\n\t\t// Terser removes the `continue` here and wraps the loop body\n\t\t// in a `if (childVNode) { ... } condition\n\t\tif (childVNode == null) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tchildVNode._parent = newParentVNode;\n\t\tchildVNode._depth = newParentVNode._depth + 1;\n\n\t\t// Check if we find a corresponding element in oldChildren.\n\t\t// If found, delete the array item by setting to `undefined`.\n\t\t// We use `undefined`, as `null` is reserved for empty placeholders\n\t\t// (holes).\n\t\toldVNode = oldChildren[i];\n\n\t\tif (\n\t\t\toldVNode === null ||\n\t\t\t(oldVNode &&\n\t\t\t\tchildVNode.key == oldVNode.key &&\n\t\t\t\tchildVNode.type === oldVNode.type)\n\t\t) {\n\t\t\toldChildren[i] = undefined;\n\t\t} else {\n\t\t\t// Either oldVNode === undefined or oldChildrenLength > 0,\n\t\t\t// so after this loop oldVNode == null or oldVNode is a valid value.\n\t\t\tfor (j = 0; j < oldChildrenLength; j++) {\n\t\t\t\toldVNode = oldChildren[j];\n\t\t\t\t// If childVNode is unkeyed, we only match similarly unkeyed nodes, otherwise we match by key.\n\t\t\t\t// We always match by type (in either case).\n\t\t\t\tif (\n\t\t\t\t\toldVNode &&\n\t\t\t\t\tchildVNode.key == oldVNode.key &&\n\t\t\t\t\tchildVNode.type === oldVNode.type\n\t\t\t\t) {\n\t\t\t\t\toldChildren[j] = undefined;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\toldVNode = null;\n\t\t\t}\n\t\t}\n\n\t\toldVNode = oldVNode || EMPTY_OBJ;\n\n\t\t// Morph the old element into the new one, but don't append it to the dom yet\n\t\tdiff(\n\t\t\tparentDom,\n\t\t\tchildVNode,\n\t\t\toldVNode,\n\t\t\tglobalContext,\n\t\t\tisSvg,\n\t\t\texcessDomChildren,\n\t\t\tcommitQueue,\n\t\t\toldDom,\n\t\t\tisHydrating\n\t\t);\n\n\t\tnewDom = childVNode._dom;\n\n\t\tif ((j = childVNode.ref) && oldVNode.ref != j) {\n\t\t\tif (!refs) refs = [];\n\t\t\tif (oldVNode.ref) refs.push(oldVNode.ref, null, childVNode);\n\t\t\trefs.push(j, childVNode._component || newDom, childVNode);\n\t\t}\n\n\t\tif (newDom != null) {\n\t\t\tif (firstChildDom == null) {\n\t\t\t\tfirstChildDom = newDom;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\ttypeof childVNode.type == 'function' &&\n\t\t\t\tchildVNode._children != null && // Can be null if childVNode suspended\n\t\t\t\tchildVNode._children === oldVNode._children\n\t\t\t) {\n\t\t\t\tchildVNode._nextDom = oldDom = reorderChildren(\n\t\t\t\t\tchildVNode,\n\t\t\t\t\toldDom,\n\t\t\t\t\tparentDom\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\toldDom = placeChild(\n\t\t\t\t\tparentDom,\n\t\t\t\t\tchildVNode,\n\t\t\t\t\toldVNode,\n\t\t\t\t\toldChildren,\n\t\t\t\t\tnewDom,\n\t\t\t\t\toldDom\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Browsers will infer an option's `value` from `textContent` when\n\t\t\t// no value is present. This essentially bypasses our code to set it\n\t\t\t// later in `diff()`. It works fine in all browsers except for IE11\n\t\t\t// where it breaks setting `select.value`. There it will be always set\n\t\t\t// to an empty string. Re-applying an options value will fix that, so\n\t\t\t// there are probably some internal data structures that aren't\n\t\t\t// updated properly.\n\t\t\t//\n\t\t\t// To fix it we make sure to reset the inferred value, so that our own\n\t\t\t// value check in `diff()` won't be skipped.\n\t\t\tif (!isHydrating && newParentVNode.type === 'option') {\n\t\t\t\t// @ts-ignore We have validated that the type of parentDOM is 'option'\n\t\t\t\t// in the above check\n\t\t\t\tparentDom.value = '';\n\t\t\t} else if (typeof newParentVNode.type == 'function') {\n\t\t\t\t// Because the newParentVNode is Fragment-like, we need to set it's\n\t\t\t\t// _nextDom property to the nextSibling of its last child DOM node.\n\t\t\t\t//\n\t\t\t\t// `oldDom` contains the correct value here because if the last child\n\t\t\t\t// is a Fragment-like, then oldDom has already been set to that child's _nextDom.\n\t\t\t\t// If the last child is a DOM VNode, then oldDom will be set to that DOM\n\t\t\t\t// node's nextSibling.\n\t\t\t\tnewParentVNode._nextDom = oldDom;\n\t\t\t}\n\t\t} else if (\n\t\t\toldDom &&\n\t\t\toldVNode._dom == oldDom &&\n\t\t\toldDom.parentNode != parentDom\n\t\t) {\n\t\t\t// The above condition is to handle null placeholders. See test in placeholder.test.js:\n\t\t\t// `efficiently replace null placeholders in parent rerenders`\n\t\t\toldDom = getDomSibling(oldVNode);\n\t\t}\n\t}\n\n\tnewParentVNode._dom = firstChildDom;\n\n\t// Remove remaining oldChildren if there are any.\n\tfor (i = oldChildrenLength; i--; ) {\n\t\tif (oldChildren[i] != null) {\n\t\t\tif (\n\t\t\t\ttypeof newParentVNode.type == 'function' &&\n\t\t\t\toldChildren[i]._dom != null &&\n\t\t\t\toldChildren[i]._dom == newParentVNode._nextDom\n\t\t\t) {\n\t\t\t\t// If the newParentVNode.__nextDom points to a dom node that is about to\n\t\t\t\t// be unmounted, then get the next sibling of that vnode and set\n\t\t\t\t// _nextDom to it\n\t\t\t\tnewParentVNode._nextDom = getDomSibling(oldParentVNode, i + 1);\n\t\t\t}\n\n\t\t\tunmount(oldChildren[i], oldChildren[i]);\n\t\t}\n\t}\n\n\t// Set refs only after unmount\n\tif (refs) {\n\t\tfor (i = 0; i < refs.length; i++) {\n\t\t\tapplyRef(refs[i], refs[++i], refs[++i]);\n\t\t}\n\t}\n}\n\nfunction reorderChildren(childVNode, oldDom, parentDom) {\n\tfor (let tmp = 0; tmp < childVNode._children.length; tmp++) {\n\t\tlet vnode = childVNode._children[tmp];\n\t\tif (vnode) {\n\t\t\t// We typically enter this code path on sCU bailout, where we copy\n\t\t\t// oldVNode._children to newVNode._children. If that is the case, we need\n\t\t\t// to update the old children's _parent pointer to point to the newVNode\n\t\t\t// (childVNode here).\n\t\t\tvnode._parent = childVNode;\n\n\t\t\tif (typeof vnode.type == 'function') {\n\t\t\t\toldDom = reorderChildren(vnode, oldDom, parentDom);\n\t\t\t} else {\n\t\t\t\toldDom = placeChild(\n\t\t\t\t\tparentDom,\n\t\t\t\t\tvnode,\n\t\t\t\t\tvnode,\n\t\t\t\t\tchildVNode._children,\n\t\t\t\t\tvnode._dom,\n\t\t\t\t\toldDom\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn oldDom;\n}\n\n/**\n * Flatten and loop through the children of a virtual node\n * @param {import('../index').ComponentChildren} children The unflattened\n * children of a virtual node\n * @returns {import('../internal').VNode[]}\n */\nexport function toChildArray(children, out) {\n\tout = out || [];\n\tif (children == null || typeof children == 'boolean') {\n\t} else if (Array.isArray(children)) {\n\t\tchildren.some(child => {\n\t\t\ttoChildArray(child, out);\n\t\t});\n\t} else {\n\t\tout.push(children);\n\t}\n\treturn out;\n}\n\nfunction placeChild(\n\tparentDom,\n\tchildVNode,\n\toldVNode,\n\toldChildren,\n\tnewDom,\n\toldDom\n) {\n\tlet nextDom;\n\tif (childVNode._nextDom !== undefined) {\n\t\t// Only Fragments or components that return Fragment like VNodes will\n\t\t// have a non-undefined _nextDom. Continue the diff from the sibling\n\t\t// of last DOM child of this child VNode\n\t\tnextDom = childVNode._nextDom;\n\n\t\t// Eagerly cleanup _nextDom. We don't need to persist the value because\n\t\t// it is only used by `diffChildren` to determine where to resume the diff after\n\t\t// diffing Components and Fragments. Once we store it the nextDOM local var, we\n\t\t// can clean up the property\n\t\tchildVNode._nextDom = undefined;\n\t} else if (\n\t\toldVNode == null ||\n\t\tnewDom != oldDom ||\n\t\tnewDom.parentNode == null\n\t) {\n\t\touter: if (oldDom == null || oldDom.parentNode !== parentDom) {\n\t\t\tparentDom.appendChild(newDom);\n\t\t\tnextDom = null;\n\t\t} else {\n\t\t\t// `j href (xlink:href was removed from SVG and isn't needed)\n\t\t\t// - className --> class\n\t\t\tname = name.replace(/xlink[H:h]/, 'h').replace(/sName$/, 's');\n\t\t} else if (\n\t\t\tname !== 'href' &&\n\t\t\tname !== 'list' &&\n\t\t\tname !== 'form' &&\n\t\t\t// Default value in browsers is `-1` and an empty string is\n\t\t\t// cast to `0` instead\n\t\t\tname !== 'tabIndex' &&\n\t\t\tname !== 'download' &&\n\t\t\tname in dom\n\t\t) {\n\t\t\ttry {\n\t\t\t\tdom[name] = value == null ? '' : value;\n\t\t\t\t// labelled break is 1b smaller here than a return statement (sorry)\n\t\t\t\tbreak o;\n\t\t\t} catch (e) {}\n\t\t}\n\n\t\t// ARIA-attributes have a different notion of boolean values.\n\t\t// The value `false` is different from the attribute not\n\t\t// existing on the DOM, so we can't remove it. For non-boolean\n\t\t// ARIA-attributes we could treat false as a removal, but the\n\t\t// amount of exceptions would cost us too many bytes. On top of\n\t\t// that other VDOM frameworks also always stringify `false`.\n\n\t\tif (typeof value === 'function') {\n\t\t\t// never serialize functions as attribute values\n\t\t} else if (\n\t\t\tvalue != null &&\n\t\t\t(value !== false || (name[0] === 'a' && name[1] === 'r'))\n\t\t) {\n\t\t\tdom.setAttribute(name, value);\n\t\t} else {\n\t\t\tdom.removeAttribute(name);\n\t\t}\n\t}\n}\n\n/**\n * Proxy an event to hooked event handlers\n * @param {Event} e The event object from the browser\n * @private\n */\nfunction eventProxy(e) {\n\tthis._listeners[e.type + false](options.event ? options.event(e) : e);\n}\n\nfunction eventProxyCapture(e) {\n\tthis._listeners[e.type + true](options.event ? options.event(e) : e);\n}\n","import { EMPTY_OBJ } from '../constants';\nimport { Component, getDomSibling } from '../component';\nimport { Fragment } from '../create-element';\nimport { diffChildren } from './children';\nimport { diffProps, setProperty } from './props';\nimport { assign, removeNode, slice } from '../util';\nimport options from '../options';\n\n/**\n * Diff two virtual nodes and apply proper changes to the DOM\n * @param {import('../internal').PreactElement} parentDom The parent of the DOM element\n * @param {import('../internal').VNode} newVNode The new virtual node\n * @param {import('../internal').VNode} oldVNode The old virtual node\n * @param {object} globalContext The current context object. Modified by getChildContext\n * @param {boolean} isSvg Whether or not this element is an SVG node\n * @param {Array} excessDomChildren\n * @param {Array} commitQueue List of components\n * which have callbacks to invoke in commitRoot\n * @param {import('../internal').PreactElement} oldDom The current attached DOM\n * element any new dom elements should be placed around. Likely `null` on first\n * render (except when hydrating). Can be a sibling DOM element when diffing\n * Fragments that have siblings. In most cases, it starts out as `oldChildren[0]._dom`.\n * @param {boolean} [isHydrating] Whether or not we are in hydration\n */\nexport function diff(\n\tparentDom,\n\tnewVNode,\n\toldVNode,\n\tglobalContext,\n\tisSvg,\n\texcessDomChildren,\n\tcommitQueue,\n\toldDom,\n\tisHydrating\n) {\n\tlet tmp,\n\t\tnewType = newVNode.type;\n\n\t// When passing through createElement it assigns the object\n\t// constructor as undefined. This to prevent JSON-injection.\n\tif (newVNode.constructor !== undefined) return null;\n\n\t// If the previous diff bailed out, resume creating/hydrating.\n\tif (oldVNode._hydrating != null) {\n\t\tisHydrating = oldVNode._hydrating;\n\t\toldDom = newVNode._dom = oldVNode._dom;\n\t\t// if we resume, we want the tree to be \"unlocked\"\n\t\tnewVNode._hydrating = null;\n\t\texcessDomChildren = [oldDom];\n\t}\n\n\tif ((tmp = options._diff)) tmp(newVNode);\n\n\ttry {\n\t\touter: if (typeof newType == 'function') {\n\t\t\tlet c, isNew, oldProps, oldState, snapshot, clearProcessingException;\n\t\t\tlet newProps = newVNode.props;\n\n\t\t\t// Necessary for createContext api. Setting this property will pass\n\t\t\t// the context value as `this.context` just for this component.\n\t\t\ttmp = newType.contextType;\n\t\t\tlet provider = tmp && globalContext[tmp._id];\n\t\t\tlet componentContext = tmp\n\t\t\t\t? provider\n\t\t\t\t\t? provider.props.value\n\t\t\t\t\t: tmp._defaultValue\n\t\t\t\t: globalContext;\n\n\t\t\t// Get component and set it to `c`\n\t\t\tif (oldVNode._component) {\n\t\t\t\tc = newVNode._component = oldVNode._component;\n\t\t\t\tclearProcessingException = c._processingException = c._pendingError;\n\t\t\t} else {\n\t\t\t\t// Instantiate the new component\n\t\t\t\tif ('prototype' in newType && newType.prototype.render) {\n\t\t\t\t\t// @ts-ignore The check above verifies that newType is suppose to be constructed\n\t\t\t\t\tnewVNode._component = c = new newType(newProps, componentContext); // eslint-disable-line new-cap\n\t\t\t\t} else {\n\t\t\t\t\t// @ts-ignore Trust me, Component implements the interface we want\n\t\t\t\t\tnewVNode._component = c = new Component(newProps, componentContext);\n\t\t\t\t\tc.constructor = newType;\n\t\t\t\t\tc.render = doRender;\n\t\t\t\t}\n\t\t\t\tif (provider) provider.sub(c);\n\n\t\t\t\tc.props = newProps;\n\t\t\t\tif (!c.state) c.state = {};\n\t\t\t\tc.context = componentContext;\n\t\t\t\tc._globalContext = globalContext;\n\t\t\t\tisNew = c._dirty = true;\n\t\t\t\tc._renderCallbacks = [];\n\t\t\t}\n\n\t\t\t// Invoke getDerivedStateFromProps\n\t\t\tif (c._nextState == null) {\n\t\t\t\tc._nextState = c.state;\n\t\t\t}\n\t\t\tif (newType.getDerivedStateFromProps != null) {\n\t\t\t\tif (c._nextState == c.state) {\n\t\t\t\t\tc._nextState = assign({}, c._nextState);\n\t\t\t\t}\n\n\t\t\t\tassign(\n\t\t\t\t\tc._nextState,\n\t\t\t\t\tnewType.getDerivedStateFromProps(newProps, c._nextState)\n\t\t\t\t);\n\t\t\t}\n\n\t\t\toldProps = c.props;\n\t\t\toldState = c.state;\n\n\t\t\t// Invoke pre-render lifecycle methods\n\t\t\tif (isNew) {\n\t\t\t\tif (\n\t\t\t\t\tnewType.getDerivedStateFromProps == null &&\n\t\t\t\t\tc.componentWillMount != null\n\t\t\t\t) {\n\t\t\t\t\tc.componentWillMount();\n\t\t\t\t}\n\n\t\t\t\tif (c.componentDidMount != null) {\n\t\t\t\t\tc._renderCallbacks.push(c.componentDidMount);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (\n\t\t\t\t\tnewType.getDerivedStateFromProps == null &&\n\t\t\t\t\tnewProps !== oldProps &&\n\t\t\t\t\tc.componentWillReceiveProps != null\n\t\t\t\t) {\n\t\t\t\t\tc.componentWillReceiveProps(newProps, componentContext);\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\t(!c._force &&\n\t\t\t\t\t\tc.shouldComponentUpdate != null &&\n\t\t\t\t\t\tc.shouldComponentUpdate(\n\t\t\t\t\t\t\tnewProps,\n\t\t\t\t\t\t\tc._nextState,\n\t\t\t\t\t\t\tcomponentContext\n\t\t\t\t\t\t) === false) ||\n\t\t\t\t\tnewVNode._original === oldVNode._original\n\t\t\t\t) {\n\t\t\t\t\tc.props = newProps;\n\t\t\t\t\tc.state = c._nextState;\n\t\t\t\t\t// More info about this here: https://gist.github.com/JoviDeCroock/bec5f2ce93544d2e6070ef8e0036e4e8\n\t\t\t\t\tif (newVNode._original !== oldVNode._original) c._dirty = false;\n\t\t\t\t\tc._vnode = newVNode;\n\t\t\t\t\tnewVNode._dom = oldVNode._dom;\n\t\t\t\t\tnewVNode._children = oldVNode._children;\n\t\t\t\t\tnewVNode._children.forEach(vnode => {\n\t\t\t\t\t\tif (vnode) vnode._parent = newVNode;\n\t\t\t\t\t});\n\t\t\t\t\tif (c._renderCallbacks.length) {\n\t\t\t\t\t\tcommitQueue.push(c);\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak outer;\n\t\t\t\t}\n\n\t\t\t\tif (c.componentWillUpdate != null) {\n\t\t\t\t\tc.componentWillUpdate(newProps, c._nextState, componentContext);\n\t\t\t\t}\n\n\t\t\t\tif (c.componentDidUpdate != null) {\n\t\t\t\t\tc._renderCallbacks.push(() => {\n\t\t\t\t\t\tc.componentDidUpdate(oldProps, oldState, snapshot);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tc.context = componentContext;\n\t\t\tc.props = newProps;\n\t\t\tc.state = c._nextState;\n\n\t\t\tif ((tmp = options._render)) tmp(newVNode);\n\n\t\t\tc._dirty = false;\n\t\t\tc._vnode = newVNode;\n\t\t\tc._parentDom = parentDom;\n\n\t\t\ttmp = c.render(c.props, c.state, c.context);\n\n\t\t\t// Handle setState called in render, see #2553\n\t\t\tc.state = c._nextState;\n\n\t\t\tif (c.getChildContext != null) {\n\t\t\t\tglobalContext = assign(assign({}, globalContext), c.getChildContext());\n\t\t\t}\n\n\t\t\tif (!isNew && c.getSnapshotBeforeUpdate != null) {\n\t\t\t\tsnapshot = c.getSnapshotBeforeUpdate(oldProps, oldState);\n\t\t\t}\n\n\t\t\tlet isTopLevelFragment =\n\t\t\t\ttmp != null && tmp.type === Fragment && tmp.key == null;\n\t\t\tlet renderResult = isTopLevelFragment ? tmp.props.children : tmp;\n\n\t\t\tdiffChildren(\n\t\t\t\tparentDom,\n\t\t\t\tArray.isArray(renderResult) ? renderResult : [renderResult],\n\t\t\t\tnewVNode,\n\t\t\t\toldVNode,\n\t\t\t\tglobalContext,\n\t\t\t\tisSvg,\n\t\t\t\texcessDomChildren,\n\t\t\t\tcommitQueue,\n\t\t\t\toldDom,\n\t\t\t\tisHydrating\n\t\t\t);\n\n\t\t\tc.base = newVNode._dom;\n\n\t\t\t// We successfully rendered this VNode, unset any stored hydration/bailout state:\n\t\t\tnewVNode._hydrating = null;\n\n\t\t\tif (c._renderCallbacks.length) {\n\t\t\t\tcommitQueue.push(c);\n\t\t\t}\n\n\t\t\tif (clearProcessingException) {\n\t\t\t\tc._pendingError = c._processingException = null;\n\t\t\t}\n\n\t\t\tc._force = false;\n\t\t} else if (\n\t\t\texcessDomChildren == null &&\n\t\t\tnewVNode._original === oldVNode._original\n\t\t) {\n\t\t\tnewVNode._children = oldVNode._children;\n\t\t\tnewVNode._dom = oldVNode._dom;\n\t\t} else {\n\t\t\tnewVNode._dom = diffElementNodes(\n\t\t\t\toldVNode._dom,\n\t\t\t\tnewVNode,\n\t\t\t\toldVNode,\n\t\t\t\tglobalContext,\n\t\t\t\tisSvg,\n\t\t\t\texcessDomChildren,\n\t\t\t\tcommitQueue,\n\t\t\t\tisHydrating\n\t\t\t);\n\t\t}\n\n\t\tif ((tmp = options.diffed)) tmp(newVNode);\n\t} catch (e) {\n\t\tnewVNode._original = null;\n\t\t// if hydrating or creating initial tree, bailout preserves DOM:\n\t\tif (isHydrating || excessDomChildren != null) {\n\t\t\tnewVNode._dom = oldDom;\n\t\t\tnewVNode._hydrating = !!isHydrating;\n\t\t\texcessDomChildren[excessDomChildren.indexOf(oldDom)] = null;\n\t\t\t// ^ could possibly be simplified to:\n\t\t\t// excessDomChildren.length = 0;\n\t\t}\n\t\toptions._catchError(e, newVNode, oldVNode);\n\t}\n}\n\n/**\n * @param {Array} commitQueue List of components\n * which have callbacks to invoke in commitRoot\n * @param {import('../internal').VNode} root\n */\nexport function commitRoot(commitQueue, root) {\n\tif (options._commit) options._commit(root, commitQueue);\n\n\tcommitQueue.some(c => {\n\t\ttry {\n\t\t\t// @ts-ignore Reuse the commitQueue variable here so the type changes\n\t\t\tcommitQueue = c._renderCallbacks;\n\t\t\tc._renderCallbacks = [];\n\t\t\tcommitQueue.some(cb => {\n\t\t\t\t// @ts-ignore See above ts-ignore on commitQueue\n\t\t\t\tcb.call(c);\n\t\t\t});\n\t\t} catch (e) {\n\t\t\toptions._catchError(e, c._vnode);\n\t\t}\n\t});\n}\n\n/**\n * Diff two virtual nodes representing DOM element\n * @param {import('../internal').PreactElement} dom The DOM element representing\n * the virtual nodes being diffed\n * @param {import('../internal').VNode} newVNode The new virtual node\n * @param {import('../internal').VNode} oldVNode The old virtual node\n * @param {object} globalContext The current context object\n * @param {boolean} isSvg Whether or not this DOM node is an SVG node\n * @param {*} excessDomChildren\n * @param {Array} commitQueue List of components\n * which have callbacks to invoke in commitRoot\n * @param {boolean} isHydrating Whether or not we are in hydration\n * @returns {import('../internal').PreactElement}\n */\nfunction diffElementNodes(\n\tdom,\n\tnewVNode,\n\toldVNode,\n\tglobalContext,\n\tisSvg,\n\texcessDomChildren,\n\tcommitQueue,\n\tisHydrating\n) {\n\tlet oldProps = oldVNode.props;\n\tlet newProps = newVNode.props;\n\tlet nodeType = newVNode.type;\n\tlet i = 0;\n\n\t// Tracks entering and exiting SVG namespace when descending through the tree.\n\tif (nodeType === 'svg') isSvg = true;\n\n\tif (excessDomChildren != null) {\n\t\tfor (; i < excessDomChildren.length; i++) {\n\t\t\tconst child = excessDomChildren[i];\n\n\t\t\t// if newVNode matches an element in excessDomChildren or the `dom`\n\t\t\t// argument matches an element in excessDomChildren, remove it from\n\t\t\t// excessDomChildren so it isn't later removed in diffChildren\n\t\t\tif (\n\t\t\t\tchild &&\n\t\t\t\t(child === dom ||\n\t\t\t\t\t(nodeType ? child.localName == nodeType : child.nodeType == 3))\n\t\t\t) {\n\t\t\t\tdom = child;\n\t\t\t\texcessDomChildren[i] = null;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (dom == null) {\n\t\tif (nodeType === null) {\n\t\t\t// @ts-ignore createTextNode returns Text, we expect PreactElement\n\t\t\treturn document.createTextNode(newProps);\n\t\t}\n\n\t\tif (isSvg) {\n\t\t\tdom = document.createElementNS(\n\t\t\t\t'http://www.w3.org/2000/svg',\n\t\t\t\t// @ts-ignore We know `newVNode.type` is a string\n\t\t\t\tnodeType\n\t\t\t);\n\t\t} else {\n\t\t\tdom = document.createElement(\n\t\t\t\t// @ts-ignore We know `newVNode.type` is a string\n\t\t\t\tnodeType,\n\t\t\t\tnewProps.is && newProps\n\t\t\t);\n\t\t}\n\n\t\t// we created a new parent, so none of the previously attached children can be reused:\n\t\texcessDomChildren = null;\n\t\t// we are creating a new node, so we can assume this is a new subtree (in case we are hydrating), this deopts the hydrate\n\t\tisHydrating = false;\n\t}\n\n\tif (nodeType === null) {\n\t\t// During hydration, we still have to split merged text from SSR'd HTML.\n\t\tif (oldProps !== newProps && (!isHydrating || dom.data !== newProps)) {\n\t\t\tdom.data = newProps;\n\t\t}\n\t} else {\n\t\t// If excessDomChildren was not null, repopulate it with the current element's children:\n\t\texcessDomChildren = excessDomChildren && slice.call(dom.childNodes);\n\n\t\toldProps = oldVNode.props || EMPTY_OBJ;\n\n\t\tlet oldHtml = oldProps.dangerouslySetInnerHTML;\n\t\tlet newHtml = newProps.dangerouslySetInnerHTML;\n\n\t\t// During hydration, props are not diffed at all (including dangerouslySetInnerHTML)\n\t\t// @TODO we should warn in debug mode when props don't match here.\n\t\tif (!isHydrating) {\n\t\t\t// But, if we are in a situation where we are using existing DOM (e.g. replaceNode)\n\t\t\t// we should read the existing DOM attributes to diff them\n\t\t\tif (excessDomChildren != null) {\n\t\t\t\toldProps = {};\n\t\t\t\tfor (i = 0; i < dom.attributes.length; i++) {\n\t\t\t\t\toldProps[dom.attributes[i].name] = dom.attributes[i].value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (newHtml || oldHtml) {\n\t\t\t\t// Avoid re-applying the same '__html' if it did not changed between re-render\n\t\t\t\tif (\n\t\t\t\t\t!newHtml ||\n\t\t\t\t\t((!oldHtml || newHtml.__html != oldHtml.__html) &&\n\t\t\t\t\t\tnewHtml.__html !== dom.innerHTML)\n\t\t\t\t) {\n\t\t\t\t\tdom.innerHTML = (newHtml && newHtml.__html) || '';\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tdiffProps(dom, newProps, oldProps, isSvg, isHydrating);\n\n\t\t// If the new vnode didn't have dangerouslySetInnerHTML, diff its children\n\t\tif (newHtml) {\n\t\t\tnewVNode._children = [];\n\t\t} else {\n\t\t\ti = newVNode.props.children;\n\t\t\tdiffChildren(\n\t\t\t\tdom,\n\t\t\t\tArray.isArray(i) ? i : [i],\n\t\t\t\tnewVNode,\n\t\t\t\toldVNode,\n\t\t\t\tglobalContext,\n\t\t\t\tisSvg && nodeType !== 'foreignObject',\n\t\t\t\texcessDomChildren,\n\t\t\t\tcommitQueue,\n\t\t\t\texcessDomChildren\n\t\t\t\t\t? excessDomChildren[0]\n\t\t\t\t\t: oldVNode._children && getDomSibling(oldVNode, 0),\n\t\t\t\tisHydrating\n\t\t\t);\n\n\t\t\t// Remove children that are not part of any vnode.\n\t\t\tif (excessDomChildren != null) {\n\t\t\t\tfor (i = excessDomChildren.length; i--; ) {\n\t\t\t\t\tif (excessDomChildren[i] != null) removeNode(excessDomChildren[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// (as above, don't diff props during hydration)\n\t\tif (!isHydrating) {\n\t\t\tif (\n\t\t\t\t'value' in newProps &&\n\t\t\t\t(i = newProps.value) !== undefined &&\n\t\t\t\t// #2756 For the -element the initial value is 0,\n\t\t\t\t// despite the attribute not being present. When the attribute\n\t\t\t\t// is missing the progress bar is treated as indeterminate.\n\t\t\t\t// To fix that we'll always update it when it is 0 for progress elements\n\t\t\t\t(i !== dom.value || (nodeType === 'progress' && !i))\n\t\t\t) {\n\t\t\t\tsetProperty(dom, 'value', i, oldProps.value, false);\n\t\t\t}\n\t\t\tif (\n\t\t\t\t'checked' in newProps &&\n\t\t\t\t(i = newProps.checked) !== undefined &&\n\t\t\t\ti !== dom.checked\n\t\t\t) {\n\t\t\t\tsetProperty(dom, 'checked', i, oldProps.checked, false);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn dom;\n}\n\n/**\n * Invoke or update a ref, depending on whether it is a function or object ref.\n * @param {object|function} ref\n * @param {any} value\n * @param {import('../internal').VNode} vnode\n */\nexport function applyRef(ref, value, vnode) {\n\ttry {\n\t\tif (typeof ref == 'function') ref(value);\n\t\telse ref.current = value;\n\t} catch (e) {\n\t\toptions._catchError(e, vnode);\n\t}\n}\n\n/**\n * Unmount a virtual node from the tree and apply DOM changes\n * @param {import('../internal').VNode} vnode The virtual node to unmount\n * @param {import('../internal').VNode} parentVNode The parent of the VNode that\n * initiated the unmount\n * @param {boolean} [skipRemove] Flag that indicates that a parent node of the\n * current element is already detached from the DOM.\n */\nexport function unmount(vnode, parentVNode, skipRemove) {\n\tlet r;\n\tif (options.unmount) options.unmount(vnode);\n\n\tif ((r = vnode.ref)) {\n\t\tif (!r.current || r.current === vnode._dom) applyRef(r, null, parentVNode);\n\t}\n\n\tif ((r = vnode._component) != null) {\n\t\tif (r.componentWillUnmount) {\n\t\t\ttry {\n\t\t\t\tr.componentWillUnmount();\n\t\t\t} catch (e) {\n\t\t\t\toptions._catchError(e, parentVNode);\n\t\t\t}\n\t\t}\n\n\t\tr.base = r._parentDom = null;\n\t}\n\n\tif ((r = vnode._children)) {\n\t\tfor (let i = 0; i < r.length; i++) {\n\t\t\tif (r[i]) {\n\t\t\t\tunmount(r[i], parentVNode, typeof vnode.type != 'function');\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!skipRemove && vnode._dom != null) removeNode(vnode._dom);\n\n\t// Must be set to `undefined` to properly clean up `_nextDom`\n\t// for which `null` is a valid value. See comment in `create-element.js`\n\tvnode._dom = vnode._nextDom = undefined;\n}\n\n/** The `.render()` method for a PFC backing instance. */\nfunction doRender(props, state, context) {\n\treturn this.constructor(props, context);\n}\n","import { EMPTY_OBJ } from './constants';\nimport { commitRoot, diff } from './diff/index';\nimport { createElement, Fragment } from './create-element';\nimport options from './options';\nimport { slice } from './util';\n\n/**\n * Render a Preact virtual node into a DOM element\n * @param {import('./internal').ComponentChild} vnode The virtual node to render\n * @param {import('./internal').PreactElement} parentDom The DOM element to\n * render into\n * @param {import('./internal').PreactElement | object} [replaceNode] Optional: Attempt to re-use an\n * existing DOM tree rooted at `replaceNode`\n */\nexport function render(vnode, parentDom, replaceNode) {\n\tif (options._root) options._root(vnode, parentDom);\n\n\t// We abuse the `replaceNode` parameter in `hydrate()` to signal if we are in\n\t// hydration mode or not by passing the `hydrate` function instead of a DOM\n\t// element..\n\tlet isHydrating = typeof replaceNode === 'function';\n\n\t// To be able to support calling `render()` multiple times on the same\n\t// DOM node, we need to obtain a reference to the previous tree. We do\n\t// this by assigning a new `_children` property to DOM nodes which points\n\t// to the last rendered tree. By default this property is not present, which\n\t// means that we are mounting a new tree for the first time.\n\tlet oldVNode = isHydrating\n\t\t? null\n\t\t: (replaceNode && replaceNode._children) || parentDom._children;\n\n\tvnode = (\n\t\t(!isHydrating && replaceNode) ||\n\t\tparentDom\n\t)._children = createElement(Fragment, null, [vnode]);\n\n\t// List of effects that need to be called after diffing.\n\tlet commitQueue = [];\n\tdiff(\n\t\tparentDom,\n\t\t// Determine the new vnode tree and store it on the DOM element on\n\t\t// our custom `_children` property.\n\t\tvnode,\n\t\toldVNode || EMPTY_OBJ,\n\t\tEMPTY_OBJ,\n\t\tparentDom.ownerSVGElement !== undefined,\n\t\t!isHydrating && replaceNode\n\t\t\t? [replaceNode]\n\t\t\t: oldVNode\n\t\t\t? null\n\t\t\t: parentDom.firstChild\n\t\t\t? slice.call(parentDom.childNodes)\n\t\t\t: null,\n\t\tcommitQueue,\n\t\t!isHydrating && replaceNode\n\t\t\t? replaceNode\n\t\t\t: oldVNode\n\t\t\t? oldVNode._dom\n\t\t\t: parentDom.firstChild,\n\t\tisHydrating\n\t);\n\n\t// Flush all queued effects\n\tcommitRoot(commitQueue, vnode);\n}\n\n/**\n * Update an existing DOM element with data from a Preact virtual node\n * @param {import('./internal').ComponentChild} vnode The virtual node to render\n * @param {import('./internal').PreactElement} parentDom The DOM element to\n * update\n */\nexport function hydrate(vnode, parentDom) {\n\trender(vnode, parentDom, hydrate);\n}\n","/**\n * Find the closest error boundary to a thrown error and call it\n * @param {object} error The thrown value\n * @param {import('../internal').VNode} vnode The vnode that threw\n * the error that was caught (except for unmounting when this parameter\n * is the highest parent that was being unmounted)\n */\nexport function _catchError(error, vnode) {\n\t/** @type {import('../internal').Component} */\n\tlet component, ctor, handled;\n\n\tfor (; (vnode = vnode._parent); ) {\n\t\tif ((component = vnode._component) && !component._processingException) {\n\t\t\ttry {\n\t\t\t\tctor = component.constructor;\n\n\t\t\t\tif (ctor && ctor.getDerivedStateFromError != null) {\n\t\t\t\t\tcomponent.setState(ctor.getDerivedStateFromError(error));\n\t\t\t\t\thandled = component._dirty;\n\t\t\t\t}\n\n\t\t\t\tif (component.componentDidCatch != null) {\n\t\t\t\t\tcomponent.componentDidCatch(error);\n\t\t\t\t\thandled = component._dirty;\n\t\t\t\t}\n\n\t\t\t\t// This is an error boundary. Mark it as having bailed out, and whether it was mid-hydration.\n\t\t\t\tif (handled) {\n\t\t\t\t\treturn (component._pendingError = component);\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\terror = e;\n\t\t\t}\n\t\t}\n\t}\n\n\tthrow error;\n}\n","import { assign, slice } from './util';\nimport { createVNode } from './create-element';\n\n/**\n * Clones the given VNode, optionally adding attributes/props and replacing its children.\n * @param {import('./internal').VNode} vnode The virtual DOM element to clone\n * @param {object} props Attributes/props to add when cloning\n * @param {Array} rest Any additional arguments will be used as replacement children.\n * @returns {import('./internal').VNode}\n */\nexport function cloneElement(vnode, props, children) {\n\tlet normalizedProps = assign({}, vnode.props),\n\t\tkey,\n\t\tref,\n\t\ti;\n\tfor (i in props) {\n\t\tif (i == 'key') key = props[i];\n\t\telse if (i == 'ref') ref = props[i];\n\t\telse normalizedProps[i] = props[i];\n\t}\n\n\tif (arguments.length > 2) {\n\t\tnormalizedProps.children =\n\t\t\targuments.length > 3 ? slice.call(arguments, 2) : children;\n\t}\n\n\treturn createVNode(\n\t\tvnode.type,\n\t\tnormalizedProps,\n\t\tkey || vnode.key,\n\t\tref || vnode.ref,\n\t\tnull\n\t);\n}\n","import * as preact from './index.js';\nif (typeof module < 'u') module.exports = preact;\nelse self.preact = preact;\n"],"names":["slice","options","vnodeId","isValidElement","rerenderQueue","defer","prevDebounce","i","EMPTY_OBJ","EMPTY_ARR","IS_NON_DIMENSIONAL","assign","obj","props","removeNode","node","parentNode","removeChild","createElement","type","children","key","ref","normalizedProps","arguments","length","call","defaultProps","undefined","createVNode","original","vnode","constructor","Fragment","Component","context","getDomSibling","childIndex","indexOf","sibling","updateParentDomPointers","child","base","enqueueRender","c","push","process","debounceRendering","queue","sort","a","b","some","component","commitQueue","oldVNode","oldDom","parentDom","diff","ownerSVGElement","commitRoot","diffChildren","renderResult","newParentVNode","oldParentVNode","globalContext","isSvg","excessDomChildren","isHydrating","j","childVNode","newDom","firstChildDom","refs","oldChildren","oldChildrenLength","Array","isArray","reorderChildren","placeChild","value","unmount","applyRef","tmp","nextDom","sibDom","outer","appendChild","nextSibling","insertBefore","diffProps","dom","newProps","oldProps","hydrate","setProperty","setStyle","style","test","name","oldValue","useCapture","o","cssText","replace","toLowerCase","_listeners","addEventListener","eventProxyCapture","eventProxy","removeEventListener","e","setAttribute","removeAttribute","event","newVNode","isNew","oldState","snapshot","clearProcessingException","provider","componentContext","newType","contextType","prototype","render","doRender","sub","state","getDerivedStateFromProps","componentWillMount","componentDidMount","componentWillReceiveProps","shouldComponentUpdate","forEach","componentWillUpdate","componentDidUpdate","getChildContext","getSnapshotBeforeUpdate","diffElementNodes","diffed","root","cb","oldHtml","newHtml","nodeType","localName","document","createTextNode","createElementNS","is","data","childNodes","dangerouslySetInnerHTML","attributes","innerHTML","checked","current","parentVNode","skipRemove","r","componentWillUnmount","this","replaceNode","firstChild","error","ctor","handled","getDerivedStateFromError","setState","componentDidCatch","update","callback","s","forceUpdate","Promise","then","bind","resolve","setTimeout","defaultValue","contextId","Consumer","contextValue","Provider","subs","ctx","_props","old","splice","toChildArray","out","module","exports","preact","self"],"mappings":"gBA0BaA,ECfPC,ECRFC,EA4FSC,EC2ETC,EAQEC,EAcFC,EC9LOC,ICFEC,EAAY,GACZC,EAAY,GACZC,EAAqB,oELO3B,SAASC,EAAOC,EAAKC,OAEtB,IAAIN,KAAKM,EAAOD,EAAIL,GAAKM,EAAMN,YAU9B,SAASO,EAAWC,OACtBC,EAAaD,EAAKC,WAClBA,GAAYA,EAAWC,YAAYF,GEVjC,SAASG,EAAcC,EAAMN,EAAOO,OAEzCC,EACAC,EACAf,EAHGgB,EAAkB,OAIjBhB,KAAKM,EACA,OAALN,EAAYc,EAAMR,EAAMN,GACd,OAALA,EAAYe,EAAMT,EAAMN,GAC5BgB,EAAgBhB,GAAKM,EAAMN,MAG7BiB,UAAUC,OAAS,IACtBF,EAAgBH,SACfI,UAAUC,OAAS,EAAIzB,EAAM0B,KAAKF,UAAW,GAAKJ,GAKjC,mBAARD,GAA2C,MAArBA,EAAKQ,iBAChCpB,KAAKY,EAAKQ,kBACaC,IAAvBL,EAAgBhB,KACnBgB,EAAgBhB,GAAKY,EAAKQ,aAAapB,WAKnCsB,EAAYV,EAAMI,EAAiBF,EAAKC,EAAK,MAe9C,SAASO,EAAYV,EAAMN,EAAOQ,EAAKC,EAAKQ,OAG5CC,EAAQ,CACbZ,KAAAA,EACAN,MAAAA,EACAQ,IAAAA,EACAC,IAAAA,MACW,QACF,SACD,MACF,cAKIM,MACE,SACA,KACZI,iBAAaJ,MACU,MAAZE,IAAqB5B,EAAU4B,UAGtB,MAAjB7B,EAAQ8B,OAAe9B,EAAQ8B,MAAMA,GAElCA,EAOD,SAASE,EAASpB,UACjBA,EAAMO,SC3EP,SAASc,EAAUrB,EAAOsB,QAC3BtB,MAAQA,OACRsB,QAAUA,EAyET,SAASC,EAAcL,EAAOM,MAClB,MAAdA,SAEIN,KACJK,EAAcL,KAAeA,SAAwBO,QAAQP,GAAS,GACtE,aAGAQ,EACGF,EAAaN,MAAgBN,OAAQY,OAG5B,OAFfE,EAAUR,MAAgBM,KAEa,MAAhBE,aAIfA,YASmB,mBAAdR,EAAMZ,KAAqBiB,EAAcL,GAAS,KAuCjE,SAASS,EAAwBT,GAAjC,IAGWxB,EACJkC,KAHyB,OAA1BV,EAAQA,OAA8C,MAApBA,MAA0B,KAChEA,MAAaA,MAAiBW,KAAO,KAC5BnC,EAAI,EAAGA,EAAIwB,MAAgBN,OAAQlB,OAE9B,OADTkC,EAAQV,MAAgBxB,KACO,MAAdkC,MAAoB,CACxCV,MAAaA,MAAiBW,KAAOD,mBAKhCD,EAAwBT,IAoC1B,SAASY,EAAcC,KAE1BA,QACAA,OAAW,IACZxC,EAAcyC,KAAKD,KAClBE,SACFxC,IAAiBL,EAAQ8C,sBAEzBzC,EAAeL,EAAQ8C,oBACN1C,GAAOyC,GAK1B,SAASA,YACJE,EACIF,MAAyB1C,EAAcqB,QAC9CuB,EAAQ5C,EAAc6C,KAAK,SAACC,EAAGC,UAAMD,UAAkBC,YACvD/C,EAAgB,GAGhB4C,EAAMI,KAAK,SAAAR,GApGb,IAAyBS,EAMnBC,EACEC,EANHxB,EACHyB,EACAC,EAkGKb,QAnGLY,GADGzB,GADoBsB,EAqGQT,aAlG/Ba,EAAYJ,SAGRC,EAAc,IACZC,EAAW5C,EAAO,GAAIoB,QACPA,MAAkB,EAEvC2B,EACCD,EACA1B,EACAwB,EACAF,WAC8BzB,IAA9B6B,EAAUE,gBACU,MAApB5B,MAA2B,CAACyB,GAAU,KACtCF,EACU,MAAVE,EAAiBpB,EAAcL,GAASyB,EACxCzB,OAED6B,EAAWN,EAAavB,GAEpBA,OAAcyB,GACjBhB,EAAwBT,OGtHpB,SAAS8B,EACfJ,EACAK,EACAC,EACAC,EACAC,EACAC,EACAC,EACAb,EACAE,EACAY,GAVM,IAYF7D,EAAG8D,EAAGd,EAAUe,EAAYC,EAAQC,EAAeC,EAInDC,EAAeV,GAAkBA,OAA6BvD,EAE9DkE,EAAoBD,EAAYjD,WAEpCsC,MAA2B,GACtBxD,EAAI,EAAGA,EAAIuD,EAAarC,OAAQlB,OAgDlB,OA5CjB+D,EAAaP,MAAyBxD,GADrB,OAFlB+D,EAAaR,EAAavD,KAEqB,kBAAd+D,EACW,KAMtB,iBAAdA,GACc,iBAAdA,GAEc,iBAAdA,EAEoCzC,EAC1C,KACAyC,EACA,KACA,KACAA,GAESM,MAAMC,QAAQP,GACmBzC,EAC1CI,EACA,CAAEb,SAAUkD,GACZ,KACA,KACA,MAESA,MAAoB,EAKazC,EAC1CyC,EAAWnD,KACXmD,EAAWzD,MACXyD,EAAWjD,IACX,KACAiD,OAG0CA,OAS5CA,KAAqBP,EACrBO,MAAoBP,MAAwB,EAS9B,QAHdR,EAAWmB,EAAYnE,KAIrBgD,GACAe,EAAWjD,KAAOkC,EAASlC,KAC3BiD,EAAWnD,OAASoC,EAASpC,KAE9BuD,EAAYnE,QAAKqB,WAIZyC,EAAI,EAAGA,EAAIM,EAAmBN,IAAK,KACvCd,EAAWmB,EAAYL,KAKtBC,EAAWjD,KAAOkC,EAASlC,KAC3BiD,EAAWnD,OAASoC,EAASpC,KAC5B,CACDuD,EAAYL,QAAKzC,QAGlB2B,EAAW,KAObG,EACCD,EACAa,EALDf,EAAWA,GAAY/C,EAOtByD,EACAC,EACAC,EACAb,EACAE,EACAY,GAGDG,EAASD,OAEJD,EAAIC,EAAWhD,MAAQiC,EAASjC,KAAO+C,IACtCI,IAAMA,EAAO,IACdlB,EAASjC,KAAKmD,EAAK5B,KAAKU,EAASjC,IAAK,KAAMgD,GAChDG,EAAK5B,KAAKwB,EAAGC,OAAyBC,EAAQD,IAGjC,MAAVC,GACkB,MAAjBC,IACHA,EAAgBD,GAIU,mBAAnBD,EAAWnD,MACM,MAAxBmD,OACAA,QAAyBf,MAEzBe,MAAsBd,EAASsB,EAC9BR,EACAd,EACAC,GAGDD,EAASuB,EACRtB,EACAa,EACAf,EACAmB,EACAH,EACAf,GAcGY,GAAuC,WAAxBL,EAAe5C,KAIM,mBAAvB4C,EAAe5C,OAQhC4C,MAA0BP,GAT1BC,EAAUuB,MAAQ,IAYnBxB,GACAD,OAAiBC,GACjBA,EAAOxC,YAAcyC,IAIrBD,EAASpB,EAAcmB,QAIzBQ,MAAsBS,EAGjBjE,EAAIoE,EAAmBpE,KACL,MAAlBmE,EAAYnE,KAEgB,mBAAvBwD,EAAe5C,MACC,MAAvBuD,EAAYnE,QACZmE,EAAYnE,QAAWwD,QAKvBA,MAA0B3B,EAAc4B,EAAgBzD,EAAI,IAG7D0E,EAAQP,EAAYnE,GAAImE,EAAYnE,QAKlCkE,MACElE,EAAI,EAAGA,EAAIkE,EAAKhD,OAAQlB,IAC5B2E,EAAST,EAAKlE,GAAIkE,IAAOlE,GAAIkE,IAAOlE,IAKvC,SAASuE,EAAgBR,EAAYd,EAAQC,GAA7C,IACU0B,EACJpD,MADIoD,EAAM,EAAGA,EAAMb,MAAqB7C,OAAQ0D,KAChDpD,EAAQuC,MAAqBa,MAMhCpD,KAAgBuC,EAGfd,EADwB,mBAAdzB,EAAMZ,KACP2D,EAAgB/C,EAAOyB,EAAQC,GAE/BsB,EACRtB,EACA1B,EACAA,EACAuC,MACAvC,MACAyB,WAMGA,EAsBR,SAASuB,EACRtB,EACAa,EACAf,EACAmB,EACAH,EACAf,GAND,IAQK4B,EAuBGC,EAAiBhB,UAtBIzC,IAAxB0C,MAIHc,EAAUd,MAMVA,WAAsB1C,OAChB,GACM,MAAZ2B,GACAgB,GAAUf,GACW,MAArBe,EAAOvD,WAEPsE,EAAO,GAAc,MAAV9B,GAAkBA,EAAOxC,aAAeyC,EAClDA,EAAU8B,YAAYhB,GACtBa,EAAU,SACJ,KAGDC,EAAS7B,EAAQa,EAAI,GACxBgB,EAASA,EAAOG,cAAgBnB,EAAIK,EAAYjD,OACjD4C,GAAK,KAEDgB,GAAUd,QACPe,EAGR7B,EAAUgC,aAAalB,EAAQf,GAC/B4B,EAAU5B,cAOI5B,IAAZwD,EACMA,EAEAb,EAAOiB,YC1UX,SAASE,EAAUC,EAAKC,EAAUC,EAAU3B,EAAO4B,OACrDvF,MAECA,KAAKsF,EACC,aAANtF,GAA0B,QAANA,GAAiBA,KAAKqF,GAC7CG,EAAYJ,EAAKpF,EAAG,KAAMsF,EAAStF,GAAI2D,OAIpC3D,KAAKqF,EAENE,GAAiC,mBAAfF,EAASrF,IACvB,aAANA,GACM,QAANA,GACM,UAANA,GACM,YAANA,GACAsF,EAAStF,KAAOqF,EAASrF,IAEzBwF,EAAYJ,EAAKpF,EAAGqF,EAASrF,GAAIsF,EAAStF,GAAI2D,GAKjD,SAAS8B,EAASC,EAAO5E,EAAK2D,GACd,MAAX3D,EAAI,GACP4E,EAAMF,YAAY1E,EAAK2D,GAEvBiB,EAAM5E,GADa,MAAT2D,EACG,GACa,iBAATA,GAAqBtE,EAAmBwF,KAAK7E,GACjD2D,EAEAA,EAAQ,KAYhB,SAASe,EAAYJ,EAAKQ,EAAMnB,EAAOoB,EAAUlC,GAAjD,IACFmC,EAEJC,EAAG,GAAa,UAATH,KACc,iBAATnB,EACVW,EAAIM,MAAMM,QAAUvB,MACd,IACiB,iBAAZoB,IACVT,EAAIM,MAAMM,QAAUH,EAAW,IAG5BA,MACED,KAAQC,EACNpB,GAASmB,KAAQnB,GACtBgB,EAASL,EAAIM,MAAOE,EAAM,OAKzBnB,MACEmB,KAAQnB,EACPoB,GAAYpB,EAAMmB,KAAUC,EAASD,IACzCH,EAASL,EAAIM,MAAOE,EAAMnB,EAAMmB,SAOhC,GAAgB,MAAZA,EAAK,IAA0B,MAAZA,EAAK,GAChCE,EAAaF,KAAUA,EAAOA,EAAKK,QAAQ,WAAY,KAGxBL,EAA3BA,EAAKM,gBAAiBd,EAAYQ,EAAKM,cAAczG,MAAM,GACnDmG,EAAKnG,MAAM,GAElB2F,EAAIe,IAAYf,EAAIe,EAAa,IACtCf,EAAIe,EAAWP,EAAOE,GAAcrB,EAEhCA,EACEoB,GAEJT,EAAIgB,iBAAiBR,EADLE,EAAaO,EAAoBC,EACbR,GAIrCV,EAAImB,oBAAoBX,EADRE,EAAaO,EAAoBC,EACVR,QAElC,GAAa,4BAATF,EAAoC,IAC1CjC,EAIHiC,EAAOA,EAAKK,QAAQ,aAAc,KAAKA,QAAQ,SAAU,UACnD,GACG,SAATL,GACS,SAATA,GACS,SAATA,GAGS,aAATA,GACS,aAATA,GACAA,KAAQR,MAGPA,EAAIQ,GAAiB,MAATnB,EAAgB,GAAKA,QAE3BsB,EACL,MAAOS,IAUW,mBAAV/B,IAGD,MAATA,KACW,IAAVA,GAAgC,MAAZmB,EAAK,IAA0B,MAAZA,EAAK,IAE7CR,EAAIqB,aAAab,EAAMnB,GAEvBW,EAAIsB,gBAAgBd,KAUvB,SAASU,EAAWE,QACdL,EAAWK,EAAE5F,MAAO,GAAOlB,EAAQiH,MAAQjH,EAAQiH,MAAMH,GAAKA,GAGpE,SAASH,EAAkBG,QACrBL,EAAWK,EAAE5F,MAAO,GAAMlB,EAAQiH,MAAQjH,EAAQiH,MAAMH,GAAKA,GCpI5D,SAASrD,EACfD,EACA0D,EACA5D,EACAU,EACAC,EACAC,EACAb,EACAE,EACAY,GATM,IAWFe,EAoBEvC,EAAGwE,EAAOvB,EAAUwB,EAAUC,EAAUC,EACxC3B,EAKA4B,EACAC,EAqIA3D,EA/JL4D,EAAUP,EAAShG,aAISS,IAAzBuF,EAASnF,YAA2B,OAAO,KAGpB,MAAvBuB,QACHa,EAAcb,MACdC,EAAS2D,MAAgB5D,MAEzB4D,MAAsB,KACtBhD,EAAoB,CAACX,KAGjB2B,EAAMlF,QAAgBkF,EAAIgC,OAG9B7B,EAAO,GAAsB,mBAAXoC,EAAuB,IAEpC9B,EAAWuB,EAAStG,MAKpB2G,GADJrC,EAAMuC,EAAQC,cACQ1D,EAAckB,OAChCsC,EAAmBtC,EACpBqC,EACCA,EAAS3G,MAAMmE,MACfG,KACDlB,EAGCV,MAEHgE,GADA3E,EAAIuE,MAAsB5D,UAC0BX,OAGhD,cAAe8E,GAAWA,EAAQE,UAAUC,OAE/CV,MAAsBvE,EAAI,IAAI8E,EAAQ9B,EAAU6B,IAGhDN,MAAsBvE,EAAI,IAAIV,EAAU0D,EAAU6B,GAClD7E,EAAEZ,YAAc0F,EAChB9E,EAAEiF,OAASC,GAERN,GAAUA,EAASO,IAAInF,GAE3BA,EAAE/B,MAAQ+E,EACLhD,EAAEoF,QAAOpF,EAAEoF,MAAQ,IACxBpF,EAAET,QAAUsF,EACZ7E,MAAmBqB,EACnBmD,EAAQxE,OAAW,EACnBA,MAAqB,IAIF,MAAhBA,QACHA,MAAeA,EAAEoF,OAEsB,MAApCN,EAAQO,2BACPrF,OAAgBA,EAAEoF,QACrBpF,MAAejC,EAAO,GAAIiC,QAG3BjC,EACCiC,MACA8E,EAAQO,yBAAyBrC,EAAUhD,SAI7CiD,EAAWjD,EAAE/B,MACbwG,EAAWzE,EAAEoF,MAGTZ,EAEkC,MAApCM,EAAQO,0BACgB,MAAxBrF,EAAEsF,oBAEFtF,EAAEsF,qBAGwB,MAAvBtF,EAAEuF,mBACLvF,MAAmBC,KAAKD,EAAEuF,uBAErB,IAE+B,MAApCT,EAAQO,0BACRrC,IAAaC,GACkB,MAA/BjD,EAAEwF,2BAEFxF,EAAEwF,0BAA0BxC,EAAU6B,IAIpC7E,OAC0B,MAA3BA,EAAEyF,wBAKI,IAJNzF,EAAEyF,sBACDzC,EACAhD,MACA6E,IAEFN,QAAuB5D,MACtB,CACDX,EAAE/B,MAAQ+E,EACVhD,EAAEoF,MAAQpF,MAENuE,QAAuB5D,QAAoBX,OAAW,GAC1DA,MAAWuE,EACXA,MAAgB5D,MAChB4D,MAAqB5D,MACrB4D,MAAmBmB,QAAQ,SAAAvG,GACtBA,IAAOA,KAAgBoF,KAExBvE,MAAmBnB,QACtB6B,EAAYT,KAAKD,SAGZ0C,EAGsB,MAAzB1C,EAAE2F,qBACL3F,EAAE2F,oBAAoB3C,EAAUhD,MAAc6E,GAGnB,MAAxB7E,EAAE4F,oBACL5F,MAAmBC,KAAK,WACvBD,EAAE4F,mBAAmB3C,EAAUwB,EAAUC,KAK5C1E,EAAET,QAAUsF,EACZ7E,EAAE/B,MAAQ+E,EACVhD,EAAEoF,MAAQpF,OAELuC,EAAMlF,QAAkBkF,EAAIgC,GAEjCvE,OAAW,EACXA,MAAWuE,EACXvE,MAAea,EAEf0B,EAAMvC,EAAEiF,OAAOjF,EAAE/B,MAAO+B,EAAEoF,MAAOpF,EAAET,SAGnCS,EAAEoF,MAAQpF,MAEe,MAArBA,EAAE6F,kBACLxE,EAAgBtD,EAAOA,EAAO,GAAIsD,GAAgBrB,EAAE6F,oBAGhDrB,GAAsC,MAA7BxE,EAAE8F,0BACfpB,EAAW1E,EAAE8F,wBAAwB7C,EAAUwB,IAK5CvD,EADI,MAAPqB,GAAeA,EAAIhE,OAASc,GAAuB,MAAXkD,EAAI9D,IACL8D,EAAItE,MAAMO,SAAW+D,EAE7DtB,EACCJ,EACAmB,MAAMC,QAAQf,GAAgBA,EAAe,CAACA,GAC9CqD,EACA5D,EACAU,EACAC,EACAC,EACAb,EACAE,EACAY,GAGDxB,EAAEF,KAAOyE,MAGTA,MAAsB,KAElBvE,MAAmBnB,QACtB6B,EAAYT,KAAKD,GAGd2E,IACH3E,MAAkBA,KAAyB,MAG5CA,OAAW,OAEU,MAArBuB,GACAgD,QAAuB5D,OAEvB4D,MAAqB5D,MACrB4D,MAAgB5D,OAEhB4D,MAAgBwB,EACfpF,MACA4D,EACA5D,EACAU,EACAC,EACAC,EACAb,EACAc,IAIGe,EAAMlF,EAAQ2I,SAASzD,EAAIgC,GAC/B,MAAOJ,GACRI,MAAqB,MAEjB/C,GAAoC,MAArBD,KAClBgD,MAAgB3D,EAChB2D,QAAwB/C,EACxBD,EAAkBA,EAAkB7B,QAAQkB,IAAW,MAIxDvD,MAAoB8G,EAAGI,EAAU5D,IAS5B,SAASK,EAAWN,EAAauF,GACnC5I,OAAiBA,MAAgB4I,EAAMvF,GAE3CA,EAAYF,KAAK,SAAAR,OAGfU,EAAcV,MACdA,MAAqB,GACrBU,EAAYF,KAAK,SAAA0F,GAEhBA,EAAGpH,KAAKkB,KAER,MAAOmE,GACR9G,MAAoB8G,EAAGnE,UAmB1B,SAAS+F,EACRhD,EACAwB,EACA5D,EACAU,EACAC,EACAC,EACAb,EACAc,GARD,IAoBS3B,EAsDHsG,EACAC,EAjEDnD,EAAWtC,EAAS1C,MACpB+E,EAAWuB,EAAStG,MACpBoI,EAAW9B,EAAShG,KACpBZ,EAAI,KAGS,QAAb0I,IAAoB/E,GAAQ,GAEP,MAArBC,OACI5D,EAAI4D,EAAkB1C,OAAQlB,QAC9BkC,EAAQ0B,EAAkB5D,MAO9BkC,IAAUkD,IACTsD,EAAWxG,EAAMyG,WAAaD,EAA6B,GAAlBxG,EAAMwG,WAChD,CACDtD,EAAMlD,EACN0B,EAAkB5D,GAAK,cAMf,MAAPoF,EAAa,IACC,OAAbsD,SAEIE,SAASC,eAAexD,GAI/BD,EADGzB,EACGiF,SAASE,gBACd,6BAEAJ,GAGKE,SAASjI,cAEd+H,EACArD,EAAS0D,IAAM1D,GAKjBzB,EAAoB,KAEpBC,GAAc,KAGE,OAAb6E,EAECpD,IAAaD,GAAcxB,GAAeuB,EAAI4D,OAAS3D,IAC1DD,EAAI4D,KAAO3D,OAEN,IAENzB,EAAoBA,GAAqBnE,EAAM0B,KAAKiE,EAAI6D,YAIpDT,GAFJlD,EAAWtC,EAAS1C,OAASL,GAENiJ,wBACnBT,EAAUpD,EAAS6D,yBAIlBrF,EAAa,IAGQ,MAArBD,MACH0B,EAAW,GACNtF,EAAI,EAAGA,EAAIoF,EAAI+D,WAAWjI,OAAQlB,IACtCsF,EAASF,EAAI+D,WAAWnJ,GAAG4F,MAAQR,EAAI+D,WAAWnJ,GAAGyE,OAInDgE,GAAWD,KAGZC,IACED,GAAWC,UAAkBD,UAC/BC,WAAmBrD,EAAIgE,aAExBhE,EAAIgE,UAAaX,GAAWA,UAAmB,QAKlDtD,EAAUC,EAAKC,EAAUC,EAAU3B,EAAOE,GAGtC4E,EACH7B,MAAqB,WAErB5G,EAAI4G,EAAStG,MAAMO,SACnByC,EACC8B,EACAf,MAAMC,QAAQtE,GAAKA,EAAI,CAACA,GACxB4G,EACA5D,EACAU,EACAC,GAAsB,kBAAb+E,EACT9E,EACAb,EACAa,EACGA,EAAkB,GAClBZ,OAAsBnB,EAAcmB,EAAU,GACjDa,GAIwB,MAArBD,MACE5D,EAAI4D,EAAkB1C,OAAQlB,KACN,MAAxB4D,EAAkB5D,IAAYO,EAAWqD,EAAkB5D,IAM7D6D,IAEH,UAAWwB,QACchE,KAAxBrB,EAAIqF,EAASZ,SAKbzE,IAAMoF,EAAIX,OAAuB,aAAbiE,IAA4B1I,IAEjDwF,EAAYJ,EAAK,QAASpF,EAAGsF,EAASb,OAAO,GAG7C,YAAaY,QACchE,KAA1BrB,EAAIqF,EAASgE,UACdrJ,IAAMoF,EAAIiE,SAEV7D,EAAYJ,EAAK,UAAWpF,EAAGsF,EAAS+D,SAAS,WAK7CjE,EASD,SAAST,EAAS5D,EAAK0D,EAAOjD,OAEjB,mBAAPT,EAAmBA,EAAI0D,GAC7B1D,EAAIuI,QAAU7E,EAClB,MAAO+B,GACR9G,MAAoB8G,EAAGhF,IAYlB,SAASkD,EAAQlD,EAAO+H,EAAaC,GAArC,IACFC,EAoBMzJ,KAnBNN,EAAQgF,SAAShF,EAAQgF,QAAQlD,IAEhCiI,EAAIjI,EAAMT,OACT0I,EAAEH,SAAWG,EAAEH,UAAY9H,OAAYmD,EAAS8E,EAAG,KAAMF,IAGjC,OAAzBE,EAAIjI,OAA2B,IAC/BiI,EAAEC,yBAEJD,EAAEC,uBACD,MAAOlD,GACR9G,MAAoB8G,EAAG+C,GAIzBE,EAAEtH,KAAOsH,MAAe,QAGpBA,EAAIjI,UACCxB,EAAI,EAAGA,EAAIyJ,EAAEvI,OAAQlB,IACzByJ,EAAEzJ,IACL0E,EAAQ+E,EAAEzJ,GAAIuJ,EAAkC,mBAAd/H,EAAMZ,MAKtC4I,GAA4B,MAAdhI,OAAoBjB,EAAWiB,OAIlDA,MAAaA,WAAiBH,EAI/B,SAASkG,EAASjH,EAAOmH,EAAO7F,UACxB+H,KAAKlI,YAAYnB,EAAOsB,GClfzB,SAAS0F,EAAO9F,EAAO0B,EAAW0G,GAAlC,IAMF/F,EAOAb,EAUAD,EAtBArD,MAAeA,KAAc8B,EAAO0B,GAYpCF,GAPAa,EAAqC,mBAAhB+F,GAQtB,KACCA,GAAeA,OAA0B1G,MAQzCH,EAAc,GAClBI,EACCD,EARD1B,IACGqC,GAAe+F,GACjB1G,OACavC,EAAce,EAAU,KAAM,CAACF,IAS5CwB,GAAY/C,EACZA,OAC8BoB,IAA9B6B,EAAUE,iBACTS,GAAe+F,EACb,CAACA,GACD5G,EACA,KACAE,EAAU2G,WACVpK,EAAM0B,KAAK+B,EAAU+F,YACrB,KACHlG,GACCc,GAAe+F,EACbA,EACA5G,EACAA,MACAE,EAAU2G,WACbhG,GAIDR,EAAWN,EAAavB,GTrCZ/B,EAAQS,EAAUT,MCfzBC,EAAU,KSJT,SAAqBoK,EAAOtI,WAE9BsB,EAAWiH,EAAMC,EAEbxI,EAAQA,UACVsB,EAAYtB,SAAsBsB,aAErCiH,EAAOjH,EAAUrB,cAE4B,MAAjCsI,EAAKE,2BAChBnH,EAAUoH,SAASH,EAAKE,yBAAyBH,IACjDE,EAAUlH,OAGwB,MAA/BA,EAAUqH,oBACbrH,EAAUqH,kBAAkBL,GAC5BE,EAAUlH,OAIPkH,SACKlH,MAA0BA,EAElC,MAAO0D,GACRsD,EAAQtD,QAKLsD,IRjCHnK,EAAU,EA4FDC,EAAiB,SAAA4B,UACpB,MAATA,QAAuCH,IAAtBG,EAAMC,aCtExBE,EAAU0F,UAAU6C,SAAW,SAASE,EAAQC,OAE3CC,EAEHA,EADsB,MAAnBX,UAA2BA,WAAoBA,KAAKlC,MACnDkC,SAEAA,SAAkBvJ,EAAO,GAAIuJ,KAAKlC,OAGlB,mBAAV2C,IAGVA,EAASA,EAAOhK,EAAO,GAAIkK,GAAIX,KAAKrJ,QAGjC8J,GACHhK,EAAOkK,EAAGF,GAIG,MAAVA,GAEAT,WACCU,GAAUV,SAAsBrH,KAAK+H,GACzCjI,EAAcuH,QAUhBhI,EAAU0F,UAAUkD,YAAc,SAASF,GACtCV,qBAIW,EACVU,GAAUV,SAAsBrH,KAAK+H,GACzCjI,EAAcuH,QAchBhI,EAAU0F,UAAUC,OAAS5F,EAyFzB7B,EAAgB,GAQdC,EACa,mBAAX0K,QACJA,QAAQnD,UAAUoD,KAAKC,KAAKF,QAAQG,WACpCC,WA2CJrI,MAAyB,EC9NdvC,EAAI,sBKsER,SAASuF,EAAQ/D,EAAO0B,GAC9BoE,EAAO9F,EAAO0B,EAAWqC,6CPSnB,iBACC,CAAE+D,QAAS,iDSzEZ,SAAsB9H,EAAOlB,EAAOO,OAEzCC,EACAC,EACAf,EAHGgB,EAAkBZ,EAAO,GAAIoB,EAAMlB,WAIlCN,KAAKM,EACA,OAALN,EAAYc,EAAMR,EAAMN,GACd,OAALA,EAAYe,EAAMT,EAAMN,GAC5BgB,EAAgBhB,GAAKM,EAAMN,UAG7BiB,UAAUC,OAAS,IACtBF,EAAgBH,SACfI,UAAUC,OAAS,EAAIzB,EAAM0B,KAAKF,UAAW,GAAKJ,GAG7CS,EACNE,EAAMZ,KACNI,EACAF,GAAOU,EAAMV,IACbC,GAAOS,EAAMT,IACb,qBP3BK,SAAuB8J,EAAcC,OAGrClJ,EAAU,KAFhBkJ,EAAY,OAAS9K,OAIL6K,EAEfE,kBAASzK,EAAO0K,UAIR1K,EAAMO,SAASmK,IAGvBC,kBAAS3K,OAEH4K,EACAC,SAFAxB,KAAKzB,kBACLgD,EAAO,IACPC,EAAM,IACNL,GAAanB,UAEZzB,gBAAkB,kBAAMiD,QAExBrD,sBAAwB,SAASsD,GACjCzB,KAAKrJ,MAAMmE,QAAU2G,EAAO3G,OAe/ByG,EAAKrI,KAAKT,SAIPoF,IAAM,SAAAnF,GACV6I,EAAK5I,KAAKD,OACNgJ,EAAMhJ,EAAEqH,qBACZrH,EAAEqH,qBAAuB,WACxBwB,EAAKI,OAAOJ,EAAKnJ,QAAQM,GAAI,GACzBgJ,GAAKA,EAAIlK,KAAKkB,MAKd/B,EAAMO,kBAUPe,EAAQqJ,YAAuBrJ,EAAQmJ,SAAS3D,YAAcxF,gBEqNhE,SAAS2J,EAAa1K,EAAU2K,UACtCA,EAAMA,GAAO,GACG,MAAZ3K,GAAuC,kBAAZA,IACpBwD,MAAMC,QAAQzD,GACxBA,EAASgC,KAAK,SAAAX,GACbqJ,EAAarJ,EAAOsJ,KAGrBA,EAAIlJ,KAAKzB,IAEH2K,qBMhSGC,OAAS,IAAKA,OAAOC,QAAUC,EACrCC,KAAKD,OAASA"} \ No newline at end of file diff --git a/assets/js/solight/sol.js b/assets/js/solight/sol.js new file mode 100644 index 0000000..a762615 --- /dev/null +++ b/assets/js/solight/sol.js @@ -0,0 +1,1089 @@ +'use strict'; + +// Use luxon for date and time handling +import * as luxon from "../luxon/luxon.es6.js"; + +// --------------------------------------------------------- +// Helpers + +// :: A -> Option[A] +let optional = (x) => x === null ? undefined : x; + +// :: A -> Bool +let defined = (x) => x !== undefined; + +// :: Option[A] -> (()->B) -> Option[B] +let withDefined = (x, f) => defined(x) ? f() : undefined; + +//-:: Option[A] -> (A->B) -> Option[B] +let ifDefined = (x, f) => defined(x) ? f(x) : undefined; + +// Note: use only for primitive values ("primary keys") +// :: List[A] -> List[A] +let distinct = (xs) => Array.from(new Set(xs)); + +// :: List[A] -> List[A] -> List[A] +let intersection = (xs, ys) => xs.filter(v => ys.includes(v)); + +//-:: String -> String -> Int +let stringCompare = (s1, s2) => { + if (s1 < s2) { return -1; }; + if (s1 > s2) { return 1; }; + return 0; +}; + + +// --------------------------------------------------------- +// Transform Json into proper Arrays and Maps + +//-:: EventAnswerJson -> EventAnswer +let processEventAnswer = (answerJ) => { + let m = new Map(); + m.set('question', answerJ.question); + m.set('answer', answerJ.answer); + return m; +}; + +//-:: AttachmentJson -> Attachment +let processAttachment = (attachmentJ) => undefined; + +//-:: LinkJson -> Link +let processLink = (linkJ) => undefined; + +//-:: PersonAnswerJson -> PersonAnswer +let processPersonAnswer = (answerJ) => undefined; + +//-:: PersonJson -> Person +let processPerson = (personJ) => { + let m = new Map(); + m.set('id', personJ.id); + m.set('code', personJ.code); + // Renamed field: + m.set('name', personJ.public_name); + m.set('biography', optional(personJ.biography)); + m.set('answers', personJ.answers.map(aj => processPersonAnswer(aj))); + return m; +}; + +//-:: EventJson -> DayIndex -> Event +let processEvent = (eventJ, dayIndex) => { + let start_date = luxon.DateTime.fromISO(eventJ.date); + let duration = luxon.Duration.fromISOTime(eventJ.duration); + let end_date = start_date.plus(duration); + + let m = new Map(); + m.set('id', eventJ.id); + m.set('guid', eventJ.guid); + m.set('logo', eventJ.logo); + // Same as processed start date + //m.set('date', + // luxon.DateTime.fromISO(eventJ.date)); + m.set('start_date', start_date); + // Synthetic field: + m.set('end_date', end_date); + m.set('duration', duration); + // Synthetic field: + m.set('day_index', dayIndex); + m.set('room', eventJ.room); + m.set('slug', eventJ.slug); + m.set('url', eventJ.url); + // m.set('title', eventJ.title || ""); + m.set('title', withDefined(eventJ.title, () => eventJ.title)); + m.set('subtitle', withDefined(eventJ.subtitle, () => eventJ.subtitle)); + m.set('track', eventJ.track); + m.set('type', eventJ.type); + m.set('language', eventJ.language); + // TODO: Rethink empty strings + m.set('abstract', eventJ.abstract || ""); + m.set('description', eventJ.description || ""); + m.set('recording_license', eventJ.recording_license); + m.set('do_not_record', eventJ.do_not_record); + m.set('persons', eventJ.persons.map(pj => processPerson(pj))); + m.set('links', eventJ.links.map(lj => processLink(lj))); + m.set('attachments', eventJ.attachments.map(aj => processAttachment(aj))); + m.set('answers', withDefined(eventJ.answers, + () => eventJ.answers.map(aj => processEventAnswer(aj)))); + return m; +}; + +//-:: RoomJson -> DayIndex -> Map[RoomName, List[Event]] +let processRooms = (roomJ, dayIndex) => { + let m = new Map( + Object.entries(roomJ).map( + item => [item[0], item[1].map(e => processEvent(e, dayIndex))] + ) + ); + return m; +}; + +//-:: DayJson -> Day +let processDay = (dayJ) => { + let main_date = luxon.DateTime.fromISO(dayJ.date); + let start_date = luxon.DateTime.fromISO(dayJ.day_start); + let end_date = luxon.DateTime.fromISO(dayJ.day_end); + let duration = end_date.diff(start_date); + + let m = new Map(); + m.set('index', dayJ.index); + m.set('date', main_date); + m.set('start_date', start_date); + m.set('end_date', end_date); + // Synthetic field: + m.set('duration', duration); + // Note: Pass day index down to rooms and finally events + m.set('rooms', processRooms(dayJ.rooms, dayJ.index)); + return m; +}; + +//-:: RoomDefinitionJson -> Room +let processRoomDefinition = (roomJ) => { + let m = new Map(); + m.set('name', roomJ.name); + m.set('guid', optional(roomJ.guid)); + m.set('description', optional(roomJ.description)); + m.set('capacity', optional(roomJ.capacity)); + return m; +}; + +//-:: ConferenceJson -> Conference +let processConference = (conferenceJ) => { + let start_date = luxon.DateTime.fromISO(conferenceJ.start); + let end_date = luxon.DateTime.fromISO(conferenceJ.end); + let duration = end_date.diff(start_date); + + let m = new Map(); + m.set('acronym', conferenceJ.acronym); + m.set('title', conferenceJ.title); + m.set('start_date', start_date); + m.set('end_date', end_date); + // Synthetic field: + m.set('duration', duration); + m.set('days_count', conferenceJ.daysCount); + m.set('timeslot_duration', + luxon.Duration.fromISOTime(conferenceJ.timeslot_duration)); + // TODO: + //m.set('time_zone_name', + // luxon.IANAZone.create(conferenceJ.time_zone_name)); + m.set('rooms', conferenceJ.rooms.map(rj => processRoomDefinition(rj))); + m.set('days', conferenceJ.days.map(dj => processDay(dj))); + return m; +}; + +//-:: ScheduleJson -> Schedule +let processSchedule = (scheduleJ) => { + let m = new Map(); + m.set('version', scheduleJ.version); + m.set('base_url', scheduleJ.base_url); + m.set('conference', processConference(scheduleJ.conference)); + return m; +}; + +// :: ScheduleFile -> ScheduleJson +let processScheduleFile = (scheduleFile) => + processSchedule(scheduleFile.schedule); + //processSchedule(JSON.parse(scheduleFile).schedule); + + +// --------------------------------------------------------- +// Properties and Accessors ('Data Types') + +// :: Schedule -> String +let scheduleVersion = (schedule) => schedule.get('version'); + +// :: Schedule -> String +let scheduleBaseUrl = (schedule) => schedule.get('base_url'); + + +// :: Conference -> String +let conferenceAcronym = (conference) => conference.get('acronym'); + +// :: Conference -> String +let conferenceTitle = (conference) => conference.get('title'); + +// :: Conference -> luxon.DateTime +let conferenceStartDate = (conference) => conference.get('start_date'); + +// :: Conference -> luxon.DateTime +let conferenceEndDate = (conference) => conference.get('end_date'); + +// :: Conference -> luxon.Duration +let conferenceDuration = (conference) => conference.get('duration'); + +// :: Conference -> Int +let conferenceDaysCount = (conference) => conference.get('days_count'); + +// :: Conference -> luxon.Duration +let conferenceTimeslotDuration = (conference) => conference.get('timeslot_duration'); + +// :: Conference -> luxon.IANATimeZone +let conferenceTimezoneName = (conference) => conference.get('time_zone_name'); + + +// :: Day -> DayIndex +let dayIndex = (day) => day.get('index'); + +// :: Day -> luxon.DateTime +let dayDate = (day) => day.get('date'); + +// :: Day -> luxon.DateTime +let dayStartDate = (day) => day.get('start_date'); + +// :: Day -> luxon.DateTime +let dayEndDate = (day) => day.get('end_date'); + +// :: Day -> luxon.Duration +let dayDuration = (day) => day.get('duration'); + + +// :: Room -> String +let roomName = (room) => room.get('name'); + +// :: Room -> String +let roomGuid = (room) => room.get('guid'); +let roomId = (room) => room.get('guid'); + +// :: Room -> String +let roomDescription = (room) => room.get('description'); + +// :: Room -> Int +let roomCapacity = (room) => room.get('capacity'); + + +// :: Event -> Int +let eventId = (event) => event.get('id'); + +// :: Event -> String +let eventGuid = (event) => event.get('guid'); + +// :: Event -> String +let eventLogo = (event) => event.get('logo'); + +// :: Event -> luxon.DateTime +let eventStartDate = (event) => event.get('start_date'); + +// :: Event -> luxon.DateTime +let eventEndDate = (event) => event.get('end_date'); + +// :: Event -> luxon.Duration +let eventDuration = (event) => event.get('duration'); + +// :: Event -> Int +let eventDayIndex = (event) => event.get('day_index'); + +// :: Event -> RoomName +let eventRoomName = (event) => event.get('room'); + +// :: Event -> String +let eventSlug = (event) => event.get('slug'); + +// :: Event -> String +let eventUrl = (event) => event.get('url'); + +// :: Event -> String +let eventTitle = (event) => event.get('title'); + +// :: Event -> String +let eventSubtitle = (event) => event.get('subtitle'); + +// :: Event -> TrackName +let eventTrack = (event) => event.get('track'); + +// :: Event -> EventType +let eventType = (event) => event.get('type'); + +// :: Event -> Language +let eventLanguage = (event) => event.get('language'); + +// :: Event -> String +let eventAbstract = (event) => event.get('abstract'); + +// :: Event -> String +let eventDescription = (event) => event.get('description'); + +// :: Event -> String +let eventRecordingLicense = (event) => event.get('recording_license'); + +// :: Event -> Bool +let eventDoNotRecord = (event) => event.get('do_not_record'); + +// :: Event -> List[Person] +let eventPersons = (event) => event.get('persons'); + +// :: Event -> Int +let eventPersonCount = (event) => eventPersons(event).length; + +// :: Event -> List[AnswerMap] +let eventAnswers = (event) => event.get('answers'); + + +// :: Person -> Int +let personId = (person) => person.get('id'); + +// :: Person -> String +let personCode = (person) => person.get('code'); + +// :: Person -> String +let personName = (person) => person.get('name'); + +// :: Person -> String +let personBiography = (person) => person.get('biography'); + + +// --------------------------------------------------------- +// Filters, Maps and other Pieces of Lisp + +// TODO: Use own stable IDs + +// :: List[Event] -> DayIndex -> List[Event] +let eventsByDayIndex = (events, dIndex) => + events.filter(e => eventDayIndex(e) === dIndex); + +// :: List[Event] -> Day -> List[Event] +let eventsByDay = (events, day) => + events.filter(e => eventDayIndex(e) === dayIndex(day)); + + +// :: List[Event] -> RoomName -> List[Event] +let eventsByRoomName = (events, rName) => + events.filter(e => eventRoomName(e) === rName); + +// :: List[Event] -> Room -> List[Event] +let eventsByRoom = (events, room) => + eventsByRoomName(events, roomName(room)); + + +// :: List[Event] -> PersonId -> List[Event] +let eventsByPersonId = (events, pId) => + events.filter(e => eventPersons(e).some(p => personId(p) === pId)); + +// :: List[Event] -> PersonName -> List[Event] +let eventsByPersonName = (events, pName) => + events.filter(e => eventPersons(e).some(p => personName(p) === pName)); + +// :: List[Event] -> Person -> List[Event] +let eventsByPerson = (events, person) => + eventsByPersonName(events, personName(person)); + +// :: List[Event] -> TrackName -> List[Event] +let eventsByTrack = (events, eventTrackName) => + events.filter(e => eventTrack(e) === eventTrackName); + +// :: List[Event] -> EventType -> List[Event] +let eventsByType = (events, eventTypeName) => + events.filter(e => eventType(e) === eventTypeName); + +// :: List[Event] -> Language -> List[Event] +let eventsByLanguage = (events, language) => + events.filter(e => eventLanguage(e) === language); + + +// :: List[Room] -> GUID -> Option[Room] +let roomById = (rooms, id) => rooms.find(r => roomId(r) === id); + +// :: List[Room] -> RoomName -> List[Room] +let roomsByName = (rooms, name) => rooms.filter(r => roomName(r) === name); + +// :: List[Day] -> Int -> Option[Day] +let dayByIndex = (days, index) => days.find(d => dayIndex(d) === index); + +// :: List[Person] -> Int -> Option[Person] +let personById = (persons, id) => persons.find(p => personId(p) === id); + +// :: List[Person] -> PersonName -> List[Person] +let personsByName = (persons, name) => persons.filter(p => personName(p) === name); + +// :: List[Event] -> Int -> Option[Event] +let eventById = (events, id) => events.find(e => eventId === id); + + +// :: List[Room] -> List[Room] +let distinctRooms = (rooms) => { + //let ids = distinct(rooms.map(roomId)); + //return ids.map(i => rooms.find(r => roomId(r) === i)); + // TODO: Room Id might be optional? + let rns = distinct(rooms.map(roomName)); + return rns.map(i => rooms.find(r => roomName(r) === i)); +}; + +// :: List[Day] -> List[Day] +let distinctDays = (days) => { + let ids = distinct(days.map(dayIndex)); + return ids.map(i => days.find(d => dayIndex(d) === i)); +}; + +// :: List[Event] -> List[Event] +let distinctEvents = (events) => { + let ids = distinct(events.map(eventId)); + return ids.map(i => events.find(e => eventId(e) === i)); +}; + +// :: List[Person] -> List[Person] +let distinctPersons = (persons) => { + let ids = distinct(persons.map(personId)); + return ids.map(i => persons.find(p => personId(p) === i)); +}; + +// :: List[Person] -> List[Person] +let sortPersonsByName = (persons) => + persons.sort((p1, p2) => stringCompare(personName(p1), personName(p2))); + +// :: List[Room] -> List[Room] +let sortRoomsByName = (rooms) => + rooms.sort((r1, r2) => stringCompare(roomName(r1), roomName(r2))); + +// :: List[Event] -> List[Event] +let sortEventsByTitle = (events) => + events.sort((e1, e2) => stringCompare(eventTitle(e1), eventTitle(e2))); + + +// --------------------------------------------------------- +// Advanced Accessors + +// Note: Maybe deprecate and replace with 'eventsByDay'? +// :: Day -> List[Event] +let eventsOfDay = (day) => + Array.from(day.get('rooms').values()).flat(); + +// :: List[Day] -> List[Event] +let eventsOfDays = (days) => days.flatMap(eventsOfDay); + + +// Note: Can not implement this, needs more information. +// Use 'eventsByRoom' and 'eventsByRooms' instead. +//-:: Room -> List[Event] +//let eventsOfRoom = (room) => +// Array.from(room.values()); + +//-:: List[Room] -> List[Event] +//let eventsOfRooms = (rooms) => rooms.flatMap(eventsOfRoom); + + +// :: List[Event] -> List[TrackName] +let tracksOfEvents = (events) => + distinct(events.flatMap(eventLanguage)); + +// :: List[Event] -> List[EventType] +let typesOfEvents = (events) => + distinct(events.flatMap(eventType)); + +// :: List[Event] -> List[Language] +let languagesOfEvents = (events) => + distinct(events.flatMap(eventLanguage)); + + +// :: Conference -> List[Day] +let conferenceDays = (conference) => + distinctDays(conference.get('days')); + +// :: Conference -> List[Room] +let conferenceRooms = (conference) => + distinctRooms(Array.from(conference.get('rooms').values())); + +// :: Conference -> List[Event] +let conferenceEvents = (conference) => + distinctEvents(conferenceDays(conference).flatMap(d => eventsOfDay(d))); + +// :: Conference -> List[Person] +let conferencePersons = (conference) => + distinctPersons(conferenceEvents(conference).flatMap(eventPersons)); + +// :: Conference -> List[TrackName] +let conferenceTracks = (conference) => + distinct(conferenceEvents(conference).flatMap(eventTrack)); + +// :: Conference -> List[EventType] +let conferenceTypes = (conference) => + distinct(conferenceEvents(conference).flatMap(eventType)); + +// :: Conference -> List[Language] +let conferenceLanguages = (conference) => + distinct(conferenceEvents(conference).flatMap(eventLanguage)); + + +// :: Schedule -> Conference +let conference = (schedule) => schedule.get('conference'); + + +// --------------------------------------------------------- +// Advanced Filters, Maps and Traces of SQL + +// TODO: Use own stable IDs + +// :: Conference -> List[RoomName] -> DayIndex -> List[RoomName] +let roomNamesByDayIndex = (conference, roomNames, dayIndex) => { + let evs = eventsByDayIndex(conferenceEvents(conference), dayIndex); + let rns = distinct(evs.map(eventRoomName)); + return distinct(roomNames.filter(rn => rns.includes(rn))); +}; + +// :: Conference -> List[RoomName] -> Day -> List[RoomName] +let roomNamesByDay = (conference, roomNames, day) => + roomNamesByDayIndex(conference, roomNames, dayIndex(day)); + +// :: Conference -> List[Room] -> DayIndex -> List[Room] +let roomsByDayIndex = (conference, rooms, dayIndex) => { + let rns = roomNamesByDayIndex(conference, rooms.map(roomName), dayIndex); + return rooms.filter(r => rns.includes(roomName(r))); +}; + +// :: Conference -> List[Room] -> Day => List[Room] +let roomsByDay = (conference, rooms, day) => + roomsByDayIndex(conference, rooms, dayIndex(day)); + + +// :: Conference -> List[RoomName] -> PersonId -> List[RoomName] +let roomNamesByPersonId = (conference, roomNames, id) => { + let evs = eventsByPersonId(conferenceEvents(conference), id); + let rns = distinct(evs.map(eventRoomName)); + return distinct(roomNames.filter(rn => rns.includes(rn))); +}; + +// :: Conference -> List[RoomName] -> Person -> List[RoomName] +let roomNamesByPerson = (conference, roomNames, person) => + roomNamesByPersonId(conference, roomNames, personId(person)); + +// :: Conference -> List[Room] -> PersonId -> List[Room] +let roomsByPersonId = (conference, rooms, id) => { + let rns = roomNamesByPersonId(conference, rooms.map(roomName), id); + return rooms.filter(r => rns.includes(roomName(r))); +}; + +// :: Conference -> List[Room] -> Person -> List[Room] +let roomsByPerson = (conference, rooms, person) => + roomsByPersonId(conference, rooms, personId(person)); + + +// :: Conference -> List[RoomName] -> Track -> List[RoomName] +let roomNamesByTrack = (conference, roomNames, track) => { + let evs = eventsByTrack(conferenceEvents(conference), track); + let rns = evs.map(eventRoomName); + return distinct(roomNames.filter(rn => rns.includes(rn))); +}; + +// :: Conference -> List[Room] -> Track -> List[Room] +let roomsByTrack = (conference, rooms, track) => + roomNamesByTrack(conference, rooms.map(roomName), track).flatMap(rn => + roomsByName(rooms, rn)); + +// :: Conference -> List[RoomName] -> Type -> List[RoomName] +let roomNamesByType = (conference, roomNames, type) => { + let evs = eventsByType(conferenceEvents(conference), type); + let rns = evs.map(eventRoomName); + return distinct(roomNames.filter(rn => rns.includes(rn))); +}; + +// :: Conference -> List[Room] -> Type -> List[Room] +let roomsByType = (conference, rooms, type) => + roomNamesByType(conference, rooms.map(roomName), type).flatMap(rn => + roomsByName(rooms, rn)); + +// :: Conference -> List[RoomName] -> Language -> List[RoomName] +let roomNamesByLanguage = (conference, roomNames, language) => { + let evs = eventsByLanguage(conferenceEvents(conference), language); + let rns = evs.map(eventRoomName); + return distinct(roomNames.filter(rn => rns.includes(rn))); +}; + +// :: Conference -> List[Room] -> Language -> List[Room] +let roomsByLanguage = (conference, rooms, language) => + roomNamesByLanguage(conference, rooms.map(roomName), language).flatMap(rn => + roomsByName(rooms, rn)); + + +// :: Conference -> List[PersonId] -> DayIndex -> List[PersonId] +let personIdsByDayIndex = (conference, personIds, dayIndex) => { + let evs = eventsByDayIndex(conferenceEvents(conference), dayIndex); + let pids = distinct(evs.flatMap(eventPersons).map(personId)); + return distinct(personIds.filter(pi => pids.includes(pi))); +}; + +// :: Conference -> List[PersonId] -> Day -> List[PersonId] +let personIdsByDay = (conference, personIds, day) => + personIdsByDayIndex(conference, personIds, dayIndex(day)); + +// :: Conference -> List[Person] -> DayIndex -> List[Person] +let personsByDayIndex = (conference, persons, dayIndex) => + personIdsByDayIndex(conference, persons.map(personId), dayIndex).map(pi => + personById(persons, pi)); + +// :: Conference -> List[Person] -> Day -> List[Person] +let personsByDay = (conference, persons, day) => + personsByDayIndex(conference, persons, dayIndex(day)); + + +// :: Conference -> List[PersonId] -> RoomName -> List[PersonId] +let personIdsByRoomName = (conference, personIds, roomName) => { + let evs = eventsByRoomName(conferenceEvents(conference), roomName); + let pids = distinct(evs.flatMap(eventPersons).map(personId)); + return distinct(personIds.filter(pi => pids.includes(pi))); +}; + +// :: Conference -> List[PersonId] -> Room -> List[PersonId] +let personIdsByRoom = (conference, personIds, room) => + personIdsByRoomName(conference, personIds, roomName(room)); + +// :: Conference -> List[Person] -> RoomName -> List[Person] +let personsByRoomName = (conference, persons, roomName) => + personIdsByRoomName(conference, persons.map(personId), roomName).map(pi => + personById(persons, pi)); + +// :: Conference -> List[Person] -> Room -> List[Person] +let personsByRoom = (conference, persons, room) => + personsByRoomName(conference, persons, roomName(room)); + + +// :: Conference -> List[PersonId] -> Track -> List[PersonId] +let personIdsByTrack = (conference, personIds, track) => { + let evs = eventsByTrack(conferenceEvents(conference), track); + let pids = evs.flatMap(eventPersons).map(personId); + return distinct(personIds.filter(pi => pids.includes(pi))); +}; + +// :: Conference -> List[PersonId] -> Track -> List[PersonId] +let personsByTrack = (conference, persons, track) => + personIdsByTrack(conference, persons.map(personId), track).map(pi => + personById(persons, pi)); + +// :: Conference -> List[PersonId] -> Type -> List[PersonId] +let personIdsByType = (conference, personIds, type) => { + let evs = eventsByType(conferenceEvents(conference), type); + let pids = evs.flatMap(eventPersons).map(personId); + return distinct(personIds.filter(pi => pids.includes(pi))); +}; + +// :: Conference -> List[Person] -> Type -> List[Person] +let personsByType = (conference, persons, type) => + personIdsByType(conference, persons.map(personId), type).map(pi => + personById(persons, pi)); + +// :: Conference -> List[PersonId] -> Language -> List[PersonId] +let personIdsByLanguage = (conference, personIds, language) => { + let evs = eventsByLanguage(conferenceEvents(conference), language); + let pids = evs.flatMap(eventPersons).map(personId); + return distinct(personIds.filter(pi => pids.includes(pi))); +}; + +// :: Conference -> List[Person] -> Language -> List[Person] +let personsByLanguage = (conference, persons, language) => + personIdsByLanguage(conference, persons.map(personId), language).map(pi => + personById(persons, pi)); + + +// :: Conference -> List[DayIndex] -> RoomName -> List[DayIndex] +let dayIndicesByRoomName = (conference, dayIndices, roomName) => { + let evs = eventsByRoomName(conferenceEvents(conference), roomName); + let dis = distinct(evs.map(eventDayIndex)); + return distinct(dayIndices.filter(di => dis.includes(di))); +}; + +// :: Conference -> List[DayIndex] -> Room -> List[DayIndex] +let dayIndicesByRoom = (conference, dayIndices, room) => + dayIndicesByRoomName(conference, dayIndices, roomName(room)); + +// :: Conference -> List[Day] -> RoomName -> List[Day] +let daysByRoomName = (conference, days, roomName) => + dayIndicesByRoomName(conference, days.map(dayIndex), roomName).map(di => + dayByIndex(days, di)); + +// :: Conference -> List[Day] -> Room -> List[Day] +let daysByRoom = (conference, days, room) => + daysByRoomName(conference, days, roomName(room)); + + +// :: Conference -> List[DayIndex] -> PersonId -> List[DayIndex] +let dayIndicesByPersonId = (conference, dayIndices, id) => { + let evs = eventsByPersonId(conferenceEvents(conference), id); + let dis = distinct(evs.map(eventDayIndex)); + return distinct(dayIndices.filter(di => dis.includes(di))); +}; + +// :: Conference -> List[DayIndex] -> Person -> List[DayIndex] +let dayIndicesByPerson = (conference, dayIndices, person) => + dayIndicesByPersonId(conference, dayIndices, personId(person)); + +// :: Conference -> List[Day] -> PersonId -> List[Day] +let daysByPersonId = (conference, days, id) => + dayIndicesByPersonId(conference, days.map(dayIndex), id).map(di => + dayByIndex(days, di)); + +// :: Conference -> List[Day] -> Person -> List[Day] +let daysByPerson = (conference, days, person) => + daysByPersonId(conference, days, personId(person)); + + +// :: Conference -> List[DayIndex] -> Track -> List[DayIndex] +let dayIndicesByTrack = (conference, dayIndices, track) => { + let evs = eventsByTrack(conferenceEvents(conference), track); + let dis = evs.map(eventDayIndex); + return distinct(dayIndices.filter(di => dis.includes(di))); +}; + +// :: Conference -> List[Day] -> Track -> List[Day] +let daysByTrack = (conference, days, track) => + dayIndicesByTrack(conference, days.map(dayIndex), track).map(di => + dayByIndex(days, di)); + +// :: Conference -> List[DayIndex] -> Type -> List[DayIndex] +let dayIndicesByType = (conference, dayIndices, type) => { + let evs = eventsByType(conferenceEvents(conference), type); + let dis = evs.map(eventDayIndex); + return distinct(dayIndices.filter(di => dis.includes(di))); +}; + +// :: Conference -> List[Day] -> Type -> List[Day] +let daysByType = (conference, days, type) => + dayIndicesByType(conference, days.map(dayIndex), type).map(di => + dayByIndex(days, di)); + +// :: Conference -> List[DayIndex] -> Language -> List[DayIndex] +let dayIndicesByLanguage = (conference, dayIndices, language) => { + let evs = eventsByLanguage(conferenceEvents(conference), language); + let dis = evs.map(eventDayIndex); + return distinct(dayIndices.filter(di => dis.includes(di))); +}; + +// :: Conference -> List[Day] -> Language -> List[Day] +let daysByLanguage = (conference, days, language) => + dayIndicesByLanguage(conference, days.map(dayIndex), language).map(di => + dayByIndex(days, di)); + + +// :: Conference -> List[Track] -> DayIndex -> List[Track] +let tracksByDayIndex = (conference, tracks, dayIndex) => + tracksOfEvents(eventsByDayIndex(conferenceEvents(conference), dayIndex)); + +// :: Conference -> List[Track] -> Day -> List[Track] +let tracksByDay = (conference, tracks, day) => + tracksOfEvents(eventsByDay(conferenceEvents(conference), day)); + +// :: Conference -> List[Track] -> RoomName -> List[Track] +let tracksByRoomName = (conference, tracks, roomName) => + tracksOfEvents(eventsByRoomName(conferenceEvents(conference), roomName)); + +// :: Conference -> List[Track] -> Room -> List[Track] +let tracksByRoom = (conference, tracks, room) => + tracksOfEvents(eventsByRoom(conferenceEvents(conference), room)); + + +// :: Conference -> List[Type] -> DayIndex -> List[Type] +let typesByDayIndex = (conference, types, dayIndex) => + typesOfEvents(eventsByDayIndex(conferenceEvents(conference), dayIndex)); + +// :: Conference -> List[Type] -> Day -> List[Type] +let typesByDay = (conference, types, day) => + typesOfEvents(eventsByDay(conferenceEvents(conference), day)); + +// :: Conference -> List[Type] -> RoomName -> List[Type] +let typesByRoomName = (conference, types, roomName) => + typesOfEvents(eventsByRoomName(conferenceEvents(conference), roomName)); + +// :: Conference -> List[Type] -> Room -> List[Type] +let typesByRoom = (conference, types, room) => + typesOfEvents(eventsByRoom(conferenceEvents(conference), room)); + + +// :: Conference -> List[Language] -> DayIndex -> List[Language] +let languagesByDayIndex = (conference, languages, dayIndex) => + languagesOfEvents(eventsByDayIndex(conferenceEvents(conference), dayIndex)); + +// :: Conference -> List[Language] -> Day -> List[Language] +let languagesByDay = (conference, languages, day) => + languagesOfEvents(eventsByDay(conferenceEvents(conference), day)); + +// :: Conference -> List[Language] -> RoomName -> List[Language] +let languagesByRoomName = (conference, languages, roomName) => + languagesOfEvents(eventsByRoomName(conferenceEvents(conference), roomName)); + +// :: Conference -> List[Language] -> Room -> List[Language] +let languagesByRoom = (conference, languages, room) => + languagesOfEvents(eventsByRoom(conferenceEvents(conference), room)); + + +// --------------------------------------------------------- +// Timing of Events and Days + +// :: List[Event] -> luxon.DateTime -> List[Event] +let futureEvents = (events, now) => + events.filter(e => now.toMillis() < eventStartDate(e).toMillis()); + +// :: List[Event] -> luxon.DateTime -> List[Event] +let currentEvents = (events, now) => + events.filter(e => + (eventStartDate(e).toMillis() <= now.toMillis() && + now.toMillis() <= eventEndDate(e).toMillis())); + +// :: List[Event] -> luxon.DateTime -> List[Event] +let pastEvents = (events, now) => + events.filter(e => eventEndDate(e).toMillis() < now.toMillis()); + + +// :: List[Event] -> luxon.DateTime -> luxon.Duration -> List[Event] +let startingEvents = (events, now, dt) => + events.filter(e => + (eventStartDate(e).minus(dt).toMillis() <= now.toMillis() && + now.toMillis() < eventStartDate(e).toMillis())); + +// :: List[Event] -> luxon.DateTime -> luxon.Duration -> List[Event] +let startedEvents = (events, now, dt) => + events.filter(e => + (eventStartDate(e).toMillis() <= now.toMillis() && + now.toMillis() <= eventStartDate(e).plus(dt).toMillis())); + +// :: List[Event] -> luxon.DateTime -> luxon.Duration -> List[Event] +let endingEvents = (events, now, dt) => + events.filter(e => + (eventEndDate(e).minus(dt).toMillis() <= now.toMillis() && + now.toMillis() <= eventEndDate(e).toMillis())); + +// :: List[Event] -> luxon.DateTime -> luxon.Duration -> List[Event] +let endedEvents = (events, now, dt) => + events.filter(e => + (eventEndDate(e).toMillis() < now.toMillis() && + now.toMillis() <= eventStartDate(e).plus(dt).toMillis())); + + +// :: List[Event] -> List[Event] +let sortEventsByStartDate = (events) => + events.sort((e1, e2) => + eventStartDate(e1).toMillis() - eventStartDate(e2).toMillis()); + +// :: List[Event] -> List[Event] +let sortEventsByEndDate = (events) => + events.sort((e1, e2) => + eventEndDate(e1).toMillis() - eventEndDate(e2).toMillis()); + +// :: List[Event] -> List[Event] +let sortEventsByDuration = (events) => + events.sort((e1, e2) => + eventDuration(e1).toMillis() - eventDuration(e2).toMillis()); + + +// :: List[Day] -> luxon.DateTime -> List[Day] +let futureDays = (days, now) => + days.filter(d => now.toMillis() < dayStartDate(d).toMillis()); + +// :: List[Day] -> luxon.DateTime -> List[Day] +let currentDays = (days, now) => + days.filter(d => + (dayStartDate(d).toMillis() <= now.toMillis() && + now.toMillis() <= dayEndDate(d).toMillis())); + +// :: List[Day] -> luxon.DateTime -> List[Day] +let pastDays = (days, now) => + days.filter(d => dayEndDate(d).toMillis() < now.toMillis()); + + +// :: List[Day] -> List[Day] +let sortDaysByStartDate = (days) => + days.sort((d1, d2) => + dayStartDate(d1).toMillis() - dayStartDate(d2).toMillis()); + +// :: List[Day] -> List[Day] +let sortDaysByEndDate = (days) => + days.sort((d1, d2) => + dayEndDate(d1).toMillis() - dayEndDate(d2).toMillis()); + +// :: List[Day] -> List[Day] +let sortDaysByDuration = (days) => + days.sort((d1, d2) => + dayDuration(d1).toMillis() - dayDuration(d2).toMillis()); + + +// --------------------------------------------------------- +// Extractors: Shortcut entry points + +// :: Schedule -> List[Day] +let allDays = (schedule) => conferenceDays(conference(schedule)); + +// :: Schedule -> List[Room] +let allRooms = (schedule) => conferenceRooms(conference(schedule)); + +// :: Schedule -> List[Event] +let allEvents = (schedule) => conferenceEvents(conference(schedule)); + +// :: Schedule -> List[Person] +let allPersons = (schedule) => conferencePersons(conference(schedule)); + +// :: Schedule -> List[TrackName] +let allTracks = (schedule) => conferenceTracks(conference(schedule)); + +// :: Schedule -> List[EventType] +let allTypes = (schedule) => conferenceTypes(conference(schedule)); + +// :: Schedule -> List[Language] +let allLanguages = (schedule) => conferenceLanguages(conference(schedule)); + + +// --------------------------------------------------------- +// Public API Exports + +export { + optional, + defined, + withDefined, + distinct, + intersection, + processScheduleFile, + scheduleVersion, + scheduleBaseUrl, + conferenceAcronym, + conferenceTitle, + conferenceStartDate, + conferenceEndDate, + conferenceDuration, + conferenceDaysCount, + conferenceTimeslotDuration, + conferenceTimezoneName, + dayIndex, + dayDate, + dayStartDate, + dayEndDate, + dayDuration, + roomName, + roomGuid, + roomDescription, + roomCapacity, + eventId, + eventGuid, + eventLogo, + eventStartDate, + eventEndDate, + eventDuration, + eventDayIndex, + eventRoomName, + eventSlug, + eventUrl, + eventTitle, + eventSubtitle, + eventTrack, + eventType, + eventLanguage, + eventAbstract, + eventDescription, + eventRecordingLicense, + eventDoNotRecord, + eventPersons, + eventPersonCount, + eventAnswers, + personId, + personCode, + personName, + personBiography, + eventsByDayIndex, + eventsByDay, + eventsByRoomName, + eventsByRoom, + eventsByPersonId, + eventsByPersonName, + eventsByPerson, + eventsByTrack, + eventsByType, + eventsByLanguage, + roomById, + roomsByName, + dayByIndex, + personById, + personsByName, + eventById, + distinctRooms, + distinctDays, + distinctEvents, + distinctPersons, + sortPersonsByName, + sortRoomsByName, + sortEventsByTitle, + eventsOfDay, + eventsOfDays, + tracksOfEvents, + typesOfEvents, + languagesOfEvents, + conferenceDays, + conferenceRooms, + conferenceEvents, + conferencePersons, + conferenceTracks, + conferenceTypes, + conferenceLanguages, + conference, + roomNamesByDayIndex, + roomNamesByDay, + roomsByDayIndex, + roomsByDay, + roomNamesByPersonId, + roomNamesByPerson, + roomsByPersonId, + roomsByPerson, + roomNamesByTrack, + roomsByTrack, + roomNamesByType, + roomsByType, + roomNamesByLanguage, + roomsByLanguage, + personIdsByDayIndex, + personIdsByDay, + personsByDayIndex, + personsByDay, + personIdsByRoomName, + personIdsByRoom, + personsByRoomName, + personsByRoom, + personIdsByTrack, + personsByTrack, + personIdsByType, + personsByType, + personIdsByLanguage, + personsByLanguage, + dayIndicesByRoomName, + dayIndicesByRoom, + daysByRoomName, + daysByRoom, + dayIndicesByPersonId, + dayIndicesByPerson, + daysByPersonId, + daysByPerson, + dayIndicesByTrack, + daysByTrack, + dayIndicesByType, + daysByType, + dayIndicesByLanguage, + daysByLanguage, + tracksByDayIndex, + tracksByDay, + tracksByRoomName, + tracksByRoom, + typesByDayIndex, + typesByDay, + typesByRoomName, + typesByRoom, + languagesByDayIndex, + languagesByDay, + languagesByRoomName, + languagesByRoom, + futureEvents, + currentEvents, + pastEvents, + startingEvents, + startedEvents, + endingEvents, + endedEvents, + sortEventsByStartDate, + sortEventsByEndDate, + sortEventsByDuration, + futureDays, + currentDays, + pastDays, + sortDaysByStartDate, + sortDaysByEndDate, + sortDaysByDuration, + allDays, + allRooms, + allEvents, + allPersons, + allTracks, + allTypes, + allLanguages +}; + +// Command to generate API exports: +// grep -A 1 -e '// :: ' sol.js | sed -e '/^--$/d' -e '/ :: /d' -e 's/^let / /g' -e 's/ = .*$/,/g' > names.txt +// Note: Type signatures starting with '//-:: ' instead of '// :: ' denote unexported internal functions. diff --git a/config/_default/config.toml b/config/_default/config.toml new file mode 100644 index 0000000..b685c04 --- /dev/null +++ b/config/_default/config.toml @@ -0,0 +1,21 @@ +baseURL = "https://files.chvoc.ch/" +languageCode = 'de-DE' +title = 'DGWK24' + +defaultContentLanguage = "en" + +disableHugoGeneratorInject = true +enableRobotsTXT = false +disableKinds = ["taxonomy", "term", "RSS", "sitemap", "robotsTXT", "404"] + +[outputs] + home = ["HTML"] + page = ["HTML"] + + +[params] +workerBaseURL = '/js/custom/core/' + +scheduleURL = '/schedule.json' +#scheduleURL = 'https://cfp.winterkongress.ch/wk24/schedule/export/schedule.json' +scheduleFetchInterval = 60 diff --git a/config/production/config.toml b/config/production/config.toml new file mode 100644 index 0000000..969f962 --- /dev/null +++ b/config/production/config.toml @@ -0,0 +1,9 @@ +baseURL = "https://files.chvoc.ch/dgwk24/info/" + + +[params] +workerBaseURL = '/dgwk24/info/js/custom/core/' + +scheduleURL = '/dgwk24/info/schedule.json' +#scheduleURL = 'https://cfp.winterkongress.ch/wk24/schedule/export/schedule.json' +scheduleFetchInterval = 60 diff --git a/content/_index.md b/content/_index.md new file mode 100644 index 0000000..a845151 --- /dev/null +++ b/content/_index.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/content/schedule-hall1/index.md b/content/schedule-hall1/index.md new file mode 100644 index 0000000..cf4f648 --- /dev/null +++ b/content/schedule-hall1/index.md @@ -0,0 +1,4 @@ +--- +title: "Schedule Hall 1: Festsaal" +type: schedule-hall1 +--- diff --git a/content/schedule-hall2/index.md b/content/schedule-hall2/index.md new file mode 100644 index 0000000..5a9415b --- /dev/null +++ b/content/schedule-hall2/index.md @@ -0,0 +1,4 @@ +--- +title: "Schedule Hall 2: Bankettsaal" +type: schedule-hall2 +--- diff --git a/content/schedule-hall3/index.md b/content/schedule-hall3/index.md new file mode 100644 index 0000000..59a07ef --- /dev/null +++ b/content/schedule-hall3/index.md @@ -0,0 +1,4 @@ +--- +title: "Schedule Hall 3: Tanzsaal" +type: schedule-hall3 +--- diff --git a/content/schedule/index.md b/content/schedule/index.md new file mode 100644 index 0000000..e937e71 --- /dev/null +++ b/content/schedule/index.md @@ -0,0 +1,4 @@ +--- +title: "Schedule" +type: schedule +--- diff --git a/content/speaker-info-hall1/index.md b/content/speaker-info-hall1/index.md new file mode 100644 index 0000000..0359207 --- /dev/null +++ b/content/speaker-info-hall1/index.md @@ -0,0 +1,4 @@ +--- +title: "Speaker Info Hall 1: Festsaal" +type: speaker-info-hall1 +--- diff --git a/content/speaker-info-hall2/index.md b/content/speaker-info-hall2/index.md new file mode 100644 index 0000000..71bd6cb --- /dev/null +++ b/content/speaker-info-hall2/index.md @@ -0,0 +1,4 @@ +--- +title: "Speaker Info Hall 2: Bankettsaal" +type: speaker-info-hall2 +--- diff --git a/content/speaker-info-hall3/index.md b/content/speaker-info-hall3/index.md new file mode 100644 index 0000000..12f0d1e --- /dev/null +++ b/content/speaker-info-hall3/index.md @@ -0,0 +1,4 @@ +--- +title: "Speaker Info Hall 3: Tanzsaal" +type: speaker-info-hall3 +--- diff --git a/content/talk-info-hall1/index.md b/content/talk-info-hall1/index.md new file mode 100644 index 0000000..4868b83 --- /dev/null +++ b/content/talk-info-hall1/index.md @@ -0,0 +1,4 @@ +--- +title: "Talk Info Hall 1: Festsaal" +type: talk-info-hall1 +--- diff --git a/content/talk-info-hall2/index.md b/content/talk-info-hall2/index.md new file mode 100644 index 0000000..1d4174c --- /dev/null +++ b/content/talk-info-hall2/index.md @@ -0,0 +1,4 @@ +--- +title: "Talk Info Hall 2: Bankettsaal" +type: talk-info-hall2 +--- diff --git a/content/talk-info-hall3/index.md b/content/talk-info-hall3/index.md new file mode 100644 index 0000000..dfe47c4 --- /dev/null +++ b/content/talk-info-hall3/index.md @@ -0,0 +1,4 @@ +--- +title: "Talk Info Hall 3: Tanzsaal" +type: talk-info-hall3 +--- diff --git a/content/upcoming-talk-hall1/index.md b/content/upcoming-talk-hall1/index.md new file mode 100644 index 0000000..32dddef --- /dev/null +++ b/content/upcoming-talk-hall1/index.md @@ -0,0 +1,4 @@ +--- +title: "Upcoming Talk Hall 1: Festsaal" +type: upcoming-talk-hall1 +--- diff --git a/content/upcoming-talk-hall2/index.md b/content/upcoming-talk-hall2/index.md new file mode 100644 index 0000000..09492c4 --- /dev/null +++ b/content/upcoming-talk-hall2/index.md @@ -0,0 +1,4 @@ +--- +title: "Upcoming Talk Hall 2: Bankettsaal" +type: upcoming-talk-hall2 +--- diff --git a/content/upcoming-talk-hall3/index.md b/content/upcoming-talk-hall3/index.md new file mode 100644 index 0000000..eccf3e3 --- /dev/null +++ b/content/upcoming-talk-hall3/index.md @@ -0,0 +1,4 @@ +--- +title: "Upcoming Talk Hall 3: Tanzsaal" +type: upcoming-talk-hall3 +--- diff --git a/content/voc-schedule-hall1/index.md b/content/voc-schedule-hall1/index.md new file mode 100644 index 0000000..d0275ab --- /dev/null +++ b/content/voc-schedule-hall1/index.md @@ -0,0 +1,4 @@ +--- +title: "VOC Schedule Hall 1: Festsaal" +type: voc-schedule-hall1 +--- diff --git a/content/voc-schedule-hall2/index.md b/content/voc-schedule-hall2/index.md new file mode 100644 index 0000000..46dc965 --- /dev/null +++ b/content/voc-schedule-hall2/index.md @@ -0,0 +1,4 @@ +--- +title: "VOC Schedule Hall 2: Bankettsaal" +type: voc-schedule-hall2 +--- diff --git a/content/voc-schedule-hall3/index.md b/content/voc-schedule-hall3/index.md new file mode 100644 index 0000000..2611760 --- /dev/null +++ b/content/voc-schedule-hall3/index.md @@ -0,0 +1,4 @@ +--- +title: "VOC Schedule Hall 3: Tanzsaal" +type: voc-schedule-hall3 +--- diff --git a/content/voc-schedule/index.md b/content/voc-schedule/index.md new file mode 100644 index 0000000..6659ed6 --- /dev/null +++ b/content/voc-schedule/index.md @@ -0,0 +1,4 @@ +--- +title: "VOC Schedule" +type: voc-schedule +--- diff --git a/content/voc-speaker/index.md b/content/voc-speaker/index.md new file mode 100644 index 0000000..1682129 --- /dev/null +++ b/content/voc-speaker/index.md @@ -0,0 +1,4 @@ +--- +title: "VOC Speaker" +type: voc-speaker +--- diff --git a/content/voc-talks/index.md b/content/voc-talks/index.md new file mode 100644 index 0000000..8cc7415 --- /dev/null +++ b/content/voc-talks/index.md @@ -0,0 +1,4 @@ +--- +title: "VOC Talks" +type: voc-talks +--- diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html new file mode 100644 index 0000000..74fd2be --- /dev/null +++ b/layouts/_default/baseof.html @@ -0,0 +1,56 @@ + + + + + + + {{ block "metaincludes" . }} + {{ partial "redirect.html" .Params }} + {{ end }} + + {{ .Site.Title }} + + {{ block "cssdependencyincludes" . }} + + + {{ end }} + + {{ block "cssincludes" . }} + {{ $options := dict "targetPath" "default.css" "outputStyle" "compressed" "enableSourceMap" false -}} + {{ $style := resources.Get "/css/custom/nodes/default.scss" | resources.ToCSS $options | resources.Minify | resources.Fingerprint -}} + + {{ end }} + + {{ $configData := dict "workerBaseURL" .Site.Params.workerBaseURL "scheduleURL" .Site.Params.scheduleURL "scheduleFetchInterval" .Site.Params.scheduleFetchInterval "twitterURL" .Site.Params.twitterURL "twitterFetchInterval" .Site.Params.twitterFetchInterval "mastodonURL" .Site.Params.mastodonURL "mastodonFetchInterval" .Site.Params.mastodonFetchInterval "musicURL" .Site.Params.musicURL "musicFetchInterval" .Site.Params.musicFetchInterval "cmsURL" .Site.Params.cmsURL "cmsFetchInterval" .Site.Params.cmsFetchInterval }} + {{ $configjs := resources.Get "/js/custom/core/config.js" | js.Build (dict "params" $configData) | resources.Fingerprint }} + + + {{ block "jsworkerincludes" . }} + + + {{ $fetchworkerjs := resources.Get "/js/custom/core/generic_fetch_worker.js" }} + + {{ end }} + + + {{ block "main" . }} +
+ +
+ {{ end }} + + {{ block "jsdependencyincludes" . }} + {{ $luxon := resources.Get "/js/luxon/luxon.min.js" | resources.Fingerprint }} + + + {{ $preact := resources.Get "/js/preact/preact.min.js" | resources.Fingerprint }} + + + {{ $htm := resources.Get "/js/htm/htm.js" | resources.Fingerprint }} + + {{ end }} + + {{ block "jsincludes" . }} + {{ end }} + + diff --git a/layouts/index.html b/layouts/index.html new file mode 100644 index 0000000..425e05d --- /dev/null +++ b/layouts/index.html @@ -0,0 +1,53 @@ +{{ define "main" }} +

:HugInfo:

+ +
+

Static Information Endpoints:

+
    + {{ range .Pages }} + {{ if not .Params.redirect }} +
  • + {{ .Title }}:{{ .RelPermalink }} +
  • + {{ end }} + {{ end }} +
+ +

Redirecting Information Endpoints:

+
    + {{ range .Pages }} + {{ if .Params.redirect }} +
  • + + + {{ .Title }}:{{ .RelPermalink }} + {{ with .Params.redirect }} +
    +
    Configured redirect:
    + +
    + {{ end }} +
    +
  • + {{ end }} + {{ end }} +
+
+{{ end }} + + +{{ define "cssincludes" }} +{{ $options := dict "targetPath" "_index.css" "outputStyle" "compressed" "enableSourceMap" false -}} +{{ $style := resources.Get "/css/custom/core/_index.scss" | resources.ToCSS $options | resources.Minify | resources.Fingerprint -}} + +{{ end }} + + +{{ define "jsworkerincludes" }}{{ end }} + +{{ define "jsdependencyincludes" }}{{ end }} + +{{ define "jsincludes" }}{{ end }} diff --git a/layouts/partials/logo.html b/layouts/partials/logo.html new file mode 100644 index 0000000..4b14ecf --- /dev/null +++ b/layouts/partials/logo.html @@ -0,0 +1,5 @@ +
+ + + +
diff --git a/layouts/partials/redirect.html b/layouts/partials/redirect.html new file mode 100644 index 0000000..8786445 --- /dev/null +++ b/layouts/partials/redirect.html @@ -0,0 +1,3 @@ +{{ with .redirect }} + +{{ end }} diff --git a/layouts/schedule-hall1/single.html b/layouts/schedule-hall1/single.html new file mode 100644 index 0000000..22a2cef --- /dev/null +++ b/layouts/schedule-hall1/single.html @@ -0,0 +1,21 @@ +{{ define "cssincludes" }} +{{ $options := dict "targetPath" "schedule-hall1.css" "outputStyle" "compressed" "enableSourceMap" false -}} +{{ $style := resources.Get "/css/custom/nodes/schedule-hall1.scss" | resources.ToCSS $options | resources.Minify | resources.Fingerprint -}} + +{{ end }} + +{{ define "jsincludes" }} +{{ $externals := slice "htm" "preact" "luxon" }} +{{ $buildOptions := dict "targetPath" "schedule-hall1.js" "externals" $externals }} +{{ $nodejs := resources.Get "/js/custom/nodes/schedule-hall1.js" | js.Build $buildOptions | resources.Fingerprint }} + +{{ end }} + +{{ define "main" }} + +{{ partial "logo.html" . }} +
+ +
+
+{{ end }} diff --git a/layouts/schedule-hall2/single.html b/layouts/schedule-hall2/single.html new file mode 100644 index 0000000..c40190e --- /dev/null +++ b/layouts/schedule-hall2/single.html @@ -0,0 +1,21 @@ +{{ define "cssincludes" }} +{{ $options := dict "targetPath" "schedule-hall2.css" "outputStyle" "compressed" "enableSourceMap" false -}} +{{ $style := resources.Get "/css/custom/nodes/schedule-hall2.scss" | resources.ToCSS $options | resources.Minify | resources.Fingerprint -}} + +{{ end }} + +{{ define "jsincludes" }} +{{ $externals := slice "htm" "preact" "luxon" }} +{{ $buildOptions := dict "targetPath" "schedule-hall2.js" "externals" $externals }} +{{ $nodejs := resources.Get "/js/custom/nodes/schedule-hall2.js" | js.Build $buildOptions | resources.Fingerprint }} + +{{ end }} + +{{ define "main" }} + +{{ partial "logo.html" . }} +
+ +
+
+{{ end }} diff --git a/layouts/schedule-hall3/single.html b/layouts/schedule-hall3/single.html new file mode 100644 index 0000000..87b1eae --- /dev/null +++ b/layouts/schedule-hall3/single.html @@ -0,0 +1,21 @@ +{{ define "cssincludes" }} +{{ $options := dict "targetPath" "schedule-hall3.css" "outputStyle" "compressed" "enableSourceMap" false -}} +{{ $style := resources.Get "/css/custom/nodes/schedule-hall3.scss" | resources.ToCSS $options | resources.Minify | resources.Fingerprint -}} + +{{ end }} + +{{ define "jsincludes" }} +{{ $externals := slice "htm" "preact" "luxon" }} +{{ $buildOptions := dict "targetPath" "schedule-hall3.js" "externals" $externals }} +{{ $nodejs := resources.Get "/js/custom/nodes/schedule-hall3.js" | js.Build $buildOptions | resources.Fingerprint }} + +{{ end }} + +{{ define "main" }} + +{{ partial "logo.html" . }} +
+ +
+
+{{ end }} diff --git a/layouts/schedule/single.html b/layouts/schedule/single.html new file mode 100644 index 0000000..2db298d --- /dev/null +++ b/layouts/schedule/single.html @@ -0,0 +1,21 @@ +{{ define "cssincludes" }} +{{ $options := dict "targetPath" "schedule.css" "outputStyle" "compressed" "enableSourceMap" false -}} +{{ $style := resources.Get "/css/custom/nodes/schedule.scss" | resources.ToCSS $options | resources.Minify | resources.Fingerprint -}} + +{{ end }} + +{{ define "jsincludes" }} +{{ $externals := slice "htm" "preact" "luxon" }} +{{ $buildOptions := dict "targetPath" "schedule.js" "externals" $externals }} +{{ $nodejs := resources.Get "/js/custom/nodes/schedule.js" | js.Build $buildOptions | resources.Fingerprint }} + +{{ end }} + +{{ define "main" }} + +{{ partial "logo.html" . }} +
+ +
+
+{{ end }} diff --git a/layouts/speaker-info-hall1/single.html b/layouts/speaker-info-hall1/single.html new file mode 100644 index 0000000..402b232 --- /dev/null +++ b/layouts/speaker-info-hall1/single.html @@ -0,0 +1,19 @@ +{{ define "cssincludes" }} +{{ $options := dict "targetPath" "speaker-info-hall1.css" "outputStyle" "compressed" "enableSourceMap" false -}} +{{ $style := resources.Get "/css/custom/nodes/speaker-info-hall1.scss" | resources.ToCSS $options | resources.Minify | resources.Fingerprint -}} + +{{ end }} + +{{ define "jsincludes" }} +{{ $externals := slice "htm" "preact" "luxon" }} +{{ $buildOptions := dict "targetPath" "speaker-info-hall1.js" "externals" $externals }} +{{ $nodejs := resources.Get "/js/custom/nodes/speaker-info-hall1.js" | js.Build $buildOptions | resources.Fingerprint }} + +{{ end }} + +{{ define "main" }} + +
+ +
+{{ end }} diff --git a/layouts/speaker-info-hall2/single.html b/layouts/speaker-info-hall2/single.html new file mode 100644 index 0000000..337a5ee --- /dev/null +++ b/layouts/speaker-info-hall2/single.html @@ -0,0 +1,19 @@ +{{ define "cssincludes" }} +{{ $options := dict "targetPath" "speaker-info-hall2.css" "outputStyle" "compressed" "enableSourceMap" false -}} +{{ $style := resources.Get "/css/custom/nodes/speaker-info-hall2.scss" | resources.ToCSS $options | resources.Minify | resources.Fingerprint -}} + +{{ end }} + +{{ define "jsincludes" }} +{{ $externals := slice "htm" "preact" "luxon" }} +{{ $buildOptions := dict "targetPath" "speaker-info-hall2.js" "externals" $externals }} +{{ $nodejs := resources.Get "/js/custom/nodes/speaker-info-hall2.js" | js.Build $buildOptions | resources.Fingerprint }} + +{{ end }} + +{{ define "main" }} + +
+ +
+{{ end }} diff --git a/layouts/speaker-info-hall3/single.html b/layouts/speaker-info-hall3/single.html new file mode 100644 index 0000000..a6e1d4d --- /dev/null +++ b/layouts/speaker-info-hall3/single.html @@ -0,0 +1,19 @@ +{{ define "cssincludes" }} +{{ $options := dict "targetPath" "speaker-info-hall3.css" "outputStyle" "compressed" "enableSourceMap" false -}} +{{ $style := resources.Get "/css/custom/nodes/speaker-info-hall3.scss" | resources.ToCSS $options | resources.Minify | resources.Fingerprint -}} + +{{ end }} + +{{ define "jsincludes" }} +{{ $externals := slice "htm" "preact" "luxon" }} +{{ $buildOptions := dict "targetPath" "speaker-info-hall3.js" "externals" $externals }} +{{ $nodejs := resources.Get "/js/custom/nodes/speaker-info-hall3.js" | js.Build $buildOptions | resources.Fingerprint }} + +{{ end }} + +{{ define "main" }} + +
+ +
+{{ end }} diff --git a/layouts/talk-info-hall1/single.html b/layouts/talk-info-hall1/single.html new file mode 100644 index 0000000..c818d04 --- /dev/null +++ b/layouts/talk-info-hall1/single.html @@ -0,0 +1,19 @@ +{{ define "cssincludes" }} +{{ $options := dict "targetPath" "talk-info-hall1.css" "outputStyle" "compressed" "enableSourceMap" false -}} +{{ $style := resources.Get "/css/custom/nodes/talk-info-hall1.scss" | resources.ToCSS $options | resources.Minify | resources.Fingerprint -}} + +{{ end }} + +{{ define "jsincludes" }} +{{ $externals := slice "htm" "preact" "luxon" }} +{{ $buildOptions := dict "targetPath" "talk-info-hall1.js" "externals" $externals }} +{{ $nodejs := resources.Get "/js/custom/nodes/talk-info-hall1.js" | js.Build $buildOptions | resources.Fingerprint }} + +{{ end }} + +{{ define "main" }} + +
+ +
+{{ end }} diff --git a/layouts/talk-info-hall2/single.html b/layouts/talk-info-hall2/single.html new file mode 100644 index 0000000..e69e72c --- /dev/null +++ b/layouts/talk-info-hall2/single.html @@ -0,0 +1,19 @@ +{{ define "cssincludes" }} +{{ $options := dict "targetPath" "talk-info-hall2.css" "outputStyle" "compressed" "enableSourceMap" false -}} +{{ $style := resources.Get "/css/custom/nodes/talk-info-hall2.scss" | resources.ToCSS $options | resources.Minify | resources.Fingerprint -}} + +{{ end }} + +{{ define "jsincludes" }} +{{ $externals := slice "htm" "preact" "luxon" }} +{{ $buildOptions := dict "targetPath" "talk-info-hall2.js" "externals" $externals }} +{{ $nodejs := resources.Get "/js/custom/nodes/talk-info-hall2.js" | js.Build $buildOptions | resources.Fingerprint }} + +{{ end }} + +{{ define "main" }} + +
+ +
+{{ end }} diff --git a/layouts/talk-info-hall3/single.html b/layouts/talk-info-hall3/single.html new file mode 100644 index 0000000..19bb250 --- /dev/null +++ b/layouts/talk-info-hall3/single.html @@ -0,0 +1,19 @@ +{{ define "cssincludes" }} +{{ $options := dict "targetPath" "talk-info-hall3.css" "outputStyle" "compressed" "enableSourceMap" false -}} +{{ $style := resources.Get "/css/custom/nodes/talk-info-hall3.scss" | resources.ToCSS $options | resources.Minify | resources.Fingerprint -}} + +{{ end }} + +{{ define "jsincludes" }} +{{ $externals := slice "htm" "preact" "luxon" }} +{{ $buildOptions := dict "targetPath" "talk-info-hall3.js" "externals" $externals }} +{{ $nodejs := resources.Get "/js/custom/nodes/talk-info-hall3.js" | js.Build $buildOptions | resources.Fingerprint }} + +{{ end }} + +{{ define "main" }} + +
+ +
+{{ end }} diff --git a/layouts/upcoming-talk-hall1/single.html b/layouts/upcoming-talk-hall1/single.html new file mode 100644 index 0000000..f87af5c --- /dev/null +++ b/layouts/upcoming-talk-hall1/single.html @@ -0,0 +1,20 @@ +{{ define "cssincludes" }} +{{ $options := dict "targetPath" "upcoming-talk-hall1.css" "outputStyle" "compressed" "enableSourceMap" false -}} +{{ $style := resources.Get "/css/custom/nodes/upcoming-talk-hall1.scss" | resources.ToCSS $options | resources.Minify | resources.Fingerprint -}} + +{{ end }} + +{{ define "jsincludes" }} +{{ $externals := slice "htm" "preact" "luxon" }} +{{ $buildOptions := dict "targetPath" "upcoming-talk-hall1.js" "externals" $externals }} +{{ $nodejs := resources.Get "/js/custom/nodes/upcoming-talk-hall1.js" | js.Build $buildOptions | resources.Fingerprint }} + +{{ end }} + +{{ define "main" }} + +{{ partial "logo.html" . }} +
+ +
+{{ end }} diff --git a/layouts/upcoming-talk-hall2/single.html b/layouts/upcoming-talk-hall2/single.html new file mode 100644 index 0000000..55b643c --- /dev/null +++ b/layouts/upcoming-talk-hall2/single.html @@ -0,0 +1,20 @@ +{{ define "cssincludes" }} +{{ $options := dict "targetPath" "upcoming-talk-hall2.css" "outputStyle" "compressed" "enableSourceMap" false -}} +{{ $style := resources.Get "/css/custom/nodes/upcoming-talk-hall2.scss" | resources.ToCSS $options | resources.Minify | resources.Fingerprint -}} + +{{ end }} + +{{ define "jsincludes" }} +{{ $externals := slice "htm" "preact" "luxon" }} +{{ $buildOptions := dict "targetPath" "upcoming-talk-hall2.js" "externals" $externals }} +{{ $nodejs := resources.Get "/js/custom/nodes/upcoming-talk-hall2.js" | js.Build $buildOptions | resources.Fingerprint }} + +{{ end }} + +{{ define "main" }} + +{{ partial "logo.html" . }} +
+ +
+{{ end }} diff --git a/layouts/upcoming-talk-hall3/single.html b/layouts/upcoming-talk-hall3/single.html new file mode 100644 index 0000000..bb58ca6 --- /dev/null +++ b/layouts/upcoming-talk-hall3/single.html @@ -0,0 +1,20 @@ +{{ define "cssincludes" }} +{{ $options := dict "targetPath" "upcoming-talk-hall3.css" "outputStyle" "compressed" "enableSourceMap" false -}} +{{ $style := resources.Get "/css/custom/nodes/upcoming-talk-hall3.scss" | resources.ToCSS $options | resources.Minify | resources.Fingerprint -}} + +{{ end }} + +{{ define "jsincludes" }} +{{ $externals := slice "htm" "preact" "luxon" }} +{{ $buildOptions := dict "targetPath" "upcoming-talk-hall3.js" "externals" $externals }} +{{ $nodejs := resources.Get "/js/custom/nodes/upcoming-talk-hall3.js" | js.Build $buildOptions | resources.Fingerprint }} + +{{ end }} + +{{ define "main" }} + +{{ partial "logo.html" . }} +
+ +
+{{ end }} diff --git a/layouts/voc-schedule-hall1/single.html b/layouts/voc-schedule-hall1/single.html new file mode 100644 index 0000000..ad7c13c --- /dev/null +++ b/layouts/voc-schedule-hall1/single.html @@ -0,0 +1,12 @@ +{{ define "cssincludes" }} +{{ $options := dict "targetPath" "default.css" "outputStyle" "compressed" "enableSourceMap" false -}} +{{ $style := resources.Get "/css/custom/nodes/voc-schedule.scss" | resources.ToCSS $options | resources.Minify | resources.Fingerprint -}} + +{{ end }} + +{{ define "jsincludes" }} +{{ $externals := slice "htm" "preact" "luxon" }} +{{ $buildOptions := dict "targetPath" "voc-schedule-hall1.js" "externals" $externals }} +{{ $nodejs := resources.Get "/js/custom/nodes/voc-schedule-hall1.js" | js.Build $buildOptions | resources.Fingerprint }} + +{{ end }} diff --git a/layouts/voc-schedule-hall2/single.html b/layouts/voc-schedule-hall2/single.html new file mode 100644 index 0000000..cd5ea40 --- /dev/null +++ b/layouts/voc-schedule-hall2/single.html @@ -0,0 +1,12 @@ +{{ define "cssincludes" }} +{{ $options := dict "targetPath" "default.css" "outputStyle" "compressed" "enableSourceMap" false -}} +{{ $style := resources.Get "/css/custom/nodes/voc-schedule.scss" | resources.ToCSS $options | resources.Minify | resources.Fingerprint -}} + +{{ end }} + +{{ define "jsincludes" }} +{{ $externals := slice "htm" "preact" "luxon" }} +{{ $buildOptions := dict "targetPath" "voc-schedule-hall2.js" "externals" $externals }} +{{ $nodejs := resources.Get "/js/custom/nodes/voc-schedule-hall2.js" | js.Build $buildOptions | resources.Fingerprint }} + +{{ end }} diff --git a/layouts/voc-schedule-hall3/single.html b/layouts/voc-schedule-hall3/single.html new file mode 100644 index 0000000..449033d --- /dev/null +++ b/layouts/voc-schedule-hall3/single.html @@ -0,0 +1,12 @@ +{{ define "cssincludes" }} +{{ $options := dict "targetPath" "default.css" "outputStyle" "compressed" "enableSourceMap" false -}} +{{ $style := resources.Get "/css/custom/nodes/voc-schedule.scss" | resources.ToCSS $options | resources.Minify | resources.Fingerprint -}} + +{{ end }} + +{{ define "jsincludes" }} +{{ $externals := slice "htm" "preact" "luxon" }} +{{ $buildOptions := dict "targetPath" "voc-schedule-hall3.js" "externals" $externals }} +{{ $nodejs := resources.Get "/js/custom/nodes/voc-schedule-hall3.js" | js.Build $buildOptions | resources.Fingerprint }} + +{{ end }} diff --git a/layouts/voc-schedule/single.html b/layouts/voc-schedule/single.html new file mode 100644 index 0000000..db09b69 --- /dev/null +++ b/layouts/voc-schedule/single.html @@ -0,0 +1,12 @@ +{{ define "cssincludes" }} +{{ $options := dict "targetPath" "default.css" "outputStyle" "compressed" "enableSourceMap" false -}} +{{ $style := resources.Get "/css/custom/nodes/voc-schedule.scss" | resources.ToCSS $options | resources.Minify | resources.Fingerprint -}} + +{{ end }} + +{{ define "jsincludes" }} +{{ $externals := slice "htm" "preact" "luxon" }} +{{ $buildOptions := dict "targetPath" "voc-schedule.js" "externals" $externals }} +{{ $nodejs := resources.Get "/js/custom/nodes/voc-schedule.js" | js.Build $buildOptions | resources.Fingerprint }} + +{{ end }} diff --git a/layouts/voc-speaker/single.html b/layouts/voc-speaker/single.html new file mode 100644 index 0000000..e9e09da --- /dev/null +++ b/layouts/voc-speaker/single.html @@ -0,0 +1,12 @@ +{{ define "cssincludes" }} +{{ $options := dict "targetPath" "default.css" "outputStyle" "compressed" "enableSourceMap" false -}} +{{ $style := resources.Get "/css/custom/nodes/voc-speaker.scss" | resources.ToCSS $options | resources.Minify | resources.Fingerprint -}} + +{{ end }} + +{{ define "jsincludes" }} +{{ $externals := slice "htm" "preact" "luxon" }} +{{ $buildOptions := dict "targetPath" "voc-speaker.js" "externals" $externals }} +{{ $nodejs := resources.Get "/js/custom/nodes/voc-speaker.js" | js.Build $buildOptions | resources.Fingerprint }} + +{{ end }} diff --git a/layouts/voc-talks/single.html b/layouts/voc-talks/single.html new file mode 100644 index 0000000..d640242 --- /dev/null +++ b/layouts/voc-talks/single.html @@ -0,0 +1,12 @@ +{{ define "cssincludes" }} +{{ $options := dict "targetPath" "default.css" "outputStyle" "compressed" "enableSourceMap" false -}} +{{ $style := resources.Get "/css/custom/nodes/voc-talks.scss" | resources.ToCSS $options | resources.Minify | resources.Fingerprint -}} + +{{ end }} + +{{ define "jsincludes" }} +{{ $externals := slice "htm" "preact" "luxon" }} +{{ $buildOptions := dict "targetPath" "voc-talks.js" "externals" $externals }} +{{ $nodejs := resources.Get "/js/custom/nodes/voc-talks.js" | js.Build $buildOptions | resources.Fingerprint }} + +{{ end }} diff --git a/license.txt b/license.txt new file mode 100644 index 0000000..11ce6a2 --- /dev/null +++ b/license.txt @@ -0,0 +1,7 @@ +License +======= + +This work is licensed under Attribution-NonCommercial-NoDerivatives 4.0 International. +To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/ + +All external dependencies and assets are licensed under their own respective licenses. diff --git a/static/fonts/architects-daughter-v11-latin-regular.woff b/static/fonts/architects-daughter-v11-latin-regular.woff new file mode 100644 index 0000000..174a63b Binary files /dev/null and b/static/fonts/architects-daughter-v11-latin-regular.woff differ diff --git a/static/fonts/architects-daughter-v11-latin-regular.woff2 b/static/fonts/architects-daughter-v11-latin-regular.woff2 new file mode 100644 index 0000000..6003bf7 Binary files /dev/null and b/static/fonts/architects-daughter-v11-latin-regular.woff2 differ diff --git a/static/fonts/lato-v22-latin-ext_latin-100.woff b/static/fonts/lato-v22-latin-ext_latin-100.woff new file mode 100644 index 0000000..767edde Binary files /dev/null and b/static/fonts/lato-v22-latin-ext_latin-100.woff differ diff --git a/static/fonts/lato-v22-latin-ext_latin-100.woff2 b/static/fonts/lato-v22-latin-ext_latin-100.woff2 new file mode 100644 index 0000000..a7aeca5 Binary files /dev/null and b/static/fonts/lato-v22-latin-ext_latin-100.woff2 differ diff --git a/static/fonts/lato-v22-latin-ext_latin-100italic.woff b/static/fonts/lato-v22-latin-ext_latin-100italic.woff new file mode 100644 index 0000000..c1d07df Binary files /dev/null and b/static/fonts/lato-v22-latin-ext_latin-100italic.woff differ diff --git a/static/fonts/lato-v22-latin-ext_latin-100italic.woff2 b/static/fonts/lato-v22-latin-ext_latin-100italic.woff2 new file mode 100644 index 0000000..710107f Binary files /dev/null and b/static/fonts/lato-v22-latin-ext_latin-100italic.woff2 differ diff --git a/static/fonts/lato-v22-latin-ext_latin-300.woff b/static/fonts/lato-v22-latin-ext_latin-300.woff new file mode 100644 index 0000000..0078346 Binary files /dev/null and b/static/fonts/lato-v22-latin-ext_latin-300.woff differ diff --git a/static/fonts/lato-v22-latin-ext_latin-300.woff2 b/static/fonts/lato-v22-latin-ext_latin-300.woff2 new file mode 100644 index 0000000..461c169 Binary files /dev/null and b/static/fonts/lato-v22-latin-ext_latin-300.woff2 differ diff --git a/static/fonts/lato-v22-latin-ext_latin-300italic.woff b/static/fonts/lato-v22-latin-ext_latin-300italic.woff new file mode 100644 index 0000000..8a8a4b9 Binary files /dev/null and b/static/fonts/lato-v22-latin-ext_latin-300italic.woff differ diff --git a/static/fonts/lato-v22-latin-ext_latin-300italic.woff2 b/static/fonts/lato-v22-latin-ext_latin-300italic.woff2 new file mode 100644 index 0000000..ac8b035 Binary files /dev/null and b/static/fonts/lato-v22-latin-ext_latin-300italic.woff2 differ diff --git a/static/fonts/lato-v22-latin-ext_latin-700.woff b/static/fonts/lato-v22-latin-ext_latin-700.woff new file mode 100644 index 0000000..8ff1545 Binary files /dev/null and b/static/fonts/lato-v22-latin-ext_latin-700.woff differ diff --git a/static/fonts/lato-v22-latin-ext_latin-700.woff2 b/static/fonts/lato-v22-latin-ext_latin-700.woff2 new file mode 100644 index 0000000..b10c152 Binary files /dev/null and b/static/fonts/lato-v22-latin-ext_latin-700.woff2 differ diff --git a/static/fonts/lato-v22-latin-ext_latin-700italic.woff b/static/fonts/lato-v22-latin-ext_latin-700italic.woff new file mode 100644 index 0000000..a1e110e Binary files /dev/null and b/static/fonts/lato-v22-latin-ext_latin-700italic.woff differ diff --git a/static/fonts/lato-v22-latin-ext_latin-700italic.woff2 b/static/fonts/lato-v22-latin-ext_latin-700italic.woff2 new file mode 100644 index 0000000..e480a20 Binary files /dev/null and b/static/fonts/lato-v22-latin-ext_latin-700italic.woff2 differ diff --git a/static/fonts/lato-v22-latin-ext_latin-900.woff b/static/fonts/lato-v22-latin-ext_latin-900.woff new file mode 100644 index 0000000..7d0ae47 Binary files /dev/null and b/static/fonts/lato-v22-latin-ext_latin-900.woff differ diff --git a/static/fonts/lato-v22-latin-ext_latin-900.woff2 b/static/fonts/lato-v22-latin-ext_latin-900.woff2 new file mode 100644 index 0000000..c756b8b Binary files /dev/null and b/static/fonts/lato-v22-latin-ext_latin-900.woff2 differ diff --git a/static/fonts/lato-v22-latin-ext_latin-900italic.woff b/static/fonts/lato-v22-latin-ext_latin-900italic.woff new file mode 100644 index 0000000..7f50044 Binary files /dev/null and b/static/fonts/lato-v22-latin-ext_latin-900italic.woff differ diff --git a/static/fonts/lato-v22-latin-ext_latin-900italic.woff2 b/static/fonts/lato-v22-latin-ext_latin-900italic.woff2 new file mode 100644 index 0000000..77e849b Binary files /dev/null and b/static/fonts/lato-v22-latin-ext_latin-900italic.woff2 differ diff --git a/static/fonts/lato-v22-latin-ext_latin-italic.woff b/static/fonts/lato-v22-latin-ext_latin-italic.woff new file mode 100644 index 0000000..06fe84c Binary files /dev/null and b/static/fonts/lato-v22-latin-ext_latin-italic.woff differ diff --git a/static/fonts/lato-v22-latin-ext_latin-italic.woff2 b/static/fonts/lato-v22-latin-ext_latin-italic.woff2 new file mode 100644 index 0000000..d28c025 Binary files /dev/null and b/static/fonts/lato-v22-latin-ext_latin-italic.woff2 differ diff --git a/static/fonts/lato-v22-latin-ext_latin-regular.woff b/static/fonts/lato-v22-latin-ext_latin-regular.woff new file mode 100644 index 0000000..40ed56a Binary files /dev/null and b/static/fonts/lato-v22-latin-ext_latin-regular.woff differ diff --git a/static/fonts/lato-v22-latin-ext_latin-regular.woff2 b/static/fonts/lato-v22-latin-ext_latin-regular.woff2 new file mode 100644 index 0000000..1d46153 Binary files /dev/null and b/static/fonts/lato-v22-latin-ext_latin-regular.woff2 differ diff --git a/static/fonts/permanent-marker-v10-latin-regular.woff b/static/fonts/permanent-marker-v10-latin-regular.woff new file mode 100644 index 0000000..458b4bb Binary files /dev/null and b/static/fonts/permanent-marker-v10-latin-regular.woff differ diff --git a/static/fonts/permanent-marker-v10-latin-regular.woff2 b/static/fonts/permanent-marker-v10-latin-regular.woff2 new file mode 100644 index 0000000..203ccae Binary files /dev/null and b/static/fonts/permanent-marker-v10-latin-regular.woff2 differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-200.woff b/static/fonts/source-code-pro-v20-latin-ext_latin-200.woff new file mode 100644 index 0000000..2370c12 Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-200.woff differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-200.woff2 b/static/fonts/source-code-pro-v20-latin-ext_latin-200.woff2 new file mode 100644 index 0000000..0ef5e9c Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-200.woff2 differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-200italic.woff b/static/fonts/source-code-pro-v20-latin-ext_latin-200italic.woff new file mode 100644 index 0000000..ffcb603 Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-200italic.woff differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-200italic.woff2 b/static/fonts/source-code-pro-v20-latin-ext_latin-200italic.woff2 new file mode 100644 index 0000000..4a823aa Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-200italic.woff2 differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-300.woff b/static/fonts/source-code-pro-v20-latin-ext_latin-300.woff new file mode 100644 index 0000000..992b4f4 Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-300.woff differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-300.woff2 b/static/fonts/source-code-pro-v20-latin-ext_latin-300.woff2 new file mode 100644 index 0000000..e2dac68 Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-300.woff2 differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-300italic.woff b/static/fonts/source-code-pro-v20-latin-ext_latin-300italic.woff new file mode 100644 index 0000000..1383393 Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-300italic.woff differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-300italic.woff2 b/static/fonts/source-code-pro-v20-latin-ext_latin-300italic.woff2 new file mode 100644 index 0000000..43488ea Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-300italic.woff2 differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-500.woff b/static/fonts/source-code-pro-v20-latin-ext_latin-500.woff new file mode 100644 index 0000000..0a75369 Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-500.woff differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-500.woff2 b/static/fonts/source-code-pro-v20-latin-ext_latin-500.woff2 new file mode 100644 index 0000000..eed5366 Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-500.woff2 differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-500italic.woff b/static/fonts/source-code-pro-v20-latin-ext_latin-500italic.woff new file mode 100644 index 0000000..c933af4 Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-500italic.woff differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-500italic.woff2 b/static/fonts/source-code-pro-v20-latin-ext_latin-500italic.woff2 new file mode 100644 index 0000000..8081bde Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-500italic.woff2 differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-600.woff b/static/fonts/source-code-pro-v20-latin-ext_latin-600.woff new file mode 100644 index 0000000..7b879b3 Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-600.woff differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-600.woff2 b/static/fonts/source-code-pro-v20-latin-ext_latin-600.woff2 new file mode 100644 index 0000000..80b75ec Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-600.woff2 differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-600italic.woff b/static/fonts/source-code-pro-v20-latin-ext_latin-600italic.woff new file mode 100644 index 0000000..8272171 Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-600italic.woff differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-600italic.woff2 b/static/fonts/source-code-pro-v20-latin-ext_latin-600italic.woff2 new file mode 100644 index 0000000..6239c79 Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-600italic.woff2 differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-700.woff b/static/fonts/source-code-pro-v20-latin-ext_latin-700.woff new file mode 100644 index 0000000..8a83d4f Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-700.woff differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-700.woff2 b/static/fonts/source-code-pro-v20-latin-ext_latin-700.woff2 new file mode 100644 index 0000000..2b85b51 Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-700.woff2 differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-700italic.woff b/static/fonts/source-code-pro-v20-latin-ext_latin-700italic.woff new file mode 100644 index 0000000..0f5fd53 Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-700italic.woff differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-700italic.woff2 b/static/fonts/source-code-pro-v20-latin-ext_latin-700italic.woff2 new file mode 100644 index 0000000..cea9627 Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-700italic.woff2 differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-800.woff b/static/fonts/source-code-pro-v20-latin-ext_latin-800.woff new file mode 100644 index 0000000..0f0eb21 Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-800.woff differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-800.woff2 b/static/fonts/source-code-pro-v20-latin-ext_latin-800.woff2 new file mode 100644 index 0000000..21c876d Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-800.woff2 differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-800italic.woff b/static/fonts/source-code-pro-v20-latin-ext_latin-800italic.woff new file mode 100644 index 0000000..1ae744b Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-800italic.woff differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-800italic.woff2 b/static/fonts/source-code-pro-v20-latin-ext_latin-800italic.woff2 new file mode 100644 index 0000000..b0e7929 Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-800italic.woff2 differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-900.woff b/static/fonts/source-code-pro-v20-latin-ext_latin-900.woff new file mode 100644 index 0000000..d100787 Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-900.woff differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-900.woff2 b/static/fonts/source-code-pro-v20-latin-ext_latin-900.woff2 new file mode 100644 index 0000000..a9af059 Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-900.woff2 differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-900italic.woff b/static/fonts/source-code-pro-v20-latin-ext_latin-900italic.woff new file mode 100644 index 0000000..79b0769 Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-900italic.woff differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-900italic.woff2 b/static/fonts/source-code-pro-v20-latin-ext_latin-900italic.woff2 new file mode 100644 index 0000000..32f39ca Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-900italic.woff2 differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-italic.woff b/static/fonts/source-code-pro-v20-latin-ext_latin-italic.woff new file mode 100644 index 0000000..76faf3d Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-italic.woff differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-italic.woff2 b/static/fonts/source-code-pro-v20-latin-ext_latin-italic.woff2 new file mode 100644 index 0000000..7938dbb Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-italic.woff2 differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-regular.woff b/static/fonts/source-code-pro-v20-latin-ext_latin-regular.woff new file mode 100644 index 0000000..c134396 Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-regular.woff differ diff --git a/static/fonts/source-code-pro-v20-latin-ext_latin-regular.woff2 b/static/fonts/source-code-pro-v20-latin-ext_latin-regular.woff2 new file mode 100644 index 0000000..0644f21 Binary files /dev/null and b/static/fonts/source-code-pro-v20-latin-ext_latin-regular.woff2 differ diff --git a/static/fork-awesome/css/fork-awesome.css b/static/fork-awesome/css/fork-awesome.css new file mode 100644 index 0000000..b6b3b5d --- /dev/null +++ b/static/fork-awesome/css/fork-awesome.css @@ -0,0 +1,2573 @@ +/*! +Fork Awesome 1.1.7 +License - https://forkaweso.me/Fork-Awesome/license + +Copyright 2018 Dave Gandy & Fork Awesome + +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. + */ +/* FONT PATH + * -------------------------- */ +@font-face { + font-family: 'ForkAwesome'; + src: url('../fonts/forkawesome-webfont.eot?v=1.1.7'); + src: url('../fonts/forkawesome-webfont.eot?#iefix&v=1.1.7') format('embedded-opentype'), url('../fonts/forkawesome-webfont.woff2?v=1.1.7') format('woff2'), url('../fonts/forkawesome-webfont.woff?v=1.1.7') format('woff'), url('../fonts/forkawesome-webfont.ttf?v=1.1.7') format('truetype'), url('../fonts/forkawesome-webfont.svg?v=1.1.7#forkawesomeregular') format('svg'); + font-weight: normal; + font-style: normal; +} +.fa { + display: inline-block; + font: normal normal normal 14px/1 ForkAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +/* makes the font 33% larger relative to the icon container */ +.fa-lg { + font-size: 1.33333333em; + line-height: 0.75em; + vertical-align: -15%; +} +.fa-2x { + font-size: 2em; +} +.fa-3x { + font-size: 3em; +} +.fa-4x { + font-size: 4em; +} +.fa-5x { + font-size: 5em; +} +.fa-fw { + width: 1.28571429em; + text-align: center; +} +.fa-ul { + padding-left: 0; + margin-left: 2.14285714em; + list-style-type: none; +} +.fa-ul > li { + position: relative; +} +.fa-li { + position: absolute; + left: -2.14285714em; + width: 2.14285714em; + top: 0.14285714em; + text-align: center; +} +.fa-li.fa-lg { + left: -1.85714286em; +} +.fa-border { + padding: .2em .25em .15em; + border: solid 0.08em #eee; + border-radius: .1em; +} +.fa-pull-left { + float: left; +} +.fa-pull-right { + float: right; +} +.fa.fa-pull-left { + margin-right: .3em; +} +.fa.fa-pull-right { + margin-left: .3em; +} +/* Deprecated as of 4.4.0 */ +.pull-right { + float: right; +} +.pull-left { + float: left; +} +.fa.pull-left { + margin-right: .3em; +} +.fa.pull-right { + margin-left: .3em; +} +.fa-spin { + -webkit-animation: fa-spin 2s infinite linear; + animation: fa-spin 2s infinite linear; +} +.fa-pulse { + -webkit-animation: fa-spin 1s infinite steps(8); + animation: fa-spin 1s infinite steps(8); +} +@-webkit-keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +@keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +.fa-rotate-90 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"; + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg); +} +.fa-rotate-180 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)"; + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} +.fa-rotate-270 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)"; + -webkit-transform: rotate(270deg); + -ms-transform: rotate(270deg); + transform: rotate(270deg); +} +.fa-flip-horizontal { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)"; + -webkit-transform: scale(-1, 1); + -ms-transform: scale(-1, 1); + transform: scale(-1, 1); +} +.fa-flip-vertical { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; + -webkit-transform: scale(1, -1); + -ms-transform: scale(1, -1); + transform: scale(1, -1); +} +:root .fa-rotate-90, +:root .fa-rotate-180, +:root .fa-rotate-270, +:root .fa-flip-horizontal, +:root .fa-flip-vertical { + filter: none; +} +.fa-stack { + position: relative; + display: inline-block; + width: 2em; + height: 2em; + line-height: 2em; + vertical-align: middle; +} +.fa-stack-1x, +.fa-stack-2x { + position: absolute; + left: 0; + width: 100%; + text-align: center; +} +.fa-stack-1x { + line-height: inherit; +} +.fa-stack-2x { + font-size: 2em; +} +.fa-inverse { + color: #fff; +} +/* Fork Awesome uses the Unicode Private Use Area (PUA) to ensure screen + readers do not read off random characters that represent icons */ +.fa-glass:before { + content: "\f000"; +} +.fa-music:before { + content: "\f001"; +} +.fa-search:before { + content: "\f002"; +} +.fa-envelope-o:before { + content: "\f003"; +} +.fa-heart:before { + content: "\f004"; +} +.fa-star:before { + content: "\f005"; +} +.fa-star-o:before { + content: "\f006"; +} +.fa-user:before { + content: "\f007"; +} +.fa-film:before { + content: "\f008"; +} +.fa-th-large:before { + content: "\f009"; +} +.fa-th:before { + content: "\f00a"; +} +.fa-th-list:before { + content: "\f00b"; +} +.fa-check:before { + content: "\f00c"; +} +.fa-remove:before, +.fa-close:before, +.fa-times:before { + content: "\f00d"; +} +.fa-search-plus:before { + content: "\f00e"; +} +.fa-search-minus:before { + content: "\f010"; +} +.fa-power-off:before { + content: "\f011"; +} +.fa-signal:before { + content: "\f012"; +} +.fa-gear:before, +.fa-cog:before { + content: "\f013"; +} +.fa-trash-o:before { + content: "\f014"; +} +.fa-home:before { + content: "\f015"; +} +.fa-file-o:before { + content: "\f016"; +} +.fa-clock-o:before { + content: "\f017"; +} +.fa-road:before { + content: "\f018"; +} +.fa-download:before { + content: "\f019"; +} +.fa-arrow-circle-o-down:before { + content: "\f01a"; +} +.fa-arrow-circle-o-up:before { + content: "\f01b"; +} +.fa-inbox:before { + content: "\f01c"; +} +.fa-play-circle-o:before { + content: "\f01d"; +} +.fa-rotate-right:before, +.fa-repeat:before { + content: "\f01e"; +} +.fa-sync:before, +.fa-refresh:before { + content: "\f021"; +} +.fa-list-alt:before { + content: "\f022"; +} +.fa-lock:before { + content: "\f023"; +} +.fa-flag:before { + content: "\f024"; +} +.fa-headphones:before { + content: "\f025"; +} +.fa-volume-off:before { + content: "\f026"; +} +.fa-volume-down:before { + content: "\f027"; +} +.fa-volume-up:before { + content: "\f028"; +} +.fa-qrcode:before { + content: "\f029"; +} +.fa-barcode:before { + content: "\f02a"; +} +.fa-tag:before { + content: "\f02b"; +} +.fa-tags:before { + content: "\f02c"; +} +.fa-book:before { + content: "\f02d"; +} +.fa-bookmark:before { + content: "\f02e"; +} +.fa-print:before { + content: "\f02f"; +} +.fa-camera:before { + content: "\f030"; +} +.fa-font:before { + content: "\f031"; +} +.fa-bold:before { + content: "\f032"; +} +.fa-italic:before { + content: "\f033"; +} +.fa-text-height:before { + content: "\f034"; +} +.fa-text-width:before { + content: "\f035"; +} +.fa-align-left:before { + content: "\f036"; +} +.fa-align-center:before { + content: "\f037"; +} +.fa-align-right:before { + content: "\f038"; +} +.fa-align-justify:before { + content: "\f039"; +} +.fa-list:before { + content: "\f03a"; +} +.fa-dedent:before, +.fa-outdent:before { + content: "\f03b"; +} +.fa-indent:before { + content: "\f03c"; +} +.fa-video:before, +.fa-video-camera:before { + content: "\f03d"; +} +.fa-photo:before, +.fa-image:before, +.fa-picture-o:before { + content: "\f03e"; +} +.fa-pencil:before { + content: "\f040"; +} +.fa-map-marker:before { + content: "\f041"; +} +.fa-adjust:before { + content: "\f042"; +} +.fa-tint:before { + content: "\f043"; +} +.fa-edit:before, +.fa-pencil-square-o:before { + content: "\f044"; +} +.fa-share-square-o:before { + content: "\f045"; +} +.fa-check-square-o:before { + content: "\f046"; +} +.fa-arrows:before { + content: "\f047"; +} +.fa-step-backward:before { + content: "\f048"; +} +.fa-fast-backward:before { + content: "\f049"; +} +.fa-backward:before { + content: "\f04a"; +} +.fa-play:before { + content: "\f04b"; +} +.fa-pause:before { + content: "\f04c"; +} +.fa-stop:before { + content: "\f04d"; +} +.fa-forward:before { + content: "\f04e"; +} +.fa-fast-forward:before { + content: "\f050"; +} +.fa-step-forward:before { + content: "\f051"; +} +.fa-eject:before { + content: "\f052"; +} +.fa-chevron-left:before { + content: "\f053"; +} +.fa-chevron-right:before { + content: "\f054"; +} +.fa-plus-circle:before { + content: "\f055"; +} +.fa-minus-circle:before { + content: "\f056"; +} +.fa-times-circle:before { + content: "\f057"; +} +.fa-check-circle:before { + content: "\f058"; +} +.fa-question-circle:before { + content: "\f059"; +} +.fa-info-circle:before { + content: "\f05a"; +} +.fa-crosshairs:before { + content: "\f05b"; +} +.fa-times-circle-o:before { + content: "\f05c"; +} +.fa-check-circle-o:before { + content: "\f05d"; +} +.fa-ban:before { + content: "\f05e"; +} +.fa-arrow-left:before { + content: "\f060"; +} +.fa-arrow-right:before { + content: "\f061"; +} +.fa-arrow-up:before { + content: "\f062"; +} +.fa-arrow-down:before { + content: "\f063"; +} +.fa-mail-forward:before, +.fa-share:before { + content: "\f064"; +} +.fa-expand:before { + content: "\f065"; +} +.fa-compress:before { + content: "\f066"; +} +.fa-plus:before { + content: "\f067"; +} +.fa-minus:before { + content: "\f068"; +} +.fa-asterisk:before { + content: "\f069"; +} +.fa-exclamation-circle:before { + content: "\f06a"; +} +.fa-gift:before { + content: "\f06b"; +} +.fa-leaf:before { + content: "\f06c"; +} +.fa-fire:before { + content: "\f06d"; +} +.fa-eye:before { + content: "\f06e"; +} +.fa-eye-slash:before { + content: "\f070"; +} +.fa-warning:before, +.fa-exclamation-triangle:before { + content: "\f071"; +} +.fa-plane:before { + content: "\f072"; +} +.fa-calendar:before { + content: "\f073"; +} +.fa-random:before { + content: "\f074"; +} +.fa-comment:before { + content: "\f075"; +} +.fa-magnet:before { + content: "\f076"; +} +.fa-chevron-up:before { + content: "\f077"; +} +.fa-chevron-down:before { + content: "\f078"; +} +.fa-retweet:before { + content: "\f079"; +} +.fa-shopping-cart:before { + content: "\f07a"; +} +.fa-folder:before { + content: "\f07b"; +} +.fa-folder-open:before { + content: "\f07c"; +} +.fa-arrows-v:before { + content: "\f07d"; +} +.fa-arrows-h:before { + content: "\f07e"; +} +.fa-bar-chart-o:before, +.fa-bar-chart:before { + content: "\f080"; +} +.fa-twitter-square:before { + content: "\f081"; +} +.fa-facebook-square:before { + content: "\f082"; +} +.fa-camera-retro:before { + content: "\f083"; +} +.fa-key:before { + content: "\f084"; +} +.fa-gears:before, +.fa-cogs:before { + content: "\f085"; +} +.fa-comments:before { + content: "\f086"; +} +.fa-thumbs-o-up:before { + content: "\f087"; +} +.fa-thumbs-o-down:before { + content: "\f088"; +} +.fa-star-half:before { + content: "\f089"; +} +.fa-heart-o:before { + content: "\f08a"; +} +.fa-sign-out:before { + content: "\f08b"; +} +.fa-linkedin-square:before { + content: "\f08c"; +} +.fa-thumb-tack:before { + content: "\f08d"; +} +.fa-external-link:before { + content: "\f08e"; +} +.fa-sign-in:before { + content: "\f090"; +} +.fa-trophy:before { + content: "\f091"; +} +.fa-github-square:before { + content: "\f092"; +} +.fa-upload:before { + content: "\f093"; +} +.fa-lemon-o:before { + content: "\f094"; +} +.fa-phone:before { + content: "\f095"; +} +.fa-square-o:before { + content: "\f096"; +} +.fa-bookmark-o:before { + content: "\f097"; +} +.fa-phone-square:before { + content: "\f098"; +} +.fa-twitter:before { + content: "\f099"; +} +.fa-facebook-f:before, +.fa-facebook:before { + content: "\f09a"; +} +.fa-github:before { + content: "\f09b"; +} +.fa-unlock:before { + content: "\f09c"; +} +.fa-credit-card:before { + content: "\f09d"; +} +.fa-feed:before, +.fa-rss:before { + content: "\f09e"; +} +.fa-hdd-o:before { + content: "\f0a0"; +} +.fa-bullhorn:before { + content: "\f0a1"; +} +.fa-bell-o:before { + content: "\f0f3"; +} +.fa-certificate:before { + content: "\f0a3"; +} +.fa-hand-o-right:before { + content: "\f0a4"; +} +.fa-hand-o-left:before { + content: "\f0a5"; +} +.fa-hand-o-up:before { + content: "\f0a6"; +} +.fa-hand-o-down:before { + content: "\f0a7"; +} +.fa-arrow-circle-left:before { + content: "\f0a8"; +} +.fa-arrow-circle-right:before { + content: "\f0a9"; +} +.fa-arrow-circle-up:before { + content: "\f0aa"; +} +.fa-arrow-circle-down:before { + content: "\f0ab"; +} +.fa-globe:before { + content: "\f0ac"; +} +.fa-globe-e:before { + content: "\f304"; +} +.fa-globe-w:before { + content: "\f305"; +} +.fa-wrench:before { + content: "\f0ad"; +} +.fa-tasks:before { + content: "\f0ae"; +} +.fa-filter:before { + content: "\f0b0"; +} +.fa-briefcase:before { + content: "\f0b1"; +} +.fa-arrows-alt:before { + content: "\f0b2"; +} +.fa-community:before, +.fa-group:before, +.fa-users:before { + content: "\f0c0"; +} +.fa-chain:before, +.fa-link:before { + content: "\f0c1"; +} +.fa-cloud:before { + content: "\f0c2"; +} +.fa-flask:before { + content: "\f0c3"; +} +.fa-cut:before, +.fa-scissors:before { + content: "\f0c4"; +} +.fa-copy:before, +.fa-files-o:before { + content: "\f0c5"; +} +.fa-paperclip:before { + content: "\f0c6"; +} +.fa-save:before, +.fa-floppy-o:before { + content: "\f0c7"; +} +.fa-square:before { + content: "\f0c8"; +} +.fa-navicon:before, +.fa-reorder:before, +.fa-bars:before { + content: "\f0c9"; +} +.fa-list-ul:before { + content: "\f0ca"; +} +.fa-list-ol:before { + content: "\f0cb"; +} +.fa-strikethrough:before { + content: "\f0cc"; +} +.fa-underline:before { + content: "\f0cd"; +} +.fa-table:before { + content: "\f0ce"; +} +.fa-magic:before { + content: "\f0d0"; +} +.fa-truck:before { + content: "\f0d1"; +} +.fa-pinterest:before { + content: "\f0d2"; +} +.fa-pinterest-square:before { + content: "\f0d3"; +} +.fa-google-plus-square:before { + content: "\f0d4"; +} +.fa-google-plus-g:before, +.fa-google-plus:before { + content: "\f0d5"; +} +.fa-money:before { + content: "\f0d6"; +} +.fa-caret-down:before { + content: "\f0d7"; +} +.fa-caret-up:before { + content: "\f0d8"; +} +.fa-caret-left:before { + content: "\f0d9"; +} +.fa-caret-right:before { + content: "\f0da"; +} +.fa-columns:before { + content: "\f0db"; +} +.fa-unsorted:before, +.fa-sort:before { + content: "\f0dc"; +} +.fa-sort-down:before, +.fa-sort-desc:before { + content: "\f0dd"; +} +.fa-sort-up:before, +.fa-sort-asc:before { + content: "\f0de"; +} +.fa-envelope:before { + content: "\f0e0"; +} +.fa-linkedin:before { + content: "\f0e1"; +} +.fa-rotate-left:before, +.fa-undo:before { + content: "\f0e2"; +} +.fa-legal:before, +.fa-gavel:before { + content: "\f0e3"; +} +.fa-dashboard:before, +.fa-tachometer:before { + content: "\f0e4"; +} +.fa-comment-o:before { + content: "\f0e5"; +} +.fa-comments-o:before { + content: "\f0e6"; +} +.fa-flash:before, +.fa-bolt:before { + content: "\f0e7"; +} +.fa-sitemap:before { + content: "\f0e8"; +} +.fa-umbrella:before { + content: "\f0e9"; +} +.fa-paste:before, +.fa-clipboard:before { + content: "\f0ea"; +} +.fa-lightbulb-o:before { + content: "\f0eb"; +} +.fa-exchange:before { + content: "\f0ec"; +} +.fa-cloud-download:before { + content: "\f0ed"; +} +.fa-cloud-upload:before { + content: "\f0ee"; +} +.fa-user-md:before { + content: "\f0f0"; +} +.fa-stethoscope:before { + content: "\f0f1"; +} +.fa-suitcase:before { + content: "\f0f2"; +} +.fa-bell:before { + content: "\f0a2"; +} +.fa-coffee:before { + content: "\f0f4"; +} +.fa-utensils:before, +.fa-cutlery:before { + content: "\f0f5"; +} +.fa-file-text-o:before { + content: "\f0f6"; +} +.fa-building-o:before { + content: "\f0f7"; +} +.fa-hospital-o:before { + content: "\f0f8"; +} +.fa-ambulance:before { + content: "\f0f9"; +} +.fa-medkit:before { + content: "\f0fa"; +} +.fa-fighter-jet:before { + content: "\f0fb"; +} +.fa-beer:before { + content: "\f0fc"; +} +.fa-h-square:before { + content: "\f0fd"; +} +.fa-plus-square:before { + content: "\f0fe"; +} +.fa-angle-double-left:before { + content: "\f100"; +} +.fa-angle-double-right:before { + content: "\f101"; +} +.fa-angle-double-up:before { + content: "\f102"; +} +.fa-angle-double-down:before { + content: "\f103"; +} +.fa-angle-left:before { + content: "\f104"; +} +.fa-angle-right:before { + content: "\f105"; +} +.fa-angle-up:before { + content: "\f106"; +} +.fa-angle-down:before { + content: "\f107"; +} +.fa-desktop:before { + content: "\f108"; +} +.fa-laptop:before { + content: "\f109"; +} +.fa-tablet:before { + content: "\f10a"; +} +.fa-mobile-phone:before, +.fa-mobile:before { + content: "\f10b"; +} +.fa-circle-o:before { + content: "\f10c"; +} +.fa-quote-left:before { + content: "\f10d"; +} +.fa-quote-right:before { + content: "\f10e"; +} +.fa-spinner:before { + content: "\f110"; +} +.fa-circle:before { + content: "\f111"; +} +.fa-mail-reply:before, +.fa-reply:before { + content: "\f112"; +} +.fa-github-alt:before { + content: "\f113"; +} +.fa-folder-o:before { + content: "\f114"; +} +.fa-folder-open-o:before { + content: "\f115"; +} +.fa-smile-o:before { + content: "\f118"; +} +.fa-frown-o:before { + content: "\f119"; +} +.fa-meh-o:before { + content: "\f11a"; +} +.fa-gamepad:before { + content: "\f11b"; +} +.fa-keyboard-o:before { + content: "\f11c"; +} +.fa-flag-o:before { + content: "\f11d"; +} +.fa-flag-checkered:before { + content: "\f11e"; +} +.fa-terminal:before { + content: "\f120"; +} +.fa-code:before { + content: "\f121"; +} +.fa-mail-reply-all:before, +.fa-reply-all:before { + content: "\f122"; +} +.fa-star-half-empty:before, +.fa-star-half-full:before, +.fa-star-half-o:before { + content: "\f123"; +} +.fa-location-arrow:before { + content: "\f124"; +} +.fa-crop:before { + content: "\f125"; +} +.fa-code-fork:before { + content: "\f126"; +} +.fa-unlink:before, +.fa-chain-broken:before { + content: "\f127"; +} +.fa-question:before { + content: "\f128"; +} +.fa-info:before { + content: "\f129"; +} +.fa-exclamation:before { + content: "\f12a"; +} +.fa-superscript:before { + content: "\f12b"; +} +.fa-subscript:before { + content: "\f12c"; +} +.fa-eraser:before { + content: "\f12d"; +} +.fa-puzzle-piece:before { + content: "\f12e"; +} +.fa-microphone:before { + content: "\f130"; +} +.fa-microphone-slash:before { + content: "\f131"; +} +.fa-shield:before { + content: "\f132"; +} +.fa-calendar-o:before { + content: "\f133"; +} +.fa-fire-extinguisher:before { + content: "\f134"; +} +.fa-rocket:before { + content: "\f135"; +} +.fa-maxcdn:before { + content: "\f136"; +} +.fa-chevron-circle-left:before { + content: "\f137"; +} +.fa-chevron-circle-right:before { + content: "\f138"; +} +.fa-chevron-circle-up:before { + content: "\f139"; +} +.fa-chevron-circle-down:before { + content: "\f13a"; +} +.fa-html5:before { + content: "\f13b"; +} +.fa-css3:before { + content: "\f13c"; +} +.fa-anchor:before { + content: "\f13d"; +} +.fa-unlock-alt:before { + content: "\f13e"; +} +.fa-bullseye:before { + content: "\f140"; +} +.fa-ellipsis-h:before { + content: "\f141"; +} +.fa-ellipsis-v:before { + content: "\f142"; +} +.fa-rss-square:before { + content: "\f143"; +} +.fa-play-circle:before { + content: "\f144"; +} +.fa-ticket:before { + content: "\f145"; +} +.fa-minus-square:before { + content: "\f146"; +} +.fa-minus-square-o:before { + content: "\f147"; +} +.fa-level-up:before { + content: "\f148"; +} +.fa-level-down:before { + content: "\f149"; +} +.fa-check-square:before { + content: "\f14a"; +} +.fa-pencil-square:before { + content: "\f14b"; +} +.fa-external-link-square:before { + content: "\f14c"; +} +.fa-share-square:before { + content: "\f14d"; +} +.fa-compass:before { + content: "\f14e"; +} +.fa-toggle-down:before, +.fa-caret-square-o-down:before { + content: "\f150"; +} +.fa-toggle-up:before, +.fa-caret-square-o-up:before { + content: "\f151"; +} +.fa-toggle-right:before, +.fa-caret-square-o-right:before { + content: "\f152"; +} +.fa-euro:before, +.fa-eur:before { + content: "\f153"; +} +.fa-pound:before, +.fa-gbp:before { + content: "\f154"; +} +.fa-dollar:before, +.fa-usd:before { + content: "\f155"; +} +.fa-rupee:before, +.fa-inr:before { + content: "\f156"; +} +.fa-cny:before, +.fa-rmb:before, +.fa-yen:before, +.fa-jpy:before { + content: "\f157"; +} +.fa-ruble:before, +.fa-rouble:before, +.fa-rub:before { + content: "\f158"; +} +.fa-won:before, +.fa-krw:before { + content: "\f159"; +} +.fa-bitcoin:before, +.fa-btc:before { + content: "\f15a"; +} +.fa-file:before { + content: "\f15b"; +} +.fa-file-text:before { + content: "\f15c"; +} +.fa-sort-alpha-down:before, +.fa-sort-alpha-asc:before { + content: "\f15d"; +} +.fa-sort-alpha-up:before, +.fa-sort-alpha-desc:before { + content: "\f15e"; +} +.fa-sort-amount-down:before, +.fa-sort-amount-asc:before { + content: "\f160"; +} +.fa-sort-amount-up:before, +.fa-sort-amount-desc:before { + content: "\f161"; +} +.fa-sort-numeric-down:before, +.fa-sort-numeric-asc:before { + content: "\f162"; +} +.fa-sort-numeric-up:before, +.fa-sort-numeric-desc:before { + content: "\f163"; +} +.fa-thumbs-up:before { + content: "\f164"; +} +.fa-thumbs-down:before { + content: "\f165"; +} +.fa-youtube-square:before { + content: "\f166"; +} +.fa-youtube:before { + content: "\f167"; +} +.fa-xing:before { + content: "\f168"; +} +.fa-xing-square:before { + content: "\f169"; +} +.fa-youtube-play:before { + content: "\f16a"; +} +.fa-dropbox:before { + content: "\f16b"; +} +.fa-stack-overflow:before { + content: "\f16c"; +} +.fa-instagram:before { + content: "\f16d"; +} +.fa-flickr:before { + content: "\f16e"; +} +.fa-adn:before { + content: "\f170"; +} +.fa-bitbucket:before { + content: "\f171"; +} +.fa-bitbucket-square:before { + content: "\f172"; +} +.fa-tumblr:before { + content: "\f173"; +} +.fa-tumblr-square:before { + content: "\f174"; +} +.fa-long-arrow-down:before { + content: "\f175"; +} +.fa-long-arrow-up:before { + content: "\f176"; +} +.fa-long-arrow-left:before { + content: "\f177"; +} +.fa-long-arrow-right:before { + content: "\f178"; +} +.fa-apple:before { + content: "\f179"; +} +.fa-windows:before { + content: "\f17a"; +} +.fa-android:before { + content: "\f17b"; +} +.fa-linux:before { + content: "\f17c"; +} +.fa-dribbble:before { + content: "\f17d"; +} +.fa-skype:before { + content: "\f17e"; +} +.fa-foursquare:before { + content: "\f180"; +} +.fa-trello:before { + content: "\f181"; +} +.fa-female:before { + content: "\f182"; +} +.fa-male:before { + content: "\f183"; +} +.fa-gittip:before, +.fa-gratipay:before { + content: "\f184"; +} +.fa-sun-o:before { + content: "\f185"; +} +.fa-moon-o:before { + content: "\f186"; +} +.fa-archive:before { + content: "\f187"; +} +.fa-bug:before { + content: "\f188"; +} +.fa-vk:before { + content: "\f189"; +} +.fa-weibo:before { + content: "\f18a"; +} +.fa-renren:before { + content: "\f18b"; +} +.fa-pagelines:before { + content: "\f18c"; +} +.fa-stack-exchange:before { + content: "\f18d"; +} +.fa-arrow-circle-o-right:before { + content: "\f18e"; +} +.fa-arrow-circle-o-left:before { + content: "\f190"; +} +.fa-toggle-left:before, +.fa-caret-square-o-left:before { + content: "\f191"; +} +.fa-dot-circle-o:before { + content: "\f192"; +} +.fa-wheelchair:before { + content: "\f193"; +} +.fa-vimeo-square:before { + content: "\f194"; +} +.fa-turkish-lira:before, +.fa-try:before { + content: "\f195"; +} +.fa-plus-square-o:before { + content: "\f196"; +} +.fa-space-shuttle:before { + content: "\f197"; +} +.fa-slack:before { + content: "\f198"; +} +.fa-envelope-square:before { + content: "\f199"; +} +.fa-wordpress:before { + content: "\f19a"; +} +.fa-openid:before { + content: "\f19b"; +} +.fa-institution:before, +.fa-bank:before, +.fa-university:before { + content: "\f19c"; +} +.fa-mortar-board:before, +.fa-graduation-cap:before { + content: "\f19d"; +} +.fa-yahoo:before { + content: "\f19e"; +} +.fa-google:before { + content: "\f1a0"; +} +.fa-reddit:before { + content: "\f1a1"; +} +.fa-reddit-square:before { + content: "\f1a2"; +} +.fa-stumbleupon-circle:before { + content: "\f1a3"; +} +.fa-stumbleupon:before { + content: "\f1a4"; +} +.fa-delicious:before { + content: "\f1a5"; +} +.fa-digg:before { + content: "\f1a6"; +} +.fa-drupal:before { + content: "\f1a9"; +} +.fa-joomla:before { + content: "\f1aa"; +} +.fa-language:before { + content: "\f1ab"; +} +.fa-fax:before { + content: "\f1ac"; +} +.fa-building:before { + content: "\f1ad"; +} +.fa-child:before { + content: "\f1ae"; +} +.fa-paw:before { + content: "\f1b0"; +} +.fa-utensil-spoon:before, +.fa-spoon:before { + content: "\f1b1"; +} +.fa-cube:before { + content: "\f1b2"; +} +.fa-cubes:before { + content: "\f1b3"; +} +.fa-behance:before { + content: "\f1b4"; +} +.fa-behance-square:before { + content: "\f1b5"; +} +.fa-steam:before { + content: "\f1b6"; +} +.fa-steam-square:before { + content: "\f1b7"; +} +.fa-recycle:before { + content: "\f1b8"; +} +.fa-automobile:before, +.fa-car:before { + content: "\f1b9"; +} +.fa-cab:before, +.fa-taxi:before { + content: "\f1ba"; +} +.fa-tree:before { + content: "\f1bb"; +} +.fa-spotify:before { + content: "\f1bc"; +} +.fa-deviantart:before { + content: "\f1bd"; +} +.fa-soundcloud:before { + content: "\f1be"; +} +.fa-database:before { + content: "\f1c0"; +} +.fa-file-pdf-o:before { + content: "\f1c1"; +} +.fa-file-word-o:before { + content: "\f1c2"; +} +.fa-file-excel-o:before { + content: "\f1c3"; +} +.fa-file-powerpoint-o:before { + content: "\f1c4"; +} +.fa-file-photo-o:before, +.fa-file-picture-o:before, +.fa-file-image-o:before { + content: "\f1c5"; +} +.fa-file-zip-o:before, +.fa-file-archive-o:before { + content: "\f1c6"; +} +.fa-file-sound-o:before, +.fa-file-audio-o:before { + content: "\f1c7"; +} +.fa-file-movie-o:before, +.fa-file-video-o:before { + content: "\f1c8"; +} +.fa-file-code-o:before { + content: "\f1c9"; +} +.fa-vine:before { + content: "\f1ca"; +} +.fa-codepen:before { + content: "\f1cb"; +} +.fa-jsfiddle:before { + content: "\f1cc"; +} +.fa-life-bouy:before, +.fa-life-buoy:before, +.fa-life-saver:before, +.fa-support:before, +.fa-life-ring:before { + content: "\f1cd"; +} +.fa-circle-o-notch:before { + content: "\f1ce"; +} +.fa-ra:before, +.fa-resistance:before, +.fa-rebel:before { + content: "\f1d0"; +} +.fa-ge:before, +.fa-empire:before { + content: "\f1d1"; +} +.fa-git-square:before { + content: "\f1d2"; +} +.fa-git:before { + content: "\f1d3"; +} +.fa-y-combinator-square:before, +.fa-yc-square:before, +.fa-hacker-news:before { + content: "\f1d4"; +} +.fa-tencent-weibo:before { + content: "\f1d5"; +} +.fa-qq:before { + content: "\f1d6"; +} +.fa-wechat:before, +.fa-weixin:before { + content: "\f1d7"; +} +.fa-send:before, +.fa-paper-plane:before { + content: "\f1d8"; +} +.fa-send-o:before, +.fa-paper-plane-o:before { + content: "\f1d9"; +} +.fa-history:before { + content: "\f1da"; +} +.fa-circle-thin:before { + content: "\f1db"; +} +.fa-heading:before, +.fa-header:before { + content: "\f1dc"; +} +.fa-paragraph:before { + content: "\f1dd"; +} +.fa-sliders:before { + content: "\f1de"; +} +.fa-share-alt:before { + content: "\f1e0"; +} +.fa-share-alt-square:before { + content: "\f1e1"; +} +.fa-bomb:before { + content: "\f1e2"; +} +.fa-soccer-ball-o:before, +.fa-futbol-o:before { + content: "\f1e3"; +} +.fa-tty:before { + content: "\f1e4"; +} +.fa-binoculars:before { + content: "\f1e5"; +} +.fa-plug:before { + content: "\f1e6"; +} +.fa-slideshare:before { + content: "\f1e7"; +} +.fa-twitch:before { + content: "\f1e8"; +} +.fa-yelp:before { + content: "\f1e9"; +} +.fa-newspaper-o:before { + content: "\f1ea"; +} +.fa-wifi:before { + content: "\f1eb"; +} +.fa-calculator:before { + content: "\f1ec"; +} +.fa-paypal:before { + content: "\f1ed"; +} +.fa-google-wallet:before { + content: "\f1ee"; +} +.fa-cc-visa:before { + content: "\f1f0"; +} +.fa-cc-mastercard:before { + content: "\f1f1"; +} +.fa-cc-discover:before { + content: "\f1f2"; +} +.fa-cc-amex:before { + content: "\f1f3"; +} +.fa-cc-paypal:before { + content: "\f1f4"; +} +.fa-cc-stripe:before { + content: "\f1f5"; +} +.fa-bell-slash:before { + content: "\f1f6"; +} +.fa-bell-slash-o:before { + content: "\f1f7"; +} +.fa-trash:before { + content: "\f1f8"; +} +.fa-copyright:before { + content: "\f1f9"; +} +.fa-at:before { + content: "\f1fa"; +} +.fa-eyedropper:before { + content: "\f1fb"; +} +.fa-paint-brush:before { + content: "\f1fc"; +} +.fa-birthday-cake:before { + content: "\f1fd"; +} +.fa-area-chart:before { + content: "\f1fe"; +} +.fa-pie-chart:before { + content: "\f200"; +} +.fa-line-chart:before { + content: "\f201"; +} +.fa-lastfm:before { + content: "\f202"; +} +.fa-lastfm-square:before { + content: "\f203"; +} +.fa-toggle-off:before { + content: "\f204"; +} +.fa-toggle-on:before { + content: "\f205"; +} +.fa-bicycle:before { + content: "\f206"; +} +.fa-bus:before { + content: "\f207"; +} +.fa-ioxhost:before { + content: "\f208"; +} +.fa-angellist:before { + content: "\f209"; +} +.fa-closed-captioning:before, +.fa-cc:before { + content: "\f20a"; +} +.fa-shekel:before, +.fa-sheqel:before, +.fa-ils:before { + content: "\f20b"; +} +.fa-meanpath:before { + content: "\f20c"; +} +.fa-buysellads:before { + content: "\f20d"; +} +.fa-connectdevelop:before { + content: "\f20e"; +} +.fa-dashcube:before { + content: "\f210"; +} +.fa-forumbee:before { + content: "\f211"; +} +.fa-leanpub:before { + content: "\f212"; +} +.fa-sellsy:before { + content: "\f213"; +} +.fa-shirtsinbulk:before { + content: "\f214"; +} +.fa-simplybuilt:before { + content: "\f215"; +} +.fa-skyatlas:before { + content: "\f216"; +} +.fa-cart-plus:before { + content: "\f217"; +} +.fa-cart-arrow-down:before { + content: "\f218"; +} +.fa-gem:before, +.fa-diamond:before { + content: "\f219"; +} +.fa-ship:before { + content: "\f21a"; +} +.fa-user-secret:before { + content: "\f21b"; +} +.fa-motorcycle:before { + content: "\f21c"; +} +.fa-street-view:before { + content: "\f21d"; +} +.fa-heartbeat:before { + content: "\f21e"; +} +.fa-venus:before { + content: "\f221"; +} +.fa-mars:before { + content: "\f222"; +} +.fa-mercury:before { + content: "\f223"; +} +.fa-intersex:before, +.fa-transgender:before { + content: "\f224"; +} +.fa-transgender-alt:before { + content: "\f225"; +} +.fa-venus-double:before { + content: "\f226"; +} +.fa-mars-double:before { + content: "\f227"; +} +.fa-venus-mars:before { + content: "\f228"; +} +.fa-mars-stroke:before { + content: "\f229"; +} +.fa-mars-stroke-v:before { + content: "\f22a"; +} +.fa-mars-stroke-h:before { + content: "\f22b"; +} +.fa-neuter:before { + content: "\f22c"; +} +.fa-genderless:before { + content: "\f22d"; +} +.fa-facebook-official:before { + content: "\f230"; +} +.fa-pinterest-p:before { + content: "\f231"; +} +.fa-whatsapp:before { + content: "\f232"; +} +.fa-server:before { + content: "\f233"; +} +.fa-user-plus:before { + content: "\f234"; +} +.fa-user-times:before { + content: "\f235"; +} +.fa-hotel:before, +.fa-bed:before { + content: "\f236"; +} +.fa-viacoin:before { + content: "\f237"; +} +.fa-train:before { + content: "\f238"; +} +.fa-subway:before { + content: "\f239"; +} +.fa-medium:before { + content: "\f23a"; +} +.fa-medium-square:before { + content: "\f2f8"; +} +.fa-yc:before, +.fa-y-combinator:before { + content: "\f23b"; +} +.fa-optin-monster:before { + content: "\f23c"; +} +.fa-opencart:before { + content: "\f23d"; +} +.fa-expeditedssl:before { + content: "\f23e"; +} +.fa-battery-4:before, +.fa-battery:before, +.fa-battery-full:before { + content: "\f240"; +} +.fa-battery-3:before, +.fa-battery-three-quarters:before { + content: "\f241"; +} +.fa-battery-2:before, +.fa-battery-half:before { + content: "\f242"; +} +.fa-battery-1:before, +.fa-battery-quarter:before { + content: "\f243"; +} +.fa-battery-0:before, +.fa-battery-empty:before { + content: "\f244"; +} +.fa-mouse-pointer:before { + content: "\f245"; +} +.fa-i-cursor:before { + content: "\f246"; +} +.fa-object-group:before { + content: "\f247"; +} +.fa-object-ungroup:before { + content: "\f248"; +} +.fa-sticky-note:before { + content: "\f249"; +} +.fa-sticky-note-o:before { + content: "\f24a"; +} +.fa-cc-jcb:before { + content: "\f24b"; +} +.fa-cc-diners-club:before { + content: "\f24c"; +} +.fa-clone:before { + content: "\f24d"; +} +.fa-balance-scale:before { + content: "\f24e"; +} +.fa-hourglass-o:before { + content: "\f250"; +} +.fa-hourglass-1:before, +.fa-hourglass-start:before { + content: "\f251"; +} +.fa-hourglass-2:before, +.fa-hourglass-half:before { + content: "\f252"; +} +.fa-hourglass-3:before, +.fa-hourglass-end:before { + content: "\f253"; +} +.fa-hourglass:before { + content: "\f254"; +} +.fa-hand-grab-o:before, +.fa-hand-rock-o:before { + content: "\f255"; +} +.fa-hand-stop-o:before, +.fa-hand-paper-o:before { + content: "\f256"; +} +.fa-hand-scissors-o:before { + content: "\f257"; +} +.fa-hand-lizard-o:before { + content: "\f258"; +} +.fa-hand-spock-o:before { + content: "\f259"; +} +.fa-hand-pointer-o:before { + content: "\f25a"; +} +.fa-hand-peace-o:before { + content: "\f25b"; +} +.fa-trademark:before { + content: "\f25c"; +} +.fa-registered:before { + content: "\f25d"; +} +.fa-creative-commons:before { + content: "\f25e"; +} +.fa-gg:before { + content: "\f260"; +} +.fa-gg-circle:before { + content: "\f261"; +} +.fa-tripadvisor:before { + content: "\f262"; +} +.fa-odnoklassniki:before { + content: "\f263"; +} +.fa-odnoklassniki-square:before { + content: "\f264"; +} +.fa-get-pocket:before { + content: "\f265"; +} +.fa-wikipedia-w:before { + content: "\f266"; +} +.fa-safari:before { + content: "\f267"; +} +.fa-chrome:before { + content: "\f268"; +} +.fa-firefox:before { + content: "\f269"; +} +.fa-opera:before { + content: "\f26a"; +} +.fa-internet-explorer:before { + content: "\f26b"; +} +.fa-tv:before, +.fa-television:before { + content: "\f26c"; +} +.fa-contao:before { + content: "\f26d"; +} +.fa-500px:before { + content: "\f26e"; +} +.fa-amazon:before { + content: "\f270"; +} +.fa-calendar-plus-o:before { + content: "\f271"; +} +.fa-calendar-minus-o:before { + content: "\f272"; +} +.fa-calendar-times-o:before { + content: "\f273"; +} +.fa-calendar-check-o:before { + content: "\f274"; +} +.fa-industry:before { + content: "\f275"; +} +.fa-map-pin:before { + content: "\f276"; +} +.fa-map-signs:before { + content: "\f277"; +} +.fa-map-o:before { + content: "\f278"; +} +.fa-map:before { + content: "\f279"; +} +.fa-commenting:before { + content: "\f27a"; +} +.fa-commenting-o:before { + content: "\f27b"; +} +.fa-houzz:before { + content: "\f27c"; +} +.fa-vimeo-v:before, +.fa-vimeo:before { + content: "\f27d"; +} +.fa-black-tie:before { + content: "\f27e"; +} +.fa-fonticons:before { + content: "\f280"; +} +.fa-reddit-alien:before { + content: "\f281"; +} +.fa-edge:before { + content: "\f282"; +} +.fa-credit-card-alt:before { + content: "\f283"; +} +.fa-codiepie:before { + content: "\f284"; +} +.fa-modx:before { + content: "\f285"; +} +.fa-fort-awesome:before { + content: "\f286"; +} +.fa-usb:before { + content: "\f287"; +} +.fa-product-hunt:before { + content: "\f288"; +} +.fa-mixcloud:before { + content: "\f289"; +} +.fa-scribd:before { + content: "\f28a"; +} +.fa-pause-circle:before { + content: "\f28b"; +} +.fa-pause-circle-o:before { + content: "\f28c"; +} +.fa-stop-circle:before { + content: "\f28d"; +} +.fa-stop-circle-o:before { + content: "\f28e"; +} +.fa-shopping-bag:before { + content: "\f290"; +} +.fa-shopping-basket:before { + content: "\f291"; +} +.fa-hashtag:before { + content: "\f292"; +} +.fa-bluetooth:before { + content: "\f293"; +} +.fa-bluetooth-b:before { + content: "\f294"; +} +.fa-percent:before { + content: "\f295"; +} +.fa-gitlab:before { + content: "\f296"; +} +.fa-wpbeginner:before { + content: "\f297"; +} +.fa-wpforms:before { + content: "\f298"; +} +.fa-envira:before { + content: "\f299"; +} +.fa-universal-access:before { + content: "\f29a"; +} +.fa-wheelchair-alt:before { + content: "\f29b"; +} +.fa-question-circle-o:before { + content: "\f29c"; +} +.fa-blind:before { + content: "\f29d"; +} +.fa-audio-description:before { + content: "\f29e"; +} +.fa-phone-volume:before, +.fa-volume-control-phone:before { + content: "\f2a0"; +} +.fa-braille:before { + content: "\f2a1"; +} +.fa-assistive-listening-systems:before { + content: "\f2a2"; +} +.fa-asl-interpreting:before, +.fa-american-sign-language-interpreting:before { + content: "\f2a3"; +} +.fa-deafness:before, +.fa-hard-of-hearing:before, +.fa-deaf:before { + content: "\f2a4"; +} +.fa-glide:before { + content: "\f2a5"; +} +.fa-glide-g:before { + content: "\f2a6"; +} +.fa-signing:before, +.fa-sign-language:before { + content: "\f2a7"; +} +.fa-low-vision:before { + content: "\f2a8"; +} +.fa-viadeo:before { + content: "\f2a9"; +} +.fa-viadeo-square:before { + content: "\f2aa"; +} +.fa-snapchat:before { + content: "\f2ab"; +} +.fa-snapchat-ghost:before { + content: "\f2ac"; +} +.fa-snapchat-square:before { + content: "\f2ad"; +} +.fa-first-order:before { + content: "\f2b0"; +} +.fa-yoast:before { + content: "\f2b1"; +} +.fa-themeisle:before { + content: "\f2b2"; +} +.fa-google-plus-circle:before, +.fa-google-plus-official:before { + content: "\f2b3"; +} +.fa-fa:before, +.fa-font-awesome:before { + content: "\f2b4"; +} +.fa-handshake-o:before { + content: "\f2b5"; +} +.fa-envelope-open:before { + content: "\f2b6"; +} +.fa-envelope-open-o:before { + content: "\f2b7"; +} +.fa-linode:before { + content: "\f2b8"; +} +.fa-address-book:before { + content: "\f2b9"; +} +.fa-address-book-o:before { + content: "\f2ba"; +} +.fa-vcard:before, +.fa-address-card:before { + content: "\f2bb"; +} +.fa-vcard-o:before, +.fa-address-card-o:before { + content: "\f2bc"; +} +.fa-user-circle:before { + content: "\f2bd"; +} +.fa-user-circle-o:before { + content: "\f2be"; +} +.fa-user-o:before { + content: "\f2c0"; +} +.fa-id-badge:before { + content: "\f2c1"; +} +.fa-drivers-license:before, +.fa-id-card:before { + content: "\f2c2"; +} +.fa-drivers-license-o:before, +.fa-id-card-o:before { + content: "\f2c3"; +} +.fa-quora:before { + content: "\f2c4"; +} +.fa-free-code-camp:before { + content: "\f2c5"; +} +.fa-telegram:before { + content: "\f2c6"; +} +.fa-thermometer-4:before, +.fa-thermometer:before, +.fa-thermometer-full:before { + content: "\f2c7"; +} +.fa-thermometer-3:before, +.fa-thermometer-three-quarters:before { + content: "\f2c8"; +} +.fa-thermometer-2:before, +.fa-thermometer-half:before { + content: "\f2c9"; +} +.fa-thermometer-1:before, +.fa-thermometer-quarter:before { + content: "\f2ca"; +} +.fa-thermometer-0:before, +.fa-thermometer-empty:before { + content: "\f2cb"; +} +.fa-shower:before { + content: "\f2cc"; +} +.fa-bathtub:before, +.fa-s15:before, +.fa-bath:before { + content: "\f2cd"; +} +.fa-podcast:before { + content: "\f2ce"; +} +.fa-window-maximize:before { + content: "\f2d0"; +} +.fa-window-minimize:before { + content: "\f2d1"; +} +.fa-window-restore:before { + content: "\f2d2"; +} +.fa-times-rectangle:before, +.fa-window-close:before { + content: "\f2d3"; +} +.fa-times-rectangle-o:before, +.fa-window-close-o:before { + content: "\f2d4"; +} +.fa-bandcamp:before { + content: "\f2d5"; +} +.fa-grav:before { + content: "\f2d6"; +} +.fa-etsy:before { + content: "\f2d7"; +} +.fa-imdb:before { + content: "\f2d8"; +} +.fa-ravelry:before { + content: "\f2d9"; +} +.fa-eercast:before { + content: "\f2da"; +} +.fa-microchip:before { + content: "\f2db"; +} +.fa-snowflake-o:before { + content: "\f2dc"; +} +.fa-superpowers:before { + content: "\f2dd"; +} +.fa-wpexplorer:before { + content: "\f2de"; +} +.fa-meetup:before { + content: "\f2e0"; +} +.fa-mastodon:before { + content: "\f2e1"; +} +.fa-mastodon-alt:before { + content: "\f2e2"; +} +.fa-fork-circle:before, +.fa-fork-awesome:before { + content: "\f2e3"; +} +.fa-peertube:before { + content: "\f2e4"; +} +.fa-diaspora:before { + content: "\f2e5"; +} +.fa-friendica:before { + content: "\f2e6"; +} +.fa-gnu-social:before { + content: "\f2e7"; +} +.fa-liberapay-square:before { + content: "\f2e8"; +} +.fa-liberapay:before { + content: "\f2e9"; +} +.fa-ssb:before, +.fa-scuttlebutt:before { + content: "\f2ea"; +} +.fa-hubzilla:before { + content: "\f2eb"; +} +.fa-social-home:before { + content: "\f2ec"; +} +.fa-artstation:before { + content: "\f2ed"; +} +.fa-discord:before { + content: "\f2ee"; +} +.fa-discord-alt:before { + content: "\f2ef"; +} +.fa-patreon:before { + content: "\f2f0"; +} +.fa-snowdrift:before { + content: "\f2f1"; +} +.fa-activitypub:before { + content: "\f2f2"; +} +.fa-ethereum:before { + content: "\f2f3"; +} +.fa-keybase:before { + content: "\f2f4"; +} +.fa-shaarli:before { + content: "\f2f5"; +} +.fa-shaarli-o:before { + content: "\f2f6"; +} +.fa-cut-key:before, +.fa-key-modern:before { + content: "\f2f7"; +} +.fa-xmpp:before { + content: "\f2f9"; +} +.fa-archive-org:before { + content: "\f2fc"; +} +.fa-freedombox:before { + content: "\f2fd"; +} +.fa-facebook-messenger:before { + content: "\f2fe"; +} +.fa-debian:before { + content: "\f2ff"; +} +.fa-mastodon-square:before { + content: "\f300"; +} +.fa-tipeee:before { + content: "\f301"; +} +.fa-react:before { + content: "\f302"; +} +.fa-dogmazic:before { + content: "\f303"; +} +.fa-zotero:before { + content: "\f309"; +} +.fa-nodejs:before { + content: "\f308"; +} +.fa-nextcloud:before { + content: "\f306"; +} +.fa-nextcloud-square:before { + content: "\f307"; +} +.fa-hackaday:before { + content: "\f30a"; +} +.fa-laravel:before { + content: "\f30b"; +} +.fa-signalapp:before { + content: "\f30c"; +} +.fa-gnupg:before { + content: "\f30d"; +} +.fa-php:before { + content: "\f30e"; +} +.fa-ffmpeg:before { + content: "\f30f"; +} +.fa-joplin:before { + content: "\f310"; +} +.fa-syncthing:before { + content: "\f311"; +} +.fa-inkscape:before { + content: "\f312"; +} +.fa-matrix-org:before { + content: "\f313"; +} +.fa-pixelfed:before { + content: "\f314"; +} +.fa-bootstrap:before { + content: "\f315"; +} +.fa-dev-to:before { + content: "\f316"; +} +.fa-hashnode:before { + content: "\f317"; +} +.fa-jirafeau:before { + content: "\f318"; +} +.fa-emby:before { + content: "\f319"; +} +.fa-wikidata:before { + content: "\f31a"; +} +.fa-gimp:before { + content: "\f31b"; +} +.fa-c:before { + content: "\f31c"; +} +.fa-digitalocean:before { + content: "\f31d"; +} +.fa-att:before { + content: "\f31e"; +} +.fa-gitea:before { + content: "\f31f"; +} +.fa-file-epub:before { + content: "\f321"; +} +.fa-python:before { + content: "\f322"; +} +.fa-archlinux:before { + content: "\f323"; +} +.fa-pleroma:before { + content: "\f324"; +} +.fa-unsplash:before { + content: "\f325"; +} +.fa-hackster:before { + content: "\f326"; +} +.fa-spell-check:before { + content: "\f327"; +} +.fa-moon:before { + content: "\f328"; +} +.fa-sun:before { + content: "\f329"; +} +.fa-f-droid:before { + content: "\f32a"; +} +.fa-biometric:before { + content: "\f32b"; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} diff --git a/static/fork-awesome/css/fork-awesome.min.css b/static/fork-awesome/css/fork-awesome.min.css new file mode 100644 index 0000000..6c4010c --- /dev/null +++ b/static/fork-awesome/css/fork-awesome.min.css @@ -0,0 +1,12 @@ +/*! +Fork Awesome 1.1.7 +License - https://forkaweso.me/Fork-Awesome/license + +Copyright 2018 Dave Gandy & Fork Awesome + +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. + */@font-face{font-family:ForkAwesome;src:url(../fonts/forkawesome-webfont.eot?v=1.1.7);src:url(../fonts/forkawesome-webfont.eot?#iefix&v=1.1.7) format('embedded-opentype'),url(../fonts/forkawesome-webfont.woff2?v=1.1.7) format('woff2'),url(../fonts/forkawesome-webfont.woff?v=1.1.7) format('woff'),url(../fonts/forkawesome-webfont.ttf?v=1.1.7) format('truetype'),url(../fonts/forkawesome-webfont.svg?v=1.1.7#forkawesomeregular) format('svg');font-weight:400;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 ForkAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1,1);-ms-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1,-1);-ms-transform:scale(1,-1);transform:scale(1,-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-rotate-90{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-close:before,.fa-remove:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-cog:before,.fa-gear:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-repeat:before,.fa-rotate-right:before{content:"\f01e"}.fa-refresh:before,.fa-sync:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before,.fa-video:before{content:"\f03d"}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-exclamation-triangle:before,.fa-warning:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-cogs:before,.fa-gears:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell-o:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-globe-e:before{content:"\f304"}.fa-globe-w:before{content:"\f305"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-community:before,.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-floppy-o:before,.fa-save:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus-g:before,.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-sort:before,.fa-unsorted:before{content:"\f0dc"}.fa-sort-desc:before,.fa-sort-down:before{content:"\f0dd"}.fa-sort-asc:before,.fa-sort-up:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-gavel:before,.fa-legal:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-bolt:before,.fa-flash:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-clipboard:before,.fa-paste:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before,.fa-utensils:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-chain-broken:before,.fa-unlink:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:"\f150"}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:"\f151"}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:"\f152"}.fa-eur:before,.fa-euro:before{content:"\f153"}.fa-gbp:before,.fa-pound:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-inr:before,.fa-rupee:before{content:"\f156"}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:"\f157"}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:"\f158"}.fa-krw:before,.fa-won:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before,.fa-sort-alpha-down:before{content:"\f15d"}.fa-sort-alpha-desc:before,.fa-sort-alpha-up:before{content:"\f15e"}.fa-sort-amount-asc:before,.fa-sort-amount-down:before{content:"\f160"}.fa-sort-amount-desc:before,.fa-sort-amount-up:before{content:"\f161"}.fa-sort-numeric-asc:before,.fa-sort-numeric-down:before{content:"\f162"}.fa-sort-numeric-desc:before,.fa-sort-numeric-up:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-try:before,.fa-turkish-lira:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-bank:before,.fa-institution:before,.fa-university:before{content:"\f19c"}.fa-graduation-cap:before,.fa-mortar-board:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before,.fa-utensil-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:"\f1c5"}.fa-file-archive-o:before,.fa-file-zip-o:before{content:"\f1c6"}.fa-file-audio-o:before,.fa-file-sound-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:"\f1d0"}.fa-empire:before,.fa-ge:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-paper-plane:before,.fa-send:before{content:"\f1d8"}.fa-paper-plane-o:before,.fa-send-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before,.fa-heading:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before,.fa-closed-captioning:before{content:"\f20a"}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before,.fa-gem:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-bed:before,.fa-hotel:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-medium-square:before{content:"\f2f8"}.fa-y-combinator:before,.fa-yc:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-television:before,.fa-tv:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo-v:before,.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-phone-volume:before,.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:"\f2a3"}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-sign-language:before,.fa-signing:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-address-card:before,.fa-vcard:before{content:"\f2bb"}.fa-address-card-o:before,.fa-vcard-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.fa-mastodon:before{content:"\f2e1"}.fa-mastodon-alt:before{content:"\f2e2"}.fa-fork-awesome:before,.fa-fork-circle:before{content:"\f2e3"}.fa-peertube:before{content:"\f2e4"}.fa-diaspora:before{content:"\f2e5"}.fa-friendica:before{content:"\f2e6"}.fa-gnu-social:before{content:"\f2e7"}.fa-liberapay-square:before{content:"\f2e8"}.fa-liberapay:before{content:"\f2e9"}.fa-scuttlebutt:before,.fa-ssb:before{content:"\f2ea"}.fa-hubzilla:before{content:"\f2eb"}.fa-social-home:before{content:"\f2ec"}.fa-artstation:before{content:"\f2ed"}.fa-discord:before{content:"\f2ee"}.fa-discord-alt:before{content:"\f2ef"}.fa-patreon:before{content:"\f2f0"}.fa-snowdrift:before{content:"\f2f1"}.fa-activitypub:before{content:"\f2f2"}.fa-ethereum:before{content:"\f2f3"}.fa-keybase:before{content:"\f2f4"}.fa-shaarli:before{content:"\f2f5"}.fa-shaarli-o:before{content:"\f2f6"}.fa-cut-key:before,.fa-key-modern:before{content:"\f2f7"}.fa-xmpp:before{content:"\f2f9"}.fa-archive-org:before{content:"\f2fc"}.fa-freedombox:before{content:"\f2fd"}.fa-facebook-messenger:before{content:"\f2fe"}.fa-debian:before{content:"\f2ff"}.fa-mastodon-square:before{content:"\f300"}.fa-tipeee:before{content:"\f301"}.fa-react:before{content:"\f302"}.fa-dogmazic:before{content:"\f303"}.fa-zotero:before{content:"\f309"}.fa-nodejs:before{content:"\f308"}.fa-nextcloud:before{content:"\f306"}.fa-nextcloud-square:before{content:"\f307"}.fa-hackaday:before{content:"\f30a"}.fa-laravel:before{content:"\f30b"}.fa-signalapp:before{content:"\f30c"}.fa-gnupg:before{content:"\f30d"}.fa-php:before{content:"\f30e"}.fa-ffmpeg:before{content:"\f30f"}.fa-joplin:before{content:"\f310"}.fa-syncthing:before{content:"\f311"}.fa-inkscape:before{content:"\f312"}.fa-matrix-org:before{content:"\f313"}.fa-pixelfed:before{content:"\f314"}.fa-bootstrap:before{content:"\f315"}.fa-dev-to:before{content:"\f316"}.fa-hashnode:before{content:"\f317"}.fa-jirafeau:before{content:"\f318"}.fa-emby:before{content:"\f319"}.fa-wikidata:before{content:"\f31a"}.fa-gimp:before{content:"\f31b"}.fa-c:before{content:"\f31c"}.fa-digitalocean:before{content:"\f31d"}.fa-att:before{content:"\f31e"}.fa-gitea:before{content:"\f31f"}.fa-file-epub:before{content:"\f321"}.fa-python:before{content:"\f322"}.fa-archlinux:before{content:"\f323"}.fa-pleroma:before{content:"\f324"}.fa-unsplash:before{content:"\f325"}.fa-hackster:before{content:"\f326"}.fa-spell-check:before{content:"\f327"}.fa-moon:before{content:"\f328"}.fa-sun:before{content:"\f329"}.fa-f-droid:before{content:"\f32a"}.fa-biometric:before{content:"\f32b"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}/*# sourceMappingURL=fork-awesome.min.css.map */ \ No newline at end of file diff --git a/static/fork-awesome/css/fork-awesome.min.css.map b/static/fork-awesome/css/fork-awesome.min.css.map new file mode 100644 index 0000000..df02930 --- /dev/null +++ b/static/fork-awesome/css/fork-awesome.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["fork-awesome.css"],"names":[],"mappings":";;;;;;;;;;;AAcA,WACE,YAAA,YACA,IAAS,8CACT,IAAS,qDAAoF,4BAAA,gDAAmE,gBAAA,+CAAiE,eAAA,8CAAoE,mBAAA,iEAArS,cACA,YAAA,IACA,WAAA,OAEF,IACE,QAAA,aACA,KAAA,OAAA,OAAA,OAAA,KAAA,EAAA,YACA,UAAA,QACA,eAAA,KACA,uBAAA,YACA,wBAAA,UAGF,OACE,UAAA,aACA,YAAA,MACA,eAAA,KAEF,OACE,UAAA,IAEF,OACE,UAAA,IAEF,OACE,UAAA,IAEF,OACE,UAAA,IAEF,OACE,MAAA,aACA,WAAA,OAEF,OACE,aAAA,EACA,YAAA,aACA,gBAAA,KAEK,UACL,SAAA,SAEF,OACE,SAAA,SACA,KAAA,cACA,MAAA,aACA,IAAA,YACA,WAAA,OAEI,aACJ,KAAA,cAEF,WACE,QAAA,KAAA,MAAA,MACA,OAAA,MAAA,MAAA,KACA,cAAA,KAEF,cACE,MAAA,KAEF,eACE,MAAA,MAEC,iBACD,aAAA,KAEC,kBACD,YAAA,KAGF,YACE,MAAA,MAEF,WACE,MAAA,KAEC,cACD,aAAA,KAEC,eACD,YAAA,KAEF,SACE,kBAAA,QAAA,GAAA,SAAA,OACA,UAAA,QAAA,GAAA,SAAA,OAEF,UACE,kBAAA,QAAA,GAAA,SAAuC,SACvC,UAAA,QAAA,GAAA,SAA+B,SAEjC,2BACE,GACE,kBAAmB,UACnB,UAAW,UAEb,KACE,kBAAmB,eACnB,UAAW,gBAGf,mBACE,GACE,kBAAmB,UACnB,UAAW,UAEb,KACE,kBAAmB,eACnB,UAAW,gBAGf,cACE,WAAY,2DACZ,kBAAmB,cACnB,cAAe,cACf,UAAW,cAEb,eACE,WAAY,2DACZ,kBAAmB,eACnB,cAAe,eACf,UAAW,eAEb,eACE,WAAY,2DACZ,kBAAmB,eACnB,cAAe,eACf,UAAW,eAEb,oBACE,WAAY,qEACZ,kBAAmB,YACnB,cAAe,YACf,UAAW,YAEb,kBACE,WAAY,qEACZ,kBAAmB,YACnB,cAAe,YACf,UAAW,YAKP,0BACA,wBAHA,qBACA,qBAFA,oBAKJ,OAAA,KAEF,UACE,SAAA,SACA,QAAA,aACA,MAAA,IACA,OAAA,IACA,YAAA,IACA,eAAA,OAEF,aACA,aACE,SAAA,SACA,KAAA,EACA,MAAA,KACA,WAAA,OAEF,aACE,YAAA,QAEF,aACE,UAAA,IAEF,YACE,MAAA,KAIO,iBACP,QAAA,QAEO,iBACP,QAAA,QAEQ,kBACR,QAAA,QAEY,sBACZ,QAAA,QAEO,iBACP,QAAA,QAEM,gBACN,QAAA,QAEQ,kBACR,QAAA,QAEM,gBACN,QAAA,QAEM,gBACN,QAAA,QAEU,oBACV,QAAA,QAEI,cACJ,QAAA,QAES,mBACT,QAAA,QAEO,iBACP,QAAA,QAGO,iBADC,kBAED,iBACP,QAAA,QAEa,uBACb,QAAA,QAEc,wBACd,QAAA,QAEW,qBACX,QAAA,QAEQ,kBACR,QAAA,QAGK,eADC,gBAEN,QAAA,QAES,mBACT,QAAA,QAEM,gBACN,QAAA,QAEQ,kBACR,QAAA,QAES,mBACT,QAAA,QAEM,gBACN,QAAA,QAEU,oBACV,QAAA,QAEqB,+BACrB,QAAA,QAEmB,6BACnB,QAAA,QAEO,iBACP,QAAA,QAEe,yBACf,QAAA,QAGQ,kBADM,wBAEd,QAAA,QAGS,mBADH,gBAEN,QAAA,QAEU,oBACV,QAAA,QAEM,gBACN,QAAA,QAEM,gBACN,QAAA,QAEY,sBACZ,QAAA,QAEY,sBACZ,QAAA,QAEa,uBACb,QAAA,QAEW,qBACX,QAAA,QAEQ,kBACR,QAAA,QAES,mBACT,QAAA,QAEK,eACL,QAAA,QAEM,gBACN,QAAA,QAEM,gBACN,QAAA,QAEU,oBACV,QAAA,QAEO,iBACP,QAAA,QAEQ,kBACR,QAAA,QAEM,gBACN,QAAA,QAEM,gBACN,QAAA,QAEQ,kBACR,QAAA,QAEa,uBACb,QAAA,QAEY,sBACZ,QAAA,QAEY,sBACZ,QAAA,QAEc,wBACd,QAAA,QAEa,uBACb,QAAA,QAEe,yBACf,QAAA,QAEM,gBACN,QAAA,QAEQ,kBACC,mBACT,QAAA,QAEQ,kBACR,QAAA,QAGc,wBADP,iBAEP,QAAA,QAGO,iBADA,iBAEI,qBACX,QAAA,QAEQ,kBACR,QAAA,QAEY,sBACZ,QAAA,QAEQ,kBACR,QAAA,QAEM,gBACN,QAAA,QAEM,gBACW,2BACjB,QAAA,QAEgB,0BAChB,QAAA,QAEgB,0BAChB,QAAA,QAEQ,kBACR,QAAA,QAEe,yBACf,QAAA,QAEe,yBACf,QAAA,QAEU,oBACV,QAAA,QAEM,gBACN,QAAA,QAEO,iBACP,QAAA,QAEM,gBACN,QAAA,QAES,mBACT,QAAA,QAEc,wBACd,QAAA,QAEc,wBACd,QAAA,QAEO,iBACP,QAAA,QAEc,wBACd,QAAA,QAEe,yBACf,QAAA,QAEa,uBACb,QAAA,QAEc,wBACd,QAAA,QAEc,wBACd,QAAA,QAEc,wBACd,QAAA,QAEiB,2BACjB,QAAA,QAEa,uBACb,QAAA,QAEY,sBACZ,QAAA,QAEgB,0BAChB,QAAA,QAEgB,0BAChB,QAAA,QAEK,eACL,QAAA,QAEY,sBACZ,QAAA,QAEa,uBACb,QAAA,QAEU,oBACV,QAAA,QAEY,sBACZ,QAAA,QAEc,wBACP,iBACP,QAAA,QAEQ,kBACR,QAAA,QAEU,oBACV,QAAA,QAEM,gBACN,QAAA,QAEO,iBACP,QAAA,QAEU,oBACV,QAAA,QAEoB,8BACpB,QAAA,QAEM,gBACN,QAAA,QAEM,gBACN,QAAA,QAEM,gBACN,QAAA,QAEK,eACL,QAAA,QAEW,qBACX,QAAA,QAGsB,gCADb,mBAET,QAAA,QAEO,iBACP,QAAA,QAEU,oBACV,QAAA,QAEQ,kBACR,QAAA,QAES,mBACT,QAAA,QAEQ,kBACR,QAAA,QAEY,sBACZ,QAAA,QAEc,wBACd,QAAA,QAES,mBACT,QAAA,QAEe,yBACf,QAAA,QAEQ,kBACR,QAAA,QAEa,uBACb,QAAA,QAEU,oBACV,QAAA,QAEU,oBACV,QAAA,QAEa,uBACF,qBACX,QAAA,QAEgB,0BAChB,QAAA,QAEiB,2BACjB,QAAA,QAEc,wBACd,QAAA,QAEK,eACL,QAAA,QAGM,gBADC,iBAEP,QAAA,QAEU,oBACV,QAAA,QAEa,uBACb,QAAA,QAEe,yBACf,QAAA,QAEW,qBACX,QAAA,QAES,mBACT,QAAA,QAEU,oBACV,QAAA,QAEiB,2BACjB,QAAA,QAEY,sBACZ,QAAA,QAEe,yBACf,QAAA,QAES,mBACT,QAAA,QAEQ,kBACR,QAAA,QAEe,yBACf,QAAA,QAEQ,kBACR,QAAA,QAES,mBACT,QAAA,QAEO,iBACP,QAAA,QAEU,oBACV,QAAA,QAEY,sBACZ,QAAA,QAEc,wBACd,QAAA,QAES,mBACT,QAAA,QAEY,sBACF,oBACV,QAAA,QAEQ,kBACR,QAAA,QAEQ,kBACR,QAAA,QAEa,uBACb,QAAA,QAEM,gBACD,eACL,QAAA,QAEO,iBACP,QAAA,QAEU,oBACV,QAAA,QAEQ,kBACR,QAAA,QAEa,uBACb,QAAA,QAEc,wBACd,QAAA,QAEa,uBACb,QAAA,QAEW,qBACX,QAAA,QAEa,uBACb,QAAA,QAEmB,6BACnB,QAAA,QAEoB,8BACpB,QAAA,QAEiB,2BACjB,QAAA,QAEmB,6BACnB,QAAA,QAEO,iBACP,QAAA,QAES,mBACT,QAAA,QAES,mBACT,QAAA,QAEQ,kBACR,QAAA,QAEO,iBACP,QAAA,QAEQ,kBACR,QAAA,QAEW,qBACX,QAAA,QAEY,sBACZ,QAAA,QAEW,qBACJ,iBACA,iBACP,QAAA,QAEO,iBACD,gBACN,QAAA,QAEO,iBACP,QAAA,QAEO,iBACP,QAAA,QAEK,eACK,oBACV,QAAA,QAEM,gBACG,mBACT,QAAA,QAEW,qBACX,QAAA,QAGU,oBADJ,gBAEN,QAAA,QAEQ,kBACR,QAAA,QAIM,gBAFG,mBACA,mBAET,QAAA,QAES,mBACT,QAAA,QAES,mBACT,QAAA,QAEe,yBACf,QAAA,QAEW,qBACX,QAAA,QAEO,iBACP,QAAA,QAEO,iBACP,QAAA,QAEO,iBACP,QAAA,QAEW,qBACX,QAAA,QAEkB,4BAClB,QAAA,QAEoB,8BACpB,QAAA,QAEe,yBACF,uBACb,QAAA,QAEO,iBACP,QAAA,QAEY,sBACZ,QAAA,QAEU,oBACV,QAAA,QAEY,sBACZ,QAAA,QAEa,uBACb,QAAA,QAES,mBACT,QAAA,QAGM,gBADI,oBAEV,QAAA,QAGW,qBADA,qBAEX,QAAA,QAGU,oBADD,mBAET,QAAA,QAEU,oBACV,QAAA,QAEU,oBACV,QAAA,QAEa,uBACP,gBACN,QAAA,QAGO,iBADA,iBAEP,QAAA,QAEW,qBACC,sBACZ,QAAA,QAEW,qBACX,QAAA,QAEY,sBACZ,QAAA,QAGM,gBADC,iBAEP,QAAA,QAES,mBACT,QAAA,QAEU,oBACV,QAAA,QAGW,qBADJ,iBAEP,QAAA,QAEa,uBACb,QAAA,QAEU,oBACV,QAAA,QAEgB,0BAChB,QAAA,QAEc,wBACd,QAAA,QAES,mBACT,QAAA,QAEa,uBACb,QAAA,QAEU,oBACV,QAAA,QAEM,gBACN,QAAA,QAEQ,kBACR,QAAA,QAGS,mBADC,oBAEV,QAAA,QAEa,uBACb,QAAA,QAEY,sBACZ,QAAA,QAEY,sBACZ,QAAA,QAEW,qBACX,QAAA,QAEQ,kBACR,QAAA,QAEa,uBACb,QAAA,QAEM,gBACN,QAAA,QAEU,oBACV,QAAA,QAEa,uBACb,QAAA,QAEmB,6BACnB,QAAA,QAEoB,8BACpB,QAAA,QAEiB,2BACjB,QAAA,QAEmB,6BACnB,QAAA,QAEY,sBACZ,QAAA,QAEa,uBACb,QAAA,QAEU,oBACV,QAAA,QAEY,sBACZ,QAAA,QAES,mBACT,QAAA,QAEQ,kBACR,QAAA,QAEQ,kBACR,QAAA,QAEc,wBACN,kBACR,QAAA,QAEU,oBACV,QAAA,QAEY,sBACZ,QAAA,QAEa,uBACb,QAAA,QAES,mBACT,QAAA,QAEQ,kBACR,QAAA,QAEY,sBACL,iBACP,QAAA,QAEY,sBACZ,QAAA,QAEU,oBACV,QAAA,QAEe,yBACf,QAAA,QAES,mBACT,QAAA,QAES,mBACT,QAAA,QAEO,iBACP,QAAA,QAES,mBACT,QAAA,QAEY,sBACZ,QAAA,QAEQ,kBACR,QAAA,QAEgB,0BAChB,QAAA,QAEU,oBACV,QAAA,QAEM,gBACN,QAAA,QAEgB,0BACL,qBACX,QAAA,QAEiB,2BACD,0BACH,uBACb,QAAA,QAEgB,0BAChB,QAAA,QAEM,gBACN,QAAA,QAEW,qBACX,QAAA,QAGc,wBADN,kBAER,QAAA,QAEU,oBACV,QAAA,QAEM,gBACN,QAAA,QAEa,uBACb,QAAA,QAEa,uBACb,QAAA,QAEW,qBACX,QAAA,QAEQ,kBACR,QAAA,QAEc,wBACd,QAAA,QAEY,sBACZ,QAAA,QAEkB,4BAClB,QAAA,QAEQ,kBACR,QAAA,QAEY,sBACZ,QAAA,QAEmB,6BACnB,QAAA,QAEQ,kBACR,QAAA,QAEQ,kBACR,QAAA,QAEqB,+BACrB,QAAA,QAEsB,gCACtB,QAAA,QAEmB,6BACnB,QAAA,QAEqB,+BACrB,QAAA,QAEO,iBACP,QAAA,QAEM,gBACN,QAAA,QAEQ,kBACR,QAAA,QAEY,sBACZ,QAAA,QAEU,oBACV,QAAA,QAEY,sBACZ,QAAA,QAEY,sBACZ,QAAA,QAEY,sBACZ,QAAA,QAEa,uBACb,QAAA,QAEQ,kBACR,QAAA,QAEc,wBACd,QAAA,QAEgB,0BAChB,QAAA,QAEU,oBACV,QAAA,QAEY,sBACZ,QAAA,QAEc,wBACd,QAAA,QAEe,yBACf,QAAA,QAEsB,gCACtB,QAAA,QAEc,wBACd,QAAA,QAES,mBACT,QAAA,QAGqB,+BADR,uBAEb,QAAA,QAGmB,6BADR,qBAEX,QAAA,QAGsB,gCADR,wBAEd,QAAA,QAGK,eADC,gBAEN,QAAA,QAGK,eADE,iBAEP,QAAA,QAEQ,kBACH,eACL,QAAA,QAGK,eADE,iBAEP,QAAA,QAEK,eAGA,eAFA,eACA,eAEL,QAAA,QAGQ,kBACH,eAFE,iBAGP,QAAA,QAGK,eADA,eAEL,QAAA,QAES,mBACJ,eACL,QAAA,QAEM,gBACN,QAAA,QAEW,qBACX,QAAA,QAGgB,0BADC,2BAEjB,QAAA,QAGiB,2BADF,yBAEf,QAAA,QAGiB,2BADC,4BAElB,QAAA,QAGkB,4BADF,0BAEhB,QAAA,QAGkB,4BADC,6BAEnB,QAAA,QAGmB,6BADF,2BAEjB,QAAA,QAEW,qBACX,QAAA,QAEa,uBACb,QAAA,QAEgB,0BAChB,QAAA,QAES,mBACT,QAAA,QAEM,gBACN,QAAA,QAEa,uBACb,QAAA,QAEc,wBACd,QAAA,QAES,mBACT,QAAA,QAEgB,0BAChB,QAAA,QAEW,qBACX,QAAA,QAEQ,kBACR,QAAA,QAEK,eACL,QAAA,QAEW,qBACX,QAAA,QAEkB,4BAClB,QAAA,QAEQ,kBACR,QAAA,QAEe,yBACf,QAAA,QAEiB,2BACjB,QAAA,QAEe,yBACf,QAAA,QAEiB,2BACjB,QAAA,QAEkB,4BAClB,QAAA,QAEO,iBACP,QAAA,QAES,mBACT,QAAA,QAES,mBACT,QAAA,QAEO,iBACP,QAAA,QAEU,oBACV,QAAA,QAEO,iBACP,QAAA,QAEY,sBACZ,QAAA,QAEQ,kBACR,QAAA,QAEQ,kBACR,QAAA,QAEM,gBACN,QAAA,QAEQ,kBACE,oBACV,QAAA,QAEO,iBACP,QAAA,QAEQ,kBACR,QAAA,QAES,mBACT,QAAA,QAEK,eACL,QAAA,QAEI,cACJ,QAAA,QAEO,iBACP,QAAA,QAEQ,kBACR,QAAA,QAEW,qBACX,QAAA,QAEgB,0BAChB,QAAA,QAEsB,gCACtB,QAAA,QAEqB,+BACrB,QAAA,QAGqB,+BADR,uBAEb,QAAA,QAEc,wBACd,QAAA,QAEY,sBACZ,QAAA,QAEc,wBACd,QAAA,QAGK,eADS,wBAEd,QAAA,QAEe,yBACf,QAAA,QAEe,yBACf,QAAA,QAEO,iBACP,QAAA,QAEiB,2BACjB,QAAA,QAEW,qBACX,QAAA,QAEQ,kBACR,QAAA,QAGM,gBADO,uBAED,sBACZ,QAAA,QAGgB,0BADF,wBAEd,QAAA,QAEO,iBACP,QAAA,QAEQ,kBACR,QAAA,QAEQ,kBACR,QAAA,QAEe,yBACf,QAAA,QAEoB,8BACpB,QAAA,QAEa,uBACb,QAAA,QAEW,qBACX,QAAA,QAEM,gBACN,QAAA,QAEQ,kBACR,QAAA,QAEQ,kBACR,QAAA,QAEU,oBACV,QAAA,QAEK,eACL,QAAA,QAEU,oBACV,QAAA,QAEO,iBACP,QAAA,QAEK,eACL,QAAA,QAGO,iBADQ,yBAEf,QAAA,QAEM,gBACN,QAAA,QAEO,iBACP,QAAA,QAES,mBACT,QAAA,QAEgB,0BAChB,QAAA,QAEO,iBACP,QAAA,QAEc,wBACd,QAAA,QAES,mBACT,QAAA,QAEY,sBACP,eACL,QAAA,QAEK,eACC,gBACN,QAAA,QAEM,gBACN,QAAA,QAES,mBACT,QAAA,QAEY,sBACZ,QAAA,QAEY,sBACZ,QAAA,QAEU,oBACV,QAAA,QAEY,sBACZ,QAAA,QAEa,uBACb,QAAA,QAEc,wBACd,QAAA,QAEmB,6BACnB,QAAA,QAIc,wBAFA,wBACE,0BAEhB,QAAA,QAGgB,0BADJ,sBAEZ,QAAA,QAGc,wBADA,wBAEd,QAAA,QAEc,wBACA,wBACd,QAAA,QAEa,uBACb,QAAA,QAEM,gBACN,QAAA,QAES,mBACT,QAAA,QAEU,oBACV,QAAA,QAEW,qBACA,qBAGA,qBAFC,sBACH,mBAET,QAAA,QAEgB,0BAChB,QAAA,QAEI,cAEG,iBADK,sBAEZ,QAAA,QAGQ,kBADJ,cAEJ,QAAA,QAEY,sBACZ,QAAA,QAEK,eACL,QAAA,QAIa,uBAFQ,+BACV,qBAEX,QAAA,QAEe,yBACf,QAAA,QAEI,cACJ,QAAA,QAEQ,kBACA,kBACR,QAAA,QAGa,uBADP,gBAEN,QAAA,QAGe,yBADP,kBAER,QAAA,QAES,mBACT,QAAA,QAEa,uBACb,QAAA,QAGQ,kBADC,mBAET,QAAA,QAEW,qBACX,QAAA,QAES,mBACT,QAAA,QAEW,qBACX,QAAA,QAEkB,4BAClB,QAAA,QAEM,gBACN,QAAA,QAGU,oBADK,yBAEf,QAAA,QAEK,eACL,QAAA,QAEY,sBACZ,QAAA,QAEM,gBACN,QAAA,QAEY,sBACZ,QAAA,QAEQ,kBACR,QAAA,QAEM,gBACN,QAAA,QAEa,uBACb,QAAA,QAEM,gBACN,QAAA,QAEY,sBACZ,QAAA,QAEQ,kBACR,QAAA,QAEe,yBACf,QAAA,QAES,mBACT,QAAA,QAEe,yBACf,QAAA,QAEa,uBACb,QAAA,QAES,mBACT,QAAA,QAEW,qBACX,QAAA,QAEW,qBACX,QAAA,QAEY,sBACZ,QAAA,QAEc,wBACd,QAAA,QAEO,iBACP,QAAA,QAEW,qBACX,QAAA,QAEI,cACJ,QAAA,QAEY,sBACZ,QAAA,QAEa,uBACb,QAAA,QAEe,yBACf,QAAA,QAEY,sBACZ,QAAA,QAEW,qBACX,QAAA,QAEY,sBACZ,QAAA,QAEQ,kBACR,QAAA,QAEe,yBACf,QAAA,QAEY,sBACZ,QAAA,QAEW,qBACX,QAAA,QAES,mBACT,QAAA,QAEK,eACL,QAAA,QAES,mBACT,QAAA,QAEW,qBACX,QAAA,QAGI,cADe,6BAEnB,QAAA,QAIK,eAFG,kBACA,kBAER,QAAA,QAEU,oBACV,QAAA,QAEY,sBACZ,QAAA,QAEgB,0BAChB,QAAA,QAEU,oBACV,QAAA,QAEU,oBACV,QAAA,QAES,mBACT,QAAA,QAEQ,kBACR,QAAA,QAEc,wBACd,QAAA,QAEa,uBACb,QAAA,QAEU,oBACV,QAAA,QAEW,qBACX,QAAA,QAEiB,2BACjB,QAAA,QAGS,mBADJ,eAEL,QAAA,QAEM,gBACN,QAAA,QAEa,uBACb,QAAA,QAEY,sBACZ,QAAA,QAEa,uBACb,QAAA,QAEW,qBACX,QAAA,QAEO,iBACP,QAAA,QAEM,gBACN,QAAA,QAES,mBACT,QAAA,QAEU,oBACG,uBACb,QAAA,QAEiB,2BACjB,QAAA,QAEc,wBACd,QAAA,QAEa,uBACb,QAAA,QAEY,sBACZ,QAAA,QAEa,uBACb,QAAA,QAEe,yBACf,QAAA,QAEe,yBACf,QAAA,QAEQ,kBACR,QAAA,QAEY,sBACZ,QAAA,QAEmB,6BACnB,QAAA,QAEa,uBACb,QAAA,QAEU,oBACV,QAAA,QAEQ,kBACR,QAAA,QAEW,qBACX,QAAA,QAEY,sBACZ,QAAA,QAGK,eADE,iBAEP,QAAA,QAES,mBACT,QAAA,QAEO,iBACP,QAAA,QAEQ,kBACR,QAAA,QAEQ,kBACR,QAAA,QAEe,yBACf,QAAA,QAGc,wBADV,cAEJ,QAAA,QAEe,yBACf,QAAA,QAEU,oBACV,QAAA,QAEc,wBACd,QAAA,QAEW,qBAEG,wBADL,mBAET,QAAA,QAEW,qBACa,kCACxB,QAAA,QAEW,qBACG,wBACd,QAAA,QAEW,qBACM,2BACjB,QAAA,QAEW,qBACI,yBACf,QAAA,QAEe,yBACf,QAAA,QAEU,oBACV,QAAA,QAEc,wBACd,QAAA,QAEgB,0BAChB,QAAA,QAEa,uBACb,QAAA,QAEe,yBACf,QAAA,QAEQ,kBACR,QAAA,QAEgB,0BAChB,QAAA,QAEO,iBACP,QAAA,QAEe,yBACf,QAAA,QAEa,uBACb,QAAA,QAEa,uBACI,2BACjB,QAAA,QAEa,uBACG,0BAChB,QAAA,QAEa,uBACE,yBACf,QAAA,QAEW,qBACX,QAAA,QAEa,uBACA,uBACb,QAAA,QAGc,wBADD,uBAEb,QAAA,QAEiB,2BACjB,QAAA,QAEe,yBACf,QAAA,QAEc,wBACd,QAAA,QAEgB,0BAChB,QAAA,QAEc,wBACd,QAAA,QAEW,qBACX,QAAA,QAEY,sBACZ,QAAA,QAEkB,4BAClB,QAAA,QAEI,cACJ,QAAA,QAEW,qBACX,QAAA,QAEa,uBACb,QAAA,QAEe,yBACf,QAAA,QAEsB,gCACtB,QAAA,QAEY,sBACZ,QAAA,QAEa,uBACb,QAAA,QAEQ,kBACR,QAAA,QAEQ,kBACR,QAAA,QAES,mBACT,QAAA,QAEO,iBACP,QAAA,QAEmB,6BACnB,QAAA,QAGY,sBADR,cAEJ,QAAA,QAEQ,kBACR,QAAA,QAEO,iBACP,QAAA,QAEQ,kBACR,QAAA,QAEiB,2BACjB,QAAA,QAEkB,4BAClB,QAAA,QAEkB,4BAClB,QAAA,QAEkB,4BAClB,QAAA,QAEU,oBACV,QAAA,QAES,mBACT,QAAA,QAEW,qBACX,QAAA,QAEO,iBACP,QAAA,QAEK,eACL,QAAA,QAEY,sBACZ,QAAA,QAEc,wBACd,QAAA,QAEO,iBACP,QAAA,QAES,mBACF,iBACP,QAAA,QAEW,qBACX,QAAA,QAEW,qBACX,QAAA,QAEc,wBACd,QAAA,QAEM,gBACN,QAAA,QAEiB,2BACjB,QAAA,QAEU,oBACV,QAAA,QAEM,gBACN,QAAA,QAEc,wBACd,QAAA,QAEK,eACL,QAAA,QAEc,wBACd,QAAA,QAEU,oBACV,QAAA,QAEQ,kBACR,QAAA,QAEc,wBACd,QAAA,QAEgB,0BAChB,QAAA,QAEa,uBACb,QAAA,QAEe,yBACf,QAAA,QAEc,wBACd,QAAA,QAEiB,2BACjB,QAAA,QAES,mBACT,QAAA,QAEW,qBACX,QAAA,QAEa,uBACb,QAAA,QAES,mBACT,QAAA,QAEQ,kBACR,QAAA,QAEY,sBACZ,QAAA,QAES,mBACT,QAAA,QAEQ,kBACR,QAAA,QAEkB,4BAClB,QAAA,QAEgB,0BAChB,QAAA,QAEmB,6BACnB,QAAA,QAEO,iBACP,QAAA,QAEmB,6BACnB,QAAA,QAEc,wBACQ,gCACtB,QAAA,QAES,mBACT,QAAA,QAE6B,uCAC7B,QAAA,QAGqC,+CADnB,4BAElB,QAAA,QAIM,gBAFI,oBACO,2BAEjB,QAAA,QAEO,iBACP,QAAA,QAES,mBACT,QAAA,QAGe,yBADN,mBAET,QAAA,QAEY,sBACZ,QAAA,QAEQ,kBACR,QAAA,QAEe,yBACf,QAAA,QAEU,oBACV,QAAA,QAEgB,0BAChB,QAAA,QAEiB,2BACjB,QAAA,QAEa,uBACb,QAAA,QAEO,iBACP,QAAA,QAEW,qBACX,QAAA,QAEoB,8BACE,gCACtB,QAAA,QAEI,cACU,wBACd,QAAA,QAEa,uBACb,QAAA,QAEe,yBACf,QAAA,QAEiB,2BACjB,QAAA,QAEQ,kBACR,QAAA,QAEc,wBACd,QAAA,QAEgB,0BAChB,QAAA,QAGc,wBADP,iBAEP,QAAA,QAGgB,0BADP,mBAET,QAAA,QAEa,uBACb,QAAA,QAEe,yBACf,QAAA,QAEQ,kBACR,QAAA,QAEU,oBACV,QAAA,QAEiB,2BACR,mBACT,QAAA,QAEmB,6BACR,qBACX,QAAA,QAEO,iBACP,QAAA,QAEgB,0BAChB,QAAA,QAEU,oBACV,QAAA,QAEe,yBAEG,4BADL,uBAEb,QAAA,QAEe,yBACa,sCAC5B,QAAA,QAEe,yBACG,4BAClB,QAAA,QAEe,yBACM,+BACrB,QAAA,QAEe,yBACI,6BACnB,QAAA,QAEQ,kBACR,QAAA,QAIM,gBAFG,mBACJ,eAEL,QAAA,QAES,mBACT,QAAA,QAEiB,2BACjB,QAAA,QAEiB,2BACjB,QAAA,QAEgB,0BAChB,QAAA,QAEiB,2BACH,wBACd,QAAA,QAEmB,6BACH,0BAChB,QAAA,QAEU,oBACV,QAAA,QAEM,gBACN,QAAA,QAEM,gBACN,QAAA,QAEM,gBACN,QAAA,QAES,mBACT,QAAA,QAES,mBACT,QAAA,QAEW,qBACX,QAAA,QAEa,uBACb,QAAA,QAEa,uBACb,QAAA,QAEY,sBACZ,QAAA,QAEQ,kBACR,QAAA,QAEU,oBACV,QAAA,QAEc,wBACd,QAAA,QAGc,wBADD,uBAEb,QAAA,QAEU,oBACV,QAAA,QAEU,oBACV,QAAA,QAEW,qBACX,QAAA,QAEY,sBACZ,QAAA,QAEkB,4BAClB,QAAA,QAEW,qBACX,QAAA,QAGa,uBADR,eAEL,QAAA,QAEU,oBACV,QAAA,QAEa,uBACb,QAAA,QAEY,sBACZ,QAAA,QAES,mBACT,QAAA,QAEa,uBACb,QAAA,QAES,mBACT,QAAA,QAEW,qBACX,QAAA,QAEa,uBACb,QAAA,QAEU,oBACV,QAAA,QAES,mBACT,QAAA,QAES,mBACT,QAAA,QAEW,qBACX,QAAA,QAES,mBACG,sBACZ,QAAA,QAEM,gBACN,QAAA,QAEa,uBACb,QAAA,QAEY,sBACZ,QAAA,QAEoB,8BACpB,QAAA,QAEQ,kBACR,QAAA,QAEiB,2BACjB,QAAA,QAEQ,kBACR,QAAA,QAEO,iBACP,QAAA,QAEU,oBACV,QAAA,QAEQ,kBACR,QAAA,QAEQ,kBACR,QAAA,QAEW,qBACX,QAAA,QAEkB,4BAClB,QAAA,QAEU,oBACV,QAAA,QAES,mBACT,QAAA,QAEW,qBACX,QAAA,QAEO,iBACP,QAAA,QAEK,eACL,QAAA,QAEQ,kBACR,QAAA,QAEQ,kBACR,QAAA,QAEW,qBACX,QAAA,QAEU,oBACV,QAAA,QAEY,sBACZ,QAAA,QAEU,oBACV,QAAA,QAEW,qBACX,QAAA,QAEQ,kBACR,QAAA,QAEU,oBACV,QAAA,QAEU,oBACV,QAAA,QAEM,gBACN,QAAA,QAEU,oBACV,QAAA,QAEM,gBACN,QAAA,QAEG,aACH,QAAA,QAEc,wBACd,QAAA,QAEK,eACL,QAAA,QAEO,iBACP,QAAA,QAEW,qBACX,QAAA,QAEQ,kBACR,QAAA,QAEW,qBACX,QAAA,QAES,mBACT,QAAA,QAEU,oBACV,QAAA,QAEU,oBACV,QAAA,QAEa,uBACb,QAAA,QAEM,gBACN,QAAA,QAEK,eACL,QAAA,QAES,mBACT,QAAA,QAEW,qBACX,QAAA,QAEF,SACE,SAAA,SACA,MAAA,IACA,OAAA,IACA,QAAA,EACA,OAAA,KACA,SAAA,OACA,KAAM,cACN,OAAA,EAEgB,0BACA,yBAChB,SAAA,OACA,MAAA,KACA,OAAA,KACA,OAAA,EACA,SAAA,QACA,KAAA"} \ No newline at end of file diff --git a/static/fork-awesome/css/v5-compat.css b/static/fork-awesome/css/v5-compat.css new file mode 100644 index 0000000..2d6ce70 --- /dev/null +++ b/static/fork-awesome/css/v5-compat.css @@ -0,0 +1,446 @@ +/*! +Fork Awesome 1.1.7 +License - https://forkaweso.me/Fork-Awesome/license + +Copyright 2018 Dave Gandy & Fork Awesome + +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. + */ +.fas, +.fab, +.far { + display: inline-block; + font: normal normal normal 14px/1 ForkAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.fas.fa-chart-area:before { + content: "\f1fe"; +} +.fas.fa-arrows-alt:before { + content: "\f047"; +} +.fas.fa-expand-arrows-alt:before { + content: "\f0b2"; +} +.fas.fa-arrows-alt-h:before { + content: "\f07e"; +} +.fas.fa-arrows-alt-v:before { + content: "\f07d"; +} +.fas.fa-calendar-alt:before { + content: "\f073"; +} +.fas.fa-circle-notch:before { + content: "\f1ce"; +} +.fas.fa-cloud-download-alt:before { + content: "\f0ed"; +} +.fas.fa-cloud-upload-alt:before { + content: "\f0ee"; +} +.fas.fa-credit-card:before { + content: "\f283"; +} +.fas.fa-dollar-sign:before { + content: "\f155"; +} +.fas.fa-euro-sign:before { + content: "\f153"; +} +.fas.fa-exchange-alt:before { + content: "\f0ec"; +} +.fas.fa-external-link-alt:before { + content: "\f08e"; +} +.fas.fa-external-link-square-alt:before { + content: "\f14c"; +} +.fas.fa-eye-dropper:before { + content: "\f1fb"; +} +.fas.fa-pound-sign:before { + content: "\f154"; +} +.fas.fa-glass-martini:before { + content: "\f000"; +} +.fas.fa-shekel-sign:before { + content: "\f20b"; +} +.fas.fa-rupee-sign:before { + content: "\f156"; +} +.fas.fa-won-sign:before { + content: "\f159"; +} +.fas.fa-level-down-alt:before { + content: "\f149"; +} +.fas.fa-level-up-alt:before { + content: "\f148"; +} +.fas.fa-chart-line:before { + content: "\f201"; +} +.fas.fa-long-arrow-alt-down:before { + content: "\f175"; +} +.fas.fa-long-arrow-alt-left:before { + content: "\f177"; +} +.fas.fa-long-arrow-alt-right:before { + content: "\f178"; +} +.fas.fa-long-arrow-alt-up:before { + content: "\f176"; +} +.fas.fa-map-marker-alt:before { + content: "\f041"; +} +.fas.fa-mobile-alt:before { + content: "\f10b"; +} +.fas.fa-pencil-alt:before { + content: "\f040"; +} +.fas.fa-pen-square:before { + content: "\f14b"; +} +.fas.fa-chart-pie:before { + content: "\f200"; +} +.fas.fa-yen-sign:before { + content: "\f157"; +} +.fas.fa-ruble-sign:before { + content: "\f158"; +} +.fas.fa-shield-alt:before { + content: "\f132"; +} +.fas.fa-sign-in-alt:before { + content: "\f090"; +} +.fas.fa-sign-out-alt:before { + content: "\f08b"; +} +.fas.fa-sliders-h:before { + content: "\f1de"; +} +.fas.fa-tablet-alt:before { + content: "\f10a"; +} +.fas.fa-tachometer-alt:before { + content: "\f0e4"; +} +.fas.fa-thumbtack:before { + content: "\f08d"; +} +.fas.fa-ticket-alt:before { + content: "\f145"; +} +.fas.fa-trash-alt:before { + content: "\f1f8"; +} +.fas.fa-lira-sign:before { + content: "\f195"; +} +.fab.fa-linkedin-in:before { + content: "\fe01"; +} +.fab.fa-linkedin:before { + content: "\f08c"; +} +.far.fa-address-book:before { + content: "\f2ba"; +} +.far.fa-address-card:before { + content: "\f2bc"; +} +.far.fa-arrow-alt-circle-down:before { + content: "\f01a"; +} +.far.fa-arrow-alt-circle-left:before { + content: "\f190"; +} +.far.fa-arrow-alt-circle-right:before { + content: "\f18e"; +} +.far.fa-arrow-alt-circle-up:before { + content: "\f01b"; +} +.far.fa-bell:before { + content: "\f0f3"; +} +.far.fa-bell-slash:before { + content: "\f1f7"; +} +.far.fa-bookmark:before { + content: "\f097"; +} +.far.fa-building:before { + content: "\f0f7"; +} +.far.fa-calendar-check:before { + content: "\f274"; +} +.far.fa-calendar-minus:before { + content: "\f272"; +} +.far.fa-calendar:before { + content: "\f133"; +} +.far.fa-calendar-plus:before { + content: "\f271"; +} +.far.fa-calendar-times:before { + content: "\f273"; +} +.far.fa-caret-square-down:before { + content: "\f150"; +} +.far.fa-caret-square-left:before { + content: "\f191"; +} +.far.fa-caret-square-right:before { + content: "\f152"; +} +.far.fa-caret-square-up:before { + content: "\f151"; +} +.far.fa-check-circle:before { + content: "\f05d"; +} +.far.fa-check-square:before { + content: "\f046"; +} +.far.fa-circle:before { + content: "\f10c"; +} +.far.fa-clock:before { + content: "\f017"; +} +.far.fa-comment:before { + content: "\f0e5"; +} +.far.fa-comment-dots:before { + content: "\f27b"; +} +.far.fa-comments:before { + content: "\f0e6"; +} +.far.fa-dot-circle:before { + content: "\f192"; +} +.far.fa-id-card:before { + content: "\f2c3"; +} +.far.fa-envelope:before { + content: "\f003"; +} +.far.fa-envelope-open:before { + content: "\f2b7"; +} +.far.fa-file-archive:before { + content: "\f1c6"; +} +.far.fa-file-audio:before { + content: "\f1c7"; +} +.far.fa-file-code:before { + content: "\f1c9"; +} +.far.fa-file-excel:before { + content: "\f1c3"; +} +.far.fa-file-image:before { + content: "\f1c5"; +} +.far.fa-file-video:before { + content: "\f1c8"; +} +.far.fa-copy:before, +.far.fa-file:before { + content: "\f016"; +} +.far.fa-file-pdf:before { + content: "\f1c1"; +} +.far.fa-file-powerpoint:before { + content: "\f1c4"; +} +.far.fa-file-alt:before { + content: "\f0f6"; +} +.far.fa-file-word:before { + content: "\f1c2"; +} +.far.fa-flag:before { + content: "\f11d"; +} +.far.fa-save:before { + content: "\f0c7"; +} +.far.fa-folder:before { + content: "\f114"; +} +.far.fa-folder-open:before { + content: "\f115"; +} +.far.fa-frown:before { + content: "\f119"; +} +.far.fa-futbol:before { + content: "\f1e3"; +} +.far.fa-hand-rock:before { + content: "\f255"; +} +.far.fa-hand-lizard:before { + content: "\f258"; +} +.far.fa-hand-point-down:before { + content: "\f0a7"; +} +.far.fa-hand-point-left:before { + content: "\f0a5"; +} +.far.fa-hand-point-right:before { + content: "\f0a4"; +} +.far.fa-hand-point-up:before { + content: "\f0a6"; +} +.far.fa-hand-paper:before { + content: "\256"; +} +.far.fa-hand-pointer:before { + content: "\f25a"; +} +.far.fa-hand-scissors:before { + content: "\f257"; +} +.far.fa-hand-spock:before { + content: "\f259"; +} +.far.fa-handshake:before { + content: "\f2b5"; +} +.far.fa-hdd:before { + content: "\f0a0"; +} +.far.fa-heart:before { + content: "\f08a"; +} +.far.fa-hospital:before { + content: "\f0f8"; +} +.far.fa-hourglass:before { + content: "\f250"; +} +.far.fa-id-card:before { + content: "\f2c3"; +} +.far.fa-keyboard:before { + content: "\f11c"; +} +.far.fa-lemon:before { + content: "\f094"; +} +.far.fa-lightbulb:before { + content: "\f0eb"; +} +.far.fa-meh:before { + content: "\f11a"; +} +.far.fa-minus-square:before { + content: "\f147"; +} +.far.fa-money-bill-alt:before { + content: "\f0d6"; +} +.far.fa-moon:before { + content: "\f186"; +} +.far.fa-newspaper:before { + content: "\f1ea"; +} +.far.fa-paper-plane:before { + content: "\f1d9"; +} +.far.fa-pause-circle:before { + content: "\f28c"; +} +.far.fa-edit:before { + content: "\f044"; +} +.far.fa-image:before { + content: "\f03e"; +} +.far.fa-play-circle:before { + content: "\f01d"; +} +.far.fa-plus-square:before { + content: "\f196"; +} +.far.fa-question-circle:before { + content: "\f92c"; +} +.far.fa-share-square:before { + content: "\f045"; +} +.far.fa-smile:before { + content: "\f118"; +} +.far.fa-snowflake:before { + content: "\f2dc"; +} +.far.fa-futbol:before { + content: "\f1e3"; +} +.far.fa-star-half:before { + content: "\f089"; +} +.far.fa-star:before { + content: "\f006"; +} +.far.fa-sticky-note:before { + content: "\f24a"; +} +.far.fa-stop-circle:before { + content: "\f28e"; +} +.far.fa-sun:before { + content: "\f185"; +} +.far.fa-thumbs-down:before { + content: "\f088"; +} +.far.fa-thumbs-up:before { + content: "\f087"; +} +.far.fa-times-circle:before { + content: "\f05c"; +} +.far.fa-window-close:before { + content: "\f2d4"; +} +.far.fa-trash-alt:before { + content: "\f014"; +} +.far.fa-user-circle:before { + content: "\f2be"; +} +.far.fa-user:before { + content: "\f2c0"; +} diff --git a/static/fork-awesome/css/v5-compat.min.css b/static/fork-awesome/css/v5-compat.min.css new file mode 100644 index 0000000..eafc2f7 --- /dev/null +++ b/static/fork-awesome/css/v5-compat.min.css @@ -0,0 +1,12 @@ +/*! +Fork Awesome 1.1.7 +License - https://forkaweso.me/Fork-Awesome/license + +Copyright 2018 Dave Gandy & Fork Awesome + +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. + */.fab,.far,.fas{display:inline-block;font:normal normal normal 14px/1 ForkAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fas.fa-chart-area:before{content:"\f1fe"}.fas.fa-arrows-alt:before{content:"\f047"}.fas.fa-expand-arrows-alt:before{content:"\f0b2"}.fas.fa-arrows-alt-h:before{content:"\f07e"}.fas.fa-arrows-alt-v:before{content:"\f07d"}.fas.fa-calendar-alt:before{content:"\f073"}.fas.fa-circle-notch:before{content:"\f1ce"}.fas.fa-cloud-download-alt:before{content:"\f0ed"}.fas.fa-cloud-upload-alt:before{content:"\f0ee"}.fas.fa-credit-card:before{content:"\f283"}.fas.fa-dollar-sign:before{content:"\f155"}.fas.fa-euro-sign:before{content:"\f153"}.fas.fa-exchange-alt:before{content:"\f0ec"}.fas.fa-external-link-alt:before{content:"\f08e"}.fas.fa-external-link-square-alt:before{content:"\f14c"}.fas.fa-eye-dropper:before{content:"\f1fb"}.fas.fa-pound-sign:before{content:"\f154"}.fas.fa-glass-martini:before{content:"\f000"}.fas.fa-shekel-sign:before{content:"\f20b"}.fas.fa-rupee-sign:before{content:"\f156"}.fas.fa-won-sign:before{content:"\f159"}.fas.fa-level-down-alt:before{content:"\f149"}.fas.fa-level-up-alt:before{content:"\f148"}.fas.fa-chart-line:before{content:"\f201"}.fas.fa-long-arrow-alt-down:before{content:"\f175"}.fas.fa-long-arrow-alt-left:before{content:"\f177"}.fas.fa-long-arrow-alt-right:before{content:"\f178"}.fas.fa-long-arrow-alt-up:before{content:"\f176"}.fas.fa-map-marker-alt:before{content:"\f041"}.fas.fa-mobile-alt:before{content:"\f10b"}.fas.fa-pencil-alt:before{content:"\f040"}.fas.fa-pen-square:before{content:"\f14b"}.fas.fa-chart-pie:before{content:"\f200"}.fas.fa-yen-sign:before{content:"\f157"}.fas.fa-ruble-sign:before{content:"\f158"}.fas.fa-shield-alt:before{content:"\f132"}.fas.fa-sign-in-alt:before{content:"\f090"}.fas.fa-sign-out-alt:before{content:"\f08b"}.fas.fa-sliders-h:before{content:"\f1de"}.fas.fa-tablet-alt:before{content:"\f10a"}.fas.fa-tachometer-alt:before{content:"\f0e4"}.fas.fa-thumbtack:before{content:"\f08d"}.fas.fa-ticket-alt:before{content:"\f145"}.fas.fa-trash-alt:before{content:"\f1f8"}.fas.fa-lira-sign:before{content:"\f195"}.fab.fa-linkedin-in:before{content:"\fe01"}.fab.fa-linkedin:before{content:"\f08c"}.far.fa-address-book:before{content:"\f2ba"}.far.fa-address-card:before{content:"\f2bc"}.far.fa-arrow-alt-circle-down:before{content:"\f01a"}.far.fa-arrow-alt-circle-left:before{content:"\f190"}.far.fa-arrow-alt-circle-right:before{content:"\f18e"}.far.fa-arrow-alt-circle-up:before{content:"\f01b"}.far.fa-bell:before{content:"\f0f3"}.far.fa-bell-slash:before{content:"\f1f7"}.far.fa-bookmark:before{content:"\f097"}.far.fa-building:before{content:"\f0f7"}.far.fa-calendar-check:before{content:"\f274"}.far.fa-calendar-minus:before{content:"\f272"}.far.fa-calendar:before{content:"\f133"}.far.fa-calendar-plus:before{content:"\f271"}.far.fa-calendar-times:before{content:"\f273"}.far.fa-caret-square-down:before{content:"\f150"}.far.fa-caret-square-left:before{content:"\f191"}.far.fa-caret-square-right:before{content:"\f152"}.far.fa-caret-square-up:before{content:"\f151"}.far.fa-check-circle:before{content:"\f05d"}.far.fa-check-square:before{content:"\f046"}.far.fa-circle:before{content:"\f10c"}.far.fa-clock:before{content:"\f017"}.far.fa-comment:before{content:"\f0e5"}.far.fa-comment-dots:before{content:"\f27b"}.far.fa-comments:before{content:"\f0e6"}.far.fa-dot-circle:before{content:"\f192"}.far.fa-id-card:before{content:"\f2c3"}.far.fa-envelope:before{content:"\f003"}.far.fa-envelope-open:before{content:"\f2b7"}.far.fa-file-archive:before{content:"\f1c6"}.far.fa-file-audio:before{content:"\f1c7"}.far.fa-file-code:before{content:"\f1c9"}.far.fa-file-excel:before{content:"\f1c3"}.far.fa-file-image:before{content:"\f1c5"}.far.fa-file-video:before{content:"\f1c8"}.far.fa-copy:before,.far.fa-file:before{content:"\f016"}.far.fa-file-pdf:before{content:"\f1c1"}.far.fa-file-powerpoint:before{content:"\f1c4"}.far.fa-file-alt:before{content:"\f0f6"}.far.fa-file-word:before{content:"\f1c2"}.far.fa-flag:before{content:"\f11d"}.far.fa-save:before{content:"\f0c7"}.far.fa-folder:before{content:"\f114"}.far.fa-folder-open:before{content:"\f115"}.far.fa-frown:before{content:"\f119"}.far.fa-futbol:before{content:"\f1e3"}.far.fa-hand-rock:before{content:"\f255"}.far.fa-hand-lizard:before{content:"\f258"}.far.fa-hand-point-down:before{content:"\f0a7"}.far.fa-hand-point-left:before{content:"\f0a5"}.far.fa-hand-point-right:before{content:"\f0a4"}.far.fa-hand-point-up:before{content:"\f0a6"}.far.fa-hand-paper:before{content:"\256"}.far.fa-hand-pointer:before{content:"\f25a"}.far.fa-hand-scissors:before{content:"\f257"}.far.fa-hand-spock:before{content:"\f259"}.far.fa-handshake:before{content:"\f2b5"}.far.fa-hdd:before{content:"\f0a0"}.far.fa-heart:before{content:"\f08a"}.far.fa-hospital:before{content:"\f0f8"}.far.fa-hourglass:before{content:"\f250"}.far.fa-id-card:before{content:"\f2c3"}.far.fa-keyboard:before{content:"\f11c"}.far.fa-lemon:before{content:"\f094"}.far.fa-lightbulb:before{content:"\f0eb"}.far.fa-meh:before{content:"\f11a"}.far.fa-minus-square:before{content:"\f147"}.far.fa-money-bill-alt:before{content:"\f0d6"}.far.fa-moon:before{content:"\f186"}.far.fa-newspaper:before{content:"\f1ea"}.far.fa-paper-plane:before{content:"\f1d9"}.far.fa-pause-circle:before{content:"\f28c"}.far.fa-edit:before{content:"\f044"}.far.fa-image:before{content:"\f03e"}.far.fa-play-circle:before{content:"\f01d"}.far.fa-plus-square:before{content:"\f196"}.far.fa-question-circle:before{content:"\f92c"}.far.fa-share-square:before{content:"\f045"}.far.fa-smile:before{content:"\f118"}.far.fa-snowflake:before{content:"\f2dc"}.far.fa-futbol:before{content:"\f1e3"}.far.fa-star-half:before{content:"\f089"}.far.fa-star:before{content:"\f006"}.far.fa-sticky-note:before{content:"\f24a"}.far.fa-stop-circle:before{content:"\f28e"}.far.fa-sun:before{content:"\f185"}.far.fa-thumbs-down:before{content:"\f088"}.far.fa-thumbs-up:before{content:"\f087"}.far.fa-times-circle:before{content:"\f05c"}.far.fa-window-close:before{content:"\f2d4"}.far.fa-trash-alt:before{content:"\f014"}.far.fa-user-circle:before{content:"\f2be"}.far.fa-user:before{content:"\f2c0"}/*# sourceMappingURL=v5-compat.min.css.map */ \ No newline at end of file diff --git a/static/fork-awesome/css/v5-compat.min.css.map b/static/fork-awesome/css/v5-compat.min.css.map new file mode 100644 index 0000000..44c6790 --- /dev/null +++ b/static/fork-awesome/css/v5-compat.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["v5-compat.css"],"names":[],"mappings":";;;;;;;;;;;AAaA,KACA,KAFA,KAGE,QAAA,aACA,KAAA,OAAA,OAAA,OAAA,KAAA,EAAA,YACA,UAAA,QACA,eAAA,KACA,uBAAA,YACA,wBAAA,UAEgB,0BAChB,QAAA,QAEgB,0BAChB,QAAA,QAEuB,iCACvB,QAAA,QAEkB,4BAClB,QAAA,QAEkB,4BAClB,QAAA,QAEkB,4BAClB,QAAA,QAEkB,4BAClB,QAAA,QAEwB,kCACxB,QAAA,QAEsB,gCACtB,QAAA,QAEiB,2BACjB,QAAA,QAEiB,2BACjB,QAAA,QAEe,yBACf,QAAA,QAEkB,4BAClB,QAAA,QAEuB,iCACvB,QAAA,QAE8B,wCAC9B,QAAA,QAEiB,2BACjB,QAAA,QAEgB,0BAChB,QAAA,QAEmB,6BACnB,QAAA,QAEiB,2BACjB,QAAA,QAEgB,0BAChB,QAAA,QAEc,wBACd,QAAA,QAEoB,8BACpB,QAAA,QAEkB,4BAClB,QAAA,QAEgB,0BAChB,QAAA,QAEyB,mCACzB,QAAA,QAEyB,mCACzB,QAAA,QAE0B,oCAC1B,QAAA,QAEuB,iCACvB,QAAA,QAEoB,8BACpB,QAAA,QAEgB,0BAChB,QAAA,QAEgB,0BAChB,QAAA,QAEgB,0BAChB,QAAA,QAEe,yBACf,QAAA,QAEc,wBACd,QAAA,QAEgB,0BAChB,QAAA,QAEgB,0BAChB,QAAA,QAEiB,2BACjB,QAAA,QAEkB,4BAClB,QAAA,QAEe,yBACf,QAAA,QAEgB,0BAChB,QAAA,QAEoB,8BACpB,QAAA,QAEe,yBACf,QAAA,QAEgB,0BAChB,QAAA,QAEe,yBACf,QAAA,QAEe,yBACf,QAAA,QAEiB,2BACjB,QAAA,QAEc,wBACd,QAAA,QAEkB,4BAClB,QAAA,QAEkB,4BAClB,QAAA,QAE2B,qCAC3B,QAAA,QAE2B,qCAC3B,QAAA,QAE4B,sCAC5B,QAAA,QAEyB,mCACzB,QAAA,QAEU,oBACV,QAAA,QAEgB,0BAChB,QAAA,QAEc,wBACd,QAAA,QAEc,wBACd,QAAA,QAEoB,8BACpB,QAAA,QAEoB,8BACpB,QAAA,QAEc,wBACd,QAAA,QAEmB,6BACnB,QAAA,QAEoB,8BACpB,QAAA,QAEuB,iCACvB,QAAA,QAEuB,iCACvB,QAAA,QAEwB,kCACxB,QAAA,QAEqB,+BACrB,QAAA,QAEkB,4BAClB,QAAA,QAEkB,4BAClB,QAAA,QAEY,sBACZ,QAAA,QAEW,qBACX,QAAA,QAEa,uBACb,QAAA,QAEkB,4BAClB,QAAA,QAEc,wBACd,QAAA,QAEgB,0BAChB,QAAA,QAEa,uBACb,QAAA,QAEc,wBACd,QAAA,QAEmB,6BACnB,QAAA,QAEkB,4BAClB,QAAA,QAEgB,0BAChB,QAAA,QAEe,yBACf,QAAA,QAEgB,0BAChB,QAAA,QAEgB,0BAChB,QAAA,QAEgB,0BAChB,QAAA,QAEU,oBACA,oBACV,QAAA,QAEc,wBACd,QAAA,QAEqB,+BACrB,QAAA,QAEc,wBACd,QAAA,QAEe,yBACf,QAAA,QAEU,oBACV,QAAA,QAEU,oBACV,QAAA,QAEY,sBACZ,QAAA,QAEiB,2BACjB,QAAA,QAEW,qBACX,QAAA,QAEY,sBACZ,QAAA,QAEe,yBACf,QAAA,QAEiB,2BACjB,QAAA,QAEqB,+BACrB,QAAA,QAEqB,+BACrB,QAAA,QAEsB,gCACtB,QAAA,QAEmB,6BACnB,QAAA,QAEgB,0BAChB,QAAA,OAEkB,4BAClB,QAAA,QAEmB,6BACnB,QAAA,QAEgB,0BAChB,QAAA,QAEe,yBACf,QAAA,QAES,mBACT,QAAA,QAEW,qBACX,QAAA,QAEc,wBACd,QAAA,QAEe,yBACf,QAAA,QAEa,uBACb,QAAA,QAEc,wBACd,QAAA,QAEW,qBACX,QAAA,QAEe,yBACf,QAAA,QAES,mBACT,QAAA,QAEkB,4BAClB,QAAA,QAEoB,8BACpB,QAAA,QAEU,oBACV,QAAA,QAEe,yBACf,QAAA,QAEiB,2BACjB,QAAA,QAEkB,4BAClB,QAAA,QAEU,oBACV,QAAA,QAEW,qBACX,QAAA,QAEiB,2BACjB,QAAA,QAEiB,2BACjB,QAAA,QAEqB,+BACrB,QAAA,QAEkB,4BAClB,QAAA,QAEW,qBACX,QAAA,QAEe,yBACf,QAAA,QAEY,sBACZ,QAAA,QAEe,yBACf,QAAA,QAEU,oBACV,QAAA,QAEiB,2BACjB,QAAA,QAEiB,2BACjB,QAAA,QAES,mBACT,QAAA,QAEiB,2BACjB,QAAA,QAEe,yBACf,QAAA,QAEkB,4BAClB,QAAA,QAEkB,4BAClB,QAAA,QAEe,yBACf,QAAA,QAEiB,2BACjB,QAAA,QAEU,oBACV,QAAA"} \ No newline at end of file diff --git a/static/fork-awesome/fonts/forkawesome-webfont.eot b/static/fork-awesome/fonts/forkawesome-webfont.eot new file mode 100644 index 0000000..b96d208 Binary files /dev/null and b/static/fork-awesome/fonts/forkawesome-webfont.eot differ diff --git a/static/fork-awesome/fonts/forkawesome-webfont.svg b/static/fork-awesome/fonts/forkawesome-webfont.svg new file mode 100644 index 0000000..e997204 --- /dev/null +++ b/static/fork-awesome/fonts/forkawesome-webfont.svg @@ -0,0 +1,2849 @@ + + + + + +Created by FontForge 20180321 at Mon Feb 18 18:29:30 2019 + By Julien Deswaef +The Fork Awesome font is licensed under the SIL OFL 1.1 (http://scripts.sil.org/OFL). Fork Awesome is a fork based of off Font Awesome 4.7.0 by Dave Gandy. More info on licenses at https://forkawesome.github.io + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/static/fork-awesome/fonts/forkawesome-webfont.ttf b/static/fork-awesome/fonts/forkawesome-webfont.ttf new file mode 100644 index 0000000..6cf62ef Binary files /dev/null and b/static/fork-awesome/fonts/forkawesome-webfont.ttf differ diff --git a/static/fork-awesome/fonts/forkawesome-webfont.woff b/static/fork-awesome/fonts/forkawesome-webfont.woff new file mode 100644 index 0000000..477da44 Binary files /dev/null and b/static/fork-awesome/fonts/forkawesome-webfont.woff differ diff --git a/static/fork-awesome/fonts/forkawesome-webfont.woff2 b/static/fork-awesome/fonts/forkawesome-webfont.woff2 new file mode 100644 index 0000000..f3520b5 Binary files /dev/null and b/static/fork-awesome/fonts/forkawesome-webfont.woff2 differ diff --git a/static/header.png b/static/header.png new file mode 100644 index 0000000..ca6faf6 Binary files /dev/null and b/static/header.png differ diff --git a/static/logo_darkgreen.png b/static/logo_darkgreen.png new file mode 100644 index 0000000..37c28e3 Binary files /dev/null and b/static/logo_darkgreen.png differ diff --git a/static/logo_gray.png b/static/logo_gray.png new file mode 100644 index 0000000..c1bb56c Binary files /dev/null and b/static/logo_gray.png differ diff --git a/static/logo_lightgreen.png b/static/logo_lightgreen.png new file mode 100644 index 0000000..f9a5b11 Binary files /dev/null and b/static/logo_lightgreen.png differ diff --git a/static/schedule.json b/static/schedule.json new file mode 100644 index 0000000..c1d5d5d --- /dev/null +++ b/static/schedule.json @@ -0,0 +1 @@ +{"schedule": {"version": "0.3", "base_url": "https://cfp.winterkongress.ch/wk24/schedule/", "conference": {"acronym": "wk24", "title": "Winterkongress", "start": "2024-03-01", "end": "2024-03-02", "daysCount": 2, "timeslot_duration": "00:05", "time_zone_name": "Europe/Zurich", "rooms": [{"name": "Festsaal", "guid": null, "description": null, "capacity": 300}, {"name": "Bankettsaal", "guid": null, "description": null, "capacity": 150}, {"name": "Tanzsaal", "guid": null, "description": null, "capacity": 100}], "days": [{"index": 1, "date": "2024-03-01", "day_start": "2024-03-01T04:00:00+01:00", "day_end": "2024-03-02T03:59:00+01:00", "rooms": {"Festsaal": [{"id": 39991, "guid": "969901db-fa5a-5d7f-ba90-6267dfae75a3", "logo": "", "date": "2024-03-01T19:00:00+01:00", "start": "19:00", "duration": "00:15", "room": "Festsaal", "slug": "wk24-39991-erffnung-freitag", "url": "https://cfp.winterkongress.ch/wk24/talk/JTS8YA/", "title": "Er\u00f6ffnung Freitag", "subtitle": "", "track": "Andere", "type": "Moderation", "language": "de", "abstract": "Dies ist die Er\u00f6ffnung am Freitag.", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"id": 7877, "code": "PLBTRP", "public_name": "Team Winterkongress", "biography": null, "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39076, "guid": "7a22d039-e65e-5899-b73f-7621fc5cc373", "logo": "", "date": "2024-03-01T19:15:00+01:00", "start": "19:15", "duration": "00:45", "room": "Festsaal", "slug": "wk24-39076-predator-files-eskalierende-berwachung", "url": "https://cfp.winterkongress.ch/wk24/talk/FFRNAJ/", "title": "Predator Files - Eskalierende \u00dcberwachung", "subtitle": "", "track": "Netzwerke, Security, Hard- & Software", "type": "Vortrag", "language": "de", "abstract": "Im Oktober 2023 ver\u00f6ffentlichte die Wochenzeitung WOZ in Zusammenarbeit mit anderen Medien und unter Koordination des Recherchenetzwerkes EIC die \u00abPredator Files\u00bb. Sie beleuchten die fragw\u00fcrdigen Gesch\u00e4fte der Intellexa-Allianz, einem Zusammenschluss von \u00dcberwachungsunternehmen, die von Europa aus m\u00e4chtige Cyberwaffen in die ganze Welt exportierte. Ihr Aush\u00e4ngeschild: Predator, ein Trojaner, der Mobiltelefone infiltriert. Die Auswertung von tausenden Dokumenten zeichnet ein besorgniserregendes Bild. Und zahlreiche Spuren f\u00fchren in die Schweiz. H\u00f6chste Zeit, genauer hinzuschauen!", "description": "Unternehmen wie Intellexa k\u00f6nnen weitgehend ungest\u00f6rt ihre m\u00e4chtigen Technologien verkaufen. Europ\u00e4ische Beh\u00f6rden sind willige Komplizinnen. Sicher auch, weil sie die Technologien ebenfalls einsetzen. Und wie so oft dient die Schweiz als wichtige Drehscheibe f\u00fcr die Gesch\u00e4fte. Tal Dilian, ehemaliger israelischer Geheimdienstler und treibende Kraft bei Intellexa, besitzt ein Chalet im Wallis. Und wer den Besitzstrukturen folgt, landet in Lugano: Ein Schweizer Treuh\u00e4nder ist auf dem Papier wirtschaftlich Berechtigter der Unternhemensholding hinter Intellexa. Auch ein Tochterunternhemen hat eine Gesch\u00e4ftsadresse in Lugano. Dieses ist auch operativ t\u00e4tig, wie unsere Recherchen aufzeigen. Und die Beh\u00f6rden? Die k\u00f6nnen oder wollen nichts tun. Die VIM-Gesetzgebung \u00fcber die Vermittlung von G\u00fctern zur Internet- und Mobilfunk\u00fcberwachung, wird kaum aktiv angewendet. Letzteres kritisieren Expert:innen mit Blick auf den Fall Intellexa. Und die Sicherheitsdienste? Die schweigen, wie \u00fcblich. Wer die Skandale mit Spionage- und \u00dcberwachungstechnologie der letzten Jahre eim Blick hat weiss: Das ist ein Problem. Denn das Missbrauchspotential ist riesig - die Kontrollmechanismen derweil d\u00fcrftig. Europ\u00e4ische Politiker:innen sind alarmiert. Doch in der Schweiz bleibt es bisher ruhig um das Thema.\r\n\r\nAlle WOZ-Artikel zum Thema: https://www.woz.ch/t/predator-files\r\nAlle Artikel in verschiedenen Sprachen: https://eic.network/projects/predator-files.html", "recording_license": "", "do_not_record": false, "persons": [{"id": 36396, "code": "L7AKQM", "public_name": "Lorenz Naegeli", "biography": "Journalist beim WAV-Recherchekollektiv (www.wav.info). Hat zusammen mit der Wochenzeitung WOZ (www.woz.ch) und internationalen Medienpartnern an den \u00abPredator Files\u00bb mitgearbeitet. Ausgangspunkt f\u00fcr die Recherche waren vertrauliche Dokumente, die das franz\u00f6sische Portal \u00abMediapart\u00bb und das deutsche Nachrichtenmagazin \u00abDer Spiegel\u00bb erhielten. \r\n\r\nAlle WOZ-Artikel zum Thema: https://www.woz.ch/t/predator-files\r\n\r\nS\u00e4mtliche Artikel gibt es auf der Webseite vom European Investigative Collaborations, dem Recherchenetzwerk: https://eic.network/projects/predator-files.html", "answers": []}, {"id": 7827, "code": "HWRMPV", "public_name": "Jan Jirat", "biography": "Journalist (Ressort Politik) bei der WOZ - Die Wochenzeitung. Sicherheits-, Energiepolitik und Rechtsextremismus.", "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39684, "guid": "d8c28094-90fa-5f3c-acb1-b9f272901b27", "logo": "", "date": "2024-03-01T20:15:00+01:00", "start": "20:15", "duration": "00:30", "room": "Festsaal", "slug": "wk24-39684-ich-wei-was-du-letzten-sommer-bestellt-hast", "url": "https://cfp.winterkongress.ch/wk24/talk/XNAHNG/", "title": "Ich wei\u00df, was du letzten Sommer bestellt hast", "subtitle": "", "track": "Netzwerke, Security, Hard- & Software", "type": "Vortrag", "language": "de", "abstract": "Dieser Vortrag beschreibt, wie wir fehlerhafte Prozesse in der Paketverfolgung der meisten deutschen Paketzustelldienste entdeckt haben, wie diese auf unsere Erkenntnisse reagiert haben und warum dies sehr wahrscheinlich auch deine Privatsph\u00e4re betrifft.", "description": "In Zeiten des Online-Shoppings sind die Menschen besorgt, ob Online-Shops ihre Daten vern\u00fcnftig behandeln und sichern. Online-Shops k\u00f6nnen \u00fcber g\u00e4ngige Web-Schwachstellen wie SQL-Injections, XSS usw. angegriffen werden. Dadurch k\u00f6nnten Angreifer pers\u00f6nliche Informationen wie Name, Adresse und Bankdaten kopieren.\r\n\r\nWir haben jedoch eine noch einfachere - und bisher unbeachtete - M\u00f6glichkeit gefunden, an die pers\u00f6nlichen Daten der Kunden von Online-Shops zu gelangen - ohne irgendwelche Schwachstellen auszunutzen. Da fast alle online bestellten physischen Waren von Paketdiensten ausgeliefert werden, haben wir das Tracking der wichtigsten Akteure im deutschen Paketmarkt analysiert. \r\n\r\nDurch die Verwendung \u00f6ffentlich zug\u00e4nglicher Daten und trivialer Statistik konnten wir Empf\u00e4ngerinformationen (Name, Adresse) schnell und in gro\u00dfer Zahl ermitteln. Dabei war es bei einigen Diensten sogar m\u00f6glich, die Zustellung von Paketen zu beeinflussen. Gezielte Angriffe k\u00f6nnten dazu f\u00fchren, dass Adressen und Einkaufsverhalten von Politikern und anderen Personen des \u00f6ffentlichen Lebens aufgedeckt werden. Auch die Identifizierung von Kunden bestimmter Gesch\u00e4fte ist denkbar.\r\nDie Art und Weise, wie die Sendungsnummern generiert werden, erm\u00f6glicht es uns n\u00e4mlich, gezielt bestimmte Online-Shops anzugreifen.\r\n\r\nW\u00e4hrend unserer Recherche haben wir mehrere Paketdienste kontaktiert (Responsible Disclosure), was zu einigen Verbesserungen f\u00fchrte. Einige Disclosure-Prozesse hatten schnelle und effektive Ma\u00dfnahmen zur Folge und k\u00f6nnen als gute Beispiele dienen, w\u00e4hrend andere noch Raum f\u00fcr Optimierungen bieten. Wir werden auch dar\u00fcber reden, wie Disclosure-Prozesse besser ablaufen k\u00f6nnen, und werden ein paar unterhaltsame Ereignisse darstellen. \r\n\r\nWir kommen zu dem Schluss, dass Paketdienste eine - vielleicht - untersch\u00e4tzte Gefahr f\u00fcr die Privatsph\u00e4re darstellen. Anstatt zahllose Online-Shops anzugreifen, ist der Missbrauch fehlerhafter Prozesse bei den wenigen marktbeherrschenden Paketzustelldiensten, die von fast allen Shops genutzt werden, ein ziemlich effizienter Weg, um an Adressen und in einigen F\u00e4llen an die M\u00f6glichkeit zu gelangen, in den Zustellprozess einzugreifen. \r\n\r\nIn unserem Vortrag werden wir den statistischen Ansatz zum Brechen der Authentifizierung f\u00fcr die Paketverfolgung, die zugrundeliegenden Probleme, (negative und positive) Highlights aus den Disclosure-Prozessen und nat\u00fcrlich die Auswirkungen auf die Privatsph\u00e4re aufzeigen, die dies gehabt haben k\u00f6nnte und noch haben kann.", "recording_license": "", "do_not_record": false, "persons": [{"id": 37141, "code": "RZSXYB", "public_name": "Florian Bausch", "biography": "Florian Bausch hat Informatik und Digitale Forensik studiert. In seiner Masterarbeit analysierte er Spuren in Ceph-Clustern aus einer IT-forensischen Perspektive. Seit 2019 ist er als Incident Analyst, Penetration Tester und Security Consultant bei der ERNW Research GmbH t\u00e4tig.", "answers": []}, {"id": 37150, "code": "CDVEQE", "public_name": "Dennis Kniel", "biography": "Dennis Kniel hat nach seinem Informatikstudium mehrere Jahre als Berater im Bereich Penetrationstests und Incident Response gearbeitet. Nach dem Ausstieg aus der IT-Branche verfolgte er einige Themen privat weiter", "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39652, "guid": "51d182b3-4d38-5cb8-955d-3aeb85d19bdf", "logo": "", "date": "2024-03-01T21:00:00+01:00", "start": "21:00", "duration": "00:45", "room": "Festsaal", "slug": "wk24-39652-prompt-entzaubert-wie-ki-floskeln-uns-manipulieren", "url": "https://cfp.winterkongress.ch/wk24/talk/C8UNQV/", "title": "Prompt entzaubert: Wie KI-Floskeln uns manipulieren", "subtitle": "", "track": "Ethik, Wissenschaft, Kultur & Gesellschaft", "type": "Vortrag", "language": "de", "abstract": "Technologie oder Magie? - KI schl\u00e4gt uns alle in einen Bann. Dabei braucht das Thema dringend mehr n\u00fcchterne Reflexion statt marktschreierischer \u00dcbertreibungen. Wir entzaubern daher ein paar weit verbreitete Spr\u00fcche, die im Hype um k\u00fcnstliche Intelligenz die Runde machen.", "description": "\u00abDie KI wird mindestens die H\u00e4lfte aller Arbeitspl\u00e4tze vernichten\u00bb oder \"Dank KI werden wir viel effizienter\" rufen uns Schlagzeilen regelm\u00e4ssig zu. Das sind nur zwei von vielen Floskeln, die wir im aktuellen KI-Hype immer wieder h\u00f6ren. Diese Session greift solche mantra-artig wiederholten Aussagen auf und\r\n- zeigt wie die \"Magie\" dieser Spr\u00fcche funktioniert\r\n- macht die eigentliche Bedeutung hinter ihnen transparent\r\n- gibt Anregungen, wie wir den KI-Diskurs konstruktiver gestalten k\u00f6nnten\r\n\r\n\r\nDas Ziel der Session:\r\nDie Teilnehmer\\*innen \r\n* durchschauen rhetorischen Zaubertricks rund um \"k\u00fcnstliche Intelligenz\"\r\n* erkennen die Macht von Geschichten auch bei technologischen Themen\r\n* erhalten Anregungen, wie sie sich ihre eigenen Glaubenss\u00e4tze bewusst machen und ihre Haltung souver\u00e4ner reflektieren k\u00f6nnen", "recording_license": "", "do_not_record": false, "persons": [{"id": 7844, "code": "EXGCGQ", "public_name": "Chris B\u00fchler", "biography": "Chris B\u00fchler (https://chrisbuehler.ch) ist lizenzierter Cyberethiker mit einem Hackerherz. Beruflich ebenso wie privat denkt, diskutiert und ber\u00e4t er mit Vorliebe rund um den Themenkomplex \u00abGesellschaft im digitalen Wandel\u00bb.\r\n\r\nAls Lehrbeauftragter f\u00fcr Ethik an verschiedenen Hochschulen ebenso wie als selbst\u00e4ndiger Coach und Consultant f\u00f6rdert er Future Skills wie kritisches Denken und Kommunikationskompetenzen.", "answers": []}], "links": [], "attachments": [], "answers": []}], "Bankettsaal": [{"id": 39556, "guid": "03081b59-a579-5403-b44d-146aa22ed0a2", "logo": "", "date": "2024-03-01T19:15:00+01:00", "start": "19:15", "duration": "00:45", "room": "Bankettsaal", "slug": "wk24-39556-regulierung-automatisierter-entscheidungssysteme-usa-eu-china-schweiz", "url": "https://cfp.winterkongress.ch/wk24/talk/KKDUBY/", "title": "Regulierung automatisierter Entscheidungssysteme: USA, EU, China, Schweiz", "subtitle": "", "track": "Recht & Politik", "type": "Vortrag", "language": "de", "abstract": "Die bei der k\u00fcnstlichen Intelligenz f\u00fchrenden L\u00e4nder/Bl\u00f6cke (USA, China, EU) haben alle bereits Regulierungsentw\u00fcrfe f\u00fcr automatisierte Entscheidungssysteme (ADMS) vorgelegt. Wir geben einen aktualisierten \u00dcberblick \u00fcber diese Vorhaben, ihre Gemeinsamkeiten und Unterschiede sowie ihre Schwachstellen aus unserer Sicht. Ausserdem diskutieren wir den gegenw\u00e4rtigen Stand der Bestrebungen in der Schweiz.\r\n\r\nIm zweiten Teil ziehen wir einen Vergleich zum \u00fcberarbeiteten Positionspapier der Digitalen Gesellschaft, welches einen Regulierungsrahmen f\u00fcr ADMS f\u00fcr die Schweiz vorschl\u00e4gt.", "description": "Dies ist eine Gemeinschaftsarbeit der Fachgruppe \"Automatisierte Entscheidungssysteme\" der Digitalen Gesellschaft.", "recording_license": "", "do_not_record": false, "persons": [{"id": 7836, "code": "G8YBXF", "public_name": "David Sommer", "biography": "David Sommer interessiert sich f\u00fcr gesellschaftliche Entwicklungen, Privatsph\u00e4re und maschinelles Lernen. In letzter Zeit hat er sich auf ADM-Systeme und ihre Auswirkungen in der Praxis konzentriert. Daf\u00fcr ist er f\u00fcr die Digitale Gesellschaft zivilgesellschaftlicher Beobachter bei den Verhandlungen des Europarats zum internationalen Rahmenabkommen zur Regulierung von KI.", "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39424, "guid": "c1c192f2-51d5-5967-885e-5f77d6e4cb1b", "logo": "", "date": "2024-03-01T20:15:00+01:00", "start": "20:15", "duration": "00:30", "room": "Bankettsaal", "slug": "wk24-39424-revision-nachrichtendienstgesetz-vom-umgang-mit-grundrechtsverletzungen", "url": "https://cfp.winterkongress.ch/wk24/talk/RZHR3N/", "title": "Revision Nachrichtendienstgesetz - vom Umgang mit Grundrechtsverletzungen", "subtitle": "", "track": "Recht & Politik", "type": "Vortrag kurz", "language": "de", "abstract": "Der Bundesrat will mit der Revision des Nachrichtendienstgesetzes neue, viel zu weitgehende \u00dcberwachungsbefugnisse erm\u00f6glichen. Eine Koalition aus Menschenrechtsorganisationen der NGO-Plattform Menschenrechte Schweiz wehrt sich dagegen: Welche Grund- und Menschenrechte sind auf welche Weise betroffen? Inwiefern bildet dies eine Konstante in der nachrichtendienstlichen Praxis? Wie gehen wir als Zivilgesellschaft damit um?", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"id": 36752, "code": "VTQDN7", "public_name": "Tarek Naguib", "biography": "Koordinator NGO-Plattform Menschenrechte Schweiz\r\n\r\nTarek Naguib ist Jurist und hat bis dahin auf der Schnittstelle von Wissenschaft und Aktivismus im Bereich Diskriminierungs- und Menschenrechtsschutz gearbeitet. W\u00e4hrend 11 Jahren war er am Zentrum f\u00fcr Sozialrecht der Z\u00fcrcher Hochschule f\u00fcr Angewandte Wissenschaften ZHAW t\u00e4tig. Zudem hat er das Institut Neue Schweiz INES, die Allianz gegen Racial Profiling und die Aktion Vierviertel mitbegr\u00fcndet. In seiner neuen Funktion als Koordinator der NGO-Plattform arbeitet er seit August mit einem Pensum von 60%.", "answers": []}, {"id": 37261, "code": "7HZNT9", "public_name": "Florian Schweri", "biography": "Florian Schweri ist Jurist. In seiner Masterarbeit besch\u00e4ftigte er sich mit dem rechtlichen Rahmen der geheimen \u00dcberwachungen durch den Nachrichtendienst des Bundes und analysierte die Vereinbarkeit des Schweizer Rechts mit der Europ\u00e4ischen Menschenrechtskonvention.", "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39663, "guid": "28fc95c2-feab-5b47-bee0-9a30aaade1c8", "logo": "", "date": "2024-03-01T21:00:00+01:00", "start": "21:00", "duration": "00:45", "room": "Bankettsaal", "slug": "wk24-39663-wundersame-geldvermehrung-bilder-abmahnungen-aus-deutschland", "url": "https://cfp.winterkongress.ch/wk24/talk/SABVFG/", "title": "Wundersame Geldvermehrung: Bilder-Abmahnungen aus Deutschland", "subtitle": "", "track": "Recht & Politik", "type": "Vortrag", "language": "de", "abstract": "Bilder-Abmahnungen aus Deutschlang gelangen in grosser Zahl in die Schweiz: Wer ein Bild auf seiner Website oder seinem Social-Media-Profil ver\u00f6ffentlicht hat, erh\u00e4lt pl\u00f6tzlich Anwaltspost aus Deutschland: Abmahnanw\u00e4lte fordern aggressiv und mit kurzen Fristen, dass viel Geld bezahlt und eine Unterlassungserk\u00e4rung abgegeben wird.\r\n\r\nBilder, die nur einen geringen oder gar keinen wirtschaftlichen Wert haben, sollen pl\u00f6tzlich 1'000 Euro und mehr kosten: Wie funktioniert diese wundersame Geldvermehrung? Wieso soll pl\u00f6tzlich deutsches Recht gelten? Wie sollen schweizerische Betroffene reagieren?", "description": "Im Vortrag wird mit Beispielen aus der Praxis erkl\u00e4rt, wie die deutsche Abmahnindustrie funktioniert und wieso die Schweiz ein attraktives Ziel f\u00fcr deutsche Abmahnanw\u00e4lte ist. Erkl\u00e4rt werden unter anderem die finanziellen und rechtlichen Anreize f\u00fcr deutsche Abmahner und ihre Rechtsanw\u00e4lte.\r\n\r\nDas Publikum lernt, wie Abmahnungen von Anfang an vermieden werden k\u00f6nnen. F\u00fcr den Fall, dass eine Abmahnung eintrifft, erf\u00e4hrt das Publikum, wie man richtig reagiert. Gleichzeitig wird dem Publikum vermittelt, wie das Urheberrecht bei Bildern funktioniert, auch grenz\u00fcberschreitend.", "recording_license": "", "do_not_record": false, "persons": [{"id": 15358, "code": "DEJSWW", "public_name": "Martin Steiger", "biography": "Martin Steiger ist Anwalt und Unternehmer f\u00fcr Recht im digitalen Raum in Z\u00fcrich. Martin Steiger ist Sprecher der Digitalen Gesellschaft in der Schweiz sowie langj\u00e4hrig in der schweizerischen Netzpolitik engagiert.", "answers": []}], "links": [], "attachments": [], "answers": []}], "Tanzsaal": [{"id": 39756, "guid": "2ab84783-c213-5837-a084-e0e9c8eae66c", "logo": "", "date": "2024-03-01T19:15:00+01:00", "start": "19:15", "duration": "00:45", "room": "Tanzsaal", "slug": "wk24-39756-update-statt-stillstand-wie-wir-die-schweiz-aktualisieren-fr-mehr-demokratie", "url": "https://cfp.winterkongress.ch/wk24/talk/YUUSDL/", "title": "Update statt Stillstand: Wie wir die Schweiz aktualisieren f\u00fcr mehr Demokratie", "subtitle": "", "track": "Recht & Politik", "type": "Vortrag", "language": "de", "abstract": "Unsere Welt ist im Umbruch begriffen: Der Klimawandel, der demografische Wandel und die Digitalisierung fordern uns heraus. H\u00f6chste Zeit f\u00fcr ein Update des politischen Systems! Mit einer Volksinitiative f\u00fcr eine Totalrevision (Art. 138 BV) k\u00f6nnen wir den Prozess f\u00fcr eine zeitgem\u00e4sse Verfassung anstossen. Eine Verfassung, welche die direkte Demokratie st\u00e4rkt und die Macht einflussreicher Interessengruppen begrenzt. Mehr \u00fcber das vielleicht gr\u00f6sste Demokratieprojekt der Schweiz und die wichtigsten Etappen erfahrt ihr in diesem Inputreferat.", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"id": 6884, "code": "DXB9LF", "public_name": "Daniel Graf", "biography": "Daniel hat die Stiftung f\u00fcr direkte Demokratie und den Verein Public Beta aufgebaut. Er hat mehrere Initiativen und Referenden mitinitiiert. Dazu geh\u00f6ren die Gletscherinitiative, das Referendum zur e-ID und die Inklusionsinitiative. Sein Hauptinteresse gilt der Digitalisierung der Demokratie. Dazu hat Daniel die Online-Plattform WeCollect gegr\u00fcndet, B\u00fccher geschrieben und plant aktuell eine Volksinitiative f\u00fcr eine Totalrevision der Bundesverfassung.", "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39403, "guid": "360c6ef7-7df8-5e95-9fa7-7bc2c83f9133", "logo": "", "date": "2024-03-01T20:15:00+01:00", "start": "20:15", "duration": "00:30", "room": "Tanzsaal", "slug": "wk24-39403-elektronisches-notariat-in-nten-ein-praxisbericht", "url": "https://cfp.winterkongress.ch/wk24/talk/RBNNV9/", "title": "Elektronisches Notariat in N\u00f6ten? Ein Praxisbericht", "subtitle": "", "track": "Recht & Politik", "type": "Vortrag kurz", "language": "de", "abstract": "Rund zehn Jahre ist es her, seit die Verordnung vom 23. September 2011 \u00fcber die Erstellung elektronischer \u00f6ffentlicher Urkunden und elektronischer Beglaubigungen (E\u00d6BV; SR 211.435.1) am 1. Januar 2012 in Kraft getreten ist. Wie geht die Praxis (u.a. Notariate, Grundbuch\u00e4mter, Handelsregister\u00e4mter) heute mit elektronischen Urkunden und dem elekronischen Gesch\u00e4ftsverkehr im Notariatsbereich um und was ist vom neuen Bundesgesetz \u00fcber die Digitalisierung im Notariat (DNG) zu erwarten? Ein Praxisbericht.", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"id": 24257, "code": "EBWLDE", "public_name": "Claudia Schreiber", "biography": "Claudia Schreiber (Mitglied des Vorstands Digiges) ist seit 2009 als Rechtsanw\u00e4ltin in Bern t\u00e4tig mit den Schwerpunkten Strafrecht und Agrarrecht. Sie publiziert und unterrichtet auch zum Thema elektronische Anwalts- und Notariatskanzlei. Im Archiv f\u00fcr Agrargeschichte leitet Claudia Schreiber die Bereiche Archivierung, Records Management und Archivrecht. Weitere Engagements: Verein entscheidsuche.ch.", "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39689, "guid": "9cf620de-8d95-5922-90a0-e4fc19b54472", "logo": "", "date": "2024-03-01T21:00:00+01:00", "start": "21:00", "duration": "00:45", "room": "Tanzsaal", "slug": "wk24-39689-datenethik-in-der-praxis-von-anonymisierung-zu-operativer-datengovernance", "url": "https://cfp.winterkongress.ch/wk24/talk/9KZAPR/", "title": "Datenethik in der Praxis: Von Anonymisierung zu operativer Datengovernance", "subtitle": "", "track": "Ethik, Wissenschaft, Kultur & Gesellschaft", "type": "Vortrag", "language": "de", "abstract": "In unserem Vortrag erl\u00e4utern wir, wie die Datengenossenschaft Posmo mit einem starken Datengovernanceprozess die ethische Nutzung der ihr angetrauten Daten gew\u00e4hrleistet. \r\n\r\nUm die Privatsph\u00e4re der Datensubjekte erfolgreich zu sch\u00fctzen setzen wir sowohl auf technische Anonymisierungsverfahren als auch auf eine ethische Bewertung der jeweiligen Datennutzungen anhand vordefinierter Kriterien.", "description": "Als Datengenossenschaft f\u00fcr Mobilit\u00e4t ist Posmos zentrale Mission, personenbezogene Mobilit\u00e4tsdaten verantwortungsvoll zu verwalten. Interessierten Abnehmern stellen wir diese Daten zur L\u00f6sung von gesellschaftlichen Herausforderungen im Bereich nachhaltige Mobilit\u00e4t und Stadtplanung unter Einhaltung strikter ethischer Richtlinien zur Verf\u00fcgung. Die Privatsph\u00e4re der Datensubjekte zu sch\u00fctzen steht f\u00fcr uns an erster Stelle.\r\nEine zentrale Rolle spielen dabei technische Anonymisierungsverfahren. Bei individuellen Mobilit\u00e4tsdaten ist eine vollst\u00e4ndige Anonymisierung jedoch nur schwer erreichbar, zumindest wenn die entstehenden Datens\u00e4tze einen hohen Informationsgrad behalten sollen. Um den bekannten Trade-off zwischen Anonymisierung und Nutzbarkeit von Daten teilweise zu l\u00f6sen, setzen wir auf einen starken Datengovernanceprozess, umgesetzt durch den operativ eingebundenen Ethikrat.\r\n\r\nIn unserem Vortrag erl\u00e4utern wir, wie Posmo durch technische Anonymisierungsverfahren und Datengovernance die ethische Nutzung der uns angetrauten Daten gew\u00e4hrleistet.", "recording_license": "", "do_not_record": false, "persons": [{"id": 27965, "code": "SBURQ8", "public_name": "Lea Strohm", "biography": "Nach ihrem Studium in Genf, S\u00e3o Paulo und Utrecht arbeitete Lea bei ethix, einem Thinktank f\u00fcr digitale Ethik. Seit der Gr\u00fcndung im Jahr 2020, ist sie Verwaltungsmitglied von Posmo, einer Datengenossenschaft f\u00fcr Mobilit\u00e4t. Posmo entwickelt ein innovatives Modell f\u00fcr die Verwaltung und den Vertrieb von Mobilit\u00e4tsdaten. Hauptberuflich ist sie als Lead Data and AI Ethics bei Thomson Reuters im Bereich Governance und Ethik der K\u00fcnstlichen Intelligenz t\u00e4tig.", "answers": []}, {"id": 7806, "code": "NX8JVD", "public_name": "Nicolas Zahn", "biography": "Als Vorsitzender des Ethikrates bei POSMO k\u00fcmmere ich mich um die Wahrung unserer Standards und erarbeite zusammen mit den anderen Mitgliedern des Ethikrates unsere Grundlagendokumente", "answers": []}], "links": [], "attachments": [], "answers": []}]}}, {"index": 2, "date": "2024-03-02", "day_start": "2024-03-02T04:00:00+01:00", "day_end": "2024-03-03T03:59:00+01:00", "rooms": {"Festsaal": [{"id": 39992, "guid": "f9b51a29-d19d-573c-84c1-69a2f280c98c", "logo": "", "date": "2024-03-02T11:00:00+01:00", "start": "11:00", "duration": "00:15", "room": "Festsaal", "slug": "wk24-39992-erffnung-samstag", "url": "https://cfp.winterkongress.ch/wk24/talk/UZQJZC/", "title": "Er\u00f6ffnung Samstag", "subtitle": "", "track": "Andere", "type": "Moderation", "language": "de", "abstract": "Dies ist die Er\u00f6ffnung am Samstag.", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"id": 7877, "code": "PLBTRP", "public_name": "Team Winterkongress", "biography": null, "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39993, "guid": "06fcf7f9-46c2-585a-af21-cc30bd6023a6", "logo": "", "date": "2024-03-02T11:15:00+01:00", "start": "11:15", "duration": "00:30", "room": "Festsaal", "slug": "wk24-39993-knstliche-intelligenz-von-der-theorie-zur-praxis", "url": "https://cfp.winterkongress.ch/wk24/talk/LVKEGK/", "title": "K\u00fcnstliche Intelligenz: Von der Theorie zur Praxis", "subtitle": "", "track": "Andere", "type": "Keynote", "language": "de", "abstract": "Seit der allgemeinen Verf\u00fcgbarkeit von ChatGPT ist KI in aller Munde. Doch was ist \u00abK\u00fcnstliche Intelligenz\u00bb \u00fcberhaupt? Welche\r\nVerwendungszwecke gibt es? Was muss beachtet werden bei der Erstellung und Verwendung solcher Systeme? Und was sind die Risiken?", "description": "Ein beachtlicher Teil der Vortr\u00e4ge am Winterkongress besch\u00e4ftigt sich mit KI. Die Keynote f\u00fchrt uns in das Thema ein und erkl\u00e4rt, was wir haben m\u00f6chten: Eine nutzbringende Anwendung der Technik. KI als Tool, welches den Menschen unterst\u00fctzt, anstatt ihn zu ersetzen (Augmented Intelligence statt Artificial Intelligence).", "recording_license": "", "do_not_record": false, "persons": [{"id": 37961, "code": "RTQTXM", "public_name": "Mascha Kurpicz-Briki", "biography": "Dr. Mascha Kurpicz-Briki promovierte im Bereich energieeffizientes Cloud Computing an der Universit\u00e4t Neuch\u00e2tel. Nach ihrer Promotion arbeitete sie einige Jahre in der Privatwirtschaft in den Bereichen Open-Source-Engineering, Cloud Computing und Analytics. Heute ist sie Professorin f\u00fcr Data Engineering und Co-Leiterin der Forschungsgruppe Applied Machine Intelligence an der Berner Fachhochschule in Biel. Sie erforscht, wie digitale Methoden und insbesondere die Verarbeitung nat\u00fcrlicher Sprache auf soziale und gesellschaftliche Herausforderungen angewendet werden k\u00f6nnen.", "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39561, "guid": "c7836627-6a64-5acb-8156-e3aa93761ee7", "logo": "", "date": "2024-03-02T12:00:00+01:00", "start": "12:00", "duration": "00:45", "room": "Festsaal", "slug": "wk24-39561-automatische-gesichtserkennung-auf-dem-weg-zum-nationalen-verbot", "url": "https://cfp.winterkongress.ch/wk24/talk/NPREEJ/", "title": "Automatische Gesichtserkennung: Auf dem Weg zum nationalen Verbot", "subtitle": "", "track": "Recht & Politik", "type": "Podiumsgespr\u00e4ch", "language": "de", "abstract": "Die Kampagne \u00abGesichtserkennung stoppen\u00bb, die am Winterkongress 2021 lanciert wurde, f\u00fchrte in mehreren St\u00e4dten und Kantonen zu Verboten biometrischer Massen\u00fcberwachung. Auch auf europ\u00e4ischer Ebene wird mit dem \u00abAI Act\u00bb ein solches Verbot verhandelt. Jetzt wollen wir ein nationales Verbot auf den Weg bringen! Wie k\u00f6nnen wir den n\u00f6tigen Druck auf das neue Parlament erzeugen? Welche H\u00fcrden sind auf dem Weg zu bef\u00fcrchten? Eine Podiumsdiskussion mit Vertreter*innen der lokalen und nationalen Politik sowie von NGO. Organisiert von AlgorithmWatch CH, Amnesty International und Digitale Gesellschaft", "description": "Die Kampagne \u00abGesichtserkennung stoppen\u00bb f\u00fchrte zu Erfolgen, die uns f\u00fcr den n\u00e4chsten Schritt ermutigen: Verbote in mehreren St\u00e4dten und Kantonen sind bereits beschlossen oder in Diskussion. Und laut smartvote-Umfrag vor den eidgen\u00f6ssischen Wahlen, ist die klare Mehrheit der Kandidat*innen f\u00fcr ein Verbot. Nun ist es Zeit f\u00fcr ein nationales Verbot! Diskutiert mit uns \u00fcber die n\u00f6tigen Schritte und die richtige Strategie.\r\nPodiumsdiskussion mit Vertreter*innen der lokalen und nationalen Politik sowie von NGO, anschliessend Q&A mit dem Publikum.\r\nOrganisiert von AlgorithmWatch CH, Amnesty International und Digitale Gesellschaft", "recording_license": "", "do_not_record": false, "persons": [{"id": 7802, "code": "AL9KDP", "public_name": "Patrick Walder", "biography": "Kampagnenkoordinator, Amnesty International Schweiz\r\nKoalition \"Gesichtserkennung stoppen\"", "answers": []}, {"id": 36990, "code": "FHSFPN", "public_name": "Estelle Pannatier", "biography": "Estelle Pannatier ist Policy & Advocacy Managerin bei AlgorithmWatch CH. Sie hat einen Master in politischer Anthropologie und in Kommunikations- und Medienwissenschaften. Vor ihrer T\u00e4tigkeit bei AlgorithmWatch CH hat Estelle zu \u00f6ffentlicher Politik im Kontext der Digitalisierung des Bildungswesens in der Schweiz mitgewirkt.", "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39692, "guid": "1a55011a-ac94-5a90-851c-b74350342235", "logo": "", "date": "2024-03-02T13:00:00+01:00", "start": "13:00", "duration": "01:00", "room": "Festsaal", "slug": "wk24-39692-den-planet-einfach-brennen-lassen-", "url": "https://cfp.winterkongress.ch/wk24/talk/YRNCUL/", "title": "Den Planet einfach brennen lassen?", "subtitle": "", "track": "Ethik, Wissenschaft, Kultur & Gesellschaft", "type": "Vortrag", "language": "de", "abstract": "Wie wir die gamifizierten Ablenkungen absch\u00fctteln und nachhaltige Bewegungen aufbauen\r\nW\u00e4hrend die letzten Ressourcen des Planeten leer geschl\u00fcrft werden, befinden sich viele zwischen Wut, Panik & Verzweiflung. Ein Dilemma ist, dass wir in einer hyper-vernetzten Welt leben in der nicht nur Vorteile, sondern auch Nachteile vernetzt sind. W\u00e4hrend manche Probleme durch Technologien l\u00f6sbar sind, sind technologische L\u00f6sungen aber nicht universell einsetzbar. Manches, wie etwa Elektro-Autos, sind nur L\u00f6sung f\u00fcr Industrie, nicht f\u00fcr den Planeten oder es sind digitale Beruhigungsnuggis f\u00fcr Individuen", "description": "Dieser Vortrag begegnet der Klimakrise, indem der Zustand des Planeten in Zusammenhang mit der Wirtschaftsordnung, den politischen Systemen und den daraus resultierenden sozialen Problemen stellt. Es wird die Frage nach Macht und Verantwortlichkeiten gestellt und inwiefern Philosophie und Ethik mit L\u00f6sungen verbunden sind. F\u00fcr eine m\u00f6gliche Antwort wird aus den Erfahrungen internationaler sozialer Bewegungen gesch\u00f6pft, um einen Blick auf eine m\u00f6gliche und nachhaltige Zukunft zu werfen.\r\n\r\nDie Welt, in der wir leben ist sehr vernetzt auf der wirtschaftlichen Ebene, aber keinesfalls so gut auf der gesellschaftlichen. Verbindungen laufen vor allem \u00fcber Kabel und Containerschifffe, nicht \u00fcber die Interaktionen zwischen gesellschaftlichen Gruppen. Und ungeachtet allen Redens \u00fcber Demokratie und Mitbestimmung flie\u00dfen Macht und Geld immer noch in die H\u00e4nde sehr weniger. Und diese wenigen l\u00f6sen unsere Probleme nicht.\r\n\r\nDie Herausforderungen, vor denen wir stehen, sind gigantisch. Aber das muss nicht gleichbedeutend mit schrecklich sein \u2013 es bedeutet erst einmal, dass es nicht langweilig wird. Und es bedeutet auf gar keinen Fall, dass wir nun unseren Humor verlieren sollten! Dieser Vortrag zielt darauf, Wege aus furchtbar erscheinenden Situationen zu zeigen und euch zugleich zum Lachen zu bringen.\r\n\r\nUm eine gemeinsame Basis f\u00fcr \u00dcberlegungen zu haben, startet der Vortrag mit einer kurzen Analyse der Urspr\u00fcnge unser jetzigen Situation, unter der Einbeziehung ihrer theoretischen und philosophischen Grundlagen. Dieses gemeinsame Wissen wird dazu genutzt, um im zweiten Schritt vier kurze Matches zu betrachten: Theorien sozialer Bewegungen treten gegen Aufstandsbek\u00e4mpfungstheorien an, Ethik gegen die Kybernetik, Ideen der Entscheidungsfreiheit gegen Gamifizierung und Meinungsfreiheit gegen \u00dcberwachung.\r\n\r\nDie Ergebnisse werden im letzten Teil dazu genutzt, um sie mit Erfahrungen aus sozialen Bewegungen aus unterschiedlichen Teilen der Welt zu verbinden. In dem den F\u00e4den der Macht gefolgt wird, wird die Frage nach Verantwortung gestellt, um L\u00f6sungswege herauszuarbeiten.\r\n\r\nDenn weder Panik noch Verzweiflung werden den Planeten retten. Aber mit einer guten Bewegung k\u00f6nnen das.", "recording_license": "", "do_not_record": false, "persons": [{"id": 37143, "code": "83WEGP", "public_name": "Katika", "biography": "Katika K\u00fchnreich ist Politikwissenschaftlerin und Sinologin. Zu ihren Forschungsschwerpunkten z\u00e4hlen die gesellschaftlichen Auswirkungen der Digitalisierung. Dadurch erregten die Planung und Einf\u00fchrung von Digitalen Gesellschaftlichen Bewertungssystemen (Social Credit Systemen) in China ihre Aufmerksamkeit. Sie analysiert Macht, digitalisierte Lenkungs- und Beeinflussungssysteme mit dem Fokus auf China und dem sogenannten Westen.", "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39527, "guid": "15af17d2-bbc5-5d41-91ed-b8afda6939e1", "logo": "", "date": "2024-03-02T14:45:00+01:00", "start": "14:45", "duration": "00:30", "room": "Festsaal", "slug": "wk24-39527-schweizer-cryptowars-wie-ndb-dienst-pf-fedpol-gegen-verschlsselung-kmpfen", "url": "https://cfp.winterkongress.ch/wk24/talk/LW8DQZ/", "title": "Schweizer Cryptowars- wie NDB, Dienst \u00dcPF & Fedpol gegen Verschl\u00fcsselung k\u00e4mpfen", "subtitle": "", "track": "Recht & Politik", "type": "Vortrag kurz", "language": "de", "abstract": "Seit den Snowden-Enth\u00fcllungen haben Tech-Konzerne die digitale Kommunikation verschl\u00fcsselt, zum Missfallen der Schweizer \u00dcberwachungsbeh\u00f6rden. Ich zeige basierend auf meinen Recherchen auf, wie der Dienst \u00dcPF, der Nachrichtendienst und das Bundesamt f\u00fcr Polizei/Fedpol versuchen gegen diese technischen Errungenschaften des Datenschutzes anzuk\u00e4mpfen. Durch den Einkauf von neuem \u00dcberwachungssystemen (FLICC), den Kampf gegen die 5G-Verschl\u00fcsselung, der Ausweitung gesetzeswidrigen Massen-Scanning (Kabelaufkl\u00e4rung) und dem vermehrten Einsatz von Staatstrojanern wie Pegasus.", "description": "Zus\u00e4tzlich m\u00f6chte ich dabei die Herausforderungen bei einer solchen Recherche aufzeigen: wie kann ich \u00fcber \u00dcberwachung recherchieren ohne meine Quellen zu kompromittieren und im Wissen selber \u00fcberwacht zu werden?\r\n\r\nDieser Vortrag wird nicht gestreamt und aufgezeichnet.", "recording_license": "", "do_not_record": true, "persons": [{"id": 7532, "code": "W9ULH8", "public_name": "Adrienne Fichter", "biography": "Tech-Reporterin f\u00fcr Republik.ch seit Tag 1.\r\nHerausgeberin des Blogs \"Das Netz ist politisch\" DNIP.ch\r\nCo-Pr\u00e4sidentin Verein Swiss Tech Journalists", "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39517, "guid": "dccdb869-be72-5e8a-beac-1c651ded1586", "logo": "", "date": "2024-03-02T15:30:00+01:00", "start": "15:30", "duration": "00:45", "room": "Festsaal", "slug": "wk24-39517-datenschutz-konzept-und-initiative", "url": "https://cfp.winterkongress.ch/wk24/talk/KAEG78/", "title": "Datenschutz-Konzept und -Initiative", "subtitle": "", "track": "Recht & Politik", "type": "Vortrag", "language": "de", "abstract": "Die Digitale Gesellschaft hat ein neues Datenschutz-Konzept erarbeitet. Das Konzept adressiert die M\u00e4ngel im geltenden Datenschutzrecht, indem es sich auf die vielseitigen Folgen der Datennutzung konzentriert. Das Konzept geht als eigentliches Datengesetz jedoch \u00fcber den Datenschutz hinaus. Es schafft auch einen Rechtsrahmen f\u00fcr den Umgang mit \u00abK\u00fcnstlicher Intelligenz\u00bb und bietet eine L\u00f6sung f\u00fcr die Sekund\u00e4rnutzung von Daten. Dabei nimmt das neue Konzept die Datenbearbeiter:innen konkret in die Pflicht und erm\u00f6glicht eine vertrauensvolle Datennutzung.", "description": "Ausgehend von der Kritik am zu wenig spezifischen Zweck des geltenden Datenschutzrechts und seinem unklaren Schutzbereich gibt das Datenschutz-Konzept sieben Schutzziele vor:\r\n\r\n* Schutz vor Manipulation\r\n* Schutz vor Diskriminierung\r\n* Schutz vor \u00dcberwachung und Recht auf Anonymit\u00e4t\r\n* Schutz vor Beeintr\u00e4chtigung der Gesundheit sowie der Lebens- und Entwicklungschancen\r\n* Recht auf Transparenz und Pflicht zur Sorgfalt\r\n* Recht auf Vergessenwerden\r\n* Schutz der offenen Gesellschaft und freien Demokratie\r\n\r\nBasierend auf diesen Schutzzielen ergibt sich ein Konzept f\u00fcr einen wirksamen und zielgerichteten Datenschutz, der Vertrauen schafft und Innovation f\u00f6rdert. Das Konzept stellt die Einhaltung und Durchsetzung der Schutzziele ins Zentrum und l\u00f6st sich vom Prinzip der Einwilligung zur Datenbearbeitung und der Zweckbindung. Geregelt wird der Umgang mit Daten und nicht bloss mit Personendaten an sich.\r\n\r\nDas Konzept beinhaltet:\r\n\r\n* Grunds\u00e4tze zur Datenbearbeitung, wonach Private und staatliche Datenbearbeitungen die Schutzziele f\u00fcr die Individuen und die Gesellschaft wahren m\u00fcssen.\r\n* Ein absolutes Verbot f\u00fcr bestimmte Datenbearbeitungen, welche ein zu grosses Risiko f\u00fcr Individuen oder die Gesellschaft bergen und die Schutzziele nicht gew\u00e4hrleisten k\u00f6nnen (wie biometrische Massen\u00fcberwachung und Social Scoring).\r\n* Eine substantielle Mitbestimmung der Betroffenen, wonach insbesondere eine Datenbearbeitung f\u00fcr diese erkennbar und eine M\u00f6glichkeit zu einem einfach wahrzunehmenden Widerspruchsrecht gegeben sein m\u00fcssen.\r\n* Bestimmungen zur Durchsetzung des Konzepts wie wirksame Sanktionen, wenn die Schutzziele nicht eingehalten werden.\r\n\r\nUnter Einhaltung der Schutzziele k\u00f6nnen Daten und insbesondere auch Personendaten unbeschr\u00e4nkt bearbeitet werden. Dabei werden die Datenbearbeiter:innen jedoch verst\u00e4rkt in die Pflicht genommen, die Interessen der betroffenen Personen und der Gesellschaft zu wahren. Das Vertrauen in die Datennutzung und die Datenbearbeitung wird dadurch gest\u00e4rkt.\r\n\r\nParallel zum Datenschutz-Konzept arbeitet die Digitale Gesellschaft an einer Datenschutz-Initiative. Die geplante Volksinitiative hat das Ziel, das Konzept in der Bundesverfassung zu verankern.\r\n\r\nIn unserem Vortrag werden wir das Datenschutz-Konzept vorstellen und den Stand der Datenschutz-Initiative erl\u00e4utern.", "recording_license": "", "do_not_record": false, "persons": [{"id": 24615, "code": "8ZF7RG", "public_name": "Anna Walter", "biography": "Anna Walter arbeitet im Legal Counsel der Digitalen Gesellschaft und studiert Recht an der UZH im Master.", "answers": []}, {"id": 7780, "code": "NAHT7M", "public_name": "Viktor Gy\u00f6rffy", "biography": "Viktor Gy\u00f6rffy ist seit 1999 als Anwalt in Z\u00fcrich t\u00e4tig mit Schwerpunkten in den Bereichen Grundrechte, Haftpflicht- und Sozialversicherungsrecht sowie Strafrecht. Er ist Vorstandsmitglied der Digitalen Gesellschaft und Pr\u00e4sident des Vereins grundrechte.ch.", "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39641, "guid": "ade08643-d6dc-5266-b50a-29b958bc6446", "logo": "", "date": "2024-03-02T16:30:00+01:00", "start": "16:30", "duration": "00:30", "room": "Festsaal", "slug": "wk24-39641-das-geld-die-politik-mehr-finanztransparenz-in-der-schweizer-politik", "url": "https://cfp.winterkongress.ch/wk24/talk/VVM9BR/", "title": "Das Geld + die Politik: Mehr Finanztransparenz in der Schweizer Politik", "subtitle": "", "track": "Ethik, Wissenschaft, Kultur & Gesellschaft", "type": "Vortrag kurz", "language": "de", "abstract": "In der Politik ist Geld oft matchentscheidend, und doch selten Thema. Bis jetzt. Neu m\u00fcssen Kampagnen ab 50K und Spenden ab 15K offengelegt werden. Doch Daten allein machen keine Transparenz. Daher haben wir sie auf aufbereitet. Auf moneyinpolitics.ch k\u00f6nnen alle, wer mit wie viel (und wessen) Geld Politik macht. Doch die Regelungen sind l\u00f6chrig. Wir stellen das Tool vor und diskutieren, ob und welcher Kontext(daten) die Grenzen der aktuellen Politiktransparenz aufzeigen k\u00f6nnen. \u00abDas Geld + die Politik\u00bb ist ein Projekt des WAV Recherchekollektivs, Lobbywatch, investigativ.ch und opendata.ch.", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"id": 37102, "code": "WZ9ASP", "public_name": "Balz Oertli", "biography": "Journalist beim WAV Recherchekollektiv (wav.info).", "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39686, "guid": "a2c6af2d-fd62-5074-b587-64584777b4ce", "logo": "", "date": "2024-03-02T18:00:00+01:00", "start": "18:00", "duration": "00:45", "room": "Festsaal", "slug": "wk24-39686-google-der-meta-monopolist", "url": "https://cfp.winterkongress.ch/wk24/talk/9FGLGY/", "title": "Google, der Meta-Monopolist", "subtitle": "", "track": "Digitale Selbstverteidigung", "type": "Vortrag", "language": "de", "abstract": "Google ist der heimliche Herrscher des Internets: Es kontrolliert den marktf\u00fchrenden Browser, das verbreitetste Mobile-OS, die damit verkn\u00fcpfte Google Cloud, die dominanten Suchmaschinen und Videoplattformen sowie die Werbeplattform, um die man nicht herumkommt. \r\n\r\nIn diesem Vortrag zeigen wir auf, wie Google mit AMP, Privacy Sandbox, Web Environment Integrity und anderen Entwicklungen daran arbeiten, seinen Einfluss und seine Kontrolle \u00fcber das Web auszubauen, und gehen auf Alternativen ein, mit welchen sich NutzerInnen diesem Einfluss entziehen k\u00f6nnen.", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"id": 24802, "code": "W9AWUK", "public_name": "Patrick Seemann", "biography": "Patrick Seemann hat an der ETH Informatik studiert. Er arbeitet seit 30 Jahren in kleineren und gr\u00f6sseren Unternehmen an der Schnittstelle zwischen Business und IT. Nebenbei ist er journalistisch f\u00fcr dnip.ch und zwischendurch die Republik t\u00e4tig und versucht, technische Konzepte so zu beschreiben, dass auch Menschen ohne technischen Background sie verstehen und einordnen k\u00f6nnen.", "answers": []}, {"id": 14865, "code": "9MXLFK", "public_name": "Marcel Waldvogel", "biography": "Marcel Waldvogel hat an der ETH Informatik studiert und promoviert. Er hat langj\u00e4hrige Erfahrung in Forschung und Lehre (u.a. 15 Jahre als Informatikprofessor an der Universit\u00e4t Konstanz), aber auch in der Praxis (Softwareentwicklung, Systemadministration, IT-Sicherheit, Leitungsfunktionen).\r\n\r\nEs ist ihm ein Anliegen, komplexe Themen rund um IT und neue Technologien verst\u00e4ndlich zu machen. Nur so k\u00f6nnen wir Technik richtig und verantwortungsvoll einsetzen sowie ihre Auswirkungen absch\u00e4tzen und Fehlentwicklungen vorbeugen. Aus diesem Grund bet\u00e4tigt er sich bei DNIP.ch auch als \u201cErkl\u00e4rb\u00e4r\u201d.", "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39693, "guid": "684cb866-4200-5103-889f-647db8b67487", "logo": "", "date": "2024-03-02T19:00:00+01:00", "start": "19:00", "duration": "00:45", "room": "Festsaal", "slug": "wk24-39693-das-urheberrecht-im-zeitalter-der-generativen-ki", "url": "https://cfp.winterkongress.ch/wk24/talk/97PGJB/", "title": "Das Urheberrecht im Zeitalter der generativen KI", "subtitle": "", "track": "Ethik, Wissenschaft, Kultur & Gesellschaft", "type": "Vortrag", "language": "de", "abstract": "Mit dem Auftauchen der generativen KI werden auch verschiedene Fragen des Urheberrechts zur Diskussion gestellt. Dabei geht es einerseits darum, auf welcher Basis die KI-Modelle trainiert werden k\u00f6nnen und andererseits, ob Werke, die durch generative KI erstellt wurden, einen urheberrechtlichen Schutz geniessen sollten. Ich pl\u00e4diere f\u00fcr weniger Kleingeist und mehr Offenheit in dieser Debatte und werde zeigen, warum wir gerade jetzt das Urheberrecht grunds\u00e4tzlich infrage stellen und auf keinen Fall neue Rechte schaffen sollten.", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"id": 15517, "code": "VDFYBV", "public_name": "Andreas Von Gunten", "biography": "linkslibert\u00e4rer Humanist, Citoyen und Unternehmer. Unter anderem Mitgr\u00fcnder von datenschutzpartner.ch, Verleger von dnip.ch, Autor von \u00abIntellectual Property Is Common Property\u00bb\r\nhttps://andreasvongunten.com", "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39994, "guid": "463f7ba3-d4fe-50b5-ac6b-3542122d5f4c", "logo": "", "date": "2024-03-02T20:00:00+01:00", "start": "20:00", "duration": "00:15", "room": "Festsaal", "slug": "wk24-39994-schlusswort", "url": "https://cfp.winterkongress.ch/wk24/talk/P9EVYV/", "title": "Schlusswort", "subtitle": "", "track": "Andere", "type": "Moderation", "language": "de", "abstract": "Dies ist das Schlusswort.", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"id": 7877, "code": "PLBTRP", "public_name": "Team Winterkongress", "biography": null, "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39995, "guid": "069baa2d-0c0d-5780-b150-4a6c6c9874f5", "logo": "", "date": "2024-03-02T20:15:00+01:00", "start": "20:15", "duration": "01:00", "room": "Festsaal", "slug": "wk24-39995-abendunterhaltung", "url": "https://cfp.winterkongress.ch/wk24/talk/URCRLE/", "title": "Abendunterhaltung", "subtitle": "", "track": "Andere", "type": "Unterhaltung", "language": "de", "abstract": "Dies ist die Abendunterhaltung.", "description": "", "recording_license": "", "do_not_record": false, "persons": [], "links": [], "attachments": [], "answers": []}], "Bankettsaal": [{"id": 39709, "guid": "9dbb8249-82c7-5460-ab36-652f9e53422d", "logo": "", "date": "2024-03-02T12:00:00+01:00", "start": "12:00", "duration": "00:45", "room": "Bankettsaal", "slug": "wk24-39709-sexroboter-zwischen-recht-ethik-und-it-security", "url": "https://cfp.winterkongress.ch/wk24/talk/B9LBRE/", "title": "Sexroboter zwischen Recht, Ethik und IT Security", "subtitle": "", "track": "Ethik, Wissenschaft, Kultur & Gesellschaft", "type": "Vortrag", "language": "de", "abstract": "Rechtliche und ethische Implikationen K\u00fcnstlicher Intelligenz erl\u00e4utert am Beispiel des Sexroboters. Dieser Social Robot der besonderen Art dient in diesem Vortrag nicht nur als erheiternder Zugang zum Thema K\u00fcnstliche Intelligenz und Daten, sondern gibt einen ersten Einblick in die Komplexit\u00e4t, die diese Thematik mit sich bringt. Dabei werden nicht nur bereits bestehende Gesetzesgrundlagen betrachtet und die damit einhergehenden Rechtsprobleme, sondern auch weitreichende ethische Implikationen auf die Gesellschaft.", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"id": 37155, "code": "RCSAM7", "public_name": "Iris Phan", "biography": "Assessorin juris, Volljuristin der Stabsstelle IT Recht der Uni Hannover\r\nLehrbeauftragte des Instituts f\u00fcr Philosophie\r\nDoktorandin des Center for Law and Ethics in the Life Science", "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39680, "guid": "4ca9b254-a4f4-526e-ab94-9cf4252f99ca", "logo": "", "date": "2024-03-02T13:00:00+01:00", "start": "13:00", "duration": "00:45", "room": "Bankettsaal", "slug": "wk24-39680-die-botschaft-und-der-gesetzesentwurf-zur-eid", "url": "https://cfp.winterkongress.ch/wk24/talk/7AZTVF/", "title": "Die Botschaft und der Gesetzesentwurf zur eID", "subtitle": "", "track": "Recht & Politik", "type": "Vortrag", "language": "de", "abstract": "Am 22. November 2023 - rund ein halbes Jahr sp\u00e4ter als zuvor in Aussicht gestellt - verabschiedete der Bundesrat die Botschaft zum Bundesgesetz \u00fcber den elektronischen Identit\u00e4tsnachweis und andere elektronische Nachweise (E-ID-Gesetz, BGEID). Die Verz\u00f6gerung wurde auch damit begr\u00fcndet, dass Bedenken gegen\u00fcber dem Vorentwurf ber\u00fccksichtigt werden sollen. Verspricht der Entwurf nun, was wir uns erhofft haben?", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"id": 24282, "code": "8DVUC9", "public_name": "Hans-Peter Oeri", "biography": "Rechtsanwalt, \u00d6konom und IT-Nerd", "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39555, "guid": "dedc329c-ad09-59b8-ac66-060596570d58", "logo": "", "date": "2024-03-02T14:45:00+01:00", "start": "14:45", "duration": "00:30", "room": "Bankettsaal", "slug": "wk24-39555-von-algorithmen-diskriminiert-wie-kann-der-schutz-verstrkt-werden-", "url": "https://cfp.winterkongress.ch/wk24/talk/AYFEYK/", "title": "Von Algorithmen diskriminiert: Wie kann der Schutz verst\u00e4rkt werden?", "subtitle": "", "track": "Recht & Politik", "type": "Vortrag kurz", "language": "de", "abstract": "Automatisierte Entscheidungen dringen zunehmend in unser t\u00e4gliches Leben ein \u2013 zum Beispiel, wenn Algorithmen unsere Stellenbewerbungen aussortieren, Steuererkl\u00e4rungen automatisch bearbeiten, Krankheiten mittels sogenannter KI diagnostizieren, Verbrechen vorhersagen oder die Arbeitsmarktintegrationschancen von Gefl\u00fcchteten vorhersagen sollen. Werden algorithmische Systeme eingesetzt, kann das allerdings zu Diskriminierungen f\u00fchren. Was steht auf dem Spiel und wie kann der Schutz vor Diskriminierung in der Schweiz gest\u00e4rkt werden? Auf diese Fragen werden wir in dieser Pr\u00e4sentation eingehen.", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"id": 36990, "code": "FHSFPN", "public_name": "Estelle Pannatier", "biography": "Estelle Pannatier ist Policy & Advocacy Managerin bei AlgorithmWatch CH. Sie hat einen Master in politischer Anthropologie und in Kommunikations- und Medienwissenschaften. Vor ihrer T\u00e4tigkeit bei AlgorithmWatch CH hat Estelle zu \u00f6ffentlicher Politik im Kontext der Digitalisierung des Bildungswesens in der Schweiz mitgewirkt.", "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39698, "guid": "62da0822-acbb-5d0a-862e-d4a18a80f20b", "logo": "", "date": "2024-03-02T15:30:00+01:00", "start": "15:30", "duration": "00:45", "room": "Bankettsaal", "slug": "wk24-39698-elektronisches-patientendossier-raus-aus-der-sackgasse", "url": "https://cfp.winterkongress.ch/wk24/talk/DYJYHF/", "title": "Elektronisches Patientendossier: Raus aus der Sackgasse", "subtitle": "", "track": "Recht & Politik", "type": "Vortrag", "language": "de", "abstract": "Seit 2017 gibt es das Gesetz \u00fcber das elektronische Patientendossier - doch das Projekt kommt nicht zum fliegen. Der Bund hat den Handlungsbedarf erkannt und eine umfassende Gesetzesrevision vorgelegt. Wir bereiten uns gemeinsam auf die parlamentarische Phase vor und beantworten folgende Fragen: was sind die gr\u00f6ssten H\u00fcrden f\u00fcr ein funktionierendes EPD? Was sind die aktuellen Machtverh\u00e4ltnisse zwischen den wichtigsten Stakeholder? Und was sind die w\u00fcnschenswerten Zukunftsszenarien f\u00fcr Gesundheitsdaten in der Schweiz?", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"id": 15402, "code": "7R8SNF", "public_name": "Olga Baranova", "biography": "Gesch\u00e4ftsleiterin CH++", "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39401, "guid": "4ea6a65c-0093-5d86-b003-28a2670b4c87", "logo": "", "date": "2024-03-02T16:30:00+01:00", "start": "16:30", "duration": "00:30", "room": "Bankettsaal", "slug": "wk24-39401-nationale-cyberwochen-2023-jetzt-zuschlagen-nur-fr-kurze-zeit-", "url": "https://cfp.winterkongress.ch/wk24/talk/WAC3UV/", "title": "Nationale Cyberwochen 2023 \u2013 jetzt zuschlagen, nur f\u00fcr kurze Zeit!", "subtitle": "", "track": "Netzwerke, Security, Hard- & Software", "type": "Vortrag kurz", "language": "de", "abstract": "Fast t\u00e4glich erreichen uns Berichte \u00fcber Sicherheitsl\u00fccken, Angriffe und Ransomware. Die \u00abNationalen Cyberwochen\u00bb wurden bereits 2022 ausgerufen. In der Zwischenzeit gab es weitere brisante Cybervorf\u00e4lle. Dieser Talk macht einige Xplain-ations der Cybervorf\u00e4lle 2023 mit Bezug zur Schweiz.", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"id": 7859, "code": "VBURNA", "public_name": "Ganti", "biography": "J\u00e4tet im Garten von Politik und Digitalisierung.", "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39706, "guid": "9d4d6b70-d2c9-5dbd-90c9-adfc0f3c0289", "logo": "", "date": "2024-03-02T18:00:00+01:00", "start": "18:00", "duration": "00:45", "room": "Bankettsaal", "slug": "wk24-39706-rechtshilfe-fr-geflchtete-mithilfe-von-legal-tech-tools", "url": "https://cfp.winterkongress.ch/wk24/talk/JJ9RMT/", "title": "Rechtshilfe f\u00fcr Gefl\u00fcchtete mithilfe von Legal Tech Tools", "subtitle": "", "track": "Ethik, Wissenschaft, Kultur & Gesellschaft", "type": "Vortrag", "language": "de", "abstract": "AsyLex bietet seit 2017 unentgeltliche online Rechtsberatung und Rechtsvertretung f\u00fcr gefl\u00fcchtete Menschen an. Ein grosser Teil der Arbeit wird von ca. 150 freiwillig engagierten Personen geleistet, welche sich in verschiedenen Regionen der Schweiz sowie in Italien, Libanon und Griechenland befinden. Zentral f\u00fcr die Arbeit von AsyLex ist dabei der Einsatz von Legal Tech Tools, welche Unterst\u00fctzung beim Verfassen von Rechtsschriften bieten, interne Prozessen vereinfachen sowie einen niederschwelligen Zugang zu rechtlichen Informationen f\u00fcr Gefl\u00fcchtete erm\u00f6glichen.", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"id": 37153, "code": "Z9YAL9", "public_name": "Lea Riedener", "biography": "Co-Head of Operations bei AsyLex", "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39584, "guid": "686b9bf2-425a-5849-8139-d454463243f2", "logo": "", "date": "2024-03-02T19:00:00+01:00", "start": "19:00", "duration": "00:45", "room": "Bankettsaal", "slug": "wk24-39584-alles-kann-nichts-muss-ki-im-spannungsfeld-von-recht-und-gesetz-mit-ki-quiz-", "url": "https://cfp.winterkongress.ch/wk24/talk/FK7RF8/", "title": "Alles kann, nichts muss? KI im Spannungsfeld von Recht und Gesetz. Mit KI-Quiz.", "subtitle": "", "track": "Recht & Politik", "type": "Vortrag", "language": "de", "abstract": "Jeden Tag schiessen neue KI-Tools wie Pilze aus dem Boden. Seit dem Launch von ChatGPT ist KI in aller Munde und auf vielen Handys und Laptops. Aber wie vertr\u00e4gt sich das mit den Schweizer und Europ\u00e4ischen Gesetzen und ist jetzt alles erlaubt? Neben einer rechtlichen und politischen Einordnung wird es ein KI-Quiz mit den Teilnehmenden geben", "description": "Referent Sven Kohlmeier, Fachanwalt f\u00fcr IT-Recht und Rechtsanwalt in Z\u00fcrich wird auf verschiedene rechtliche Aspekt bei dem Einsatz von KI eingehen: Urheberrecht, Berufsrecht, Datenschutzrecht wie auch dem Verwaltungsrecht und Zivilrecht. Neben einem Ausblick auf europ\u00e4ische Regulierung wird wird er Empfehlungen f\u00fcr rechtliche und ethische Rahmenbedingungen f\u00fcr die Beschaffung und den Einsatz von KI-Anwendungen geben. \r\nZum Abschluss wird es ein Quiz mit den Teilnehmenden zum Thema geben - mit einem garantiert nicht KI generiertem Gewinn ...", "recording_license": "", "do_not_record": false, "persons": [{"id": 24456, "code": "WD9BFH", "public_name": "Sven Kohlmeier", "biography": "Sven Kohlmeier ist Rechtsanwalt und Fachanwalt f\u00fcr IT-Recht (D) und in der Z\u00fcricher Kanzlei Wicki Partners AG (https://www.wickipartners.ch/). Er ist als Rechtsanwalt in Berlin zugelassen und war 15 Jahre als Abgeordneter im Abgeordnetenhaus von Berlin f\u00fcr Datenschutz und Netzpolitik verantwortlich. Sven Kohlmeier ist regelm\u00e4ssiger Referent auf internationalen Konferenzen zu IT-Themen wie auch aktuell zu KI-Themen. Er ist Mitgr\u00fcnder des \"Digital Education Institute\" mit KI-Learning-Angeboten f\u00fcr Unternehmen und Verwaltung. Sven ist Mitglied der Digitalen Gesellschaft.", "answers": []}], "links": [], "attachments": [], "answers": []}], "Tanzsaal": [{"id": 39495, "guid": "fd7e17c0-fa45-5c79-96b7-bbc51fe09e3d", "logo": "", "date": "2024-03-02T12:00:00+01:00", "start": "12:00", "duration": "00:45", "room": "Tanzsaal", "slug": "wk24-39495-dark-corners-eine-bias-testing-station", "url": "https://cfp.winterkongress.ch/wk24/talk/J9HPSJ/", "title": "Dark Corners - eine Bias Testing Station", "subtitle": "", "track": "Ethik, Wissenschaft, Kultur & Gesellschaft", "type": "Workshop", "language": "de", "abstract": "Dark Corners ist eine von der Turing Agency gebaute Teststation. Mit dieser k\u00f6nnen die diskriminierenden Abgr\u00fcnde, die \u00abdunklen Ecken\u00bb von GPT und Konsorten erkundet werden. Um den Einstieg ins Testen zu erleichtern, schlagen wir ein paar entlarvende Prompts vor, die man einfach anklicken kann. Die Nutzer:innen k\u00f6nnen dann selber ausprobieren, ob sie damit sexistische oder rassistische Texte und Bilder provozieren k\u00f6nnen. Der Bias-Tester soll sich noch weiterentwickeln - in Zukunft soll er auch Vergleiche zwischen verschiedenen Modelle erlauben.", "description": "Dark Corners: Willkommen zum Vorurteile-Tester\r\n\r\nKI hat Vorurteile\r\nIn den aktuellen generativen KI-Modellen (beispielsweise ChatGPT oder DALL\u00b7E) stecken nicht nur riesige Mengen an Daten, in ihnen stecken auch unsere eigenen Vorurteile und unsere diskriminierenden Strukturen. Man k\u00f6nnte auch sagen: die KI hat die Machtverh\u00e4ltnisse der \u2013 westlichen \u2013 Gesellschaft souver\u00e4n \u00fcbernommen, sie hat sie gelernt. Und reproduziert sie nun dementsprechend.\r\n\r\nF\u00fcr die Ausstellung \u00abMacht\u00bb im V\u00f6gele Kultur Zentrum in Pf\u00e4ffikon SZ hat die Turing Agecny eine Teststation gebaut, mit der die diskriminierenden Abgr\u00fcnde, die \u00abdunklen Ecken\u00bb von GPT und Konsorten erkundet werden k\u00f6nnen. Um den Einstieg ins Testen zu erleichtern, schlagen wir ein paar entlarvende Prompts vor, die man einfach anklicken kann. Die Besuchenden k\u00f6nnen dann selber ausprobieren, ob sie damit sexistische oder rassistische Texte und Bilder provozieren k\u00f6nnen. Sie d\u00fcrfen auch selber kreativ werden! Vielleicht kommen Ihnen weitere Szenerien in den Sinn, um dunkle Ecken in den Sprach- und Bildmodellen auszuleuchten.\r\n\r\nAI Bias - was ist das?\r\nK\u00fcnstliche Intelligenz kann all die Dinge die sie kann nur weil sie auf die jeweilige Funktion hin \"trainiert\" worden ist, wie das im Fachjargon heisst. Dieses Training ist eine mathematisch komplexe Sache, aber entscheidend dabei ist: Grundlage des Trainings sind Unmengen an Daten. Und diese sind zumeist menschgemacht. Bei grossen Text-KIs also: Terabytes und Terabytes an Texten, die \u00fcberall da gesammelt werden, wo sie frei verf\u00fcgbar sind. Manche sagen auch: f\u00fcr das Training h\u00e4tten sich ChatGPT und Konsorten \"das komplette Internet\" einverleibt. In diesen Daten steckt viel menschliches Wissen, aber was auch drin steckt: viele Vorurteile, viel gesellschaftliche Ungleichheit. Diese sogenannten \"Biases\" tauchen in den Sprachausgaben der KI dann wieder auf, manchmal versteckt, manchmal auch offensiv offen. Da ist die KI nicht besser, nicht kl\u00fcger, nicht fairer als wir. Ausserdem dr\u00e4ngt sich die Frage auf: welcher Teil der Welt ist dominant im Internet vertreten - und wof\u00fcr ist das Internet blind? \r\n\r\nK\u00f6nnen Maschinen \"neutral\" sein?\r\nMaschinen funktionieren und urteilen objektiver und unvoreingenommener als Menschen? Das h\u00e4tten wir gern. Und es mag vielleicht bei einem Kamera-Bild noch halbwegs stimmen, das eine Szenerie zeigt \"wie sie ist\", im Gegensatz zur unverl\u00e4sslichen Erinnerung eines Zeugen. Aber bei KI l\u00e4uft diese Hoffnung ins Leere. Die KI trifft ihre Entscheidungen nicht nach einem maschinell-logischen Raster, sondern nach Wahrscheinlichkeit. Und was sie als mehr oder weniger wahrscheinlich erachtet hat sie allein anhand menschlicher Beispiele gelernt. \r\nEs gibt zwar Versuche, KIs die menschlichen Vorurteile ganz gezielt abzugew\u00f6hnen oder sie mit Filtern zu neutralisieren. Zum Beispiel bei automatisierten Bewerbungsverfahren: K\u00f6nnen Kandidatinnen von einer KI wom\u00f6glich fairer ausgew\u00e4hlt werden? N\u00e4mlich anhand tats\u00e4chlicher Qualit\u00e4ten und nicht aufgrund von Geschlecht oder ausl\u00e4ndisch klingendem Nachnamen? So etwas wird gerade intensiv erforscht.\r\nLeider zeigt sich: Die Macht der Trainingsdaten ist gross, die \"perfekt vorurteilsfreie\" Maschine wird wohl eine Illusion bleiben. Denn am Schluss sind alle Flick-Versuche auch wieder subjektiv, jeder Filter zeigt auch wieder ein Wertsystem auf. Welche Ismen hat die KI von uns gelernt? Und wie offensichtlich reproduziert sie sie?", "recording_license": "", "do_not_record": false, "persons": [{"id": 15497, "code": "JCEAPR", "public_name": "Roland Fischer", "biography": null, "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39619, "guid": "2b8f9bda-c416-5c75-a9bc-37d83c35c6c4", "logo": "", "date": "2024-03-02T13:00:00+01:00", "start": "13:00", "duration": "00:45", "room": "Tanzsaal", "slug": "wk24-39619-automatisierte-ungleichheit", "url": "https://cfp.winterkongress.ch/wk24/talk/RKSTBD/", "title": "Automatisierte Ungleichheit", "subtitle": "", "track": "Ethik, Wissenschaft, Kultur & Gesellschaft", "type": "Vortrag", "language": "de", "abstract": "Bereits benachteiligte gesellschaftliche Gruppen (Migrierende, Erwerbslose, etc) sind automatisierten Entscheidungssystemen, Scoring und Profiling und generell der digitalen \u00dcberwachung durchg\u00e4ngig viel st\u00e4rker ausgesetzt als nicht-benachteiligte Gruppen. Gleichzeitig haben sie weniger M\u00f6glichkeiten, sich dagegen zu wehren. In unserem Vortrag geben wir Beispiele f\u00fcr dieses st\u00e4rkere Ausgesetztsein. Weiterhin diskutieren wir m\u00f6gliche Implikationen f\u00fcr netzpolitische NGOs.", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"id": 7841, "code": "SNWNEF", "public_name": "Andreas Geppert", "biography": "Andreas Geppert ist seit einigen Jahren Mitglied der Digitalen Gesellschaft und interessiert sich f\u00fcr gesellschaftliche Implikationen der Digitalisierung und Automatisierung.", "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39669, "guid": "ca745257-a38f-58c5-9ea5-b12168c082ef", "logo": "", "date": "2024-03-02T14:45:00+01:00", "start": "14:45", "duration": "00:30", "room": "Tanzsaal", "slug": "wk24-39669-netzwerkzugriff-fr-anwendungen-einschrnken-unter-linux", "url": "https://cfp.winterkongress.ch/wk24/talk/PSQP9Q/", "title": "Netzwerkzugriff f\u00fcr Anwendungen einschr\u00e4nken unter Linux", "subtitle": "", "track": "Netzwerke, Security, Hard- & Software", "type": "Vortrag kurz", "language": "de", "abstract": "Namensr\u00e4ume sind eine Grundlage f\u00fcr Container und Sandboxes unter Linux. Dieser Vortrag stellt Netzwerk-Namensr\u00e4ume vor und beschreibt wie auf sie aufbauend Netzwerkverbindungen f\u00fcr eine Anwendung auf erlaubte Ziele begrenzt werden k\u00f6nnen.\r\n\r\nSchritt f\u00fcr Schritt werden die n\u00f6tigen Konzepte vorgestellt und eine L\u00f6sung zum Einschr\u00e4nken von Netzwerkverbindungen f\u00fcr Anwendungen praktisch implementiert.", "description": "\"Linux ist weniger sicher als Windows oder Mac.\"\r\n\r\nEin Beitrag mit dieser provokanten These hat mir zur Einsicht verholfen, dass auf meinem Rechner nichts ein fehlerhaftes oder b\u00f6sartiges Programm daran hindert [alle meine Dateien zu l\u00f6schen](https://github.com/ValveSoftware/steam-for-linux/issues/3671).\r\n\r\nSandbox-L\u00f6sungen wie firejail k\u00f6nnen da Abhilfe schaffen, bieten aber nicht Profile f\u00fcr alle Anwendungen. Diese Profile muss man selbst erstellen.\r\n\r\nIch spiele manchmal Spiele im Einzelspielermodus und m\u00f6chte nicht, dass die [Netzwerkverbindungen aufbauen](https://www.pcgameshardware.de/Civilization-6-Spiel-56986/News/Patch-entfernt-umstrittene-Red-Shell-Software-1261324/).\r\n\r\nManche Spiele gibt es aber nur bei Steam. Ich habe es nicht geschafft Steam Netzwerkzugriff zu erlauben, aber Spielen nicht.\r\n\r\nDarauf folgte die Frage: Wie funktionieren diese Sandboxes eigentlich? Und: Wie kann ich Netzwerkzugriffe auf bestimmte Ziele begrenzen?\r\n\r\nIm Vortrag beschreibe ich, was ich herausgefunden habe und erkl\u00e4re Schritt f\u00fcr Schritt wie eine solche L\u00f6sung funktioniert.\r\n\r\nGrundkenntnisse in den Bereichen Linux, Programmieren und Netzwerk sind empfehlenswert. Wer von Prozessen, dem Einbinden (mount) von Dateisystemen, Netzwerkger\u00e4ten (z.B. eth0, wlan0), _if_ und Schleifen sowie IP-Addressen und TCP zumindest schon einmal geh\u00f6rt hat, sollte dem Vortrag etwas abgewinnen k\u00f6nnen.", "recording_license": "", "do_not_record": false, "persons": [{"id": 37129, "code": "QPCFUH", "public_name": "Johannes", "biography": "Johannes darf sich \"Dipl.-Wirt.-Inf. (FH)\"\u00b9 nennen. Nach einigen Jahren als Forschungsassistent in der E-Health wechselte er in Systemadministratorrollen in den Bereichen Content Delivery Network, Telekommunikation und Cloud-Dienstleistung.\r\n\r\n\u00b9 Diplom-Wirtschaftsinformatiker (Fachhochschule)", "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39997, "guid": "bbb0e3ea-a8e8-52d6-bfcd-8bf871c33042", "logo": "", "date": "2024-03-02T15:30:00+01:00", "start": "15:30", "duration": "00:45", "room": "Tanzsaal", "slug": "wk24-39997-lightning-talks", "url": "https://cfp.winterkongress.ch/wk24/talk/A9EJUQ/", "title": "Lightning Talks", "subtitle": "", "track": "Andere", "type": "Vortrag", "language": "de", "abstract": "Lightning Talks - Deine zehn Minuten Ber\u00fchmtheit!", "description": "Bringe Deinen ansteckenden Enthusiasmus an ein Publikum mit kurzer Aufmerksamkeitsspanne! Diskutieren ein Programm, ein System oder eine Technik! Stelle Deine Projekte und Ideen vor oder versuche, eine Gruppe von Menschen f\u00fcr Deine Veranstaltung oder Versammlung zu gewinnen! Was auch immer Du mitbringst, machen es kurz!\r\n\r\nWir haben vier Slots mit jeweils 10 Minuten zu vergeben. Die Spielregeln sind:\r\n\r\n* First come, first serve, es werden bis am 31.01.2024 Beitr\u00e4ge unter lightning-talks@winterkongress.ch entgegengenommen. Es wird nur ein Vortrag pro Person angenommen, ausser wir haben zu wenige Einreichungen.\r\n* Wir publizieren hier die Angenommenen Vortr\u00e4ge und werden vermerken wenn keine mehr angenommen werden.\r\n* Am Samstag bis sp\u00e4testens am Mittag muss dein Vortrag per PDF hochgeladen werden (Link kommt via E-Mail)\r\n* Du hast genau zehn Minuten Zeit\r\n* Eine Minute zum wechseln\r\n* Beitr\u00e4ge sind auf Deutsch und werden in Schriftsprache vorgetragen\r\n\r\nAlle Beitr\u00e4ge werden gestreamt und aufgezeichnet\r\n\r\nWir freuen uns auf Eure Einsendungen!\r\n\r\nBereits best\u00e4tigt:\r\n\r\n* Communities vernetzen: Das HackThePromise Festival in Basel", "recording_license": "", "do_not_record": false, "persons": [{"id": 7877, "code": "PLBTRP", "public_name": "Team Winterkongress", "biography": null, "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39423, "guid": "7e2c3642-b2aa-5c9e-98fa-7c7fdd735f27", "logo": "", "date": "2024-03-02T16:30:00+01:00", "start": "16:30", "duration": "00:30", "room": "Tanzsaal", "slug": "wk24-39423-die-bevlkerung-und-die-internetsicherheit-paradox-und-unbewusste-inkompetenz", "url": "https://cfp.winterkongress.ch/wk24/talk/NLZWNZ/", "title": "Die Bev\u00f6lkerung und die Internetsicherheit - Paradox und unbewusste Inkompetenz", "subtitle": "", "track": "Digitale Selbstverteidigung", "type": "Vortrag kurz", "language": "de", "abstract": "Vom 7. August bis 4. September 2023 fu\u0308hrte das Markt- und Sozialforschungsinstitut gfs-zu\u0308rich im Auftrag von digitalswitzerland, der Mobiliar, SATW, FHNW und SISA eine Bev\u00f6lkerungsumfrage in allen drei Landesteilen der Schweiz durch. Ziel war es, die Einstellung Schweizer Internetznutzenden zu Cyberrisiken, die Betroffenheit von Angriffen sowie die Umsetzung von Sicherheitsmassnahmen zu ermitteln. Zus\u00e4tzlich wurden Fragen zum Verhalten und Sicherheitsgefu\u0308hl beim Onlineshopping gestellt.\r\nIm Vortrag sollen die Ergebnisse zusammenfassend dargestellt und in Kontext gesetzt werden.", "description": "https://internet-sicherheit.ch/", "recording_license": "", "do_not_record": false, "persons": [{"id": 7077, "code": "HGKGBU", "public_name": "Katja D\u00f6rlemann", "biography": "Katja D\u00f6rlemann ist Security Awareness Expertin bei Switch und Pr\u00e4sidentin der Swiss Internet Security Alliance (SISA). Sie unterst\u00fctzt die Bildungs-, Forschungs-, Innovations- und Internet-Community im Umgang mit dem Faktor Mensch in der Informationssicherheit. Sie f\u00f6rdert den Wissensaustausch und die Vernetzung von Expert:innen, als Leiterin oder Teilnehmerin in Arbeitsgruppen und Expert:innenkreisen, als Rednerin und Dozentin oder auch als Co-Host des Security Awareness Insider Podcasts.", "answers": []}, {"id": 37510, "code": "DW3YK7", "public_name": "Simon Bernhard Seebeck", "biography": ".", "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39688, "guid": "efa1d942-e0b5-5572-a875-0d6902377c2f", "logo": "", "date": "2024-03-02T18:00:00+01:00", "start": "18:00", "duration": "00:45", "room": "Tanzsaal", "slug": "wk24-39688-einfhrung-in-ssrf-mgliche-angriffe-und-was-man-trotz-php-dagegen-tun-kann", "url": "https://cfp.winterkongress.ch/wk24/talk/XGGVPJ/", "title": "Einf\u00fchrung in SSRF: M\u00f6gliche Angriffe und was man (trotz PHP) dagegen tun kann", "subtitle": "", "track": "Netzwerke, Security, Hard- & Software", "type": "Vortrag", "language": "de", "abstract": "Server-Side Requests werden von Webapps verwendet, um Daten von anderen Servern abzurufen, z. B. f\u00fcr die Vorschau von Links.\r\nSie k\u00f6nnen jedoch von Angreifern exploited werden, um auf interne Ressourcen oder Dienste zuzugreifen, die nicht f\u00fcr die \u00d6ffentlichkeit bestimmt sind.\r\nDies wird als Server-Side Request Forgery (SSRF) bezeichnet.\r\nDer Talk erkl\u00e4rt was SSRF ist, wie es zum Exploiten von Servern verwendet wird und wie man sich dagegen verteidigen kann, was komplexer ist als man denkt.\r\nW\u00e4hrend des Vortrags werde ich PHP als Beispielsprache verwenden und typische PHP-Fallstricke zeigen.", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"id": 37145, "code": "JKYGVU", "public_name": "Malte Wessels", "biography": "Ich bin Doktorand am Institut f\u00fcr Anwendungssicherheit der TU Braunschweig und interessiere mich da f\u00fcr security & privacy Analysetechniken. In meiner Freizeit bin ich u.a. Beisitzer des Vorstandes des Datenanfragen.de e. V.", "answers": []}], "links": [], "attachments": [], "answers": []}, {"id": 39258, "guid": "055bcf69-60a3-5f20-a6a5-4a3b0479da19", "logo": "", "date": "2024-03-02T19:00:00+01:00", "start": "19:00", "duration": "00:45", "room": "Tanzsaal", "slug": "wk24-39258-coden-auf-exoten-neue-systemhack-geschichten-aus-der-demoszene", "url": "https://cfp.winterkongress.ch/wk24/talk/DK8P3X/", "title": "Coden auf Exoten - Neue Systemhack-Geschichten aus der Demoszene", "subtitle": "", "track": "Ethik, Wissenschaft, Kultur & Gesellschaft", "type": "Vortrag", "language": "de", "abstract": "Wir stellen ungew\u00f6hnliche Demos auf noch ungew\u00f6hnlicheren Systemen vor - vom Teletext zum Apotheken-LED-Schild, und erz\u00e4hlen etwas \u00fcber die Macher und ihren Prozess.", "description": "Die Demoszene lotet seit 40 Jahren die Grenzen von Computern aus; neben dem Siegesmarsch des PC haben sich die Kreativen auch eher ungew\u00f6hnlichen Plattformen angenommen. Wir zeigen euch Demos f\u00fcr Teletext, selbstgemachte LED-Displays, umgebaute Laufwerke und sogar Apothekenschilder, und sprechen \u00fcber die Macher, die Ideen und Herausforderungen dahinter.", "recording_license": "", "do_not_record": false, "persons": [{"id": 14679, "code": "EEC7ZA", "public_name": "Shana Marinitsch", "biography": null, "answers": []}], "links": [], "attachments": [], "answers": []}]}}]}}} \ No newline at end of file