commit efa58d25daa39eac87c5c782002085449e66cc41 Author: Ral Date: Tue Feb 4 00:47:14 2025 +0100 Inital checkin 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..9dde5e0 --- /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(30,30,30); +} + +.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..da31348 --- /dev/null +++ b/assets/css/custom/nodes/schedule-hall1.scss @@ -0,0 +1,4 @@ +@import "../styles/_base"; + +@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..da31348 --- /dev/null +++ b/assets/css/custom/nodes/schedule-hall2.scss @@ -0,0 +1,4 @@ +@import "../styles/_base"; + +@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..da31348 --- /dev/null +++ b/assets/css/custom/nodes/schedule-hall3.scss @@ -0,0 +1,4 @@ +@import "../styles/_base"; + +@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..da31348 --- /dev/null +++ b/assets/css/custom/nodes/schedule.scss @@ -0,0 +1,4 @@ +@import "../styles/_base"; + +@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..fbe38c5 --- /dev/null +++ b/assets/css/custom/nodes/upcoming-talk-hall1.scss @@ -0,0 +1,3 @@ +@import "../styles/_base"; + +@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..fbe38c5 --- /dev/null +++ b/assets/css/custom/nodes/upcoming-talk-hall2.scss @@ -0,0 +1,3 @@ +@import "../styles/_base"; + +@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..fbe38c5 --- /dev/null +++ b/assets/css/custom/nodes/upcoming-talk-hall3.scss @@ -0,0 +1,3 @@ +@import "../styles/_base"; + +@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..838758f --- /dev/null +++ b/assets/css/custom/styles/_banner-speaker.scss @@ -0,0 +1,68 @@ +@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-green; + + // border-width: 5px; + // border-style: solid; + // border-color: $color-ci-green; + + // 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-green; +} + +.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..fff0477 --- /dev/null +++ b/assets/css/custom/styles/_banner-talk.scss @@ -0,0 +1,82 @@ +@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-green; + + // border-width: 5px; + // border-style: solid; + // border-color: $color-ci-green; + + // 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-green; + + &: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..83c70c2 --- /dev/null +++ b/assets/css/custom/styles/_base.scss @@ -0,0 +1,26 @@ +@import "../../fonts/fonts"; +@import "_variables"; + +* { + box-sizing: border-box; +} + +body { + color: $colod-fg; + background: rgb(25,25,25); + 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..689dcfb --- /dev/null +++ b/assets/css/custom/styles/_clock.scss @@ -0,0 +1,22 @@ +#clock { + position: relative; + top: 0px; + left: 0px; + + width: $full-width; + height: $full-height; + overflow: hidden; + + z-index: 1000; +} + +.clock { + position: absolute; + + top: 240px; + left: 1144px; + + font-family: 'Source Code Pro'; + font-weight: 600; + font-size: 60px; +} 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..b809f7d --- /dev/null +++ b/assets/css/custom/styles/_schedule.scss @@ -0,0 +1,220 @@ +@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: 260px; + left: 1448px; + + z-index: 20; + + font-family: 'Source Code Pro'; + font-weight: 700; + font-size: 40px; + + text-align: end; + color: white; + + // 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: white; +} + + + +.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-0 { + color: #bbbbbb; +} + +.track-1 { + color: #40a56a; + // color: #119633; +} + +.track-2 { + color: #ffc91a; + // color: #91800d; +} + +.track-3 { + color: #d92635; + // color: #af0c0c; +} + +.track-4 { + color: #3caec3; + // color: #145e9a; +} diff --git a/assets/css/custom/styles/_upcoming-talk.scss b/assets/css/custom/styles/_upcoming-talk.scss new file mode 100644 index 0000000..f6148f9 --- /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-green; +} + + +.event-meta { + height: 250px; + + background-color: $color-ci-green; + + 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..46859d4 --- /dev/null +++ b/assets/css/custom/styles/_variables.scss @@ -0,0 +1,13 @@ +$full-width: 1920px; +$full-height: 1080px; + +$colod-fg: rgb(255,255,255); +$color-bg: rgb(30, 30, 30); + +// Old CI +$color-ci-gray: rgb(101, 103, 103); +$color-ci-darkgreen: rgb(5, 114, 72); +$color-ci-lightgreen: rgb(0, 156, 71); + +// New CI +$color-ci-green: rgb(78, 169, 63); 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..53e8b8f --- /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("2025-02-28T18: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..f8f5f87 --- /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 = serv.sort_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..ea5e65e --- /dev/null +++ b/assets/js/custom/dom/voc-schedule-hall.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_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..4ac3f90 --- /dev/null +++ b/assets/js/custom/dom/voc-schedule.js @@ -0,0 +1,106 @@ +'use strict'; + +import * as sol from "../../solight/sol.js"; + +import * as serv from "../services/service.js"; + +const html = htm.bind(preact.h); + + +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..d031600 --- /dev/null +++ b/assets/js/custom/services/service.js @@ -0,0 +1,45 @@ +'use strict'; + +import * as lodash from "../../lodash/lodash-core.js"; + +import * as sol from "../../solight/sol.js"; + + +const process_data = (scheduleFile) => + sol.processScheduleFile(scheduleFile); + + +const trackIndexMap = new Map([ + ['Andere', 0], + ['Ethik, Wissenschaft, Kultur & Gesellschaft', 1], + ['Recht & Politik', 2], + ['Netzwerke, Security, Hard- & Software', 3], + ['Digitale Selbstverteidigung', 4]]); + +const track_index = (track) => + trackIndexMap.get(track); + +const sort_tracks = (tracks) => + lodash.sortBy(tracks, track_index); + + +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, + track_index, + sort_tracks, + 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/lodash/lodash-core.js b/assets/js/lodash/lodash-core.js new file mode 100644 index 0000000..89c77de --- /dev/null +++ b/assets/js/lodash/lodash-core.js @@ -0,0 +1,3854 @@ +/** + * @license + * Lodash (Custom Build) + * Build: `lodash core -o ./dist/lodash.core.js` + * Copyright OpenJS Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ +;(function() { + + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + + /** Used as the semantic version number. */ + var VERSION = '4.17.15'; + + /** Error message constants. */ + var FUNC_ERROR_TEXT = 'Expected a function'; + + /** Used to compose bitmasks for value comparisons. */ + var COMPARE_PARTIAL_FLAG = 1, + COMPARE_UNORDERED_FLAG = 2; + + /** Used to compose bitmasks for function metadata. */ + var WRAP_BIND_FLAG = 1, + WRAP_PARTIAL_FLAG = 32; + + /** Used as references for various `Number` constants. */ + var INFINITY = 1 / 0, + MAX_SAFE_INTEGER = 9007199254740991; + + /** `Object#toString` result references. */ + var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + asyncTag = '[object AsyncFunction]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + numberTag = '[object Number]', + objectTag = '[object Object]', + proxyTag = '[object Proxy]', + regexpTag = '[object RegExp]', + stringTag = '[object String]'; + + /** Used to match HTML entities and HTML characters. */ + var reUnescapedHtml = /[&<>"']/g, + reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + + /** Used to detect unsigned integer values. */ + var reIsUint = /^(?:0|[1-9]\d*)$/; + + /** Used to map characters to HTML entities. */ + var htmlEscapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + }; + + /** Detect free variable `global` from Node.js. */ + var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; + + /** Detect free variable `self`. */ + var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + + /** Used as a reference to the global object. */ + var root = freeGlobal || freeSelf || Function('return this')(); + + /** Detect free variable `exports`. */ + var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; + + /** Detect free variable `module`. */ + var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; + + /*--------------------------------------------------------------------------*/ + + /** + * Appends the elements of `values` to `array`. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to append. + * @returns {Array} Returns `array`. + */ + function arrayPush(array, values) { + array.push.apply(array, values); + return array; + } + + /** + * The base implementation of `_.findIndex` and `_.findLastIndex` without + * support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} predicate The function invoked per iteration. + * @param {number} fromIndex The index to search from. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseFindIndex(array, predicate, fromIndex, fromRight) { + var length = array.length, + index = fromIndex + (fromRight ? 1 : -1); + + while ((fromRight ? index-- : ++index < length)) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; + } + + /** + * The base implementation of `_.property` without support for deep paths. + * + * @private + * @param {string} key The key of the property to get. + * @returns {Function} Returns the new accessor function. + */ + function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; + } + + /** + * The base implementation of `_.propertyOf` without support for deep paths. + * + * @private + * @param {Object} object The object to query. + * @returns {Function} Returns the new accessor function. + */ + function basePropertyOf(object) { + return function(key) { + return object == null ? undefined : object[key]; + }; + } + + /** + * The base implementation of `_.reduce` and `_.reduceRight`, without support + * for iteratee shorthands, which iterates over `collection` using `eachFunc`. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} accumulator The initial value. + * @param {boolean} initAccum Specify using the first or last element of + * `collection` as the initial value. + * @param {Function} eachFunc The function to iterate over `collection`. + * @returns {*} Returns the accumulated value. + */ + function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) { + eachFunc(collection, function(value, index, collection) { + accumulator = initAccum + ? (initAccum = false, value) + : iteratee(accumulator, value, index, collection); + }); + return accumulator; + } + + /** + * The base implementation of `_.values` and `_.valuesIn` which creates an + * array of `object` property values corresponding to the property names + * of `props`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} props The property names to get values for. + * @returns {Object} Returns the array of property values. + */ + function baseValues(object, props) { + return baseMap(props, function(key) { + return object[key]; + }); + } + + /** + * Used by `_.escape` to convert characters to HTML entities. + * + * @private + * @param {string} chr The matched character to escape. + * @returns {string} Returns the escaped character. + */ + var escapeHtmlChar = basePropertyOf(htmlEscapes); + + /** + * Creates a unary function that invokes `func` with its argument transformed. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} transform The argument transform. + * @returns {Function} Returns the new function. + */ + function overArg(func, transform) { + return function(arg) { + return func(transform(arg)); + }; + } + + /*--------------------------------------------------------------------------*/ + + /** Used for built-in method references. */ + var arrayProto = Array.prototype, + objectProto = Object.prototype; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** Used to generate unique IDs. */ + var idCounter = 0; + + /** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ + var nativeObjectToString = objectProto.toString; + + /** Used to restore the original `_` reference in `_.noConflict`. */ + var oldDash = root._; + + /** Built-in value references. */ + var objectCreate = Object.create, + propertyIsEnumerable = objectProto.propertyIsEnumerable; + + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeIsFinite = root.isFinite, + nativeKeys = overArg(Object.keys, Object), + nativeMax = Math.max; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a `lodash` object which wraps `value` to enable implicit method + * chain sequences. Methods that operate on and return arrays, collections, + * and functions can be chained together. Methods that retrieve a single value + * or may return a primitive value will automatically end the chain sequence + * and return the unwrapped value. Otherwise, the value must be unwrapped + * with `_#value`. + * + * Explicit chain sequences, which must be unwrapped with `_#value`, may be + * enabled using `_.chain`. + * + * The execution of chained methods is lazy, that is, it's deferred until + * `_#value` is implicitly or explicitly called. + * + * Lazy evaluation allows several methods to support shortcut fusion. + * Shortcut fusion is an optimization to merge iteratee calls; this avoids + * the creation of intermediate arrays and can greatly reduce the number of + * iteratee executions. Sections of a chain sequence qualify for shortcut + * fusion if the section is applied to an array and iteratees accept only + * one argument. The heuristic for whether a section qualifies for shortcut + * fusion is subject to change. + * + * Chaining is supported in custom builds as long as the `_#value` method is + * directly or indirectly included in the build. + * + * In addition to lodash methods, wrappers have `Array` and `String` methods. + * + * The wrapper `Array` methods are: + * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift` + * + * The wrapper `String` methods are: + * `replace` and `split` + * + * The wrapper methods that support shortcut fusion are: + * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`, + * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`, + * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray` + * + * The chainable wrapper methods are: + * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`, + * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`, + * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`, + * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, + * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`, + * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`, + * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`, + * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`, + * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`, + * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`, + * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, + * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`, + * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`, + * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`, + * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`, + * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`, + * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`, + * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`, + * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`, + * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`, + * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`, + * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`, + * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`, + * `zipObject`, `zipObjectDeep`, and `zipWith` + * + * The wrapper methods that are **not** chainable by default are: + * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`, + * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`, + * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`, + * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`, + * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`, + * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`, + * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`, + * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, + * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`, + * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, + * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, + * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`, + * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`, + * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`, + * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`, + * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`, + * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, + * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`, + * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`, + * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`, + * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`, + * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`, + * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`, + * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`, + * `upperFirst`, `value`, and `words` + * + * @name _ + * @constructor + * @category Seq + * @param {*} value The value to wrap in a `lodash` instance. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * function square(n) { + * return n * n; + * } + * + * var wrapped = _([1, 2, 3]); + * + * // Returns an unwrapped value. + * wrapped.reduce(_.add); + * // => 6 + * + * // Returns a wrapped value. + * var squares = wrapped.map(square); + * + * _.isArray(squares); + * // => false + * + * _.isArray(squares.value()); + * // => true + */ + function lodash(value) { + return value instanceof LodashWrapper + ? value + : new LodashWrapper(value); + } + + /** + * The base implementation of `_.create` without support for assigning + * properties to the created object. + * + * @private + * @param {Object} proto The object to inherit from. + * @returns {Object} Returns the new object. + */ + var baseCreate = (function() { + function object() {} + return function(proto) { + if (!isObject(proto)) { + return {}; + } + if (objectCreate) { + return objectCreate(proto); + } + object.prototype = proto; + var result = new object; + object.prototype = undefined; + return result; + }; + }()); + + /** + * The base constructor for creating `lodash` wrapper objects. + * + * @private + * @param {*} value The value to wrap. + * @param {boolean} [chainAll] Enable explicit method chain sequences. + */ + function LodashWrapper(value, chainAll) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__chain__ = !!chainAll; + } + + LodashWrapper.prototype = baseCreate(lodash.prototype); + LodashWrapper.prototype.constructor = LodashWrapper; + + /*------------------------------------------------------------------------*/ + + /** + * Assigns `value` to `key` of `object` if the existing value is not equivalent + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function assignValue(object, key, value) { + var objValue = object[key]; + if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); + } + } + + /** + * The base implementation of `assignValue` and `assignMergeValue` without + * value checks. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function baseAssignValue(object, key, value) { + object[key] = value; + } + + /** + * The base implementation of `_.delay` and `_.defer` which accepts `args` + * to provide to `func`. + * + * @private + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @param {Array} args The arguments to provide to `func`. + * @returns {number|Object} Returns the timer id or timeout object. + */ + function baseDelay(func, wait, args) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return setTimeout(function() { func.apply(undefined, args); }, wait); + } + + /** + * The base implementation of `_.forEach` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + */ + var baseEach = createBaseEach(baseForOwn); + + /** + * The base implementation of `_.every` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false` + */ + function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); + return result; + } + + /** + * The base implementation of methods like `_.max` and `_.min` which accepts a + * `comparator` to determine the extremum value. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The iteratee invoked per iteration. + * @param {Function} comparator The comparator used to compare values. + * @returns {*} Returns the extremum value. + */ + function baseExtremum(array, iteratee, comparator) { + var index = -1, + length = array.length; + + while (++index < length) { + var value = array[index], + current = iteratee(value); + + if (current != null && (computed === undefined + ? (current === current && !false) + : comparator(current, computed) + )) { + var computed = current, + result = value; + } + } + return result; + } + + /** + * The base implementation of `_.filter` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ + function baseFilter(collection, predicate) { + var result = []; + baseEach(collection, function(value, index, collection) { + if (predicate(value, index, collection)) { + result.push(value); + } + }); + return result; + } + + /** + * The base implementation of `_.flatten` with support for restricting flattening. + * + * @private + * @param {Array} array The array to flatten. + * @param {number} depth The maximum recursion depth. + * @param {boolean} [predicate=isFlattenable] The function invoked per iteration. + * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks. + * @param {Array} [result=[]] The initial result value. + * @returns {Array} Returns the new flattened array. + */ + function baseFlatten(array, depth, predicate, isStrict, result) { + var index = -1, + length = array.length; + + predicate || (predicate = isFlattenable); + result || (result = []); + + while (++index < length) { + var value = array[index]; + if (depth > 0 && predicate(value)) { + if (depth > 1) { + // Recursively flatten arrays (susceptible to call stack limits). + baseFlatten(value, depth - 1, predicate, isStrict, result); + } else { + arrayPush(result, value); + } + } else if (!isStrict) { + result[result.length] = value; + } + } + return result; + } + + /** + * The base implementation of `baseForOwn` which iterates over `object` + * properties returned by `keysFunc` and invokes `iteratee` for each property. + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ + var baseFor = createBaseFor(); + + /** + * The base implementation of `_.forOwn` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ + function baseForOwn(object, iteratee) { + return object && baseFor(object, iteratee, keys); + } + + /** + * The base implementation of `_.functions` which creates an array of + * `object` function property names filtered from `props`. + * + * @private + * @param {Object} object The object to inspect. + * @param {Array} props The property names to filter. + * @returns {Array} Returns the function names. + */ + function baseFunctions(object, props) { + return baseFilter(props, function(key) { + return isFunction(object[key]); + }); + } + + /** + * The base implementation of `getTag` without fallbacks for buggy environments. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ + function baseGetTag(value) { + return objectToString(value); + } + + /** + * The base implementation of `_.gt` which doesn't coerce arguments. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than `other`, + * else `false`. + */ + function baseGt(value, other) { + return value > other; + } + + /** + * The base implementation of `_.isArguments`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + */ + var baseIsArguments = noop; + + /** + * The base implementation of `_.isDate` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a date object, else `false`. + */ + function baseIsDate(value) { + return isObjectLike(value) && baseGetTag(value) == dateTag; + } + + /** + * The base implementation of `_.isEqual` which supports partial comparisons + * and tracks traversed objects. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {boolean} bitmask The bitmask flags. + * 1 - Unordered comparison + * 2 - Partial comparison + * @param {Function} [customizer] The function to customize comparisons. + * @param {Object} [stack] Tracks traversed `value` and `other` objects. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + */ + function baseIsEqual(value, other, bitmask, customizer, stack) { + if (value === other) { + return true; + } + if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack); + } + + /** + * A specialized version of `baseIsEqual` for arrays and objects which performs + * deep comparisons and tracks traversed objects enabling objects with circular + * references to be compared. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} [stack] Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) { + var objIsArr = isArray(object), + othIsArr = isArray(other), + objTag = objIsArr ? arrayTag : baseGetTag(object), + othTag = othIsArr ? arrayTag : baseGetTag(other); + + objTag = objTag == argsTag ? objectTag : objTag; + othTag = othTag == argsTag ? objectTag : othTag; + + var objIsObj = objTag == objectTag, + othIsObj = othTag == objectTag, + isSameTag = objTag == othTag; + + stack || (stack = []); + var objStack = find(stack, function(entry) { + return entry[0] == object; + }); + var othStack = find(stack, function(entry) { + return entry[0] == other; + }); + if (objStack && othStack) { + return objStack[1] == other; + } + stack.push([object, other]); + stack.push([other, object]); + if (isSameTag && !objIsObj) { + var result = (objIsArr) + ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) + : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack); + stack.pop(); + return result; + } + if (!(bitmask & COMPARE_PARTIAL_FLAG)) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), + othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); + + if (objIsWrapped || othIsWrapped) { + var objUnwrapped = objIsWrapped ? object.value() : object, + othUnwrapped = othIsWrapped ? other.value() : other; + + var result = equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack); + stack.pop(); + return result; + } + } + if (!isSameTag) { + return false; + } + var result = equalObjects(object, other, bitmask, customizer, equalFunc, stack); + stack.pop(); + return result; + } + + /** + * The base implementation of `_.isRegExp` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. + */ + function baseIsRegExp(value) { + return isObjectLike(value) && baseGetTag(value) == regexpTag; + } + + /** + * The base implementation of `_.iteratee`. + * + * @private + * @param {*} [value=_.identity] The value to convert to an iteratee. + * @returns {Function} Returns the iteratee. + */ + function baseIteratee(func) { + if (typeof func == 'function') { + return func; + } + if (func == null) { + return identity; + } + return (typeof func == 'object' ? baseMatches : baseProperty)(func); + } + + /** + * The base implementation of `_.lt` which doesn't coerce arguments. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than `other`, + * else `false`. + */ + function baseLt(value, other) { + return value < other; + } + + /** + * The base implementation of `_.map` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ + function baseMap(collection, iteratee) { + var index = -1, + result = isArrayLike(collection) ? Array(collection.length) : []; + + baseEach(collection, function(value, key, collection) { + result[++index] = iteratee(value, key, collection); + }); + return result; + } + + /** + * The base implementation of `_.matches` which doesn't clone `source`. + * + * @private + * @param {Object} source The object of property values to match. + * @returns {Function} Returns the new spec function. + */ + function baseMatches(source) { + var props = nativeKeys(source); + return function(object) { + var length = props.length; + if (object == null) { + return !length; + } + object = Object(object); + while (length--) { + var key = props[length]; + if (!(key in object && + baseIsEqual(source[key], object[key], COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG) + )) { + return false; + } + } + return true; + }; + } + + /** + * The base implementation of `_.pick` without support for individual + * property identifiers. + * + * @private + * @param {Object} object The source object. + * @param {string[]} paths The property paths to pick. + * @returns {Object} Returns the new object. + */ + function basePick(object, props) { + object = Object(object); + return reduce(props, function(result, key) { + if (key in object) { + result[key] = object[key]; + } + return result; + }, {}); + } + + /** + * The base implementation of `_.rest` which doesn't validate or coerce arguments. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + */ + function baseRest(func, start) { + return setToString(overRest(func, start, identity), func + ''); + } + + /** + * The base implementation of `_.slice` without an iteratee call guard. + * + * @private + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ + function baseSlice(array, start, end) { + var index = -1, + length = array.length; + + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = end > length ? length : end; + if (end < 0) { + end += length; + } + length = start > end ? 0 : ((end - start) >>> 0); + start >>>= 0; + + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; + } + + /** + * Copies the values of `source` to `array`. + * + * @private + * @param {Array} source The array to copy values from. + * @param {Array} [array=[]] The array to copy values to. + * @returns {Array} Returns `array`. + */ + function copyArray(source) { + return baseSlice(source, 0, source.length); + } + + /** + * The base implementation of `_.some` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + */ + function baseSome(collection, predicate) { + var result; + + baseEach(collection, function(value, index, collection) { + result = predicate(value, index, collection); + return !result; + }); + return !!result; + } + + /** + * The base implementation of `wrapperValue` which returns the result of + * performing a sequence of actions on the unwrapped `value`, where each + * successive action is supplied the return value of the previous. + * + * @private + * @param {*} value The unwrapped value. + * @param {Array} actions Actions to perform to resolve the unwrapped value. + * @returns {*} Returns the resolved value. + */ + function baseWrapperValue(value, actions) { + var result = value; + return reduce(actions, function(result, action) { + return action.func.apply(action.thisArg, arrayPush([result], action.args)); + }, result); + } + + /** + * Compares values to sort them in ascending order. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {number} Returns the sort order indicator for `value`. + */ + function compareAscending(value, other) { + if (value !== other) { + var valIsDefined = value !== undefined, + valIsNull = value === null, + valIsReflexive = value === value, + valIsSymbol = false; + + var othIsDefined = other !== undefined, + othIsNull = other === null, + othIsReflexive = other === other, + othIsSymbol = false; + + if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) || + (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) || + (valIsNull && othIsDefined && othIsReflexive) || + (!valIsDefined && othIsReflexive) || + !valIsReflexive) { + return 1; + } + if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) || + (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) || + (othIsNull && valIsDefined && valIsReflexive) || + (!othIsDefined && valIsReflexive) || + !othIsReflexive) { + return -1; + } + } + return 0; + } + + /** + * Copies properties of `source` to `object`. + * + * @private + * @param {Object} source The object to copy properties from. + * @param {Array} props The property identifiers to copy. + * @param {Object} [object={}] The object to copy properties to. + * @param {Function} [customizer] The function to customize copied values. + * @returns {Object} Returns `object`. + */ + function copyObject(source, props, object, customizer) { + var isNew = !object; + object || (object = {}); + + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index]; + + var newValue = customizer + ? customizer(object[key], source[key], key, object, source) + : undefined; + + if (newValue === undefined) { + newValue = source[key]; + } + if (isNew) { + baseAssignValue(object, key, newValue); + } else { + assignValue(object, key, newValue); + } + } + return object; + } + + /** + * Creates a function like `_.assign`. + * + * @private + * @param {Function} assigner The function to assign values. + * @returns {Function} Returns the new assigner function. + */ + function createAssigner(assigner) { + return baseRest(function(object, sources) { + var index = -1, + length = sources.length, + customizer = length > 1 ? sources[length - 1] : undefined; + + customizer = (assigner.length > 3 && typeof customizer == 'function') + ? (length--, customizer) + : undefined; + + object = Object(object); + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, index, customizer); + } + } + return object; + }); + } + + /** + * Creates a `baseEach` or `baseEachRight` function. + * + * @private + * @param {Function} eachFunc The function to iterate over a collection. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ + function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + if (collection == null) { + return collection; + } + if (!isArrayLike(collection)) { + return eachFunc(collection, iteratee); + } + var length = collection.length, + index = fromRight ? length : -1, + iterable = Object(collection); + + while ((fromRight ? index-- : ++index < length)) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; + } + + /** + * Creates a base function for methods like `_.forIn` and `_.forOwn`. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ + function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var index = -1, + iterable = Object(object), + props = keysFunc(object), + length = props.length; + + while (length--) { + var key = props[fromRight ? length : ++index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; + } + + /** + * Creates a function that produces an instance of `Ctor` regardless of + * whether it was invoked as part of a `new` expression or by `call` or `apply`. + * + * @private + * @param {Function} Ctor The constructor to wrap. + * @returns {Function} Returns the new wrapped function. + */ + function createCtor(Ctor) { + return function() { + // Use a `switch` statement to work with class constructors. See + // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist + // for more details. + var args = arguments; + var thisBinding = baseCreate(Ctor.prototype), + result = Ctor.apply(thisBinding, args); + + // Mimic the constructor's `return` behavior. + // See https://es5.github.io/#x13.2.2 for more details. + return isObject(result) ? result : thisBinding; + }; + } + + /** + * Creates a `_.find` or `_.findLast` function. + * + * @private + * @param {Function} findIndexFunc The function to find the collection index. + * @returns {Function} Returns the new find function. + */ + function createFind(findIndexFunc) { + return function(collection, predicate, fromIndex) { + var iterable = Object(collection); + if (!isArrayLike(collection)) { + var iteratee = baseIteratee(predicate, 3); + collection = keys(collection); + predicate = function(key) { return iteratee(iterable[key], key, iterable); }; + } + var index = findIndexFunc(collection, predicate, fromIndex); + return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined; + }; + } + + /** + * Creates a function that wraps `func` to invoke it with the `this` binding + * of `thisArg` and `partials` prepended to the arguments it receives. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} partials The arguments to prepend to those provided to + * the new function. + * @returns {Function} Returns the new wrapped function. + */ + function createPartial(func, bitmask, thisArg, partials) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + var isBind = bitmask & WRAP_BIND_FLAG, + Ctor = createCtor(func); + + function wrapper() { + var argsIndex = -1, + argsLength = arguments.length, + leftIndex = -1, + leftLength = partials.length, + args = Array(leftLength + argsLength), + fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + return fn.apply(isBind ? thisArg : this, args); + } + return wrapper; + } + + /** + * A specialized version of `baseIsEqualDeep` for arrays with support for + * partial deep comparisons. + * + * @private + * @param {Array} array The array to compare. + * @param {Array} other The other array to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `array` and `other` objects. + * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. + */ + function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + arrLength = array.length, + othLength = other.length; + + if (arrLength != othLength && !(isPartial && othLength > arrLength)) { + return false; + } + var index = -1, + result = true, + seen = (bitmask & COMPARE_UNORDERED_FLAG) ? [] : undefined; + + // Ignore non-index properties. + while (++index < arrLength) { + var arrValue = array[index], + othValue = other[index]; + + var compared; + if (compared !== undefined) { + if (compared) { + continue; + } + result = false; + break; + } + // Recursively compare arrays (susceptible to call stack limits). + if (seen) { + if (!baseSome(other, function(othValue, othIndex) { + if (!indexOf(seen, othIndex) && + (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) { + return seen.push(othIndex); + } + })) { + result = false; + break; + } + } else if (!( + arrValue === othValue || + equalFunc(arrValue, othValue, bitmask, customizer, stack) + )) { + result = false; + break; + } + } + return result; + } + + /** + * A specialized version of `baseIsEqualDeep` for comparing objects of + * the same `toStringTag`. + * + * **Note:** This function only supports comparing values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {string} tag The `toStringTag` of the objects to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) { + switch (tag) { + + case boolTag: + case dateTag: + case numberTag: + // Coerce booleans to `1` or `0` and dates to milliseconds. + // Invalid dates are coerced to `NaN`. + return eq(+object, +other); + + case errorTag: + return object.name == other.name && object.message == other.message; + + case regexpTag: + case stringTag: + // Coerce regexes to strings and treat strings, primitives and objects, + // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring + // for more details. + return object == (other + ''); + + } + return false; + } + + /** + * A specialized version of `baseIsEqualDeep` for objects with support for + * partial deep comparisons. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function equalObjects(object, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + objProps = keys(object), + objLength = objProps.length, + othProps = keys(other), + othLength = othProps.length; + + if (objLength != othLength && !isPartial) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + var result = true; + + var skipCtor = isPartial; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], + othValue = other[key]; + + var compared; + // Recursively compare objects (susceptible to call stack limits). + if (!(compared === undefined + ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack)) + : compared + )) { + result = false; + break; + } + skipCtor || (skipCtor = key == 'constructor'); + } + if (result && !skipCtor) { + var objCtor = object.constructor, + othCtor = other.constructor; + + // Non `Object` object instances with different constructors are not equal. + if (objCtor != othCtor && + ('constructor' in object && 'constructor' in other) && + !(typeof objCtor == 'function' && objCtor instanceof objCtor && + typeof othCtor == 'function' && othCtor instanceof othCtor)) { + result = false; + } + } + return result; + } + + /** + * A specialized version of `baseRest` which flattens the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @returns {Function} Returns the new function. + */ + function flatRest(func) { + return setToString(overRest(func, undefined, flatten), func + ''); + } + + /** + * Checks if `value` is a flattenable `arguments` object or array. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is flattenable, else `false`. + */ + function isFlattenable(value) { + return isArray(value) || isArguments(value); + } + + /** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ + function isIndex(value, length) { + var type = typeof value; + length = length == null ? MAX_SAFE_INTEGER : length; + + return !!length && + (type == 'number' || + (type != 'symbol' && reIsUint.test(value))) && + (value > -1 && value % 1 == 0 && value < length); + } + + /** + * Checks if the given arguments are from an iteratee call. + * + * @private + * @param {*} value The potential iteratee value argument. + * @param {*} index The potential iteratee index or key argument. + * @param {*} object The potential iteratee object argument. + * @returns {boolean} Returns `true` if the arguments are from an iteratee call, + * else `false`. + */ + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == 'number' + ? (isArrayLike(object) && isIndex(index, object.length)) + : (type == 'string' && index in object) + ) { + return eq(object[index], value); + } + return false; + } + + /** + * This function is like + * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * except that it includes inherited enumerable properties. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function nativeKeysIn(object) { + var result = []; + if (object != null) { + for (var key in Object(object)) { + result.push(key); + } + } + return result; + } + + /** + * Converts `value` to a string using `Object.prototype.toString`. + * + * @private + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + */ + function objectToString(value) { + return nativeObjectToString.call(value); + } + + /** + * A specialized version of `baseRest` which transforms the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @param {Function} transform The rest array transform. + * @returns {Function} Returns the new function. + */ + function overRest(func, start, transform) { + start = nativeMax(start === undefined ? (func.length - 1) : start, 0); + return function() { + var args = arguments, + index = -1, + length = nativeMax(args.length - start, 0), + array = Array(length); + + while (++index < length) { + array[index] = args[start + index]; + } + index = -1; + var otherArgs = Array(start + 1); + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = transform(array); + return func.apply(this, otherArgs); + }; + } + + /** + * Sets the `toString` method of `func` to return `string`. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var setToString = identity; + + /*------------------------------------------------------------------------*/ + + /** + * Creates an array with all falsey values removed. The values `false`, `null`, + * `0`, `""`, `undefined`, and `NaN` are falsey. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to compact. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.compact([0, 1, false, 2, '', 3]); + * // => [1, 2, 3] + */ + function compact(array) { + return baseFilter(array, Boolean); + } + + /** + * Creates a new array concatenating `array` with any additional arrays + * and/or values. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to concatenate. + * @param {...*} [values] The values to concatenate. + * @returns {Array} Returns the new concatenated array. + * @example + * + * var array = [1]; + * var other = _.concat(array, 2, [3], [[4]]); + * + * console.log(other); + * // => [1, 2, 3, [4]] + * + * console.log(array); + * // => [1] + */ + function concat() { + var length = arguments.length; + if (!length) { + return []; + } + var args = Array(length - 1), + array = arguments[0], + index = length; + + while (index--) { + args[index - 1] = arguments[index]; + } + return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1)); + } + + /** + * This method is like `_.find` except that it returns the index of the first + * element `predicate` returns truthy for instead of the element itself. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=0] The index to search from. + * @returns {number} Returns the index of the found element, else `-1`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.findIndex(users, function(o) { return o.user == 'barney'; }); + * // => 0 + * + * // The `_.matches` iteratee shorthand. + * _.findIndex(users, { 'user': 'fred', 'active': false }); + * // => 1 + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findIndex(users, ['active', false]); + * // => 0 + * + * // The `_.property` iteratee shorthand. + * _.findIndex(users, 'active'); + * // => 2 + */ + function findIndex(array, predicate, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = fromIndex == null ? 0 : toInteger(fromIndex); + if (index < 0) { + index = nativeMax(length + index, 0); + } + return baseFindIndex(array, baseIteratee(predicate, 3), index); + } + + /** + * Flattens `array` a single level deep. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to flatten. + * @returns {Array} Returns the new flattened array. + * @example + * + * _.flatten([1, [2, [3, [4]], 5]]); + * // => [1, 2, [3, [4]], 5] + */ + function flatten(array) { + var length = array == null ? 0 : array.length; + return length ? baseFlatten(array, 1) : []; + } + + /** + * Recursively flattens `array`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to flatten. + * @returns {Array} Returns the new flattened array. + * @example + * + * _.flattenDeep([1, [2, [3, [4]], 5]]); + * // => [1, 2, 3, 4, 5] + */ + function flattenDeep(array) { + var length = array == null ? 0 : array.length; + return length ? baseFlatten(array, INFINITY) : []; + } + + /** + * Gets the first element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @alias first + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the first element of `array`. + * @example + * + * _.head([1, 2, 3]); + * // => 1 + * + * _.head([]); + * // => undefined + */ + function head(array) { + return (array && array.length) ? array[0] : undefined; + } + + /** + * Gets the index at which the first occurrence of `value` is found in `array` + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. If `fromIndex` is negative, it's used as the + * offset from the end of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=0] The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.indexOf([1, 2, 1, 2], 2); + * // => 1 + * + * // Search from the `fromIndex`. + * _.indexOf([1, 2, 1, 2], 2, 2); + * // => 3 + */ + function indexOf(array, value, fromIndex) { + var length = array == null ? 0 : array.length; + if (typeof fromIndex == 'number') { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex; + } else { + fromIndex = 0; + } + var index = (fromIndex || 0) - 1, + isReflexive = value === value; + + while (++index < length) { + var other = array[index]; + if ((isReflexive ? other === value : other !== other)) { + return index; + } + } + return -1; + } + + /** + * Gets the last element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the last element of `array`. + * @example + * + * _.last([1, 2, 3]); + * // => 3 + */ + function last(array) { + var length = array == null ? 0 : array.length; + return length ? array[length - 1] : undefined; + } + + /** + * Creates a slice of `array` from `start` up to, but not including, `end`. + * + * **Note:** This method is used instead of + * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are + * returned. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ + function slice(array, start, end) { + var length = array == null ? 0 : array.length; + start = start == null ? 0 : +start; + end = end === undefined ? length : +end; + return length ? baseSlice(array, start, end) : []; + } + + /*------------------------------------------------------------------------*/ + + /** + * Creates a `lodash` wrapper instance that wraps `value` with explicit method + * chain sequences enabled. The result of such sequences must be unwrapped + * with `_#value`. + * + * @static + * @memberOf _ + * @since 1.3.0 + * @category Seq + * @param {*} value The value to wrap. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'pebbles', 'age': 1 } + * ]; + * + * var youngest = _ + * .chain(users) + * .sortBy('age') + * .map(function(o) { + * return o.user + ' is ' + o.age; + * }) + * .head() + * .value(); + * // => 'pebbles is 1' + */ + function chain(value) { + var result = lodash(value); + result.__chain__ = true; + return result; + } + + /** + * This method invokes `interceptor` and returns `value`. The interceptor + * is invoked with one argument; (value). The purpose of this method is to + * "tap into" a method chain sequence in order to modify intermediate results. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Seq + * @param {*} value The value to provide to `interceptor`. + * @param {Function} interceptor The function to invoke. + * @returns {*} Returns `value`. + * @example + * + * _([1, 2, 3]) + * .tap(function(array) { + * // Mutate input array. + * array.pop(); + * }) + * .reverse() + * .value(); + * // => [2, 1] + */ + function tap(value, interceptor) { + interceptor(value); + return value; + } + + /** + * This method is like `_.tap` except that it returns the result of `interceptor`. + * The purpose of this method is to "pass thru" values replacing intermediate + * results in a method chain sequence. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Seq + * @param {*} value The value to provide to `interceptor`. + * @param {Function} interceptor The function to invoke. + * @returns {*} Returns the result of `interceptor`. + * @example + * + * _(' abc ') + * .chain() + * .trim() + * .thru(function(value) { + * return [value]; + * }) + * .value(); + * // => ['abc'] + */ + function thru(value, interceptor) { + return interceptor(value); + } + + /** + * Creates a `lodash` wrapper instance with explicit method chain sequences enabled. + * + * @name chain + * @memberOf _ + * @since 0.1.0 + * @category Seq + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 } + * ]; + * + * // A sequence without explicit chaining. + * _(users).head(); + * // => { 'user': 'barney', 'age': 36 } + * + * // A sequence with explicit chaining. + * _(users) + * .chain() + * .head() + * .pick('user') + * .value(); + * // => { 'user': 'barney' } + */ + function wrapperChain() { + return chain(this); + } + + /** + * Executes the chain sequence to resolve the unwrapped value. + * + * @name value + * @memberOf _ + * @since 0.1.0 + * @alias toJSON, valueOf + * @category Seq + * @returns {*} Returns the resolved unwrapped value. + * @example + * + * _([1, 2, 3]).value(); + * // => [1, 2, 3] + */ + function wrapperValue() { + return baseWrapperValue(this.__wrapped__, this.__actions__); + } + + /*------------------------------------------------------------------------*/ + + /** + * Checks if `predicate` returns truthy for **all** elements of `collection`. + * Iteration is stopped once `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index|key, collection). + * + * **Note:** This method returns `true` for + * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because + * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of + * elements of empty collections. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false`. + * @example + * + * _.every([true, 1, null, 'yes'], Boolean); + * // => false + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * // The `_.matches` iteratee shorthand. + * _.every(users, { 'user': 'barney', 'active': false }); + * // => false + * + * // The `_.matchesProperty` iteratee shorthand. + * _.every(users, ['active', false]); + * // => true + * + * // The `_.property` iteratee shorthand. + * _.every(users, 'active'); + * // => false + */ + function every(collection, predicate, guard) { + predicate = guard ? undefined : predicate; + return baseEvery(collection, baseIteratee(predicate)); + } + + /** + * Iterates over elements of `collection`, returning an array of all elements + * `predicate` returns truthy for. The predicate is invoked with three + * arguments: (value, index|key, collection). + * + * **Note:** Unlike `_.remove`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + * @see _.reject + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * _.filter(users, function(o) { return !o.active; }); + * // => objects for ['fred'] + * + * // The `_.matches` iteratee shorthand. + * _.filter(users, { 'age': 36, 'active': true }); + * // => objects for ['barney'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.filter(users, ['active', false]); + * // => objects for ['fred'] + * + * // The `_.property` iteratee shorthand. + * _.filter(users, 'active'); + * // => objects for ['barney'] + */ + function filter(collection, predicate) { + return baseFilter(collection, baseIteratee(predicate)); + } + + /** + * Iterates over elements of `collection`, returning the first element + * `predicate` returns truthy for. The predicate is invoked with three + * arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=0] The index to search from. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false }, + * { 'user': 'pebbles', 'age': 1, 'active': true } + * ]; + * + * _.find(users, function(o) { return o.age < 40; }); + * // => object for 'barney' + * + * // The `_.matches` iteratee shorthand. + * _.find(users, { 'age': 1, 'active': true }); + * // => object for 'pebbles' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.find(users, ['active', false]); + * // => object for 'fred' + * + * // The `_.property` iteratee shorthand. + * _.find(users, 'active'); + * // => object for 'barney' + */ + var find = createFind(findIndex); + + /** + * Iterates over elements of `collection` and invokes `iteratee` for each element. + * The iteratee is invoked with three arguments: (value, index|key, collection). + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * **Note:** As with other "Collections" methods, objects with a "length" + * property are iterated like arrays. To avoid this behavior use `_.forIn` + * or `_.forOwn` for object iteration. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @alias each + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + * @see _.forEachRight + * @example + * + * _.forEach([1, 2], function(value) { + * console.log(value); + * }); + * // => Logs `1` then `2`. + * + * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a' then 'b' (iteration order is not guaranteed). + */ + function forEach(collection, iteratee) { + return baseEach(collection, baseIteratee(iteratee)); + } + + /** + * Creates an array of values by running each element in `collection` thru + * `iteratee`. The iteratee is invoked with three arguments: + * (value, index|key, collection). + * + * Many lodash methods are guarded to work as iteratees for methods like + * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`. + * + * The guarded methods are: + * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`, + * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`, + * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`, + * `template`, `trim`, `trimEnd`, `trimStart`, and `words` + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + * @example + * + * function square(n) { + * return n * n; + * } + * + * _.map([4, 8], square); + * // => [16, 64] + * + * _.map({ 'a': 4, 'b': 8 }, square); + * // => [16, 64] (iteration order is not guaranteed) + * + * var users = [ + * { 'user': 'barney' }, + * { 'user': 'fred' } + * ]; + * + * // The `_.property` iteratee shorthand. + * _.map(users, 'user'); + * // => ['barney', 'fred'] + */ + function map(collection, iteratee) { + return baseMap(collection, baseIteratee(iteratee)); + } + + /** + * Reduces `collection` to a value which is the accumulated result of running + * each element in `collection` thru `iteratee`, where each successive + * invocation is supplied the return value of the previous. If `accumulator` + * is not given, the first element of `collection` is used as the initial + * value. The iteratee is invoked with four arguments: + * (accumulator, value, index|key, collection). + * + * Many lodash methods are guarded to work as iteratees for methods like + * `_.reduce`, `_.reduceRight`, and `_.transform`. + * + * The guarded methods are: + * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`, + * and `sortBy` + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @returns {*} Returns the accumulated value. + * @see _.reduceRight + * @example + * + * _.reduce([1, 2], function(sum, n) { + * return sum + n; + * }, 0); + * // => 3 + * + * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { + * (result[value] || (result[value] = [])).push(key); + * return result; + * }, {}); + * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed) + */ + function reduce(collection, iteratee, accumulator) { + return baseReduce(collection, baseIteratee(iteratee), accumulator, arguments.length < 3, baseEach); + } + + /** + * Gets the size of `collection` by returning its length for array-like + * values or the number of own enumerable string keyed properties for objects. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object|string} collection The collection to inspect. + * @returns {number} Returns the collection size. + * @example + * + * _.size([1, 2, 3]); + * // => 3 + * + * _.size({ 'a': 1, 'b': 2 }); + * // => 2 + * + * _.size('pebbles'); + * // => 7 + */ + function size(collection) { + if (collection == null) { + return 0; + } + collection = isArrayLike(collection) ? collection : nativeKeys(collection); + return collection.length; + } + + /** + * Checks if `predicate` returns truthy for **any** element of `collection`. + * Iteration is stopped once `predicate` returns truthy. The predicate is + * invoked with three arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + * @example + * + * _.some([null, 0, 'yes', false], Boolean); + * // => true + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false } + * ]; + * + * // The `_.matches` iteratee shorthand. + * _.some(users, { 'user': 'barney', 'active': false }); + * // => false + * + * // The `_.matchesProperty` iteratee shorthand. + * _.some(users, ['active', false]); + * // => true + * + * // The `_.property` iteratee shorthand. + * _.some(users, 'active'); + * // => true + */ + function some(collection, predicate, guard) { + predicate = guard ? undefined : predicate; + return baseSome(collection, baseIteratee(predicate)); + } + + /** + * Creates an array of elements, sorted in ascending order by the results of + * running each element in a collection thru each iteratee. This method + * performs a stable sort, that is, it preserves the original sort order of + * equal elements. The iteratees are invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {...(Function|Function[])} [iteratees=[_.identity]] + * The iteratees to sort by. + * @returns {Array} Returns the new sorted array. + * @example + * + * var users = [ + * { 'user': 'fred', 'age': 48 }, + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'barney', 'age': 34 } + * ]; + * + * _.sortBy(users, [function(o) { return o.user; }]); + * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] + * + * _.sortBy(users, ['user', 'age']); + * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]] + */ + function sortBy(collection, iteratee) { + var index = 0; + iteratee = baseIteratee(iteratee); + + return baseMap(baseMap(collection, function(value, key, collection) { + return { 'value': value, 'index': index++, 'criteria': iteratee(value, key, collection) }; + }).sort(function(object, other) { + return compareAscending(object.criteria, other.criteria) || (object.index - other.index); + }), baseProperty('value')); + } + + /*------------------------------------------------------------------------*/ + + /** + * Creates a function that invokes `func`, with the `this` binding and arguments + * of the created function, while it's called less than `n` times. Subsequent + * calls to the created function return the result of the last `func` invocation. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {number} n The number of calls at which `func` is no longer invoked. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * jQuery(element).on('click', _.before(5, addContactToList)); + * // => Allows adding up to 4 contacts to the list. + */ + function before(n, func) { + var result; + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + n = toInteger(n); + return function() { + if (--n > 0) { + result = func.apply(this, arguments); + } + if (n <= 1) { + func = undefined; + } + return result; + }; + } + + /** + * Creates a function that invokes `func` with the `this` binding of `thisArg` + * and `partials` prepended to the arguments it receives. + * + * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds, + * may be used as a placeholder for partially applied arguments. + * + * **Note:** Unlike native `Function#bind`, this method doesn't set the "length" + * property of bound functions. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to bind. + * @param {*} thisArg The `this` binding of `func`. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * function greet(greeting, punctuation) { + * return greeting + ' ' + this.user + punctuation; + * } + * + * var object = { 'user': 'fred' }; + * + * var bound = _.bind(greet, object, 'hi'); + * bound('!'); + * // => 'hi fred!' + * + * // Bound with placeholders. + * var bound = _.bind(greet, object, _, '!'); + * bound('hi'); + * // => 'hi fred!' + */ + var bind = baseRest(function(func, thisArg, partials) { + return createPartial(func, WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG, thisArg, partials); + }); + + /** + * Defers invoking the `func` until the current call stack has cleared. Any + * additional arguments are provided to `func` when it's invoked. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to defer. + * @param {...*} [args] The arguments to invoke `func` with. + * @returns {number} Returns the timer id. + * @example + * + * _.defer(function(text) { + * console.log(text); + * }, 'deferred'); + * // => Logs 'deferred' after one millisecond. + */ + var defer = baseRest(function(func, args) { + return baseDelay(func, 1, args); + }); + + /** + * Invokes `func` after `wait` milliseconds. Any additional arguments are + * provided to `func` when it's invoked. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @param {...*} [args] The arguments to invoke `func` with. + * @returns {number} Returns the timer id. + * @example + * + * _.delay(function(text) { + * console.log(text); + * }, 1000, 'later'); + * // => Logs 'later' after one second. + */ + var delay = baseRest(function(func, wait, args) { + return baseDelay(func, toNumber(wait) || 0, args); + }); + + /** + * Creates a function that negates the result of the predicate `func`. The + * `func` predicate is invoked with the `this` binding and arguments of the + * created function. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} predicate The predicate to negate. + * @returns {Function} Returns the new negated function. + * @example + * + * function isEven(n) { + * return n % 2 == 0; + * } + * + * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); + * // => [1, 3, 5] + */ + function negate(predicate) { + if (typeof predicate != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + var args = arguments; + return !predicate.apply(this, args); + }; + } + + /** + * Creates a function that is restricted to invoking `func` once. Repeat calls + * to the function return the value of the first invocation. The `func` is + * invoked with the `this` binding and arguments of the created function. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var initialize = _.once(createApplication); + * initialize(); + * initialize(); + * // => `createApplication` is invoked once + */ + function once(func) { + return before(2, func); + } + + /*------------------------------------------------------------------------*/ + + /** + * Creates a shallow clone of `value`. + * + * **Note:** This method is loosely based on the + * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm) + * and supports cloning arrays, array buffers, booleans, date objects, maps, + * numbers, `Object` objects, regexes, sets, strings, symbols, and typed + * arrays. The own enumerable properties of `arguments` objects are cloned + * as plain objects. An empty object is returned for uncloneable values such + * as error objects, functions, DOM nodes, and WeakMaps. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to clone. + * @returns {*} Returns the cloned value. + * @see _.cloneDeep + * @example + * + * var objects = [{ 'a': 1 }, { 'b': 2 }]; + * + * var shallow = _.clone(objects); + * console.log(shallow[0] === objects[0]); + * // => true + */ + function clone(value) { + if (!isObject(value)) { + return value; + } + return isArray(value) ? copyArray(value) : copyObject(value, nativeKeys(value)); + } + + /** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */ + function eq(value, other) { + return value === other || (value !== value && other !== other); + } + + /** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ + var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { + return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && + !propertyIsEnumerable.call(value, 'callee'); + }; + + /** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ + var isArray = Array.isArray; + + /** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ + function isArrayLike(value) { + return value != null && isLength(value.length) && !isFunction(value); + } + + /** + * Checks if `value` is classified as a boolean primitive or object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a boolean, else `false`. + * @example + * + * _.isBoolean(false); + * // => true + * + * _.isBoolean(null); + * // => false + */ + function isBoolean(value) { + return value === true || value === false || + (isObjectLike(value) && baseGetTag(value) == boolTag); + } + + /** + * Checks if `value` is classified as a `Date` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a date object, else `false`. + * @example + * + * _.isDate(new Date); + * // => true + * + * _.isDate('Mon April 23 2012'); + * // => false + */ + var isDate = baseIsDate; + + /** + * Checks if `value` is an empty object, collection, map, or set. + * + * Objects are considered empty if they have no own enumerable string keyed + * properties. + * + * Array-like values such as `arguments` objects, arrays, buffers, strings, or + * jQuery-like collections are considered empty if they have a `length` of `0`. + * Similarly, maps and sets are considered empty if they have a `size` of `0`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is empty, else `false`. + * @example + * + * _.isEmpty(null); + * // => true + * + * _.isEmpty(true); + * // => true + * + * _.isEmpty(1); + * // => true + * + * _.isEmpty([1, 2, 3]); + * // => false + * + * _.isEmpty({ 'a': 1 }); + * // => false + */ + function isEmpty(value) { + if (isArrayLike(value) && + (isArray(value) || isString(value) || + isFunction(value.splice) || isArguments(value))) { + return !value.length; + } + return !nativeKeys(value).length; + } + + /** + * Performs a deep comparison between two values to determine if they are + * equivalent. + * + * **Note:** This method supports comparing arrays, array buffers, booleans, + * date objects, error objects, maps, numbers, `Object` objects, regexes, + * sets, strings, symbols, and typed arrays. `Object` objects are compared + * by their own, not inherited, enumerable properties. Functions and DOM + * nodes are compared by strict equality, i.e. `===`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.isEqual(object, other); + * // => true + * + * object === other; + * // => false + */ + function isEqual(value, other) { + return baseIsEqual(value, other); + } + + /** + * Checks if `value` is a finite primitive number. + * + * **Note:** This method is based on + * [`Number.isFinite`](https://mdn.io/Number/isFinite). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a finite number, else `false`. + * @example + * + * _.isFinite(3); + * // => true + * + * _.isFinite(Number.MIN_VALUE); + * // => true + * + * _.isFinite(Infinity); + * // => false + * + * _.isFinite('3'); + * // => false + */ + function isFinite(value) { + return typeof value == 'number' && nativeIsFinite(value); + } + + /** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ + function isFunction(value) { + if (!isObject(value)) { + return false; + } + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 9 which returns 'object' for typed arrays and other constructors. + var tag = baseGetTag(value); + return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; + } + + /** + * Checks if `value` is a valid array-like length. + * + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */ + function isLength(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + + /** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ + function isObject(value) { + var type = typeof value; + return value != null && (type == 'object' || type == 'function'); + } + + /** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ + function isObjectLike(value) { + return value != null && typeof value == 'object'; + } + + /** + * Checks if `value` is `NaN`. + * + * **Note:** This method is based on + * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as + * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for + * `undefined` and other non-number values. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + * @example + * + * _.isNaN(NaN); + * // => true + * + * _.isNaN(new Number(NaN)); + * // => true + * + * isNaN(undefined); + * // => true + * + * _.isNaN(undefined); + * // => false + */ + function isNaN(value) { + // An `NaN` primitive is the only value that is not equal to itself. + // Perform the `toStringTag` check first to avoid errors with some + // ActiveX objects in IE. + return isNumber(value) && value != +value; + } + + /** + * Checks if `value` is `null`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `null`, else `false`. + * @example + * + * _.isNull(null); + * // => true + * + * _.isNull(void 0); + * // => false + */ + function isNull(value) { + return value === null; + } + + /** + * Checks if `value` is classified as a `Number` primitive or object. + * + * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are + * classified as numbers, use the `_.isFinite` method. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a number, else `false`. + * @example + * + * _.isNumber(3); + * // => true + * + * _.isNumber(Number.MIN_VALUE); + * // => true + * + * _.isNumber(Infinity); + * // => true + * + * _.isNumber('3'); + * // => false + */ + function isNumber(value) { + return typeof value == 'number' || + (isObjectLike(value) && baseGetTag(value) == numberTag); + } + + /** + * Checks if `value` is classified as a `RegExp` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. + * @example + * + * _.isRegExp(/abc/); + * // => true + * + * _.isRegExp('/abc/'); + * // => false + */ + var isRegExp = baseIsRegExp; + + /** + * Checks if `value` is classified as a `String` primitive or object. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a string, else `false`. + * @example + * + * _.isString('abc'); + * // => true + * + * _.isString(1); + * // => false + */ + function isString(value) { + return typeof value == 'string' || + (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag); + } + + /** + * Checks if `value` is `undefined`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. + * @example + * + * _.isUndefined(void 0); + * // => true + * + * _.isUndefined(null); + * // => false + */ + function isUndefined(value) { + return value === undefined; + } + + /** + * Converts `value` to an array. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to convert. + * @returns {Array} Returns the converted array. + * @example + * + * _.toArray({ 'a': 1, 'b': 2 }); + * // => [1, 2] + * + * _.toArray('abc'); + * // => ['a', 'b', 'c'] + * + * _.toArray(1); + * // => [] + * + * _.toArray(null); + * // => [] + */ + function toArray(value) { + if (!isArrayLike(value)) { + return values(value); + } + return value.length ? copyArray(value) : []; + } + + /** + * Converts `value` to an integer. + * + * **Note:** This method is loosely based on + * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toInteger(3.2); + * // => 3 + * + * _.toInteger(Number.MIN_VALUE); + * // => 0 + * + * _.toInteger(Infinity); + * // => 1.7976931348623157e+308 + * + * _.toInteger('3.2'); + * // => 3 + */ + var toInteger = Number; + + /** + * Converts `value` to a number. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to process. + * @returns {number} Returns the number. + * @example + * + * _.toNumber(3.2); + * // => 3.2 + * + * _.toNumber(Number.MIN_VALUE); + * // => 5e-324 + * + * _.toNumber(Infinity); + * // => Infinity + * + * _.toNumber('3.2'); + * // => 3.2 + */ + var toNumber = Number; + + /** + * Converts `value` to a string. An empty string is returned for `null` + * and `undefined` values. The sign of `-0` is preserved. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.toString(null); + * // => '' + * + * _.toString(-0); + * // => '-0' + * + * _.toString([1, 2, 3]); + * // => '1,2,3' + */ + function toString(value) { + if (typeof value == 'string') { + return value; + } + return value == null ? '' : (value + ''); + } + + /*------------------------------------------------------------------------*/ + + /** + * Assigns own enumerable string keyed properties of source objects to the + * destination object. Source objects are applied from left to right. + * Subsequent sources overwrite property assignments of previous sources. + * + * **Note:** This method mutates `object` and is loosely based on + * [`Object.assign`](https://mdn.io/Object/assign). + * + * @static + * @memberOf _ + * @since 0.10.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.assignIn + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * function Bar() { + * this.c = 3; + * } + * + * Foo.prototype.b = 2; + * Bar.prototype.d = 4; + * + * _.assign({ 'a': 0 }, new Foo, new Bar); + * // => { 'a': 1, 'c': 3 } + */ + var assign = createAssigner(function(object, source) { + copyObject(source, nativeKeys(source), object); + }); + + /** + * This method is like `_.assign` except that it iterates over own and + * inherited source properties. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias extend + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.assign + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * function Bar() { + * this.c = 3; + * } + * + * Foo.prototype.b = 2; + * Bar.prototype.d = 4; + * + * _.assignIn({ 'a': 0 }, new Foo, new Bar); + * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 } + */ + var assignIn = createAssigner(function(object, source) { + copyObject(source, nativeKeysIn(source), object); + }); + + /** + * Creates an object that inherits from the `prototype` object. If a + * `properties` object is given, its own enumerable string keyed properties + * are assigned to the created object. + * + * @static + * @memberOf _ + * @since 2.3.0 + * @category Object + * @param {Object} prototype The object to inherit from. + * @param {Object} [properties] The properties to assign to the object. + * @returns {Object} Returns the new object. + * @example + * + * function Shape() { + * this.x = 0; + * this.y = 0; + * } + * + * function Circle() { + * Shape.call(this); + * } + * + * Circle.prototype = _.create(Shape.prototype, { + * 'constructor': Circle + * }); + * + * var circle = new Circle; + * circle instanceof Circle; + * // => true + * + * circle instanceof Shape; + * // => true + */ + function create(prototype, properties) { + var result = baseCreate(prototype); + return properties == null ? result : assign(result, properties); + } + + /** + * Assigns own and inherited enumerable string keyed properties of source + * objects to the destination object for all destination properties that + * resolve to `undefined`. Source objects are applied from left to right. + * Once a property is set, additional values of the same property are ignored. + * + * **Note:** This method mutates `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.defaultsDeep + * @example + * + * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ + var defaults = baseRest(function(object, sources) { + object = Object(object); + + var index = -1; + var length = sources.length; + var guard = length > 2 ? sources[2] : undefined; + + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + length = 1; + } + + while (++index < length) { + var source = sources[index]; + var props = keysIn(source); + var propsIndex = -1; + var propsLength = props.length; + + while (++propsIndex < propsLength) { + var key = props[propsIndex]; + var value = object[key]; + + if (value === undefined || + (eq(value, objectProto[key]) && !hasOwnProperty.call(object, key))) { + object[key] = source[key]; + } + } + } + + return object; + }); + + /** + * Checks if `path` is a direct property of `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + * @example + * + * var object = { 'a': { 'b': 2 } }; + * var other = _.create({ 'a': _.create({ 'b': 2 }) }); + * + * _.has(object, 'a'); + * // => true + * + * _.has(object, 'a.b'); + * // => true + * + * _.has(object, ['a', 'b']); + * // => true + * + * _.has(other, 'a'); + * // => false + */ + function has(object, path) { + return object != null && hasOwnProperty.call(object, path); + } + + /** + * Creates an array of the own enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. See the + * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * for more details. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keys(new Foo); + * // => ['a', 'b'] (iteration order is not guaranteed) + * + * _.keys('hi'); + * // => ['0', '1'] + */ + var keys = nativeKeys; + + /** + * Creates an array of the own and inherited enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keysIn(new Foo); + * // => ['a', 'b', 'c'] (iteration order is not guaranteed) + */ + var keysIn = nativeKeysIn; + + /** + * Creates an object composed of the picked `object` properties. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The source object. + * @param {...(string|string[])} [paths] The property paths to pick. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.pick(object, ['a', 'c']); + * // => { 'a': 1, 'c': 3 } + */ + var pick = flatRest(function(object, paths) { + return object == null ? {} : basePick(object, paths); + }); + + /** + * This method is like `_.get` except that if the resolved value is a + * function it's invoked with the `this` binding of its parent object and + * its result is returned. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to resolve. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. + * @returns {*} Returns the resolved value. + * @example + * + * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] }; + * + * _.result(object, 'a[0].b.c1'); + * // => 3 + * + * _.result(object, 'a[0].b.c2'); + * // => 4 + * + * _.result(object, 'a[0].b.c3', 'default'); + * // => 'default' + * + * _.result(object, 'a[0].b.c3', _.constant('default')); + * // => 'default' + */ + function result(object, path, defaultValue) { + var value = object == null ? undefined : object[path]; + if (value === undefined) { + value = defaultValue; + } + return isFunction(value) ? value.call(object) : value; + } + + /** + * Creates an array of the own enumerable string keyed property values of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property values. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.values(new Foo); + * // => [1, 2] (iteration order is not guaranteed) + * + * _.values('hi'); + * // => ['h', 'i'] + */ + function values(object) { + return object == null ? [] : baseValues(object, keys(object)); + } + + /*------------------------------------------------------------------------*/ + + /** + * Converts the characters "&", "<", ">", '"', and "'" in `string` to their + * corresponding HTML entities. + * + * **Note:** No other characters are escaped. To escape additional + * characters use a third-party library like [_he_](https://mths.be/he). + * + * Though the ">" character is escaped for symmetry, characters like + * ">" and "/" don't need escaping in HTML and have no special meaning + * unless they're part of a tag or unquoted attribute value. See + * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) + * (under "semi-related fun fact") for more details. + * + * When working with HTML you should always + * [quote attribute values](http://wonko.com/post/html-escaping) to reduce + * XSS vectors. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category String + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escape('fred, barney, & pebbles'); + * // => 'fred, barney, & pebbles' + */ + function escape(string) { + string = toString(string); + return (string && reHasUnescapedHtml.test(string)) + ? string.replace(reUnescapedHtml, escapeHtmlChar) + : string; + } + + /*------------------------------------------------------------------------*/ + + /** + * This method returns the first argument it receives. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Util + * @param {*} value Any value. + * @returns {*} Returns `value`. + * @example + * + * var object = { 'a': 1 }; + * + * console.log(_.identity(object) === object); + * // => true + */ + function identity(value) { + return value; + } + + /** + * Creates a function that invokes `func` with the arguments of the created + * function. If `func` is a property name, the created function returns the + * property value for a given element. If `func` is an array or object, the + * created function returns `true` for elements that contain the equivalent + * source properties, otherwise it returns `false`. + * + * @static + * @since 4.0.0 + * @memberOf _ + * @category Util + * @param {*} [func=_.identity] The value to convert to a callback. + * @returns {Function} Returns the callback. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * // The `_.matches` iteratee shorthand. + * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true })); + * // => [{ 'user': 'barney', 'age': 36, 'active': true }] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.filter(users, _.iteratee(['user', 'fred'])); + * // => [{ 'user': 'fred', 'age': 40 }] + * + * // The `_.property` iteratee shorthand. + * _.map(users, _.iteratee('user')); + * // => ['barney', 'fred'] + * + * // Create custom iteratee shorthands. + * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) { + * return !_.isRegExp(func) ? iteratee(func) : function(string) { + * return func.test(string); + * }; + * }); + * + * _.filter(['abc', 'def'], /ef/); + * // => ['def'] + */ + var iteratee = baseIteratee; + + /** + * Creates a function that performs a partial deep comparison between a given + * object and `source`, returning `true` if the given object has equivalent + * property values, else `false`. + * + * **Note:** The created function is equivalent to `_.isMatch` with `source` + * partially applied. + * + * Partial comparisons will match empty array and empty object `source` + * values against any array or object value, respectively. See `_.isEqual` + * for a list of supported value comparisons. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Util + * @param {Object} source The object of property values to match. + * @returns {Function} Returns the new spec function. + * @example + * + * var objects = [ + * { 'a': 1, 'b': 2, 'c': 3 }, + * { 'a': 4, 'b': 5, 'c': 6 } + * ]; + * + * _.filter(objects, _.matches({ 'a': 4, 'c': 6 })); + * // => [{ 'a': 4, 'b': 5, 'c': 6 }] + */ + function matches(source) { + return baseMatches(assign({}, source)); + } + + /** + * Adds all own enumerable string keyed function properties of a source + * object to the destination object. If `object` is a function, then methods + * are added to its prototype as well. + * + * **Note:** Use `_.runInContext` to create a pristine `lodash` function to + * avoid conflicts caused by modifying the original. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Util + * @param {Function|Object} [object=lodash] The destination object. + * @param {Object} source The object of functions to add. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.chain=true] Specify whether mixins are chainable. + * @returns {Function|Object} Returns `object`. + * @example + * + * function vowels(string) { + * return _.filter(string, function(v) { + * return /[aeiou]/i.test(v); + * }); + * } + * + * _.mixin({ 'vowels': vowels }); + * _.vowels('fred'); + * // => ['e'] + * + * _('fred').vowels().value(); + * // => ['e'] + * + * _.mixin({ 'vowels': vowels }, { 'chain': false }); + * _('fred').vowels(); + * // => ['e'] + */ + function mixin(object, source, options) { + var props = keys(source), + methodNames = baseFunctions(source, props); + + if (options == null && + !(isObject(source) && (methodNames.length || !props.length))) { + options = source; + source = object; + object = this; + methodNames = baseFunctions(source, keys(source)); + } + var chain = !(isObject(options) && 'chain' in options) || !!options.chain, + isFunc = isFunction(object); + + baseEach(methodNames, function(methodName) { + var func = source[methodName]; + object[methodName] = func; + if (isFunc) { + object.prototype[methodName] = function() { + var chainAll = this.__chain__; + if (chain || chainAll) { + var result = object(this.__wrapped__), + actions = result.__actions__ = copyArray(this.__actions__); + + actions.push({ 'func': func, 'args': arguments, 'thisArg': object }); + result.__chain__ = chainAll; + return result; + } + return func.apply(object, arrayPush([this.value()], arguments)); + }; + } + }); + + return object; + } + + /** + * Reverts the `_` variable to its previous value and returns a reference to + * the `lodash` function. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Util + * @returns {Function} Returns the `lodash` function. + * @example + * + * var lodash = _.noConflict(); + */ + function noConflict() { + if (root._ === this) { + root._ = oldDash; + } + return this; + } + + /** + * This method returns `undefined`. + * + * @static + * @memberOf _ + * @since 2.3.0 + * @category Util + * @example + * + * _.times(2, _.noop); + * // => [undefined, undefined] + */ + function noop() { + // No operation performed. + } + + /** + * Generates a unique ID. If `prefix` is given, the ID is appended to it. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Util + * @param {string} [prefix=''] The value to prefix the ID with. + * @returns {string} Returns the unique ID. + * @example + * + * _.uniqueId('contact_'); + * // => 'contact_104' + * + * _.uniqueId(); + * // => '105' + */ + function uniqueId(prefix) { + var id = ++idCounter; + return toString(prefix) + id; + } + + /*------------------------------------------------------------------------*/ + + /** + * Computes the maximum value of `array`. If `array` is empty or falsey, + * `undefined` is returned. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Math + * @param {Array} array The array to iterate over. + * @returns {*} Returns the maximum value. + * @example + * + * _.max([4, 2, 8, 6]); + * // => 8 + * + * _.max([]); + * // => undefined + */ + function max(array) { + return (array && array.length) + ? baseExtremum(array, identity, baseGt) + : undefined; + } + + /** + * Computes the minimum value of `array`. If `array` is empty or falsey, + * `undefined` is returned. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Math + * @param {Array} array The array to iterate over. + * @returns {*} Returns the minimum value. + * @example + * + * _.min([4, 2, 8, 6]); + * // => 2 + * + * _.min([]); + * // => undefined + */ + function min(array) { + return (array && array.length) + ? baseExtremum(array, identity, baseLt) + : undefined; + } + + /*------------------------------------------------------------------------*/ + + // Add methods that return wrapped values in chain sequences. + lodash.assignIn = assignIn; + lodash.before = before; + lodash.bind = bind; + lodash.chain = chain; + lodash.compact = compact; + lodash.concat = concat; + lodash.create = create; + lodash.defaults = defaults; + lodash.defer = defer; + lodash.delay = delay; + lodash.filter = filter; + lodash.flatten = flatten; + lodash.flattenDeep = flattenDeep; + lodash.iteratee = iteratee; + lodash.keys = keys; + lodash.map = map; + lodash.matches = matches; + lodash.mixin = mixin; + lodash.negate = negate; + lodash.once = once; + lodash.pick = pick; + lodash.slice = slice; + lodash.sortBy = sortBy; + lodash.tap = tap; + lodash.thru = thru; + lodash.toArray = toArray; + lodash.values = values; + + // Add aliases. + lodash.extend = assignIn; + + // Add methods to `lodash.prototype`. + mixin(lodash, lodash); + + /*------------------------------------------------------------------------*/ + + // Add methods that return unwrapped values in chain sequences. + lodash.clone = clone; + lodash.escape = escape; + lodash.every = every; + lodash.find = find; + lodash.forEach = forEach; + lodash.has = has; + lodash.head = head; + lodash.identity = identity; + lodash.indexOf = indexOf; + lodash.isArguments = isArguments; + lodash.isArray = isArray; + lodash.isBoolean = isBoolean; + lodash.isDate = isDate; + lodash.isEmpty = isEmpty; + lodash.isEqual = isEqual; + lodash.isFinite = isFinite; + lodash.isFunction = isFunction; + lodash.isNaN = isNaN; + lodash.isNull = isNull; + lodash.isNumber = isNumber; + lodash.isObject = isObject; + lodash.isRegExp = isRegExp; + lodash.isString = isString; + lodash.isUndefined = isUndefined; + lodash.last = last; + lodash.max = max; + lodash.min = min; + lodash.noConflict = noConflict; + lodash.noop = noop; + lodash.reduce = reduce; + lodash.result = result; + lodash.size = size; + lodash.some = some; + lodash.uniqueId = uniqueId; + + // Add aliases. + lodash.each = forEach; + lodash.first = head; + + mixin(lodash, (function() { + var source = {}; + baseForOwn(lodash, function(func, methodName) { + if (!hasOwnProperty.call(lodash.prototype, methodName)) { + source[methodName] = func; + } + }); + return source; + }()), { 'chain': false }); + + /*------------------------------------------------------------------------*/ + + /** + * The semantic version number. + * + * @static + * @memberOf _ + * @type {string} + */ + lodash.VERSION = VERSION; + + // Add `Array` methods to `lodash.prototype`. + baseEach(['pop', 'join', 'replace', 'reverse', 'split', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) { + var func = (/^(?:replace|split)$/.test(methodName) ? String.prototype : arrayProto)[methodName], + chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru', + retUnwrapped = /^(?:pop|join|replace|shift)$/.test(methodName); + + lodash.prototype[methodName] = function() { + var args = arguments; + if (retUnwrapped && !this.__chain__) { + var value = this.value(); + return func.apply(isArray(value) ? value : [], args); + } + return this[chainName](function(value) { + return func.apply(isArray(value) ? value : [], args); + }); + }; + }); + + // Add chain sequence methods to the `lodash` wrapper. + lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; + + /*--------------------------------------------------------------------------*/ + + // Some AMD build optimizers, like r.js, check for condition patterns like: + if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { + // Expose Lodash on the global object to prevent errors when Lodash is + // loaded by a script tag in the presence of an AMD loader. + // See http://requirejs.org/docs/errors.html#mismatch for more details. + // Use `_.noConflict` to remove Lodash from the global object. + root._ = lodash; + + // Define as an anonymous module so, through path mapping, it can be + // referenced as the "underscore" module. + define(function() { + return lodash; + }); + } + // Check for `exports` after `define` in case a build optimizer adds it. + else if (freeModule) { + // Export for Node.js. + (freeModule.exports = lodash)._ = lodash; + // Export for CommonJS support. + freeExports._ = lodash; + } + else { + // Export to the global object. + root._ = lodash; + } +}.call(this)); 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..3e65ef5 --- /dev/null +++ b/assets/js/solight/sol.js @@ -0,0 +1,1090 @@ +'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(); + // TODO: Hack as id is nil in current export + m.set('id', personJ.code); + 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..5b7b88a --- /dev/null +++ b/config/_default/config.toml @@ -0,0 +1,21 @@ +baseURL = "https://files.chvoc.ch/" +languageCode = 'de-DE' +title = 'DGWK25' + +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/wk25/schedule/export/schedule.json' +scheduleFetchInterval = 60 diff --git a/config/production/config.toml b/config/production/config.toml new file mode 100644 index 0000000..4e44fc9 --- /dev/null +++ b/config/production/config.toml @@ -0,0 +1,9 @@ +baseURL = "https://files.chvoc.ch/dgwk25/info/" + + +[params] +workerBaseURL = '/dgwk25/info/js/custom/core/' + +scheduleURL = '/dgwk25/info/schedule.json' +#scheduleURL = 'https://cfp.winterkongress.ch/wk25/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/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..4b81888 --- /dev/null +++ b/layouts/schedule-hall1/single.html @@ -0,0 +1,20 @@ +{{ 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" }} + +
+ +
+
+{{ end }} diff --git a/layouts/schedule-hall2/single.html b/layouts/schedule-hall2/single.html new file mode 100644 index 0000000..874e592 --- /dev/null +++ b/layouts/schedule-hall2/single.html @@ -0,0 +1,20 @@ +{{ 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" }} + +
+ +
+
+{{ end }} diff --git a/layouts/schedule-hall3/single.html b/layouts/schedule-hall3/single.html new file mode 100644 index 0000000..d48f9e3 --- /dev/null +++ b/layouts/schedule-hall3/single.html @@ -0,0 +1,20 @@ +{{ 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" }} + +
+ +
+
+{{ end }} diff --git a/layouts/schedule/single.html b/layouts/schedule/single.html new file mode 100644 index 0000000..1438abd --- /dev/null +++ b/layouts/schedule/single.html @@ -0,0 +1,20 @@ +{{ 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" }} + +
+ +
+
+{{ 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..a279aeb --- /dev/null +++ b/layouts/upcoming-talk-hall1/single.html @@ -0,0 +1,19 @@ +{{ 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" }} + +
+ +
+{{ end }} diff --git a/layouts/upcoming-talk-hall2/single.html b/layouts/upcoming-talk-hall2/single.html new file mode 100644 index 0000000..3a86b75 --- /dev/null +++ b/layouts/upcoming-talk-hall2/single.html @@ -0,0 +1,19 @@ +{{ 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" }} + +
+ +
+{{ end }} diff --git a/layouts/upcoming-talk-hall3/single.html b/layouts/upcoming-talk-hall3/single.html new file mode 100644 index 0000000..72ed1e7 --- /dev/null +++ b/layouts/upcoming-talk-hall3/single.html @@ -0,0 +1,19 @@ +{{ 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" }} + +
+ +
+{{ 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..d60d064 Binary files /dev/null and b/static/header.png differ diff --git a/static/schedule.json b/static/schedule.json new file mode 100644 index 0000000..1abb883 --- /dev/null +++ b/static/schedule.json @@ -0,0 +1 @@ +{"$schema": "https://c3voc.de/schedule/schema.json", "generator": {"name": "pretalx", "version": "2024.4.0.dev0"}, "schedule": {"url": "https://cfp.winterkongress.ch/wk25/schedule/", "version": "0.3", "base_url": "https://cfp.winterkongress.ch", "conference": {"acronym": "wk25", "title": "Winterkongress", "start": "2025-02-28", "end": "2025-03-01", "daysCount": 2, "timeslot_duration": "00:05", "time_zone_name": "Europe/Zurich", "colors": {"primary": "#4EA93F"}, "rooms": [{"name": "Festsaal", "slug": "3758-festsaal", "guid": "5dd22456-cf6c-50ed-845b-f595b433f4fa", "description": null, "capacity": 300}, {"name": "Bankettsaal", "slug": "3759-bankettsaal", "guid": "d998d142-2db1-56c3-a800-37904a2fb3b2", "description": null, "capacity": 150}, {"name": "Tanzsaal", "slug": "3760-tanzsaal", "guid": "01292754-6298-5f1e-b35a-a3e87adb8f55", "description": null, "capacity": 100}], "tracks": [{"name": "Netzwerke, Security, Hard- & Software", "slug": "5174-netzwerke-security-hard-software", "color": "#AF0C0C"}, {"name": "Andere", "slug": "5175-andere", "color": "#BBBBBB"}, {"name": "Digitale Selbstverteidigung", "slug": "5176-digitale-selbstverteidigung", "color": "#145E9A"}, {"name": "Ethik, Wissenschaft, Kultur & Gesellschaft", "slug": "5177-ethik-wissenschaft-kultur-gesellschaft", "color": "#119633"}, {"name": "Recht & Politik", "slug": "5178-recht-politik", "color": "#91800D"}], "days": [{"index": 1, "date": "2025-02-28", "day_start": "2025-02-28T04:00:00+01:00", "day_end": "2025-03-01T03:59:00+01:00", "rooms": {"Festsaal": [{"guid": "705731d5-3a0c-5bd1-807f-3f76db045385", "code": "F9DJWC", "id": 59868, "logo": null, "date": "2025-02-28T19:00:00+01:00", "start": "19:00", "duration": "00:15", "room": "Festsaal", "slug": "wk25-59868-erffnung-freitag", "url": "https://cfp.winterkongress.ch/wk25/talk/F9DJWC/", "title": "Er\u00f6ffnung Freitag", "subtitle": "", "track": "Andere", "type": "Moderation", "language": "de", "abstract": "Die Er\u00f6ffnung am Freitag", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"code": "PLBTRP", "name": "Team Winterkongress", "avatar": null, "biography": null, "public_name": "Team Winterkongress", "guid": "6de73f8d-b1fd-5d46-9f05-b86d7c280b73", "url": "https://cfp.winterkongress.ch/wk25/speaker/PLBTRP/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/F9DJWC/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/F9DJWC/", "attachments": []}, {"guid": "c9b0c033-2096-567c-80c7-7155db3e2d65", "code": "XP3KKB", "id": 59489, "logo": null, "date": "2025-02-28T19:15:00+01:00", "start": "19:15", "duration": "00:45", "room": "Festsaal", "slug": "wk25-59489-und-kaum-eine-r-schaut-hin-polizeigesetze-und-ihre-folgen", "url": "https://cfp.winterkongress.ch/wk25/talk/XP3KKB/", "title": "Und kaum eine:r schaut hin: Polizeigesetze und ihre Folgen", "subtitle": "", "track": "Recht & Politik", "type": "Vortrag", "language": "de", "abstract": "Polizeigesetze sind Orte, wo unsere Privatsph\u00e4re, \u00dcberwachung, predictive policing und die Datennutzung durch die Polizei und in der Strafverfolgung generell verhandelt werden. Oft werden diese Polizeigesetze aber ohne \u00f6ffentliche Debatte und wenig sorgf\u00e4ltig in den Kantonen verhandelt.\r\nDer Vortrag zeigt, was die Problematiken sein k\u00f6nnen und wie sich politisch und zivilgesellschaftlich engagierte Menschen in den Kantonen in diese Debatten eingeben k\u00f6nnen. Der Fall des Luzerner Polizeigesetzes, das im November 2024 in einem spektakul\u00e4ren Urteil kassiert wurde, dient als Beispiel.", "description": "Polizeigesetze sind wichtige Orte, wo unsere Privatsph\u00e4re, \u00dcberwachung, predictive policing und die Datennutzung duch die Polizei und in der Strafverfolgung generell verhandelt werden. Die Polizei ist eine kantonale Kompetenz, und die Beratung der Polizeigesetze passiert in den Kantonsparlamenten - oft unterhalb der Schwelle der medial-\u00f6ffentlichen Debatte, mit wenig juristischem Fachwissen und mit wenig oder keinen zivilgesellschaftlichen Watchdogs. Immer wieder werde so unklare, zu wenig konkrete und unverh\u00e4ltnism\u00e4ssige Bestimmungen erlassen. Das ist problematisch, weil eine sorgf\u00e4ltige und grundrechts-sensible Gesetzgebung gerade bei Polizeigesetzen besonders wichtig ist.\r\nDer Vortrag zeigt, was die Problematik solcher Polizeigesetze sein kann und wie sich politisch und zivilgesellschaftlich engagierte Menschen in den Kantonen produktiv in diese Debatten eingeben k\u00f6nnen. Er zeigt dies auf anhand des Falls des Luzerner Polizeigesetzes. Das Bundesgericht hat dieses in einem spektakul\u00e4ren Urteil im November 2024 zersaust und die fl\u00e4chendeckende Fahrzeug-\u00dcberwachung sowie den schrankenlosen interkantonalen Datenaustausch kassiert. Methoden des \"predictive policing\" schr\u00e4nkt das Urteil massiv ein und zeigt dabei die hohen Risiken auf, welche mit dem Einsatz von K\u00fcnstlicher Intelligenz verbunden sind.\r\nDer Vortrag zeigt anhand der Geschichte des Gesetzes und der Debatten Problematiken und Chancen auf, und wie man damit im Zusammenspiel von Recht, Politik, Zivilgesellschaft und Wissenschaft umgeht. Und der Vortrag beleuchtet die Konsequenzen, welche das Urteil f\u00fcr die Polizeiarbeit sowie die Wahrung von Privatsph\u00e4re und gesellschaftlichen Freiheiten hat.", "recording_license": "", "do_not_record": false, "persons": [{"code": "B9JJL9", "name": "Rahel Estermann", "avatar": null, "biography": "Beschwerdef\u00fchrerin gegen das Luzerner Polizeigesetz vor Bundesgericht; Vorstand Digitale Gesellschaft; Luzerner Kantonsr\u00e4tin; Generalsekret\u00e4rin GR\u00dcNE Schweiz", "public_name": "Rahel Estermann", "guid": "9ad60696-8b19-5b97-b26a-cd2f9619342c", "url": "https://cfp.winterkongress.ch/wk25/speaker/B9JJL9/"}, {"code": "NAHT7M", "name": "Viktor Gy\u00f6rffy", "avatar": null, "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.", "public_name": "Viktor Gy\u00f6rffy", "guid": "9d79c455-fac8-56bf-a6bc-1248ee081234", "url": "https://cfp.winterkongress.ch/wk25/speaker/NAHT7M/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/XP3KKB/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/XP3KKB/", "attachments": []}, {"guid": "a5e7d828-d6ff-5c70-9a98-6a4ea8f3f526", "code": "MJ3LHY", "id": 59322, "logo": null, "date": "2025-02-28T20:15:00+01:00", "start": "20:15", "duration": "00:45", "room": "Festsaal", "slug": "wk25-59322-nachhaltige-ki-ein-widerspruch-in-sich-", "url": "https://cfp.winterkongress.ch/wk25/talk/MJ3LHY/", "title": "Nachhaltige KI: Ein Widerspruch in sich?", "subtitle": "", "track": "Ethik, Wissenschaft, Kultur & Gesellschaft", "type": "Podiumsgespr\u00e4ch", "language": "de", "abstract": "Algorithmen und KI werden immer mehr und mit grossen Hoffnungen eingesetzt: Sie sollen den Ressourcenverbrauch effizienter gestalten, komplexe gesellschaftliche Gestaltungsaufgaben wie die Energie- oder Mobilit\u00e4tswende l\u00f6sen, ein nachhaltigeres Energiesystem kreieren oder auch die Erforschung neuer Materialien erleichtern. KI wird sogar als wichtiges Werkzeug zur Bew\u00e4ltigung der Klimakrise gesehen. Nur blenden solche Hoffnungen aus, dass auch die Entwicklung und der Einsatz von KI viele Ressourcen wie Energie und Wasser verbraucht und in einem betr\u00e4chtlichen Ausmass CO\u2082-Emissionen verursacht.", "description": "Mit Nationalr\u00e4tin Sibel Arslan (GR\u00dcNE Schweiz), Prof. Dr. Jan Bieser (BFH) und Dr. Angela M\u00fcller (Gesch\u00e4ftsleiterin AlgorithmWatch CH) werden wir in diesem Panel versuchen, die folgenden Fragen zu beantworten:\r\n\r\n* Welche Auswirkungen hat KI auf die Umwelt?\r\n\r\n* Und wie steht es mit der sozialen und \u00f6konomischen Nachhaltigkeit?\r\n\r\n* Wie k\u00f6nnte eine nachhaltige KI aussehen?\r\n\r\n*Wie reagiert die EU auf Umweltrisiken von KI und wo steht die Schweiz?", "recording_license": "", "do_not_record": false, "persons": [{"code": "FHSFPN", "name": "Estelle Pannatier", "avatar": null, "biography": "Estelle 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 Schweiz hat Estelle zu \u00f6ffentlicher Politik im Kontext der Digitalisierung des Bildungswesens in der Schweiz mitgewirkt. Davor hatte sie f\u00fcr die Online-Wahlhilfeplattform smartvote, f\u00fcr das Eidgen\u00f6ssisches Departement f\u00fcr ausw\u00e4rtige Angelegenheiten EDA sowie f\u00fcr das Schweizer Radio und Fernsehen gearbeitet.", "public_name": "Estelle Pannatier", "guid": "8d18157d-d805-58cc-a93a-c6400124527a", "url": "https://cfp.winterkongress.ch/wk25/speaker/FHSFPN/"}, {"code": "NRMQJN", "name": "Angela Mueller", "avatar": null, "biography": "Gesch\u00e4ftsleiterin AlgorithmWatch CH", "public_name": "Angela Mueller", "guid": "6c46fed4-79bf-59b9-99d9-d2efc957a12c", "url": "https://cfp.winterkongress.ch/wk25/speaker/NRMQJN/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/MJ3LHY/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/MJ3LHY/", "attachments": []}, {"guid": "5ebae977-16b1-5ec2-ad3d-232cefe64942", "code": "KBPDLW", "id": 59468, "logo": null, "date": "2025-02-28T21:15:00+01:00", "start": "21:15", "duration": "00:45", "room": "Festsaal", "slug": "wk25-59468-wie-weiter-mit-dem-leistungsschutzrecht-", "url": "https://cfp.winterkongress.ch/wk25/talk/KBPDLW/", "title": "Wie weiter mit dem Leistungsschutzrecht?", "subtitle": "", "track": "Recht & Politik", "type": "Vortrag", "language": "de", "abstract": "Der Vortrag beleuchtet die aktuelle Situation in der Schweiz, in Europa und im Rest der Welt in Bezug auf Umsetzung und Probleme mit dem Leistungsschutzrecht, insbesondere auch unter Ber\u00fccksichtigung der neueren Entwicklungen der Generativen KI.", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"code": "MEEKJG", "name": "Christoph Schmid", "avatar": null, "biography": "Christoph Schmid setzt sich f\u00fcr eine nachhaltige digitale Welt ein. So hat er bei der Digitalen Gesellschaft am Ratgeber Nachhaltigkeit mitgearbeitet, organisiert das netzpolitische Mittagessen in Basel und arbeitet als Fachbereichsleiter an inhaltlichen Programmen, der Organisationsentwicklung und der Unterst\u00fctzung der ehrenamtlichen Fachbereiche.", "public_name": "Christoph Schmid", "guid": "6e4f31ae-fea5-5cc6-80be-6cc6e41028c0", "url": "https://cfp.winterkongress.ch/wk25/speaker/MEEKJG/"}, {"code": "VDFYBV", "name": "Andreas Von Gunten", "avatar": null, "biography": "Leidenschaftlich verzettelt. Linkslibert\u00e4rer Humanist, Citoyen und Unternehmer. Gesch\u00e4ftsf\u00fchrer von smartKMU, Co-Pr\u00e4sident des Vereins dnip.ch, Partner bei Datenschutzpartner AG, Verwaltungsratspr\u00e4sident der EWK Energie AG, Mitglied der Digitalen Gesellschaft, Co-Pr\u00e4sident der SP K\u00f6lliken", "public_name": "Andreas Von Gunten", "guid": "289e1360-81d3-5d5a-b0cd-4d6ab1187c53", "url": "https://cfp.winterkongress.ch/wk25/speaker/VDFYBV/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/KBPDLW/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/KBPDLW/", "attachments": []}], "Bankettsaal": [{"guid": "e97028bc-bd69-5277-b1c1-f9fb584eeff0", "code": "Q7QT8T", "id": 59636, "logo": null, "date": "2025-02-28T19:15:00+01:00", "start": "19:15", "duration": "00:45", "room": "Bankettsaal", "slug": "wk25-59636-die-cloud-als-schrebergarten-missverstndnisse-beharrlich-ausgerumt", "url": "https://cfp.winterkongress.ch/wk25/talk/Q7QT8T/", "title": "Die Cloud als Schrebergarten: Missverst\u00e4ndnisse beharrlich ausger\u00e4umt", "subtitle": "", "track": "Netzwerke, Security, Hard- & Software", "type": "Vortrag", "language": "de", "abstract": "\u00abDie Cloud\u00bb ist in aller Munde. Und es wird viel versprochen, insbesondere Sorglosigkeit und finanzielle Einsparungen. Dies stimmt. Aber nicht immer. Manchmal bedeutet es auch das Gegenteil, wie erste Erfahrungen von der Flucht aus der Cloud zeigen.\r\n\r\nUm diese Diskrepanz zu verstehen, m\u00fcssen wir die unterschiedlichen Aspekte rund um die Cloud zuerst trennen und strukturieren. Anhand von einfach verst\u00e4ndlichen Analogien wie dem Schrebergarten und einer Analyse des Use-Cases \u00abSwiss Government Cloud\u00bb lernen wir die Cloud kennen und identifizieren ihre Vor- und Nachteile.", "description": "Inhalt:\r\n\r\n* Die Entstehung der Cloud\r\n* Die Cloud-Buchstabensuppe erkl\u00e4rt: IaaS, PaaS, SaaS, \u2026\r\n* Die drei Dimensionen der Cloud\r\n* Die Cloud als Wertsch\u00f6pfungskette\r\n* Vertr\u00e4gt sich die Cloud mit der Souver\u00e4nit\u00e4t?\r\n* Die Missverst\u00e4ndnisse der Cloud\r\n* Wann spare ich dank der Cloud Geld und Aufwand?\r\n* Zusammenfassung: Chancen und Risiken", "recording_license": "", "do_not_record": false, "persons": [{"code": "9MXLFK", "name": "Marcel Waldvogel", "avatar": null, "biography": "Marcel Waldvogel hat an der ETH Informatik studiert und promoviert. Schon w\u00e4hrend dem Studium gr\u00fcndete er zusammen mit Freunden eine Softwareentwicklungs- und Beratungsfirma und verbrachte danach mehrere Jahre in den USA und bei IBM Research. Nach 15 Jahren als Informatikprofessor und Rechenzentrumsleiter an der Universit\u00e4t Konstanz ist er wieder in der Schweiz und k\u00fcmmert sich um IT-Sicherheit und die einfache Erkl\u00e4rung von komplexen IT-Zusammenh\u00e4ngen.", "public_name": "Marcel Waldvogel", "guid": "98f82962-bb7e-5002-b6fc-4167e027694f", "url": "https://cfp.winterkongress.ch/wk25/speaker/9MXLFK/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/Q7QT8T/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/Q7QT8T/", "attachments": []}, {"guid": "ca11b11c-de94-5f40-aa40-1afd8bc471f3", "code": "UHUJWJ", "id": 59431, "logo": null, "date": "2025-02-28T20:15:00+01:00", "start": "20:15", "duration": "00:45", "room": "Bankettsaal", "slug": "wk25-59431-die-konomie-der-digitalisierung", "url": "https://cfp.winterkongress.ch/wk25/talk/UHUJWJ/", "title": "Die \u00d6konomie der Digitalisierung", "subtitle": "", "track": "Ethik, Wissenschaft, Kultur & Gesellschaft", "type": "Vortrag", "language": "de", "abstract": "Die Digitale Gesellschaft fordert in ihrem Leitbild: \"Die Digitalisierung muss allen zugute kommen\". Aber ist das wirklich der Fall? F\u00fcr eine Antwort m\u00fcssen wir zun\u00e4chst einmal analysieren, wie Digitalisierung und Big Tech als ihre pr\u00e4genden Akteure aus wirtschaftlicher Sicht funktionieren. Wir schauen uns daf\u00fcr in diesem Vortrag Beschreibungsans\u00e4tze wie Plattform-, \u00dcberwachungs- und Digitalen Kapitalismus an. Mit einem besseren Verst\u00e4ndnis der \u00d6konomie der Digitalisierung k\u00f6nnen wir dann diskutieren, wie unser Leitbild Realit\u00e4t werden kann.", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"code": "SNWNEF", "name": "Andreas Geppert", "avatar": null, "biography": "Andreas ist Informatiker und verdient sein Geld mit der Konzeption und dem Bau von Daten(bank)plattformen. Er ist seit vielen Jahren aktives Mitglieder der DigiGes und engagiert sich f\u00fcr diverse netzpolitische Themen wie z.B. Tracking & Profiling, biometrische Identifikation, und automatisierte Entscheidungssysteme.", "public_name": "Andreas Geppert", "guid": "7c2fad53-aa02-5ccf-a081-6a37662bd773", "url": "https://cfp.winterkongress.ch/wk25/speaker/SNWNEF/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/UHUJWJ/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/UHUJWJ/", "attachments": []}, {"guid": "9606d4fb-ad66-5bab-bd33-cf49a201e9b4", "code": "7QVE8P", "id": 59487, "logo": null, "date": "2025-02-28T21:15:00+01:00", "start": "21:15", "duration": "00:45", "room": "Bankettsaal", "slug": "wk25-59487-gemeinsam-vernetzt-internetzugang-im-wohnbauprojekt-organisieren", "url": "https://cfp.winterkongress.ch/wk25/talk/7QVE8P/", "title": "Gemeinsam vernetzt: Internetzugang im Wohnbauprojekt organisieren", "subtitle": "", "track": "Ethik, Wissenschaft, Kultur & Gesellschaft", "type": "Vortrag", "language": "de", "abstract": "Bei der Berner Wohnungsbaugenossenschaft Warmb\u00e4chli wird vieles geteilt: Neben Wohnraum wurde auch gefragt, warum eigentlich alle ihren eigenen Internetanschluss organisieren m\u00fcssen. Herausgekommen ist ein gemeinsames selbstverwaltetes WLAN-Netz, das \u00fcber 60 Haushalten und Gewerbetreibenden zur Verf\u00fcgung steht und mittlerweile auf ein zweites Geb\u00e4ude in der Siedlung erweitert wurde.\r\nWir sind der \u00dcberzeugung, dass unser Ansatz auch an weiteren Orten umgesetzt werden kann und sollte. In unserem Vortrag beleuchten wir die Entstehungsgeschichte, Umsetzung und Erfahrung im 3 j\u00e4hrigen Betrieb.", "description": "Konventionen hinterfragt und Experimentierfreude gezeigt hat die Berner Genossenschaft Warmb\u00e4chli seit ihren Anf\u00e4ngen. 2013 wurde sie gegr\u00fcndet, um ein altes Lagerhaus auf dem Warmb\u00e4chliareal der ehemaligen Kehrichtverbrennungsanlage im Holligenquartier zu einem sozial und \u00f6kologisch nachhaltigen Wohnhaus mit weiteren Nutzungen umzubauen.\r\nGeteilt wird in vielen Wohnbaugenossenschaften vor allem Raum. In der Genossenschaft Warmb\u00e4chli haben wir das Thema weitergedacht: Im Holligerhof 8 in Bern haben wir ein gemeinsames selbstverwaltetes WLAN-Netz installiert, das im ganzen Geb\u00e4ude von allen Haushalten und Gewerbebetrieben genutzt werden kann. Mittlerweile wurde gar ein zweites Geb\u00e4ude eines weiteren Bautr\u00e4gers in der Siedlung angeschlossen und die gemeinsame Nutzung entsprechend erweitert. Die Umsetzung erfolgte in frewilligen Arbeit der Bewohner:innen in Zusammenarbeit mit einem professionellen Dienstleister.\r\nWir sind der \u00dcberzeugung, dass unser Ansatz auch an weiteren Orte umgesetzt werden sollte und m\u00f6chten weiteren Projekte und Interessierten aufzeigen, wie die Idee eines gemeinsamen Internetanschlusses umgesetzt werden kann. In unserem Vortrag beleuchten wir die Entstehungsgeschichte, unsere \u00dcberlegungen zu der Umsetzung, gemachte Erfahrungen bei der Ausf\u00fchrung unseres Konzeptes, aber auch unser Fazit nach dem mittlerweile dreij\u00e4hrigen Betrieb.\r\nDazu erz\u00e4hlen wir, wie die Idee entstanden ist, welche Herausforderungen zu meistern waren und wie wir m\u00f6glichst alle Bewohner:innen an Board holen konnten. Dabei beleuchten wir konzeptionelle, technische, aber auch soziale Aspekte, welche zu einer erfolgreichen Umsetzung gef\u00fchrt haben und mitgedacht werden sollten.", "recording_license": "", "do_not_record": false, "persons": [{"code": "PSMCAY", "name": "Alwin", "avatar": null, "biography": "Mitglied der AG-IP der Wohnbaugenossenschaft Warmb\u00e4chli.", "public_name": "Alwin", "guid": "f1a1ff04-5c40-5d57-b002-375caa165af1", "url": "https://cfp.winterkongress.ch/wk25/speaker/PSMCAY/"}, {"code": "MLQFE9", "name": "Marcel H\u00e4rri", "avatar": null, "biography": "Wohnt und lebt im Warmb\u00e4chli in Bern, organisiert und betreibt seit vielen Jahren selbstverwaltete Infrastruktur.", "public_name": "Marcel H\u00e4rri", "guid": "7f8806f6-0adb-5135-9057-c284743eaa83", "url": "https://cfp.winterkongress.ch/wk25/speaker/MLQFE9/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/7QVE8P/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/7QVE8P/", "attachments": []}], "Tanzsaal": [{"guid": "c39b40c4-1f28-5188-8f1a-b106239d7bb1", "code": "RUMPMC", "id": 59076, "logo": null, "date": "2025-02-28T19:15:00+01:00", "start": "19:15", "duration": "00:45", "room": "Tanzsaal", "slug": "wk25-59076-digital-rights-technology-and-online-gender-based-violence", "url": "https://cfp.winterkongress.ch/wk25/talk/RUMPMC/", "title": "Digital Rights, Technology and Online Gender-Based Violence", "subtitle": "", "track": "Recht & Politik", "type": "Workshop", "language": "en", "abstract": "We will delve into the world of Online Gender-Based Violence (OGBV), exploring its many forms, from non-consensual imagery and deepfakes to doxxing and harassment. The workshop will uncover gender biases embedded in content moderation and critically examine how digital regulations, particularly the Digital Services Act, often fail to address these issues. We will also explore how companies are better equipped to enforce copyright violations online but fail to do so for other illegal content related to gender equality, and the consequences of this discrepancy for online safety.", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"code": "HEHLFB", "name": "Raquel De Haro", "avatar": null, "biography": "I am a PhD candidate at the Center for Law & Economics at ETH Zurich, specializing in digital regulation and platform governance with a focus on gender equality and online safety. My research examines the Digital Services Act, content moderation, and the fight against online gender-based violence using empirical methods. With a background in law and business administration, I am passionate about using data-driven insights to shape more equitable and inclusive digital spaces for all.", "public_name": "Raquel De Haro", "guid": "ab4eca4c-7ffa-58ef-b06e-63b1688c90a9", "url": "https://cfp.winterkongress.ch/wk25/speaker/HEHLFB/"}, {"code": "ZDLGGC", "name": "Mariana Valente", "avatar": null, "biography": "Law researcher in AI & platform governance, copyright & access to knowledge in the digital environment, and the intersection of data, digital technologies, and inequalities.\r\n\r\nAssistant professor of international economic law at the University of St.Gallen, Switzerland; associate director and founder of InternetLab, Brazil. \r\n\r\nMy latest published work has been on online gender-based violence and policies for text and data mining for research in Latin America.", "public_name": "Mariana Valente", "guid": "ae14e9b2-4c99-5a95-8a41-abe18cb696db", "url": "https://cfp.winterkongress.ch/wk25/speaker/ZDLGGC/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/RUMPMC/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/RUMPMC/", "attachments": []}, {"guid": "39a4b689-c666-57f4-80d8-1e97a649f6ec", "code": "FRFX8L", "id": 59512, "logo": null, "date": "2025-02-28T20:15:00+01:00", "start": "20:15", "duration": "00:45", "room": "Tanzsaal", "slug": "wk25-59512-brauchen-wir-eine-geistige-landesverteidigung-2-0-", "url": "https://cfp.winterkongress.ch/wk25/talk/FRFX8L/", "title": "Brauchen wir eine geistige Landesverteidigung 2.0?", "subtitle": "", "track": "Ethik, Wissenschaft, Kultur & Gesellschaft", "type": "Vortrag", "language": "de", "abstract": "Brauchen wir einen neuen gesellschaftlichen Schulterschluss, um die Errungenschaften von Aufkl\u00e4rung und liberaler Demokratie gegen totalit\u00e4re Bedrohungen zu verteidigen, \u00e4hnlich wie einst bei der geistigen Landesverteidigung? Wir diskutieren kritisch den historischen Begriff, sowie die Rolle von Desinformation, Medien, Cybersicherheit und weiteren Aspekten eines erweiterten, zeitgem\u00e4ssen Sicherheitsbegriffs.", "description": "Trump gewinnt die Wahlen in den USA, Russland f\u00fchrt Krieg gegen die Ukraine, und rechte Parteien gewinnen in Europa zunehmend an Einfluss oder regieren bereits. In der Schweiz steigen die Milit\u00e4rausgaben \u2013 doch reicht das aus?\r\n\r\nWie kann eine digitale Zivilgesellschaft dazu beitragen, dass Informationspolitik nicht als unpopul\u00e4rer Kostenfaktor wahrgenommen wird, sondern als essenzieller Bestandteil der nationalen Sicherheit? Wie sichern wir langfristig unsere demokratischen Werte angesichts einer zunehmend dominierenden globalen Blocklogik?", "recording_license": "", "do_not_record": false, "persons": [{"code": "7R8SNF", "name": "Olga Baranova", "avatar": null, "biography": "Olga Baranova ist als Gesch\u00e4ftsleiterin von CH++ und Vorstandsmitglied vom Medienverband VMZ in der Digital- und Medienpolitik aktiv.", "public_name": "Olga Baranova", "guid": "807c4987-c923-5c50-a960-f763117c96b1", "url": "https://cfp.winterkongress.ch/wk25/speaker/7R8SNF/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/FRFX8L/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/FRFX8L/", "attachments": []}, {"guid": "9987fed7-4f35-52fd-93ae-9c246316179f", "code": "8RW7XG", "id": 58596, "logo": null, "date": "2025-02-28T21:15:00+01:00", "start": "21:15", "duration": "00:45", "room": "Tanzsaal", "slug": "wk25-58596-die-kunst-der-tuschung-chatbots-als-meister-der-illusion", "url": "https://cfp.winterkongress.ch/wk25/talk/8RW7XG/", "title": "Die Kunst der T\u00e4uschung: Chatbots als Meister der Illusion", "subtitle": "", "track": "Netzwerke, Security, Hard- & Software", "type": "Vortrag", "language": "de", "abstract": "ChatGPT, Microsoft und Google zeigen ein auf hochglanz poliertes Produkt, das fast menschlich erscheint. F\u00fcr den politischen Diskurs muss man verstehen, wie sie wirklich funktionieren. In diesem Vortrag wird aufgezeigt wie Chatbots auf verschiedene Inputs (Training) reagieren. Was sich hinter der polierten Fassade befindet, wie das im Detail funktioniert und wo die Politik wirken kann.", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"code": "ZTW7KP", "name": "Gabriel Kowalski", "avatar": null, "biography": "Als Absolvent der Universit\u00e4t Bern, bringt er die neuesten Forschungserkenntnisse mit und zeigt was Chatbots wirklich sind.", "public_name": "Gabriel Kowalski", "guid": "5c443807-d877-5533-80ea-b875d5f9d9ed", "url": "https://cfp.winterkongress.ch/wk25/speaker/ZTW7KP/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/8RW7XG/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/8RW7XG/", "attachments": []}]}}, {"index": 2, "date": "2025-03-01", "day_start": "2025-03-01T04:00:00+01:00", "day_end": "2025-03-02T03:59:00+01:00", "rooms": {"Festsaal": [{"guid": "7741035e-8cc6-52c9-9b1e-dad4a8979706", "code": "NGLZPZ", "id": 59869, "logo": null, "date": "2025-03-01T11:00:00+01:00", "start": "11:00", "duration": "00:15", "room": "Festsaal", "slug": "wk25-59869-erffnung-samstag", "url": "https://cfp.winterkongress.ch/wk25/talk/NGLZPZ/", "title": "Er\u00f6ffnung Samstag", "subtitle": "", "track": "Andere", "type": "Moderation", "language": "de", "abstract": "Die Er\u00f6ffnung am Samstag", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"code": "PLBTRP", "name": "Team Winterkongress", "avatar": null, "biography": null, "public_name": "Team Winterkongress", "guid": "6de73f8d-b1fd-5d46-9f05-b86d7c280b73", "url": "https://cfp.winterkongress.ch/wk25/speaker/PLBTRP/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/NGLZPZ/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/NGLZPZ/", "attachments": []}, {"guid": "97bcb94c-930e-581b-b472-aa29bdbfb042", "code": "YVEGWS", "id": 59867, "logo": null, "date": "2025-03-01T11:15:00+01:00", "start": "11:15", "duration": "00:30", "room": "Festsaal", "slug": "wk25-59867-it-sicherheit-sollten-wir-sie-aufgeben-", "url": "https://cfp.winterkongress.ch/wk25/talk/YVEGWS/", "title": "IT-Sicherheit: Sollten wir sie aufgeben?", "subtitle": "", "track": "Andere", "type": "Keynote", "language": "de", "abstract": "Als Journalistin mit dem Schwerpunkt Cybersecurity schaue ich st\u00e4ndig in die L\u00f6cher des Internets und der IT-Infrastrukturen. Ich mag gebiast sein, aber ich sehe nur noch Leaks. Krankenakten, Diagnosen, heimlich aufgezeichnete Telefonate, Ausweiskopien, Kontoausz\u00fcge, vertrauliche Besprechungen von Beh\u00f6rden: Ich k\u00f6nnte mich jeden Tag in die Daten anderer Leute vertiefen, und leider tue ich das viel zu oft.", "description": "Dann muss ich den Betroffenen erkl\u00e4ren, was ich jetzt alles \u00fcber sie weiss und was vermutlich auch Kriminelle und Spione \u00fcber sie wissen, und ich muss versuchen, die Verantwortlichen dazu zu bringen, die L\u00f6cher zu stopfen. Beides ist frustrierend.\r\n\r\nIch bin vor ein paar Jahren angetreten mit dem Plan, durch meine Berichterstattung zu sensibilisieren und dazu beizutragen, dass IT sicherer wird. Dass alles besser wird. Aber das wird es nicht. Es wird immer schlimmer.\r\n\r\nVon daher pl\u00e4diere ich f\u00fcr eine neue Perspektive: Vergesst es, wir haben verloren. (und ganz vielleicht habe ich - nachdem ich ein bisschen aus dem N\u00e4hk\u00e4stchen und den Tiefen meiner j\u00fcngsten Recherchen gelaudert habe, ein bis drei kleine Ans\u00e4tze, wie wir es stattdessen versuchen k\u00f6nnten).", "recording_license": "", "do_not_record": false, "persons": [{"code": "LZW9MZ", "name": "Eva Wolfangel", "avatar": null, "biography": "Eva Wolfangel ist freiberufliche Journalistin. Ihre Schwerpunkte sind Zukunftstechnologien wie k\u00fcnstliche Intelligenz und virtuelle Realit\u00e4t, Cybersicherheit, Informatik, Datenjournalismus, Interaktion zwischen digitalen und realen Welten sowie Neurowissenschaften.", "public_name": "Eva Wolfangel", "guid": "65ca594f-cd7a-51bb-8e00-35ceb33fc6e2", "url": "https://cfp.winterkongress.ch/wk25/speaker/LZW9MZ/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/YVEGWS/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/YVEGWS/", "attachments": []}, {"guid": "ffa4ae41-8986-5d34-862e-8c569e7c8b8c", "code": "UMRQNW", "id": 59047, "logo": null, "date": "2025-03-01T12:00:00+01:00", "start": "12:00", "duration": "00:45", "room": "Festsaal", "slug": "wk25-59047-landkarte-der-schweizer-berwachungsindustrie", "url": "https://cfp.winterkongress.ch/wk25/talk/UMRQNW/", "title": "Landkarte der Schweizer \u00dcberwachungsindustrie", "subtitle": "", "track": "Digitale Selbstverteidigung", "type": "Vortrag", "language": "de", "abstract": "Seit Jahren besch\u00e4ftigen wir - die WOZ und das Recherchekollektiv WAV \u2013 uns mit den Exportgesch\u00e4ften der Schweizer \u00dcberwachungsbranche und stossen dabei immer wieder auf Missbrauch: Exporte ohne Bewilligungen, Deals mit autorit\u00e4ren Regime, Umgehungsgesch\u00e4fte oder Verstrickungen mit Russland und Israel.\r\n\r\nW\u00e4hrend die Exporte bewilligungspflichtig sind, gibt es rund um die Aufsicht dieser Firmen Fragezeichen. Dies, obwohl Spionage- und \u00dcberwachungstechnologie m\u00e4chtige Instrumente mit hohem Missbrauchs- und Repressionspotenzial sind. \r\n\r\nWir werfen ein Licht auf diese verschwiegene Branche.", "description": "Im August 2024 durchsuchten Polizist:innen der Bundeskriminalpolizei Fedpol die B\u00fcror\u00e4umlichkeiten eines Treuh\u00e4nders in Lugano. Der Verdacht: Er hat mutmasslich gegen das G\u00fcterkontrollgesetz verstossen \u2013 in dem er sich am Export des ber\u00fcchtigten Intellexa-Trojaners \u00abPredator\u00bb beteiligte, der in unz\u00e4hligen L\u00e4ndern von Regierungen missbr\u00e4uchlich eingesetzt wurde. \r\n\r\nAusl\u00f6ser der polizeilichen Durchsuchung des Intellexa-Treuh\u00e4nders war eine Recherche der WOZ und internationaler Partner (1). Diese r\u00fcckte eine Branche in den \u00f6ffentlichen Fokus, die sonst gerne unter sich bleibt: die exportorientierte \u00dcberwachungsindustrie und ihre Schweizer Infrastruktur. \r\n\r\nNeoSoft, Atecs, Polus, Wavecom oder Intellexa: In der Schweiz produzieren und handeln mehrere \u00dcberwachungstechnologiefirmen, deren Produkte aufgrund ihrer \u00abF\u00e4higkeiten\u00bb eine Exportbewilligung ben\u00f6tigen. Der WOZ-R\u00fcstungsreport ver\u00f6ffentlicht jedes Jahr deren Exporte (2) \u2013 \u00fcber eine Zeitspanne von mittlerweile zehn Jahren k\u00f6nnen wir damit die Exportgesch\u00e4fte dieser sonst verschwiegenen Branche nachzeichnen. \r\n\r\nIn zahlreichen Recherchen (3) haben wir \u00fcber die Jahre einzelne Firmen, ihre Hintergr\u00fcnde und verschiedene Gesch\u00e4fte im Detail untersucht. Diese Recherchen zeigen: Die Branche ist chronisch intransparent, die Hintergr\u00fcnde und Gesch\u00e4fte der Unternehmen sind immer wieder problematisch und die geltende Gesetzgebung \u2013 oder zumindest ihre Anwendung \u2013 ist zahnlos und schwerf\u00e4llig. Immer wieder stossen wir auf Missbrauch: Mutmassliche Exporte ohne Bewilligung, Deals mit autorit\u00e4ren Regime oder repressiven Sicherheitsapparaten, Umgehungsgesch\u00e4fte \u00fcber Zwischenl\u00e4nder wie die Vereinigten Arabischen Emiraten oder Verstrickungen mit M\u00e4rkten wie Russland und Israel. \r\n\r\nUnd dabei merken wir: W\u00e4hrend die Exporte zwar eine Bewilligung brauchen, gibt es rund um die allgemeine Aufsicht dieser Unternehmen Fragezeichen: Das Mandat des Staatsskretariats f\u00fcr Wirtschaft (Seco) ist auf Exportkontrolle beschr\u00e4nkt, das Bundesamt f\u00fcr Kommunikation (Bakom) stellt Bewilligungen f\u00fcr Betrieb und Training von Infrastruktur aus, die Nachrichtendienste geben wie immer keine Auskunft. Das birgt Risiken: Spionage- und \u00dcberwachungstechnologie sind m\u00e4chtige Instrumente, sie bergen ein hohes Missbrauchs- und Repressionspotenzial \u2013 nicht nur aber auch im Inland. Und dank intransparenten und globalen Unternehmenskonstrukten lassen sich Exportkontrollen leicht umgehen und Gesch\u00e4fte verschleiern \u2013 teilweise sogar ohne dabei offensichtlich Gesetze zu verletzen. \r\n\r\nH\u00f6chste Zeit, dass wir den Spiess umkehren, die \u00dcberwacher in den Blick nehmen und ihnen auf die Finger schauen. Wir reisen mit euch durch die Landkarte der Schweizer \u00dcberwachungsunternehmen und stellen ihre Produkte, Gesch\u00e4fte und Hintergr\u00fcnde vor. Eine Reise, die von B\u00fclach nach Z\u00fcrich und dann \u00fcber Zug nach Bern bis ins Tessin f\u00fchrt. \r\n\r\n(1) https://www.woz.ch/t/predator-files\r\n(2) https://www.r\u00fcstungsreport.ch/dealers\r\n(3) https://www.r\u00fcstungsreport.ch/articles", "recording_license": "", "do_not_record": false, "persons": [{"code": "L7AKQM", "name": "Lorenz Naegeli", "avatar": null, "biography": "Journalist beim Recherchekollektiv WAV und j\u00e4hrlich dabei beim WOZ-R\u00fcstungsreport (www.r\u00fcstungsreport.ch). \u00dcberzeugter Anh\u00e4nger von Transparenzoffensiven und jouranlistischer Gegenmacht - zum Beipsiel durch das \u00dcberwachen der \u00dcberwacher.", "public_name": "Lorenz Naegeli", "guid": "5fba573d-3466-5dbc-a259-970497a9f2af", "url": "https://cfp.winterkongress.ch/wk25/speaker/L7AKQM/"}, {"code": "HWRMPV", "name": "Jan Jirat", "avatar": null, "biography": "Investigativjournalist bei der WOZ - Die Wochenzeitung. Schwerpunkte: \u00dcberwachung, Sicherheit, Energiepolitik und Rechtsextremismus", "public_name": "Jan Jirat", "guid": "44ae0f0a-6a4d-581e-a1a6-b54840000651", "url": "https://cfp.winterkongress.ch/wk25/speaker/HWRMPV/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/UMRQNW/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/UMRQNW/", "attachments": []}, {"guid": "c63a4558-4d42-5702-a672-d1fb6c8af379", "code": "QHGTAB", "id": 59541, "logo": null, "date": "2025-03-01T13:00:00+01:00", "start": "13:00", "duration": "00:45", "room": "Festsaal", "slug": "wk25-59541-e-id-und-vertrauensinfrastruktur-stand-der-arbeiten-und-ausblick", "url": "https://cfp.winterkongress.ch/wk25/talk/QHGTAB/", "title": "E-ID und Vertrauensinfrastruktur - Stand der Arbeiten und Ausblick", "subtitle": "", "track": "Recht & Politik", "type": "Vortrag", "language": "de", "abstract": "Das Vorhaben E-ID und Vertrauensinfrastruktur schreitet voran. Der Informationsbeauftragte E-ID des Bundes berichtet \u00fcber den aktuellen Stand der Gesetzgebung sowie die technischen Vorarbeiten und steht f\u00fcr Fragen zur Verf\u00fcgung.", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"code": "KHRQBH", "name": "Rolf Rauschenbach", "avatar": null, "biography": "Informationsbeauftragter E-ID, Bundesamt f\u00fcr Justiz", "public_name": "Rolf Rauschenbach", "guid": "629ac9b1-5052-5cb7-9b49-d5d32c0e3176", "url": "https://cfp.winterkongress.ch/wk25/speaker/KHRQBH/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/QHGTAB/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/QHGTAB/", "attachments": []}, {"guid": "c59c0408-b647-529c-b2ce-da661ae2d042", "code": "SGXECY", "id": 59513, "logo": null, "date": "2025-03-01T14:45:00+01:00", "start": "14:45", "duration": "00:30", "room": "Festsaal", "slug": "wk25-59513-digitale-identitt-iii", "url": "https://cfp.winterkongress.ch/wk25/talk/SGXECY/", "title": "Digitale Identit\u00e4t III", "subtitle": "", "track": "Recht & Politik", "type": "Vortrag kurz", "language": "de", "abstract": "Das neue Bundesgesetz zur Schweizer eID ist beschlossen. Freuen wir uns auf die eID?", "description": "Nach mehreren Anl\u00e4ufen und einer wuchtigen Abstimmungsniederlage ist das neue Bundesgesetz zur Schweizer eID durch die R\u00e4te. \u00dcber die technischen Grundlagen und die Entw\u00fcrfe wurde bereits eingehend diskutiert - auch am Winterkongress in den Teilen I und II zur eID.\r\n\r\nBis zur definitiven Einf\u00fchrung bleibt uns im Moment, den Abschluss des politischen Verfahrens und die letzten Weichenstellungen zu analysieren. F\u00fcr ein derart grosses und breit antizipiertes Projekt ist maximale Akzeptanz wichtig. Erf\u00fcllt der Entwurf diese Erwartungen - oder droht ein Absturz?", "recording_license": "", "do_not_record": false, "persons": [{"code": "8DVUC9", "name": "Hans-Peter Oeri", "avatar": null, "biography": "Rechtsanwalt, \u00d6konom und privat IT-Nerd, engagiert in netz- und it-politischen Themenfeldern", "public_name": "Hans-Peter Oeri", "guid": "266889ea-e5ed-559c-a278-099c055b75ea", "url": "https://cfp.winterkongress.ch/wk25/speaker/8DVUC9/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/SGXECY/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/SGXECY/", "attachments": []}, {"guid": "5ae17761-1257-56d9-b322-2e76870fee8c", "code": "SNEH9U", "id": 59287, "logo": null, "date": "2025-03-01T15:30:00+01:00", "start": "15:30", "duration": "00:45", "room": "Festsaal", "slug": "wk25-59287-dumm-gelaufen-wie-man-personendaten-nicht-bearbeiten-sollte", "url": "https://cfp.winterkongress.ch/wk25/talk/SNEH9U/", "title": "Dumm gelaufen: Wie man Personendaten NICHT bearbeiten sollte", "subtitle": "", "track": "Recht & Politik", "type": "Workshop", "language": "de", "abstract": "Jenseits der spektakul\u00e4ren Datenpannen gibt es zahlreiche allt\u00e4gliche Fehler bei der Bearbeitung von Personendaten. Dieser Vortrag beleuchtet praktische F\u00e4lle bei Beh\u00f6rden, Organisationen und Unternehmen und zeigt auf unterhaltsame Weise, wie man Personendaten NICHT behandeln sollte.", "description": "Spektakul\u00e4re Datenpannen sorgen regelm\u00e4ssig f\u00fcr Schlagzeilen. Ein grosser Teil unserer Daten wird aber ohne \u00f6ffentliche Aufmerksamkeit bei Beh\u00f6rden, Organisationen und Unternehmen bearbeitet. Datenpannen bei solchen Verantwortlichen zeigen, was bei der allt\u00e4glichen Bearbeitung von Personendaten schief gehen kann.\r\n\r\nMartin Steiger blickt auf am\u00fcsante, kuriose und lehrreiche F\u00e4lle aus dem Alltag der Datenbearbeitung. Das Publikum erf\u00e4hrt, wie man Personendaten NICHT bearbeiten sollte, sei es um die gleichen Fehler nicht selbst zu begehen, sei es zur eigenen Unterhaltung.", "recording_license": "", "do_not_record": false, "persons": [{"code": "DEJSWW", "name": "Martin Steiger", "avatar": null, "biography": "Martin Steiger ist Anwalt und Unternehmer f\u00fcr Recht im digitalen Raum in Z\u00fcrich. Martin Steiger ist unter anderem Sprecher der Digitalen Gesellschaft in der Schweiz und langj\u00e4hrig in der schweizerischen Netzpolitik engagiert.", "public_name": "Martin Steiger", "guid": "091d78a5-e84e-5177-bf3a-617fa7cd39b1", "url": "https://cfp.winterkongress.ch/wk25/speaker/DEJSWW/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/SNEH9U/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/SNEH9U/", "attachments": []}, {"guid": "a8a9b841-db2f-5889-bdce-fe28567e752c", "code": "7QATK3", "id": 59404, "logo": null, "date": "2025-03-01T16:30:00+01:00", "start": "16:30", "duration": "00:30", "room": "Festsaal", "slug": "wk25-59404-open-source-artificial-intelligence", "url": "https://cfp.winterkongress.ch/wk25/talk/7QATK3/", "title": "Open Source Artificial Intelligence", "subtitle": "", "track": "Recht & Politik", "type": "Vortrag kurz", "language": "de", "abstract": "Der Vortrag nimmt die **aktuelle Debatte um Open Source AI** auf.\r\n\r\n**Themen:**\r\n- Soll AI \"open\" sein?\r\n- Was \u00fcberhaupt ist Open Source AI? Wie gut ist die neue Definition der OSI?\r\n- Nimmt die neue EU-Regulierung f\u00fcr AI R\u00fccksicht auf Open-Source-Projekte?", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"code": "QDQDYJ", "name": "Simon Schlauri", "avatar": "https://cfp.winterkongress.ch/media/avatars/QDQDYJ_CqDPpBl.jpg", "biography": "Simon Schlauri (1973) ist Rechtsanwalt in St. Gallen und Z\u00fcrich mit Spezialisierung auf Informations- und Kommunikationsrecht. Er verbindet reiche Erfahrung aus der IT- und Telekom-Industrie und technisches Know-how mit einer Titularprofessur an der Universit\u00e4t Z\u00fcrich. Sein Fokus liegt in der Regulierung von Netzwerkindustrien und im IT-Recht, insbesondere in den Bereichen Open Source und Open Data, E-Commerce, Vertrags-, Verbraucher-, Wettbewerbs-, Urheber- und Datenschutzrecht.", "public_name": "Simon Schlauri", "guid": "f8f36ac9-da28-56fc-85a4-4df44d847535", "url": "https://cfp.winterkongress.ch/wk25/speaker/QDQDYJ/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/7QATK3/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/7QATK3/", "attachments": []}, {"guid": "b225deb7-6806-57fd-aa7e-8dea57794fc1", "code": "U8QXT8", "id": 59488, "logo": null, "date": "2025-03-01T18:00:00+01:00", "start": "18:00", "duration": "00:45", "room": "Festsaal", "slug": "wk25-59488-e-voting-eine-betrachtung-aus-digital-ethischer-perspektive", "url": "https://cfp.winterkongress.ch/wk25/talk/U8QXT8/", "title": "E-Voting \u2013 eine Betrachtung aus digital-ethischer Perspektive", "subtitle": "", "track": "Ethik, Wissenschaft, Kultur & Gesellschaft", "type": "Vortrag", "language": "de", "abstract": "E-Voting ist aus technischer, IT-Sicherheits- und demokratischer Perspektive h\u00f6chst problematisch. Dennoch hat E-Voting in der Schweiz seit \u00fcber 20 Jahren unz\u00e4hlige Bef\u00fcrworter:innen, so dass E-Voting aktuell im sogenannten \u00abVersuchsbetrieb\u00bb legal ist. Die Demokratie soll von der Digitalisierung profitieren. Zudem bietet E-Voting \u2013 neben Stimmberechtigten, die im Ausland leben \u2013 insbesondere Menschen mit einer Sehbehinderung die Hoffnung auf mehr Autonomie und politische Teilhabe. Daraus ergibt sich eine komplexe digital-ethische Fragestellung, die in diesem Vortrag behandelt wird.", "description": "In der j\u00fcngeren Vergangenheit hat das E-Voting in der \u00d6ffentlichkeit an Aufmerksamkeit verloren. Insbesondere die Kontra-Stimmen scheinen leiser geworden zu sein. Dieser Umstand soll mit diesem Vortrag ge\u00e4ndert werden. Denn vor dem Hintergrund, dass immer mehr Kantone den Versuchsbetrieb mit der E-Voting-L\u00f6sung der Schweizerischen Post aufnehmen wollen, muss der Diskurs wieder angekurbelt werden. \r\n\r\nDie Interessenfragen rund um E-Voting sind vielf\u00e4ltig und eine rein rechtliche, technologische oder \u00f6konomische Betrachtung wird der Komplexit\u00e4t des Themas nicht gerecht, weshalb die digital-ethische Auseinandersetzung mit E-Voting notwendig ist. \r\n\r\nDer Vortrag analysiert und beantwortet die zentrale moralische Fragestellung, ob E-Voting als offizieller Stimmkanal eingef\u00fchrt werden soll. Dazu wird das f\u00fcnfstufigen Schema der ethischen Entscheidungsfindung nach Bleisch et al. herangezogen. Die Argumente der Verschiedenen Interessengruppen werden dekonstruiert und bewertet. Es gilt grundlegende G\u00fcter wie die direkte Demokratie und die Menschenw\u00fcrde gegeneinander abzuw\u00e4gen \u2013 was besonders schwierig ist, weil sich diese G\u00fcter gegenseitig bedingen und kaum priorisieren lassen. \r\n\r\nDie Evaluation der Argumente liefert eine klare Antwort: E-Voting soll nicht eingef\u00fchrt werden. Der Versuch E-Voting soll abgebrochen werden. Dazu wird ein gesetzliches Verbot von E-Voting gefordert.\r\n\r\nUm dieses Verbot zu implementieren, werden verschiedenen Massnahmen vorgeschlagen. Es wird nach Alternativen zu E-Voting gesucht, die insbesondere Menschen mit einer Sehbehinderung mehr Autonomie und politische Teilhabe verschaffen. Eine weitere Massnahme ist dieser Vortrag selbst: die Zivilgesellschaft sowie die IT-Sicherheitscommunity weiter zu mobilisieren, f\u00fcr eine sichere Demokratie und gegen E-Voting aktiv zu werden.", "recording_license": "", "do_not_record": false, "persons": [{"code": "WMJDGT", "name": "Martina Kessler", "avatar": null, "biography": "Kommunikationswissenschaftlerin und strategische Designerin mit Fokus auf den gesellschaftlichen Wandel und eine digitale Transformation, die das Wohl der Menschen und des Planeten im Zentrum hat.", "public_name": "Martina Kessler", "guid": "044c7992-97b0-5739-abb4-45fb797f72c1", "url": "https://cfp.winterkongress.ch/wk25/speaker/WMJDGT/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/U8QXT8/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/U8QXT8/", "attachments": []}, {"guid": "fb904ce8-3bf3-5df5-86e9-a429e3306166", "code": "KKSNLX", "id": 57972, "logo": null, "date": "2025-03-01T19:00:00+01:00", "start": "19:00", "duration": "00:45", "room": "Festsaal", "slug": "wk25-57972-wir-kaufen-cyber-", "url": "https://cfp.winterkongress.ch/wk25/talk/KKSNLX/", "title": "Wir kaufen Cyber!", "subtitle": "", "track": "Netzwerke, Security, Hard- & Software", "type": "Vortrag", "language": "de", "abstract": "Ein Exkurs in die Welt der Enterprise IT-Security.", "description": "Habt ihr euch letztes Jahr gefragt, warum CrowdStrike - eine Firma von der man nur h\u00f6rte als Flugzeuge still standen - einen Marktwert von 80 Milliarden USD hat? \r\nWir bringen etwas Licht ins Dunkle, wie millionenschwere IT-Budgets eigentlich ausgegeben und Entscheidungen dazu getroffen werden, und was sich dabei in den letzten 25 Jahren ver\u00e4ndert hat. Wir schauen uns an, welche Probleme das IT-Security-Management mit spezifischen Produkten zu l\u00f6sen versucht, wie so ein Unterfangen angegangen wird und was dazu alles gebraucht - und gew\u00fcnscht - wird. \r\nUnd wie wurden eigentlich aus einfachen Firewalls hippe \u00a8Cybersecurity-Solutions\u00a8?", "recording_license": "", "do_not_record": false, "persons": [{"code": "U779YK", "name": "Mario Spuler", "avatar": null, "biography": "Mario hatte urspr\u00fcnglich mal ein Filmstudium absolviert, hat dann aber lange Zeit Software f\u00fcr Digitalisierungsprojekte entwickelt und k\u00fcmmert sich inzwischen um IT Sicherheit Architektur im Finanzumfeld. Als Vorstand des Vereins \"Echtzeit - Digitale Kultur\" und als Hauptorganisator f\u00fcr Technik der Demoparty \"MountainBytes\" unterst\u00fctzt er die Demoszene in der Schweiz und zu B\u00fcrozeiten versucht er IT Sicherheit zug\u00e4nglich, menschlich und ergonomisch zu gestalten.", "public_name": "Mario Spuler", "guid": "90239c29-2735-5bf5-8f0e-ac79d98652bf", "url": "https://cfp.winterkongress.ch/wk25/speaker/U779YK/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/KKSNLX/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/KKSNLX/", "attachments": []}, {"guid": "65074dba-ac7f-5a13-a471-260cbe94f2bd", "code": "REHFZD", "id": 59870, "logo": null, "date": "2025-03-01T20:00:00+01:00", "start": "20:00", "duration": "00:15", "room": "Festsaal", "slug": "wk25-59870-schlusswort", "url": "https://cfp.winterkongress.ch/wk25/talk/REHFZD/", "title": "Schlusswort", "subtitle": "", "track": "Andere", "type": "Moderation", "language": "de", "abstract": "Das Schlusswort", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"code": "PLBTRP", "name": "Team Winterkongress", "avatar": null, "biography": null, "public_name": "Team Winterkongress", "guid": "6de73f8d-b1fd-5d46-9f05-b86d7c280b73", "url": "https://cfp.winterkongress.ch/wk25/speaker/PLBTRP/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/REHFZD/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/REHFZD/", "attachments": []}, {"guid": "25870006-9281-5e7a-b803-fd56affc6896", "code": "MZ8EEB", "id": 59220, "logo": null, "date": "2025-03-01T20:15:00+01:00", "start": "20:15", "duration": "00:45", "room": "Festsaal", "slug": "wk25-59220-42-das-quiz-fr-nerds", "url": "https://cfp.winterkongress.ch/wk25/talk/MZ8EEB/", "title": "42: Das Quiz f\u00fcr Nerds", "subtitle": "", "track": "Andere", "type": "Unterhaltung", "language": "de", "abstract": "So interaktiv wie der Winterkongress ist, soll auch der Abschluss sein. So gibt es zum Abschluss des Winterkongresses auf der grossen B\u00fchne ein Quizz \u00fcber digitale Themen: Was ist in j\u00fcngster Zeit netzpolitisch passiert und und wof\u00fcr steht die Digitale Gesellschaft steht. Zum Mitspielen braucht ihr ein Handy... und ein breites digitales Wissen, um zu gewinnen.", "description": "Sehr viel ist digitalpolitisch in den letzten Monaten passiert. Und auch der Winterkongress 2025 gibt einen wunderbaren Einblick in die digitale Entwicklung. Und was ist eigentlich die Antwort auf alles?\r\n\r\nDie Crew des Netzpodcasts wird mit einem unterhaltsamen Quizz Eurer Digitales-Nerd-Wissen testen. Es gibt Fragen \u00fcber digitalpolitische Ereignisse der letzten Monate, aber auch Allgemeinfragen und die ein oder andere nicht ganz so ernstgemeinte Frage. Zum Mitspielen braucht ihr kein spezielles Wissen, sondern ein Handy und eine Internetverbindung. Zum Abschluss gibt es die Preisverleihung auf der B\u00fchne.\r\n\r\nDie Fragen kommen von Kire Sch\u00f6nenberger (Gesch\u00e4ftsleiter Digitale Gesellschaft), Rahel Estermann (Vorstand Digitale Gesellschaft) und J\u00f6rg M\u00e4der (Netzpolitiker). Moderiert wird das Quizz von Sven Kohlmeier (Rechtsanwalt).", "recording_license": "", "do_not_record": false, "persons": [{"code": "WD9BFH", "name": "Sven Kohlmeier", "avatar": null, "biography": "Sven Kohlmeier ist Rechtsanwalt und Fachanwalt f\u00fcr IT-Recht (D) und in der Z\u00fcrcher 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. Er ist Mitgr\u00fcnder des \u201cDigital Education Institute\u201d mit KI-Learning-Angeboten f\u00fcr Unternehmen und Verwaltung. Sven ist Mitglied der Digitalen Gesellschaft und im Netzpodcast zu h\u00f6ren.", "public_name": "Sven Kohlmeier", "guid": "2323ea18-e5c0-5e1b-95ed-f42a763163b3", "url": "https://cfp.winterkongress.ch/wk25/speaker/WD9BFH/"}, {"code": "QEQML7", "name": "Erik Sch\u00f6nenberger", "avatar": null, "biography": "Erik Sch\u00f6nenberger ist Informatiker und Gesch\u00e4ftsleiter der Digitalen Gesellschaft, die er mit initiiert hat. Die 10 Jahre davor hat er sich mit IT-Security besch\u00e4ftigt. Sein Interesse gilt dem Spannungsfeld aus Technologie, Gesellschaft und Recht.", "public_name": "Erik Sch\u00f6nenberger", "guid": "16870bc8-38f8-5fe7-a094-cf04183fc0ce", "url": "https://cfp.winterkongress.ch/wk25/speaker/QEQML7/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/MZ8EEB/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/MZ8EEB/", "attachments": []}], "Bankettsaal": [{"guid": "c313308b-4fa0-59fc-9c10-cf100e0786a1", "code": "JWVCFV", "id": 59476, "logo": null, "date": "2025-03-01T12:00:00+01:00", "start": "12:00", "duration": "00:45", "room": "Bankettsaal", "slug": "wk25-59476-e-collecting-pilot-gestalten-wir-das-herzstck-der-digitalen-demokratie-", "url": "https://cfp.winterkongress.ch/wk25/talk/JWVCFV/", "title": "E-Collecting-Pilot: Gestalten wir das Herzst\u00fcck der digitalen Demokratie!", "subtitle": "", "track": "Ethik, Wissenschaft, Kultur & Gesellschaft", "type": "Vortrag", "language": "de", "abstract": "E-Collecting steht in der Schweiz vor dem Durchbruch: Nach jahrelangem politischen Stillstand hat der Skandal um gef\u00e4lschte Unterschriften Bewegung in die Sache gebracht. Bundesrat und Parlament unterst\u00fctzen ein Pilotprojekt zur digitalen Unterschriftensammlung. Die Kerngruppe des E-ID-Referendums pr\u00e4sentiert ihr Konzept: E-Collecting soll b\u00fcrger:innennah, dezentral und datensparsam funktionieren.", "description": "E-Collecting wird die Art und Weise, wie wir Unterschriften f\u00fcr Volksinitiativen und Referenden sammeln, tiefgreifend ver\u00e4ndern. Die gesetzliche Grundlage existiert seit 2014 \u2013 doch Bundesrat und Parlament blockierten die Umsetzung aus Angst vor politischem Macht- und Kontrollverlust. Erst der Unterschriftenf\u00e4lschungs-Skandal erzwang ein Umdenken. Jetzt kommt das E-Collecting-Pilotprojekt, aufbauend auf der neuen E-ID.\r\n\r\nBei E-Collecting geht es um mehr als nur technische Fragen. Bei diesem Pilotprojekt werden die demokratischen Spielregeln neu geschrieben. Dieser Prozess ist zu wichtig, um ihn allein der Politik zu \u00fcberlassen.\r\n\r\nE-Collecting muss eine dezentrale, datensparsame und barrierefreie politische Partizipation erm\u00f6glichen. Das System soll transparent und \u00fcberpr\u00fcfbar sein \u2013 und die politische Teilhabe f\u00fcr alle vereinfachen statt erschweren.\r\n\r\nDaf\u00fcr braucht es eine starke zivilgesellschaftliche Allianz, die bei Planung, Umsetzung und Evaluation des Pilotprojekts aktiv mitgestaltet. Die technischen und rechtlichen Weichen m\u00fcssen \u00f6ffentlich diskutiert und gemeinsam gestellt werden.\r\n\r\nDie Kerngruppe des E-ID-Referendums zeigt in diesem Input auf, wie ein b\u00fcrger:innennahes, datensparsames und dezentrales E-Collecting konkret aussehen k\u00f6nnte. Sie pr\u00e4sentiert erste technische Konzepte und skizziert die n\u00e4chsten politischen Schritte.\r\n\r\nReferent:innen: Daniel Graf, Erik Sch\u00f6nenberger und Sandro Scalco", "recording_license": "", "do_not_record": false, "persons": [{"code": "DXB9LF", "name": "Daniel Graf", "avatar": null, "biography": "Daniel ist Gr\u00fcnder der Online-Plattform WeCollect, Stiftungsrat der Stiftung f\u00fcr direkte Demokratie und arbeitet als Campaigner f\u00fcr den Verein Public Beta. Er hat verschiedene Initiativen und Referenden mitinitiiert, darunter die Gletscher-Initiative, das E-ID-Referendum und die Inklusions-Initiative. Zusammen mit Maximilian Stern schrieb er das Buch \u00abAgenda f\u00fcr eine digitale Demokratie\u00bb.", "public_name": "Daniel Graf", "guid": "c387dd0c-ce16-513e-aff2-a2da2d5684e3", "url": "https://cfp.winterkongress.ch/wk25/speaker/DXB9LF/"}, {"code": "PA7TAE", "name": "Sandro Scalco", "avatar": null, "biography": "Sandro ist ein digitaler Demokratie-Pionier. Er hat im Kanton Schaffhausen die erste Volksmotion f\u00fcr E-Collecting lanciert und setzt sich seit Jahren f\u00fcr die Digitalisierung und Gesellschaft ein. In den letzten Jahren hat er diverse Kantone bei der Umsetzung von E-Collecting begleitet und damit wichtige Grundsteine f\u00fcr die Digitalisierung der direkten Demokratie gelegt. Zus\u00e4tzlich zu seinen Ver\u00f6ffentlichungen, darunter Studien und ein Buchkapitel zum Thema E-Collecting, hat er in Schaffhausen das Civic-Tech-Startup Owlly ins Leben gerufen.", "public_name": "Sandro Scalco", "guid": "070a794d-a0a1-5edc-b103-163e54ce4c22", "url": "https://cfp.winterkongress.ch/wk25/speaker/PA7TAE/"}, {"code": "QEQML7", "name": "Erik Sch\u00f6nenberger", "avatar": null, "biography": "Erik Sch\u00f6nenberger ist Informatiker und Gesch\u00e4ftsleiter der Digitalen Gesellschaft, die er mit initiiert hat. Die 10 Jahre davor hat er sich mit IT-Security besch\u00e4ftigt. Sein Interesse gilt dem Spannungsfeld aus Technologie, Gesellschaft und Recht.", "public_name": "Erik Sch\u00f6nenberger", "guid": "16870bc8-38f8-5fe7-a094-cf04183fc0ce", "url": "https://cfp.winterkongress.ch/wk25/speaker/QEQML7/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/JWVCFV/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/JWVCFV/", "attachments": []}, {"guid": "121b51b2-60e2-5ab2-8f96-74d08f66ab91", "code": "PPZE7M", "id": 59269, "logo": null, "date": "2025-03-01T13:00:00+01:00", "start": "13:00", "duration": "01:00", "room": "Bankettsaal", "slug": "wk25-59269-zauberhafte-ki-welt-energie-arbeit-der-ki-was-sie-mit-gesellschaften-macht", "url": "https://cfp.winterkongress.ch/wk25/talk/PPZE7M/", "title": "Zauberhafte KI-Welt? Energie & Arbeit der KI & was sie mit Gesellschaften macht", "subtitle": "", "track": "Ethik, Wissenschaft, Kultur & Gesellschaft", "type": "Vortrag", "language": "de", "abstract": "K\u00fcnstliche Intelligenz (KI) ist der Modebegriffe der letzten Jahre: KI macht alles leichter, KI hat alle L\u00f6sungen, KI wird uns retten.\r\nWas sogenannten KI eigentlich ist, worin sie sich von menschlicher Intelligenz unterscheidet, wie sie uns wohin retten wird & ob wir als Gesellschaft dorthin wollen, ist hingegen selten Thema.\r\nDer Vortrag legt die ideologischen Wurzeln von KI frei & betrachtet drei weitere Bereiche: von ihr ben\u00f6tigte Ressourcen, mit ihr zusammenh\u00e4ngende Arbeitsbedingungen sowie gesellschaftliche Auswirkungen & Verschiebungen von Macht, die sich durch diese Technologie ergeben.", "description": "K\u00fcnstliche Intelligenz (KI) wird gerade als Modebegriff oder \u201eBuzzword\u201c eingesetzt und auf nahezu alles geklebt, was nicht bei drei auf den B\u00e4umen ist. Wie von Zauberhand sollen alle Vorg\u00e4nge durch die Verwendung von KI schneller, einfacher und effektiver werden. Und viel besser, besonders im Vergleich zu ihrer Erledigung durch Menschen. Ein kleine Klick von uns und KI zaubert die L\u00f6sung von (Haus-) Aufgaben, das Schreiben von uns aufgeschobener Emails und heizt das Haus perfekt. Und wir oft m\u00fcssen noch nicht einmal Geld daf\u00fcr bezahlen!\r\n\r\nAber was sieht man, wenn man hinter den Vorhang der KI-Magie schaut? Denn wir sind alle alt genug, um zu wissen, dass Dinge nicht einfach magisch passieren. Und dass man geschenkten G\u00e4ulen immer als erstes nach den Z\u00e4hnen schauen muss. Dieser Vortag l\u00fcftet den Vorhang der KI-Magie, indem er den Anwendungen auf unterschiedliche Bereiche hin auf den virtuellen Zahn f\u00fchlt.\r\n\r\nDer erste Teil besch\u00e4ftigt sich mit der Herkunft der KI. Denn sie ist nicht pl\u00f6tzlich geschl\u00fcpft, sondern wurde entwickelt. Hinter dieser Entwicklung stehen Theorien, Geld und Vorstellungen davon, was Menschen und Gesellschaften sind. Und, in diesem Fall, wie sie durch Entwicklungen wie KI ver\u00e4ndert werden k\u00f6nnen.\r\n\r\nNach dieser Einleitung wird die KI im Hinblick auf drei Bereiche entzaubert: Im ersten Schritt auf ihren Verbrauch der schwindenden Ressourcen des Planeten, auf die mit ihr zusammenh\u00e4ngenden Arbeitsbedingungen und auf die gesellschaftlichen Ver\u00e4nderungen, die sie und ihre Entwickler:innen ausl\u00f6sen.\r\n\r\nComputerteile wachsen nicht an Str\u00e4uchern, in ihnen stecken viele Ressourcen wie Energie, Rohstoffe und Wasser. Und sehr viel menschliche Arbeit, die oft unter grausamen Bedingungen stattfindet. In diesem Bereich des Vortrags wird auch die Endlichkeitsfrage aufgeworfen, da uns neben dem Faktum des Klimawandels auch die Endlichkeit der Ressourcen des Planeten bewusst sein sollte. Zudem sind (fragile) globale Lieferketten und Abh\u00e4ngigkeiten im Zusammenhang mit der Produktion von sogenannten Supercomputern Teil dieses Abschnitts.\r\n\r\nDer n\u00e4chste Teil nimmt den Faden der Arbeitsbedingungen im Zusammenhang mit der KI wieder auf. Denn nicht nur in der Produktion der Hardware, sondern auch im Training der Software sind unz\u00e4hlige Menschen involviert und auch hier oft unter brutalen Bedingungen. Und auch hier zeigen sich wieder globale Tendenzen: Der \u201eNorden\u201c verdient, w\u00e4hrend der \u201eS\u00fcden\u201c schuftet. Zudem ist in den angeblichen KI-Anwendungen nicht alles Gold, was gl\u00e4nzt, und so werden in diesem Teil auch Tricksereien aufgedeckt, bei denen die Magie der KI nur fauler Zauber war.\r\n\r\nIm letzten Teil des Vortrags werden die Auswirkungen der Entwicklungen auf unsere Gesellschaft angerissen, um dieses Thema dann in die Abschlussdiskussion mitzunehmen. Fragen, die er\u00f6rtert werden, sind die nach den Auswirkungen, wenn eine Technologie, deren Rechenprozesse so undurchsichtig sind, so viel Macht bekommt und nach der, wer \u00fcber genug (Computer-) Macht verf\u00fcgt, um Anwendungen zu entwickeln.\r\nWie ver\u00e4ndert es unsere Arbeit, unseren sozialen Austausch mit anderen Menschen und unser politisches Engagement, wenn KI-Werkzeuge eingesetzt werden? Wie ver\u00e4ndern sich Gesellschaften, wenn \u201eTech\u201c und die Eigent\u00fcmer:innen von Tech-Unternehmen so viel Macht bekommen?\r\n\r\nJe mehr Macht wir Technologien wie KI und ihren Entwickler:innen geben, desto st\u00e4rker sollten wir uns fragen, ob wir das, was mit diesen Entwicklungen bewirkt werden soll, wollen.", "recording_license": "", "do_not_record": false, "persons": [{"code": "83WEGP", "name": "Katika", "avatar": null, "biography": "Katika K\u00fchnreich ist Politikwissenschaftlerin und Sinologin mit philosophischen Schwerpunkt. Durch einen Vortag beim CCC 2017 erlangte sie internationale Bekanntheit. Zu ihren Arbeitsschwerpunkten z\u00e4hlen die gesellschaftlichen Auswirkungen der Digitalisierung & die mit ihr verbundenen Arbeitsbedingungen sowie ihr Ressourcenverbrauch. Zudem forscht sie zu den sozialen Ver\u00e4nderungen durch KI, sogenannte Social Media & Gamifizierung, zu \u00dcberwachung & den Umgang mit Dissens. Zu diesen Themen h\u00e4lt sie Vortr\u00e4ge, bietet Workshops an & arbeitet als Publizistin & Dozentin.", "public_name": "Katika", "guid": "0a455e9f-fe8e-5326-b19e-d9ce09282df7", "url": "https://cfp.winterkongress.ch/wk25/speaker/83WEGP/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/PPZE7M/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/PPZE7M/", "attachments": []}, {"guid": "d586bfba-7695-5fa6-8c5c-71d79a3b3100", "code": "UKTUSV", "id": 59283, "logo": null, "date": "2025-03-01T14:45:00+01:00", "start": "14:45", "duration": "00:30", "room": "Bankettsaal", "slug": "wk25-59283-ki-und-automatische-entscheidungssysteme-die-regulation-kommt-nach-dem-hype-", "url": "https://cfp.winterkongress.ch/wk25/talk/UKTUSV/", "title": "KI- und Automatische Entscheidungssysteme: Die Regulation kommt nach dem Hype!", "subtitle": "", "track": "Recht & Politik", "type": "Vortrag kurz", "language": "de", "abstract": "\u00dcber KI geredet wird viel, doch was geschieht in der Schweiz? Die Fachgruppe Automated Decision-Making Systeme (ADMS) der Digitalen Gesellschaft ist seit den Anf\u00e4ngen in der Schweiz mit dabei. Gerade k\u00fcrzlich hat der Bundesrat den Bericht zu m\u00f6glichen Regulierungsans\u00e4tze f\u00fcr K\u00fcnstliche Intelligenz in der Schweiz ver\u00f6ffentlicht. Damit macht der Diskurs um eine Regulierung einen grossen Schritt nach vorne. In diesem Vortrag beleuchten wir die Grundrisiken von k\u00fcnstlicher Intelligenz, wir werfen einen Blick zur\u00fcck auf vergangene Entwicklungen und diskutieren die Strategie des n\u00e4chsten Jahres.", "description": "Wird nachgeliefert.", "recording_license": "", "do_not_record": false, "persons": [{"code": "G8YBXF", "name": "David Sommer", "avatar": null, "biography": "Ich interessiere mich f\u00fcr die Schnittstelle zwischen Mensch und Technologie. Mit einem technischen Hintergrund in Cyber-Security treibt mich mein Interesse zu den grossen Fragen unserer Infrastruktur bei K\u00fcnstlichen Intelligenz, Software und Hardware sowie die des n\u00e4chsten Abendessen voran.", "public_name": "David Sommer", "guid": "fdc6a6f3-dd25-5f98-b781-85fa126fb1ce", "url": "https://cfp.winterkongress.ch/wk25/speaker/G8YBXF/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/UKTUSV/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/UKTUSV/", "attachments": []}, {"guid": "06922864-6613-5f96-936b-655934fac7f5", "code": "UJVBJW", "id": 59499, "logo": null, "date": "2025-03-01T15:30:00+01:00", "start": "15:30", "duration": "00:45", "room": "Bankettsaal", "slug": "wk25-59499-geliebte-sucht-die-vendor-lock-in-durchsetzte-it-drogenszene", "url": "https://cfp.winterkongress.ch/wk25/talk/UJVBJW/", "title": "Geliebte Sucht - Die Vendor Lock-in durchsetzte IT Drogenszene", "subtitle": "", "track": "Ethik, Wissenschaft, Kultur & Gesellschaft", "type": "Vortrag", "language": "de", "abstract": "Was der erste Gratis-Hit f\u00fcr den Junkie ist, ist das verlockende \"Enterprise-Startpaket\" f\u00fcr IT-Entscheider:innen - Der Einstieg ist s\u00fc\u00df, der Ausstieg bitter. In diesem schonungslosen Vortrag decken wir auf, wie Tech-Giganten ihre Kunden in die digitale Abh\u00e4ngigkeit treiben \u2013 mit allen Tricks aus dem Dealer-Handbuch. Erlebt live, wie sich das Gesch\u00e4ftsmodell der Vendor-Lock-in-Dealer entlarvt und lernt die Warnsignale kennen, bevor Eurer Unternehmen oder Beh\u00f6rde zum n\u00e4chsten \"IT-Junkie\" wird.", "description": "Von der Schweizer Pr\u00e4zisionsindustrie bis zu deutschen Mittelst\u00e4ndlern, von skandinavischen Digitalchampions bis zu s\u00fcdeurop\u00e4ischen Traditionsunternehmen \u2013 die Muster des Vendor Lock-ins wiederholen sich mit erschreckender Pr\u00e4zision. Die Entwicklungen aus dem DACH-Raum und weiteren europ\u00e4ischen M\u00e4rkten zeigt: Die \"Dealer-Strategien\" der Tech-Giganten sind l\u00e4ngst global standardisiert. \r\n\r\nDer Vortrag analysiert die psychologischen und \u00f6konomischen Mechanismen, die Vendor Lock-in so effektiv und gef\u00e4hrlich machen. Anhand konkreter Beispiele aus der Praxis wird gezeigt, wie der \"erste Kontakt\" mit propriet\u00e4ren Technologien oft durch verlockende Gratisangebote oder scheinbar unschlagbare Konditionen erfolgt - \u00e4hnlich dem \"ersten Schuss zum Nulltarif\".\r\n\r\nWir betrachten die vier Phasen der technologischen Abh\u00e4ngigkeit:\r\n\r\n**Euphorie:** Die anf\u00e4ngliche Begeisterung \u00fcber schnelle Erfolge und einfache L\u00f6sungen\r\n**Gew\u00f6hnung:** Die zunehmende Integration in bestehende Systeme\r\n**Abh\u00e4ngigkeit:** Der Punkt, an dem ein Ausstieg schmerzhaft und teuer wird\r\n**Realisation:** Das Erkennen der wahren Kosten und Einschr\u00e4nkungen\r\n\r\nDer Vortrag bietet nicht nur Analyse, sondern auch konkrete Strategien zur Pr\u00e4vention und zum kontrollierten \"Entzug\" durch: Fr\u00fcherkennung von Lock-in-Risiken, Entwicklung von Exit-Strategien, Implementierung von Multi-Vendor-Strategien und dem Fokus auf offene Standards und Interoperabilit\u00e4t\r\n\r\nAbgebunden wird mit einer paneurop\u00e4ischen Perspektive und zeigt, wie gerade die kulturelle und wirtschaftliche Vielfalt Europas zum Schl\u00fcssel f\u00fcr erfolgreiche \"Entzugsstrategien\" werden kann. Denn eines ist klar: Im Kampf gegen Vendor Lock-in sind nationale Alleing\u00e4nge zum Scheitern verurteilt. Nur ein koordinierter, europ\u00e4ischer Ansatz kann den Teufelskreis der digitalen Abh\u00e4ngigkeit durchbrechen.", "recording_license": "", "do_not_record": false, "persons": [{"code": "ECETGS", "name": "derPUPE / Lars Hohl", "avatar": null, "biography": "Information Security Manager @ Deutschen Bahn AG, Hacker im Herzen und Datensch\u00fctzer aus \u00dcberzeugung - Konzerndebugger mit einer humanoiden uptime von 51 years 6 months $days ago - Generation C64 / ZX81 - beruflich: seid 20 Jahren im Bereich IT, Information Security Management und Datenschutz in internationalen Konzernen t\u00e4tig. Kulturell gepr\u00e4gt durch DFUE-Netze in den 80zigern. Mitbegr\u00fcnder der dt. Piratenpartei & F\u00f6rderer offner dezentraler Strukturen. Mag CCC & die Hacker:innen-Ethik", "public_name": "derPUPE / Lars Hohl", "guid": "977e3224-644c-513f-8100-27ff57d3682f", "url": "https://cfp.winterkongress.ch/wk25/speaker/ECETGS/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/UJVBJW/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/UJVBJW/", "attachments": []}, {"guid": "ea180248-078d-58af-9165-c928965f46e8", "code": "9BPUVR", "id": 59118, "logo": null, "date": "2025-03-01T16:30:00+01:00", "start": "16:30", "duration": "00:30", "room": "Bankettsaal", "slug": "wk25-59118-rights-in-exile-the-digital-hub-providing-access-to-justice-for-refugees", "url": "https://cfp.winterkongress.ch/wk25/talk/9BPUVR/", "title": "Rights in Exile: the Digital Hub Providing Access to Justice for Refugees", "subtitle": "", "track": "Ethik, Wissenschaft, Kultur & Gesellschaft", "type": "Vortrag kurz", "language": "en", "abstract": "AsyLex is a Swiss NGO providing free legal aid and representation to asylum seekers by making use of digital tools. Recently, we have taken over the Rights in Exile Platform, an online hub centralizing legal information for asylum seekers and legal advisories on over 150 countries worldwide. With our presentation, we aim to give an in-depth overview on the platform and discuss how the digital age provides new opportunities to tackle social challenges, in our case concretely overcoming hurdles to accessing justice for displaced people.", "description": "While the modern global refugee community faces unprecedented challenges, it has one key advantage over previous generations: it is overwhelmingly tech-savvy and smartphone enabled. Thus, there is great potential in fostering access to justice for displaced peoples by making legal information easily available through digital tools. The Rights in Exile Platform, hosted by AsyLex, follows this vision by centralizing legal information on over 150 countries. In practice, this allows displaced people all over the world to effortlessly access urgently needed information on their rights and find organizations providing protection near them. Further, the platform provides information for legal advisories, and thus contributes to a more cohesive international legal community that can exchange best practices and specialist knowledge on legal frameworks and relevant trends in the field of asylum globally.", "recording_license": "", "do_not_record": false, "persons": [{"code": "AXGTZA", "name": "Delphine Salaverry", "avatar": null, "biography": "My name is Delphine Salaverry and I co-lead to operational management of AsyLex, a Switzerland-based NGO providing free legal aid to asylum seekers. I have a bachelors in international relations from the University of Geneva and am currently completing my masters in International law and Diplomacy at Lancaster University.", "public_name": "Delphine Salaverry", "guid": "6a767593-e210-5dfd-9ad6-82ad4ed91c1a", "url": "https://cfp.winterkongress.ch/wk25/speaker/AXGTZA/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/9BPUVR/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/9BPUVR/", "attachments": []}, {"guid": "51e33e9d-9845-5cbc-8c29-270fd46bda69", "code": "UYKQNJ", "id": 59481, "logo": null, "date": "2025-03-01T18:00:00+01:00", "start": "18:00", "duration": "00:45", "room": "Bankettsaal", "slug": "wk25-59481-plattformregulierung-in-der-schweiz", "url": "https://cfp.winterkongress.ch/wk25/talk/UYKQNJ/", "title": "Plattformregulierung in der Schweiz", "subtitle": "", "track": "Ethik, Wissenschaft, Kultur & Gesellschaft", "type": "Vortrag", "language": "de", "abstract": "Der Vortrag zum Stand der Plattformregulierung in der Schweiz thematisiert die aktuellen Entwicklungen und Herausforderungen im Umgang mit digitalen Plattformen. Es werden die gesetzlichen Rahmenbedingungen (CH & global), die Bedeutung der Zivilgesellschaft und die Aktivit\u00e4ten f\u00fcr einen ausgewogenen Ansatz zwischen Innovation und Verbraucherschutz im Rahmen der Politpulse-Gruppe vorgestellt. Und schliesslich die f\u00fcr Anfang 2025 angek\u00fcndigte Vernehmlassung zu einem Gesetz, mit dem die Schweiz dieses Thema in Angriff nehmen will.", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"code": "MEEKJG", "name": "Christoph Schmid", "avatar": null, "biography": "Christoph Schmid setzt sich f\u00fcr eine nachhaltige digitale Welt ein. So hat er bei der Digitalen Gesellschaft am Ratgeber Nachhaltigkeit mitgearbeitet, organisiert das netzpolitische Mittagessen in Basel und arbeitet als Fachbereichsleiter an inhaltlichen Programmen, der Organisationsentwicklung und der Unterst\u00fctzung der ehrenamtlichen Fachbereiche.", "public_name": "Christoph Schmid", "guid": "6e4f31ae-fea5-5cc6-80be-6cc6e41028c0", "url": "https://cfp.winterkongress.ch/wk25/speaker/MEEKJG/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/UYKQNJ/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/UYKQNJ/", "attachments": []}, {"guid": "b944adb2-908f-578d-acdf-fcb4d7164fc4", "code": "PLAYEW", "id": 59355, "logo": null, "date": "2025-03-01T19:00:00+01:00", "start": "19:00", "duration": "00:45", "room": "Bankettsaal", "slug": "wk25-59355-digitale-monokulturen-machtkonzentation-und-cluster-risiken-wir-knnen-anders-", "url": "https://cfp.winterkongress.ch/wk25/talk/PLAYEW/", "title": "Digitale Monokulturen, Machtkonzentation und Cluster-Risiken: Wir k\u00f6nnen anders!", "subtitle": "", "track": "Netzwerke, Security, Hard- & Software", "type": "Vortrag", "language": "de", "abstract": "Unsere digitalen Infrastruktur w\u00e4chst in eine zunehmende Abh\u00e4ngigkeit von einigen wenigen Schl\u00fcsselakteuren. Speziell bei Cloud-Hyperscaler, Software-L\u00f6sungen und Hardware-Produkte wird dies zu einer der gr\u00f6ssten Herausforderung der n\u00e4chsten zehn Jahre. Dies f\u00fchrt zu unausweichlichen Monopolen mit begrenzten Alternativen, eingeschr\u00e4nkten Diversifikationsm\u00f6glichkeiten und einer enormen Machtkonzentration \u2013 insbesondere ausserhalb Europas, das etwa ein Jahrzehnt hinter den f\u00fchrenden Regionen zur\u00fcckliegt. Dieser Vortrag wirf einen Blick auf die derzeitige Situation und diskutiert L\u00f6sungsans\u00e4tze.", "description": "Ganze Industrien und Infrastrukturen brechen aufgrund eines einzelnen Anbieters zusammen. Durch fehlende Konkurrenz und Alternativen lassen sich Abh\u00e4ngigkeiten wirtschaftlich ausbeuten. Sabotage und Ausfallrisiken steigen dadurch, dass kritische Prozesse in geopolitisch sensiblen Gebieten stattfinden. Ein fiktives Horrorszenario? \r\n\r\nDiese Risiken bestehen leider nicht nur theoretisch. Jeden Tag schlagen neue Zeitungsartikel und Skandale auf, welche die kommende Relevanz immer deutlicher erahnen lassen. Sei es bei Marktmachtmissbrauch grosser Technologieunternehmen, St\u00f6rungen in der Lieferkette oder Exportsanktionen f\u00fcr ganze Technologiebereiche aus geopolitischen Kalk\u00fcl. \r\n\r\nDieser Vortrag illustriert die Problematik an einigen Beispielen und diskutiert im Anschluss m\u00f6gliche L\u00f6sungsans\u00e4tze. W\u00e4hren im Bereich der Hardware-Herstellungen grosse Regierungen selbst mit Milliardensubventionen die Lieferketten nur langsam Richtung Dezentralit\u00e4t motivieren, kann im Bereich Software-L\u00f6sungen z.B. mit kollaborativen open-source Ans\u00e4tzen und offenen Protokollen realistische Alternativen geschaffen werden.", "recording_license": "", "do_not_record": false, "persons": [{"code": "G8YBXF", "name": "David Sommer", "avatar": null, "biography": "Ich interessiere mich f\u00fcr die Schnittstelle zwischen Mensch und Technologie. Mit einem technischen Hintergrund in Cyber-Security treibt mich mein Interesse zu den grossen Fragen unserer Infrastruktur bei K\u00fcnstlichen Intelligenz, Software und Hardware sowie die des n\u00e4chsten Abendessen voran.", "public_name": "David Sommer", "guid": "fdc6a6f3-dd25-5f98-b781-85fa126fb1ce", "url": "https://cfp.winterkongress.ch/wk25/speaker/G8YBXF/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/PLAYEW/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/PLAYEW/", "attachments": []}], "Tanzsaal": [{"guid": "b741a86f-e80f-5015-a2d7-17d3e466ef80", "code": "MANMFW", "id": 58786, "logo": null, "date": "2025-03-01T12:00:00+01:00", "start": "12:00", "duration": "00:45", "room": "Tanzsaal", "slug": "wk25-58786-deepfakes-in-der-schweiz", "url": "https://cfp.winterkongress.ch/wk25/talk/MANMFW/", "title": "Deepfakes in der Schweiz", "subtitle": "", "track": "Ethik, Wissenschaft, Kultur & Gesellschaft", "type": "Vortrag", "language": "de", "abstract": "Wie sieht es mit Deepfakes in der Schweiz aus? In diesem Vortrag geht es um die Chancen und Risiken dieser neuen Technologien f\u00fcr die Schweizer Gesellschaft, Politik, Wirtschaft und Medienlandschaft. Anhand der neuen Studie von TA-SWISS \u00fcber Deepfakes werden auch folgende Fragen beantwortet: Wie gut k\u00f6nnen Schweizer B\u00fcrgerinnen und B\u00fcrger Deepfakes von echten Videos unterscheiden? Wie kann sich die Schweiz auf eine Zunahme von Deepfakes vorbereiten? Und was kann die Technik dazu beitragen, den Risiken vorzubeugen?", "description": "", "recording_license": "", "do_not_record": false, "persons": [{"code": "7THHPT", "name": "Laetitia Ramelet", "avatar": null, "biography": "Laetitia Ramelet ist politische Philosophin. In ihrer Rolle bei TA-SWISS ist sie zust\u00e4ndig f\u00fcr verschiedene KI-Themen wie Deepfakes, Sprach- und Gesichtserkennung sowie Sprachmodelle. Vorher hat sie an der Universit\u00e4t Lausanne doktoriert und war bei den Wirtschaftskommissionen des Parlaments im Bereich Wissenschaft und Politik t\u00e4tig.", "public_name": "Laetitia Ramelet", "guid": "d96eb671-4d3b-5740-9af7-6e9648d6dd3c", "url": "https://cfp.winterkongress.ch/wk25/speaker/7THHPT/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/MANMFW/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/MANMFW/", "attachments": [{"title": "TA-Studie \"Deepfakes\"", "url": "/media/wk25/submissions/MANMFW/resources/Studie_Deepfakes_E-bo_DLuTgTX.pdf", "type": "related"}]}, {"guid": "a9d1ca6d-bee6-5ea9-8d2d-d7dc14c415e8", "code": "UWEZQX", "id": 59356, "logo": null, "date": "2025-03-01T13:00:00+01:00", "start": "13:00", "duration": "00:45", "room": "Tanzsaal", "slug": "wk25-59356-un-cybercrime-convention-die-mutter-aller-berwachung-kommt-", "url": "https://cfp.winterkongress.ch/wk25/talk/UWEZQX/", "title": "UN-Cybercrime Convention - Die Mutter aller \u00dcberwachung kommt?", "subtitle": "", "track": "Recht & Politik", "type": "Vortrag", "language": "de", "abstract": "Mit der UN-Cybercrime Convention entsteht ein globaler \u00dcberwachungsstandard, der die Bedrohung von Sicherheit und Privatsph\u00e4re auf ein neues Level hebt. Die Konvention umfasst fast alles, wogegen wir in den letzten Jahren gek\u00e4mpft haben. Weil dieses Vorhaben weitgehend unter dem Radar der \u00d6ffentlichkeit ablief, blieb bisher auch der gro\u00dfe Widerstand aus.", "description": "Wie sicher ist unsere digitale Freiheit noch?\r\n\r\nIm Schatten der Weltpolitik und kaum bemerkt von der \u00d6ffentlichkeit schmieden Russland, China und Iran \u2013 unterst\u00fctzt von westlichen Demokratien \u2013 ein globales \u00dcberwachungspaket: die UN-Cybercrime Convention. \r\n\r\nDie UN-Cybercrime Convention beinhaltet nahezu alles wogegen wir die letzten Jahrzehnte gek\u00e4mpft und Grundrechte, die wir verteidigt haben: \r\n- Vorratsdatenspeicherung \r\n- Kabelaufkl\u00e4rung \r\n- Chatkontrolle\r\n- \u00dcberwachung aller Finanzstr\u00f6me \r\n- Plattformhaftung und Uploadfilter\r\n- Verhinderung von Whistleblowing\r\n- Illegalisierung von ethischem Hacken und IT-Sicherheitsforschung \r\n- eine so vage Definition von Cybercrime, dass nun auch weitere legale und wichtige Handlungen kriminalisiert werden.\r\nDieser v\u00f6lkerrechtlich bindende Vertrag ist auf der Zielgeraden.\r\n\r\nWie geht es nach der Annahme der Konvention in der Schweiz weiter?\r\nWie k\u00f6nnen wir trotzdem unsere digitalen Rechte noch st\u00e4rken?", "recording_license": "", "do_not_record": false, "persons": [{"code": "JA7NAH", "name": "Pascal Fouquet", "avatar": "https://cfp.winterkongress.ch/media/avatars/JA7NAH_QYh0lhI.jpg", "biography": "Pascal Fouquet ist seit \u00fcber einem Jahrzehnt digitalpolitisch unterwegs, leitete diverse nationale und internationale Kampagnen, unter anderem savetheinternet.info, die gr\u00f6sste digitalpolitische Kampagne aller Zeiten mit \u00fcber 200.000 Demonstranten auf Europas Strassen oder www.ausweiszwang-nein.ch.", "public_name": "Pascal Fouquet", "guid": "fe15ec1e-e8a5-5a83-a017-95bf47891d9c", "url": "https://cfp.winterkongress.ch/wk25/speaker/JA7NAH/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/UWEZQX/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/UWEZQX/", "attachments": []}, {"guid": "d877fd1b-f095-5ece-8650-2b53afccd7aa", "code": "TY83UM", "id": 59498, "logo": null, "date": "2025-03-01T14:45:00+01:00", "start": "14:45", "duration": "00:30", "room": "Tanzsaal", "slug": "wk25-59498-uncovering-discrimination-in-public-fraud-detection-systems", "url": "https://cfp.winterkongress.ch/wk25/talk/TY83UM/", "title": "Uncovering discrimination in public fraud detection systems", "subtitle": "", "track": "Ethik, Wissenschaft, Kultur & Gesellschaft", "type": "Vortrag kurz", "language": "de", "abstract": "In recent years, algorithmic systems used by the Dutch government for fraud detection in welfare, allowances, and student loans were found to be discriminatory, causing harm to citizens. The Childcare Benefits Scandal highlighted these issues, sparking political and societal debates, investigations, and reforms. This session will explore causes of discriminatory outcomes, why they went undetected, red flags in such systems, and steps governments and society can take to ensure fair use of public algorithms. Lessons learned as an AI expert within the Dutch government will be shared.", "description": "In recent years, several examples have come to light in the Netherlands of algorithmic systems developed and deployed by the government that were later found to be discriminatory. These systems, used to detect fraud in welfare benefits, allowances, and student loans, caused severe financial and emotional harm to citizens. The most devastating example of this was the [Childcare Benefits Scandal](https://en.wikipedia.org/wiki/Dutch_childcare_benefits_scandal).\r\n\r\nThanks to the efforts of investigative journalists, civil society organizations, auditors, and determined individuals, these injustices came to light. The systems became a focal point of political and societal debate, leading to investigations and the introduction of new legislation, policies, and tools to address the issues.\r\n\r\nIn this session, I would like to share some of the lessons I have learned as an AI expert within Dutch government. The following topics will be discussed:\r\n* _Causes of discriminatory outcomes_: What are the main causes of discriminatory outcomes in public algorithmic fraud detection systems? \r\n* _Lack of Early Detection_: How was it possible for these issues to remain unnoticed for so long? \r\n* _Red flags_: What recurring patterns can be observed in these systems, and what signals indicate potential risks?\r\n* _Measures and Actions_: What steps should governments take to prevent discrimination and other harms caused by public fraud detection algorithms? What can we, as a digital society, do to ensure the fairer use of public algorithmic systems?\r\n\r\nIt is becoming increasingly clear that not only in the Netherlands, but also in countries such as [Australia](https://en.wikipedia.org/wiki/Robodebt_scheme), the [United Kingdom](https://en.wikipedia.org/wiki/British_Post_Office_scandal), [Denmark](https://www.amnesty.org/en/documents/eur18/8709/2024/en/), and [Sweden](https://www.lighthousereports.com/investigation/swedens-suspicion-machine/), similar public fraud detection systems are causing harm. The lessons shared in this presentation are therefore more broadly applicable.", "recording_license": "", "do_not_record": false, "persons": [{"code": "33KXRM", "name": "Willy Tadema", "avatar": null, "biography": "[Willy Tadema](https://www.linkedin.com/in/willytadema/) is a Dutch expert in AI and its use in government systems. With a background in technology and public policy, she focuses on the ethical and societal implications of AI, particularly in public administration. Tadema works within Dutch government to address discrimination and ensure fairness in algorithmic decision-making, promoting transparency and accountability in public AI systems. She is a member of the [Z-Inspection initiative](https://z-inspection.org) and actively involved in creating European AI standards for the AI Act.", "public_name": "Willy Tadema", "guid": "4e3e2dff-e741-522f-b61b-c8744a1b4a76", "url": "https://cfp.winterkongress.ch/wk25/speaker/33KXRM/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/TY83UM/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/TY83UM/", "attachments": []}, {"guid": "ad48f58c-50bc-5703-a74c-a6a4d8f7ab50", "code": "HRKY9D", "id": 59844, "logo": null, "date": "2025-03-01T15:30:00+01:00", "start": "15:30", "duration": "00:45", "room": "Tanzsaal", "slug": "wk25-59844-lightning-talks-deine-zehn-minuten-berhmtheit-", "url": "https://cfp.winterkongress.ch/wk25/talk/HRKY9D/", "title": "Lightning Talks - Deine zehn Minuten Ber\u00fchmtheit!", "subtitle": "", "track": "Andere", "type": "Vortrag", "language": "de", "abstract": "Bringe Deinen ansteckenden Enthusiasmus an ein Publikum mit kurzer Aufmerksamkeitsspanne! Diskutiere 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, mache es kurz!", "description": "Wir haben vier Slots mit jeweils zehn Minuten zu vergeben. Die Spielregeln sind:\r\n\r\n* First come, first serve, es werden bis am 31. Januar 2025 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, 1. M\u00e4rz 2025 bis sp\u00e4testens 12 Uhr 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* Alle Beitr\u00e4ge werden gestreamt und aufgezeichnet\r\n\r\nWir freuen uns auf Eure Einsendungen!", "recording_license": "", "do_not_record": false, "persons": [{"code": "PLBTRP", "name": "Team Winterkongress", "avatar": null, "biography": null, "public_name": "Team Winterkongress", "guid": "6de73f8d-b1fd-5d46-9f05-b86d7c280b73", "url": "https://cfp.winterkongress.ch/wk25/speaker/PLBTRP/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/HRKY9D/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/HRKY9D/", "attachments": []}, {"guid": "52fab5d2-5881-5c75-b982-3ecbcdb88f3a", "code": "TREFKA", "id": 59201, "logo": null, "date": "2025-03-01T16:30:00+01:00", "start": "16:30", "duration": "00:30", "room": "Tanzsaal", "slug": "wk25-59201-vertrauen-und-verantwortung-cybersecurity-in-der-bevlkerung-und-kmus", "url": "https://cfp.winterkongress.ch/wk25/talk/TREFKA/", "title": "Vertrauen und Verantwortung - Cybersecurity in der Bev\u00f6lkerung und KMUs", "subtitle": "", "track": "Digitale Selbstverteidigung", "type": "Vortrag kurz", "language": "de", "abstract": "Die Cyberstudie 2024 gibt als repr\u00e4sentative Untersuchung Einblicke in das digitale Sicherheitsbewusstsein von KMU, der Bev\u00f6lkerung und IT-Dienstleistern in der Schweiz. Die Ergebnisse zeigen: Wir wissen nicht, was wir nicht wissen. Cybersecurity in Privatleben und Organisation ist reine Vertrauenssache. Aber wem vertrauen wir? Und wieviel Verantwortung m\u00fcssen wir \u00fcbernehmen?\r\nDie f\u00fcnfte Cyberstudie 2024 der Forschungspartnern Die Mobiliar, digitalswitzerland, FHNW, SATW, ADSS und YouGov liegt vor.", "description": "Die Cyberstudie 2024 gibt als repr\u00e4sentative Untersuchung Einblicke in das digitale Sicherheitsbewusstsein von KMU, der Bev\u00f6lkerung und IT-Dienstleistern in der Schweiz. Die Ergebnisse zeigen: Wir wissen nicht, was wir nicht wissen. Cybersecurity in Privatleben und Organisation ist reine Vertrauenssache. Aber wem vertrauen wir? Und wieviel Verantwortung m\u00fcssen wir \u00fcbernehmen?\r\nDie f\u00fcnfte Cyberstudie 2024 wurde durchgef\u00fchrt mit den Forschungspartner/innen Die Mobiliar, digitalswitzerland, Hochschule f\u00fcr Wirtschaft FHNW, Schweizerische Akademie der Technischen Wissenschaften SATW, Swiss Internet Security Alliance, Allianz Digitale Sicherheit Schweiz ADSS und YouGov. \r\nhttps://cyberstudie.ch/", "recording_license": "", "do_not_record": false, "persons": [{"code": "HGKGBU", "name": "Katja D\u00f6rlemann", "avatar": null, "biography": "Katja D\u00f6rlemann ist Security Awareness Expertin bei Switch und Pr\u00e4sidentin der Swiss Internet Security Alliance. Sie unterst\u00fctzt sie die Schweizer Security Community im Umgang mit dem Faktor Mensch in der Informationssicherheit. Durch die Organisation und Teilnahme an Veranstaltungen, Podcasts und anderen nationalen Cybersicherheitsinitiativen f\u00f6rdert sie den Wissensaustausch und die Vernetzung von Expertise, um das Thema Security Awareness voranzutreiben.", "public_name": "Katja D\u00f6rlemann", "guid": "ae95eed3-6ef9-52c6-ac89-48cc528acf1d", "url": "https://cfp.winterkongress.ch/wk25/speaker/HGKGBU/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/TREFKA/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/TREFKA/", "attachments": []}, {"guid": "60d9e813-2fa4-566c-84e8-e1bd6ed1b6f7", "code": "JHJLY7", "id": 58374, "logo": null, "date": "2025-03-01T18:00:00+01:00", "start": "18:00", "duration": "00:45", "room": "Tanzsaal", "slug": "wk25-58374--it-sicherheit-von-balkonsolaranlagen", "url": "https://cfp.winterkongress.ch/wk25/talk/JHJLY7/", "title": "(IT)-Sicherheit von Balkonsolaranlagen", "subtitle": "", "track": "Netzwerke, Security, Hard- & Software", "type": "Vortrag", "language": "de", "abstract": "Energiewende, ja klar, aber zu welchem Preis?\r\n\r\nKleine Solaranlagen k\u00f6nnen helfen, den Standby-Verbrauch der eigenen Wohnung zu decken und amortisieren sich nach ein paar Jahren.\r\n\r\n\u00c4hnlich wie in den Anfangszeiten von Wi-Fi gibt es jedoch auch Stolpersteine, sei es bei der Hardware oder der Software/Firmware, die mit den Ger\u00e4ten geliefert wird.", "description": "Ich werde \u00fcber einige \u00e4ltere Erkenntnisse im Bereich der IT-Sicherheit sprechen und aufzeigen, wohin die Reise langfristig geht und worauf in Zukunft geachtet werden sollte.", "recording_license": "", "do_not_record": true, "persons": [{"code": "TFMY9B", "name": "Bastian Widmer", "avatar": null, "biography": "lorem", "public_name": "Bastian Widmer", "guid": "5207f16e-ae7b-5538-ad15-82be19f7281a", "url": "https://cfp.winterkongress.ch/wk25/speaker/TFMY9B/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/JHJLY7/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/JHJLY7/", "attachments": []}, {"guid": "d6dd56b5-272d-57dd-b9c2-289e60df4e0f", "code": "K8BD3R", "id": 58360, "logo": null, "date": "2025-03-01T19:00:00+01:00", "start": "19:00", "duration": "00:45", "room": "Tanzsaal", "slug": "wk25-58360-mit-offenen-parlamentsdaten-zu-mehr-transparenz-innovation-und-mitwirkung", "url": "https://cfp.winterkongress.ch/wk25/talk/K8BD3R/", "title": "Mit offenen Parlamentsdaten zu mehr Transparenz, Innovation und Mitwirkung", "subtitle": "", "track": "Ethik, Wissenschaft, Kultur & Gesellschaft", "type": "Vortrag", "language": "de", "abstract": "Wir bauen gemeinsam einen offenen Standard und eine offene Schnittstelle (API) f\u00fcr harmonisierte Schweizer Parlamentsdaten und Daten zu politischen Gesch\u00e4ften. So f\u00f6rdern wir Transparenz, Innovation und Mitwirkung in der Politik. In diesem Vortrag stellen wir den aktuellen Stand von [OpenParlData.ch](https://openparldata.ch) vor sowie was wir noch vor und bis jetzt gelernt haben. Wir freuen uns auf eure Inputs und Feedback!", "description": "Als B\u00fcrger:in, Journalist:in, Wissenschaftler:in oder zivilgesellschaftliche Organisation ist es aktuell nur mit hohem Aufwand oder Kosten m\u00f6glich, ein spezifisches politisches Thema auf unterschiedlichen f\u00f6deralen Ebenen oder ein politisches Gesch\u00e4ft von A bis Z zu verfolgen. Der Grund: Die 26 Kantons-, 461 Gemeindeparlamente, sowie das nationale Parlament ver\u00f6ffentlichen ihre Daten in unterschiedlichen Formaten, Strukturen und Qualit\u00e4ten, die nicht miteinander kompatibel und verkn\u00fcpft sind. Es gibt keine kostenfreie M\u00f6glichkeit, Daten von mehreren Parlamenten strukturiert zu durchsuchen oder die Daten zu beziehen. Dies erschwert zivilgesellschaftliche Initiativen und stellt unn\u00f6tige Barrieren f\u00fcr eine aktive B\u00fcrger:innenbeteiligung dar. Initiativen, welche Parlamentsdaten nutzen (z.B. Prototype Fund Projekte: Demokratis, VoteLog, CH+ Games for Democracy) beschr\u00e4nken sich bisher notgedrungen auf Daten auf Bundesebene. Der Aufwand f\u00fcr den Einbezug der Kantons- und Gemeindeebene ist aufgrund der Unzul\u00e4nglichkeit der Daten unverh\u00e4ltnism\u00e4ssig gross.\r\n\r\nDiese L\u00fccke wollen wir schliessen: Wir bauen gemeinsam eine offene Infrastruktur auf, die Parlamentsdaten aller f\u00f6deralen Ebenen zusammentr\u00e4gt. Die Daten werden \u00fcber eine Schnittstelle (API) und eine Weboberfl\u00e4che (Minimal GUI) frei zug\u00e4nglich und durchsuchbar gemacht. So wird ein Grundstein f\u00fcr einen offene Weiternutzung der strukturiert erfassten Daten gelegt. Bestehende Initiativen k\u00f6nnen neu auch Daten von Kantonen und Gemeinden einbeziehen und es er\u00f6ffnen sich grunds\u00e4tzlich neue Anwendungsfelder f\u00fcr die Nutzung und Analyse von Schweizer Parlamentsdaten (z.B. Politisches Monitoring f\u00fcr zivilgesellschaftliche Organisationen (Politpulse), Transparenz von Interessenbindungen: Lobbywatch, Monitoring von Abstimmungsverhalten: Smartmonitor, techrating.ch, Ratsdebatten mittels AI durchsuchen und zusammenfassen: LegisLense).\r\n\r\nDar\u00fcber hinaus zielt das Projekt darauf ab, die Datenbereitstellung und -strukturierung bei den Parlamenten zu optimieren und einen einheitlichen Standard zu etablieren.\r\n\r\nWir arbeiten offen und kollaborativ an diesem Projekt. [Verfolge den Fortschritt und trage dazu bei auf GitLab.](https://gitlab.com/opendata.ch/openparldatach)\r\n\r\nIn diesem Vortrag stellen wir den aktuellen Stand von [OpenParlData.ch](https://openparldata.ch) vor sowie was wir noch vor und bis jetzt gelernt haben.", "recording_license": "", "do_not_record": false, "persons": [{"code": "ABNJKV", "name": "Florin Hasler", "avatar": "https://cfp.winterkongress.ch/media/avatars/ABNJKV_CbQnJvA.jpg", "biography": "Florin leitet [Opendata.ch](https://opendata.ch/), ein Verein, der sich f\u00fcr Datennutzung im Interesse des Gemeinwohls einsetzt. Nachdem er in der Aussenpolitik und der politischen Kommunikation t\u00e4tig war, fand er seine Leidenschaft an der Schnittstelle von Technologie, Politik und Gesellschaft. Bei Opendata.ch unterst\u00fctzt er den \u00f6ffentlichen Sektor auf seinem Weg zu mehr Offenheit und setzt sich f\u00fcr eine digitale Transformation ein, von der viele und nicht nur wenige profitieren. Bevor er die Gesch\u00e4ftsleitung \u00fcbernahm, leitete Florin den Prototype Fund.", "public_name": "Florin Hasler", "guid": "e43fc22a-807a-592d-8d79-12dedee5cf72", "url": "https://cfp.winterkongress.ch/wk25/speaker/ABNJKV/"}, {"code": "XT8WNL", "name": "Christian Gutknecht", "avatar": null, "biography": "Data Engineer, Open Parl Data", "public_name": "Christian Gutknecht", "guid": "f9c9a427-a1b7-5e6e-ae8e-49e200ac2f49", "url": "https://cfp.winterkongress.ch/wk25/speaker/XT8WNL/"}], "links": [], "feedback_url": "https://cfp.winterkongress.ch/wk25/talk/K8BD3R/feedback/", "origin_url": "https://cfp.winterkongress.ch/wk25/talk/K8BD3R/", "attachments": []}]}}]}}} \ No newline at end of file