summaryrefslogtreecommitdiff
path: root/date-fns/src/_lib
diff options
context:
space:
mode:
Diffstat (limited to 'date-fns/src/_lib')
-rw-r--r--date-fns/src/_lib/addLeadingZeros/index.js8
-rw-r--r--date-fns/src/_lib/assign/index.js17
-rw-r--r--date-fns/src/_lib/assign/test.js30
-rw-r--r--date-fns/src/_lib/cloneObject/index.js5
-rw-r--r--date-fns/src/_lib/cloneObject/test.js31
-rw-r--r--date-fns/src/_lib/format/formatters/index.js768
-rw-r--r--date-fns/src/_lib/format/lightFormatters/index.ts94
-rw-r--r--date-fns/src/_lib/format/longFormatters/index.js66
-rw-r--r--date-fns/src/_lib/getTimezoneOffsetInMilliseconds/index.js26
-rw-r--r--date-fns/src/_lib/getTimezoneOffsetInMilliseconds/test.js28
-rw-r--r--date-fns/src/_lib/getUTCDayOfYear/index.js18
-rw-r--r--date-fns/src/_lib/getUTCDayOfYear/test.js36
-rw-r--r--date-fns/src/_lib/getUTCISOWeek/index.js21
-rw-r--r--date-fns/src/_lib/getUTCISOWeek/test.js58
-rw-r--r--date-fns/src/_lib/getUTCISOWeekYear/index.js30
-rw-r--r--date-fns/src/_lib/getUTCISOWeekYear/test.js36
-rw-r--r--date-fns/src/_lib/getUTCWeek/index.js22
-rw-r--r--date-fns/src/_lib/getUTCWeek/test.js70
-rw-r--r--date-fns/src/_lib/getUTCWeekYear/index.js51
-rw-r--r--date-fns/src/_lib/getUTCWeekYear/test.js70
-rw-r--r--date-fns/src/_lib/isSameUTCWeek/index.js13
-rw-r--r--date-fns/src/_lib/isSameUTCWeek/test.js111
-rw-r--r--date-fns/src/_lib/protectedTokens/index.js30
-rw-r--r--date-fns/src/_lib/requiredArgs/index.ts12
-rw-r--r--date-fns/src/_lib/requiredArgs/test.js37
-rw-r--r--date-fns/src/_lib/setUTCDay/index.js38
-rw-r--r--date-fns/src/_lib/setUTCDay/test.js132
-rw-r--r--date-fns/src/_lib/setUTCISODay/index.js27
-rw-r--r--date-fns/src/_lib/setUTCISODay/test.js79
-rw-r--r--date-fns/src/_lib/setUTCISOWeek/index.js16
-rw-r--r--date-fns/src/_lib/setUTCISOWeek/test.js61
-rw-r--r--date-fns/src/_lib/setUTCWeek/index.js16
-rw-r--r--date-fns/src/_lib/setUTCWeek/test.js95
-rw-r--r--date-fns/src/_lib/startOfUTCISOWeek/index.js18
-rw-r--r--date-fns/src/_lib/startOfUTCISOWeek/test.js34
-rw-r--r--date-fns/src/_lib/startOfUTCISOWeekYear/index.js16
-rw-r--r--date-fns/src/_lib/startOfUTCISOWeekYear/test.js58
-rw-r--r--date-fns/src/_lib/startOfUTCWeek/index.js33
-rw-r--r--date-fns/src/_lib/startOfUTCWeek/test.js108
-rw-r--r--date-fns/src/_lib/startOfUTCWeekYear/index.js30
-rw-r--r--date-fns/src/_lib/startOfUTCWeekYear/test.js95
-rw-r--r--date-fns/src/_lib/test/index.ts1
-rw-r--r--date-fns/src/_lib/toInteger/index.ts13
-rw-r--r--date-fns/src/_lib/toInteger/test.js64
44 files changed, 2622 insertions, 0 deletions
diff --git a/date-fns/src/_lib/addLeadingZeros/index.js b/date-fns/src/_lib/addLeadingZeros/index.js
new file mode 100644
index 0000000..62f812b
--- /dev/null
+++ b/date-fns/src/_lib/addLeadingZeros/index.js
@@ -0,0 +1,8 @@
+export default function addLeadingZeros(number, targetLength) {
+ var sign = number < 0 ? '-' : ''
+ var output = Math.abs(number).toString()
+ while (output.length < targetLength) {
+ output = '0' + output
+ }
+ return sign + output
+}
diff --git a/date-fns/src/_lib/assign/index.js b/date-fns/src/_lib/assign/index.js
new file mode 100644
index 0000000..6fd8782
--- /dev/null
+++ b/date-fns/src/_lib/assign/index.js
@@ -0,0 +1,17 @@
+export default function assign(target, dirtyObject) {
+ if (target == null) {
+ throw new TypeError(
+ 'assign requires that input parameter not be null or undefined'
+ )
+ }
+
+ dirtyObject = dirtyObject || {}
+
+ for (var property in dirtyObject) {
+ if (dirtyObject.hasOwnProperty(property)) {
+ target[property] = dirtyObject[property]
+ }
+ }
+
+ return target
+}
diff --git a/date-fns/src/_lib/assign/test.js b/date-fns/src/_lib/assign/test.js
new file mode 100644
index 0000000..629358f
--- /dev/null
+++ b/date-fns/src/_lib/assign/test.js
@@ -0,0 +1,30 @@
+// @flow
+/* eslint-env mocha */
+
+import assert from 'power-assert'
+import assign from '.'
+
+describe('assign', function() {
+ it('assigns properties of the second argument to the first argument', function() {
+ var object = {}
+ assign(object, { a: 1, b: 2, c: 3 })
+ assert.deepEqual(object, { a: 1, b: 2, c: 3 })
+ })
+
+ it('the object passed as 2nd argument remains unchanged when the result is mutated', function() {
+ var object = { a: 1, b: 2, c: 3 }
+ var result = assign({}, object)
+ result.c = 4
+ assert.deepEqual(object, { a: 1, b: 2, c: 3 })
+ })
+
+ it('returns the first argument when the second argument is `undefined`', function() {
+ var original = { a: 1, b: 2, c: 3 }
+ var result = assign(original, undefined)
+ assert(original === result)
+ })
+
+ it('throws TypeError exception if the first argument is `undefined', function() {
+ assert.throws(assign.bind(null, undefined, { a: 1, b: 2, c: 3 }), TypeError)
+ })
+})
diff --git a/date-fns/src/_lib/cloneObject/index.js b/date-fns/src/_lib/cloneObject/index.js
new file mode 100644
index 0000000..34dd17b
--- /dev/null
+++ b/date-fns/src/_lib/cloneObject/index.js
@@ -0,0 +1,5 @@
+import assign from '../assign/index'
+
+export default function cloneObject(dirtyObject) {
+ return assign({}, dirtyObject)
+}
diff --git a/date-fns/src/_lib/cloneObject/test.js b/date-fns/src/_lib/cloneObject/test.js
new file mode 100644
index 0000000..96302bb
--- /dev/null
+++ b/date-fns/src/_lib/cloneObject/test.js
@@ -0,0 +1,31 @@
+// @flow
+/* eslint-env mocha */
+
+import assert from 'power-assert'
+import cloneObject from '.'
+
+describe('cloneObject', function () {
+ it('makes a copy of an object', function () {
+ var result = cloneObject({a: 1, b: 2, c: 3})
+ assert.deepEqual(result, {a: 1, b: 2, c: 3})
+ })
+
+ it('the copy remains unchanged when the original is changed', function () {
+ var original = {a: 1, b: 2, c: 3}
+ var copy = cloneObject(original)
+ original.c = 4
+ assert.deepEqual(copy, {a: 1, b: 2, c: 3})
+ })
+
+ it('the original remains unchanged when the copy is changed', function () {
+ var original = {a: 1, b: 2, c: 3}
+ var copy = cloneObject(original)
+ copy.c = 4
+ assert.deepEqual(original, {a: 1, b: 2, c: 3})
+ })
+
+ it('returns an empty object when argument is `undefined`', function () {
+ var result = cloneObject(undefined)
+ assert.deepEqual(result, {})
+ })
+})
diff --git a/date-fns/src/_lib/format/formatters/index.js b/date-fns/src/_lib/format/formatters/index.js
new file mode 100644
index 0000000..4638060
--- /dev/null
+++ b/date-fns/src/_lib/format/formatters/index.js
@@ -0,0 +1,768 @@
+import lightFormatters from '../lightFormatters/index'
+import getUTCDayOfYear from '../../../_lib/getUTCDayOfYear/index'
+import getUTCISOWeek from '../../../_lib/getUTCISOWeek/index'
+import getUTCISOWeekYear from '../../../_lib/getUTCISOWeekYear/index'
+import getUTCWeek from '../../../_lib/getUTCWeek/index'
+import getUTCWeekYear from '../../../_lib/getUTCWeekYear/index'
+import addLeadingZeros from '../../addLeadingZeros/index'
+
+var dayPeriodEnum = {
+ am: 'am',
+ pm: 'pm',
+ midnight: 'midnight',
+ noon: 'noon',
+ morning: 'morning',
+ afternoon: 'afternoon',
+ evening: 'evening',
+ night: 'night'
+}
+
+/*
+ * | | Unit | | Unit |
+ * |-----|--------------------------------|-----|--------------------------------|
+ * | a | AM, PM | A* | Milliseconds in day |
+ * | b | AM, PM, noon, midnight | B | Flexible day period |
+ * | c | Stand-alone local day of week | C* | Localized hour w/ day period |
+ * | d | Day of month | D | Day of year |
+ * | e | Local day of week | E | Day of week |
+ * | f | | F* | Day of week in month |
+ * | g* | Modified Julian day | G | Era |
+ * | h | Hour [1-12] | H | Hour [0-23] |
+ * | i! | ISO day of week | I! | ISO week of year |
+ * | j* | Localized hour w/ day period | J* | Localized hour w/o day period |
+ * | k | Hour [1-24] | K | Hour [0-11] |
+ * | l* | (deprecated) | L | Stand-alone month |
+ * | m | Minute | M | Month |
+ * | n | | N | |
+ * | o! | Ordinal number modifier | O | Timezone (GMT) |
+ * | p! | Long localized time | P! | Long localized date |
+ * | q | Stand-alone quarter | Q | Quarter |
+ * | r* | Related Gregorian year | R! | ISO week-numbering year |
+ * | s | Second | S | Fraction of second |
+ * | t! | Seconds timestamp | T! | Milliseconds timestamp |
+ * | u | Extended year | U* | Cyclic year |
+ * | v* | Timezone (generic non-locat.) | V* | Timezone (location) |
+ * | w | Local week of year | W* | Week of month |
+ * | x | Timezone (ISO-8601 w/o Z) | X | Timezone (ISO-8601) |
+ * | y | Year (abs) | Y | Local week-numbering year |
+ * | z | Timezone (specific non-locat.) | Z* | Timezone (aliases) |
+ *
+ * Letters marked by * are not implemented but reserved by Unicode standard.
+ *
+ * Letters marked by ! are non-standard, but implemented by date-fns:
+ * - `o` modifies the previous token to turn it into an ordinal (see `format` docs)
+ * - `i` is ISO day of week. For `i` and `ii` is returns numeric ISO week days,
+ * i.e. 7 for Sunday, 1 for Monday, etc.
+ * - `I` is ISO week of year, as opposed to `w` which is local week of year.
+ * - `R` is ISO week-numbering year, as opposed to `Y` which is local week-numbering year.
+ * `R` is supposed to be used in conjunction with `I` and `i`
+ * for universal ISO week-numbering date, whereas
+ * `Y` is supposed to be used in conjunction with `w` and `e`
+ * for week-numbering date specific to the locale.
+ * - `P` is long localized date format
+ * - `p` is long localized time format
+ */
+
+var formatters = {
+ // Era
+ G: function(date, token, localize) {
+ var era = date.getUTCFullYear() > 0 ? 1 : 0
+ switch (token) {
+ // AD, BC
+ case 'G':
+ case 'GG':
+ case 'GGG':
+ return localize.era(era, { width: 'abbreviated' })
+ // A, B
+ case 'GGGGG':
+ return localize.era(era, { width: 'narrow' })
+ // Anno Domini, Before Christ
+ case 'GGGG':
+ default:
+ return localize.era(era, { width: 'wide' })
+ }
+ },
+
+ // Year
+ y: function(date, token, localize) {
+ // Ordinal number
+ if (token === 'yo') {
+ var signedYear = date.getUTCFullYear()
+ // Returns 1 for 1 BC (which is year 0 in JavaScript)
+ var year = signedYear > 0 ? signedYear : 1 - signedYear
+ return localize.ordinalNumber(year, { unit: 'year' })
+ }
+
+ return lightFormatters.y(date, token)
+ },
+
+ // Local week-numbering year
+ Y: function(date, token, localize, options) {
+ var signedWeekYear = getUTCWeekYear(date, options)
+ // Returns 1 for 1 BC (which is year 0 in JavaScript)
+ var weekYear = signedWeekYear > 0 ? signedWeekYear : 1 - signedWeekYear
+
+ // Two digit year
+ if (token === 'YY') {
+ var twoDigitYear = weekYear % 100
+ return addLeadingZeros(twoDigitYear, 2)
+ }
+
+ // Ordinal number
+ if (token === 'Yo') {
+ return localize.ordinalNumber(weekYear, { unit: 'year' })
+ }
+
+ // Padding
+ return addLeadingZeros(weekYear, token.length)
+ },
+
+ // ISO week-numbering year
+ R: function(date, token) {
+ var isoWeekYear = getUTCISOWeekYear(date)
+
+ // Padding
+ return addLeadingZeros(isoWeekYear, token.length)
+ },
+
+ // Extended year. This is a single number designating the year of this calendar system.
+ // The main difference between `y` and `u` localizers are B.C. years:
+ // | Year | `y` | `u` |
+ // |------|-----|-----|
+ // | AC 1 | 1 | 1 |
+ // | BC 1 | 1 | 0 |
+ // | BC 2 | 2 | -1 |
+ // Also `yy` always returns the last two digits of a year,
+ // while `uu` pads single digit years to 2 characters and returns other years unchanged.
+ u: function(date, token) {
+ var year = date.getUTCFullYear()
+ return addLeadingZeros(year, token.length)
+ },
+
+ // Quarter
+ Q: function(date, token, localize) {
+ var quarter = Math.ceil((date.getUTCMonth() + 1) / 3)
+ switch (token) {
+ // 1, 2, 3, 4
+ case 'Q':
+ return String(quarter)
+ // 01, 02, 03, 04
+ case 'QQ':
+ return addLeadingZeros(quarter, 2)
+ // 1st, 2nd, 3rd, 4th
+ case 'Qo':
+ return localize.ordinalNumber(quarter, { unit: 'quarter' })
+ // Q1, Q2, Q3, Q4
+ case 'QQQ':
+ return localize.quarter(quarter, {
+ width: 'abbreviated',
+ context: 'formatting'
+ })
+ // 1, 2, 3, 4 (narrow quarter; could be not numerical)
+ case 'QQQQQ':
+ return localize.quarter(quarter, {
+ width: 'narrow',
+ context: 'formatting'
+ })
+ // 1st quarter, 2nd quarter, ...
+ case 'QQQQ':
+ default:
+ return localize.quarter(quarter, {
+ width: 'wide',
+ context: 'formatting'
+ })
+ }
+ },
+
+ // Stand-alone quarter
+ q: function(date, token, localize) {
+ var quarter = Math.ceil((date.getUTCMonth() + 1) / 3)
+ switch (token) {
+ // 1, 2, 3, 4
+ case 'q':
+ return String(quarter)
+ // 01, 02, 03, 04
+ case 'qq':
+ return addLeadingZeros(quarter, 2)
+ // 1st, 2nd, 3rd, 4th
+ case 'qo':
+ return localize.ordinalNumber(quarter, { unit: 'quarter' })
+ // Q1, Q2, Q3, Q4
+ case 'qqq':
+ return localize.quarter(quarter, {
+ width: 'abbreviated',
+ context: 'standalone'
+ })
+ // 1, 2, 3, 4 (narrow quarter; could be not numerical)
+ case 'qqqqq':
+ return localize.quarter(quarter, {
+ width: 'narrow',
+ context: 'standalone'
+ })
+ // 1st quarter, 2nd quarter, ...
+ case 'qqqq':
+ default:
+ return localize.quarter(quarter, {
+ width: 'wide',
+ context: 'standalone'
+ })
+ }
+ },
+
+ // Month
+ M: function(date, token, localize) {
+ var month = date.getUTCMonth()
+ switch (token) {
+ case 'M':
+ case 'MM':
+ return lightFormatters.M(date, token)
+ // 1st, 2nd, ..., 12th
+ case 'Mo':
+ return localize.ordinalNumber(month + 1, { unit: 'month' })
+ // Jan, Feb, ..., Dec
+ case 'MMM':
+ return localize.month(month, {
+ width: 'abbreviated',
+ context: 'formatting'
+ })
+ // J, F, ..., D
+ case 'MMMMM':
+ return localize.month(month, { width: 'narrow', context: 'formatting' })
+ // January, February, ..., December
+ case 'MMMM':
+ default:
+ return localize.month(month, { width: 'wide', context: 'formatting' })
+ }
+ },
+
+ // Stand-alone month
+ L: function(date, token, localize) {
+ var month = date.getUTCMonth()
+ switch (token) {
+ // 1, 2, ..., 12
+ case 'L':
+ return String(month + 1)
+ // 01, 02, ..., 12
+ case 'LL':
+ return addLeadingZeros(month + 1, 2)
+ // 1st, 2nd, ..., 12th
+ case 'Lo':
+ return localize.ordinalNumber(month + 1, { unit: 'month' })
+ // Jan, Feb, ..., Dec
+ case 'LLL':
+ return localize.month(month, {
+ width: 'abbreviated',
+ context: 'standalone'
+ })
+ // J, F, ..., D
+ case 'LLLLL':
+ return localize.month(month, { width: 'narrow', context: 'standalone' })
+ // January, February, ..., December
+ case 'LLLL':
+ default:
+ return localize.month(month, { width: 'wide', context: 'standalone' })
+ }
+ },
+
+ // Local week of year
+ w: function(date, token, localize, options) {
+ var week = getUTCWeek(date, options)
+
+ if (token === 'wo') {
+ return localize.ordinalNumber(week, { unit: 'week' })
+ }
+
+ return addLeadingZeros(week, token.length)
+ },
+
+ // ISO week of year
+ I: function(date, token, localize) {
+ var isoWeek = getUTCISOWeek(date)
+
+ if (token === 'Io') {
+ return localize.ordinalNumber(isoWeek, { unit: 'week' })
+ }
+
+ return addLeadingZeros(isoWeek, token.length)
+ },
+
+ // Day of the month
+ d: function(date, token, localize) {
+ if (token === 'do') {
+ return localize.ordinalNumber(date.getUTCDate(), { unit: 'date' })
+ }
+
+ return lightFormatters.d(date, token)
+ },
+
+ // Day of year
+ D: function(date, token, localize) {
+ var dayOfYear = getUTCDayOfYear(date)
+
+ if (token === 'Do') {
+ return localize.ordinalNumber(dayOfYear, { unit: 'dayOfYear' })
+ }
+
+ return addLeadingZeros(dayOfYear, token.length)
+ },
+
+ // Day of week
+ E: function(date, token, localize) {
+ var dayOfWeek = date.getUTCDay()
+ switch (token) {
+ // Tue
+ case 'E':
+ case 'EE':
+ case 'EEE':
+ return localize.day(dayOfWeek, {
+ width: 'abbreviated',
+ context: 'formatting'
+ })
+ // T
+ case 'EEEEE':
+ return localize.day(dayOfWeek, {
+ width: 'narrow',
+ context: 'formatting'
+ })
+ // Tu
+ case 'EEEEEE':
+ return localize.day(dayOfWeek, {
+ width: 'short',
+ context: 'formatting'
+ })
+ // Tuesday
+ case 'EEEE':
+ default:
+ return localize.day(dayOfWeek, { width: 'wide', context: 'formatting' })
+ }
+ },
+
+ // Local day of week
+ e: function(date, token, localize, options) {
+ var dayOfWeek = date.getUTCDay()
+ var localDayOfWeek = (dayOfWeek - options.weekStartsOn + 8) % 7 || 7
+ switch (token) {
+ // Numerical value (Nth day of week with current locale or weekStartsOn)
+ case 'e':
+ return String(localDayOfWeek)
+ // Padded numerical value
+ case 'ee':
+ return addLeadingZeros(localDayOfWeek, 2)
+ // 1st, 2nd, ..., 7th
+ case 'eo':
+ return localize.ordinalNumber(localDayOfWeek, { unit: 'day' })
+ case 'eee':
+ return localize.day(dayOfWeek, {
+ width: 'abbreviated',
+ context: 'formatting'
+ })
+ // T
+ case 'eeeee':
+ return localize.day(dayOfWeek, {
+ width: 'narrow',
+ context: 'formatting'
+ })
+ // Tu
+ case 'eeeeee':
+ return localize.day(dayOfWeek, {
+ width: 'short',
+ context: 'formatting'
+ })
+ // Tuesday
+ case 'eeee':
+ default:
+ return localize.day(dayOfWeek, { width: 'wide', context: 'formatting' })
+ }
+ },
+
+ // Stand-alone local day of week
+ c: function(date, token, localize, options) {
+ var dayOfWeek = date.getUTCDay()
+ var localDayOfWeek = (dayOfWeek - options.weekStartsOn + 8) % 7 || 7
+ switch (token) {
+ // Numerical value (same as in `e`)
+ case 'c':
+ return String(localDayOfWeek)
+ // Padded numerical value
+ case 'cc':
+ return addLeadingZeros(localDayOfWeek, token.length)
+ // 1st, 2nd, ..., 7th
+ case 'co':
+ return localize.ordinalNumber(localDayOfWeek, { unit: 'day' })
+ case 'ccc':
+ return localize.day(dayOfWeek, {
+ width: 'abbreviated',
+ context: 'standalone'
+ })
+ // T
+ case 'ccccc':
+ return localize.day(dayOfWeek, {
+ width: 'narrow',
+ context: 'standalone'
+ })
+ // Tu
+ case 'cccccc':
+ return localize.day(dayOfWeek, {
+ width: 'short',
+ context: 'standalone'
+ })
+ // Tuesday
+ case 'cccc':
+ default:
+ return localize.day(dayOfWeek, { width: 'wide', context: 'standalone' })
+ }
+ },
+
+ // ISO day of week
+ i: function(date, token, localize) {
+ var dayOfWeek = date.getUTCDay()
+ var isoDayOfWeek = dayOfWeek === 0 ? 7 : dayOfWeek
+ switch (token) {
+ // 2
+ case 'i':
+ return String(isoDayOfWeek)
+ // 02
+ case 'ii':
+ return addLeadingZeros(isoDayOfWeek, token.length)
+ // 2nd
+ case 'io':
+ return localize.ordinalNumber(isoDayOfWeek, { unit: 'day' })
+ // Tue
+ case 'iii':
+ return localize.day(dayOfWeek, {
+ width: 'abbreviated',
+ context: 'formatting'
+ })
+ // T
+ case 'iiiii':
+ return localize.day(dayOfWeek, {
+ width: 'narrow',
+ context: 'formatting'
+ })
+ // Tu
+ case 'iiiiii':
+ return localize.day(dayOfWeek, {
+ width: 'short',
+ context: 'formatting'
+ })
+ // Tuesday
+ case 'iiii':
+ default:
+ return localize.day(dayOfWeek, { width: 'wide', context: 'formatting' })
+ }
+ },
+
+ // AM or PM
+ a: function(date, token, localize) {
+ var hours = date.getUTCHours()
+ var dayPeriodEnumValue = hours / 12 >= 1 ? 'pm' : 'am'
+
+ switch (token) {
+ case 'a':
+ case 'aa':
+ return localize.dayPeriod(dayPeriodEnumValue, {
+ width: 'abbreviated',
+ context: 'formatting'
+ })
+ case 'aaa':
+ return localize
+ .dayPeriod(dayPeriodEnumValue, {
+ width: 'abbreviated',
+ context: 'formatting'
+ })
+ .toLowerCase()
+ case 'aaaaa':
+ return localize.dayPeriod(dayPeriodEnumValue, {
+ width: 'narrow',
+ context: 'formatting'
+ })
+ case 'aaaa':
+ default:
+ return localize.dayPeriod(dayPeriodEnumValue, {
+ width: 'wide',
+ context: 'formatting'
+ })
+ }
+ },
+
+ // AM, PM, midnight, noon
+ b: function(date, token, localize) {
+ var hours = date.getUTCHours()
+ var dayPeriodEnumValue
+ if (hours === 12) {
+ dayPeriodEnumValue = dayPeriodEnum.noon
+ } else if (hours === 0) {
+ dayPeriodEnumValue = dayPeriodEnum.midnight
+ } else {
+ dayPeriodEnumValue = hours / 12 >= 1 ? 'pm' : 'am'
+ }
+
+ switch (token) {
+ case 'b':
+ case 'bb':
+ return localize.dayPeriod(dayPeriodEnumValue, {
+ width: 'abbreviated',
+ context: 'formatting'
+ })
+ case 'bbb':
+ return localize
+ .dayPeriod(dayPeriodEnumValue, {
+ width: 'abbreviated',
+ context: 'formatting'
+ })
+ .toLowerCase()
+ case 'bbbbb':
+ return localize.dayPeriod(dayPeriodEnumValue, {
+ width: 'narrow',
+ context: 'formatting'
+ })
+ case 'bbbb':
+ default:
+ return localize.dayPeriod(dayPeriodEnumValue, {
+ width: 'wide',
+ context: 'formatting'
+ })
+ }
+ },
+
+ // in the morning, in the afternoon, in the evening, at night
+ B: function(date, token, localize) {
+ var hours = date.getUTCHours()
+ var dayPeriodEnumValue
+ if (hours >= 17) {
+ dayPeriodEnumValue = dayPeriodEnum.evening
+ } else if (hours >= 12) {
+ dayPeriodEnumValue = dayPeriodEnum.afternoon
+ } else if (hours >= 4) {
+ dayPeriodEnumValue = dayPeriodEnum.morning
+ } else {
+ dayPeriodEnumValue = dayPeriodEnum.night
+ }
+
+ switch (token) {
+ case 'B':
+ case 'BB':
+ case 'BBB':
+ return localize.dayPeriod(dayPeriodEnumValue, {
+ width: 'abbreviated',
+ context: 'formatting'
+ })
+ case 'BBBBB':
+ return localize.dayPeriod(dayPeriodEnumValue, {
+ width: 'narrow',
+ context: 'formatting'
+ })
+ case 'BBBB':
+ default:
+ return localize.dayPeriod(dayPeriodEnumValue, {
+ width: 'wide',
+ context: 'formatting'
+ })
+ }
+ },
+
+ // Hour [1-12]
+ h: function(date, token, localize) {
+ if (token === 'ho') {
+ var hours = date.getUTCHours() % 12
+ if (hours === 0) hours = 12
+ return localize.ordinalNumber(hours, { unit: 'hour' })
+ }
+
+ return lightFormatters.h(date, token)
+ },
+
+ // Hour [0-23]
+ H: function(date, token, localize) {
+ if (token === 'Ho') {
+ return localize.ordinalNumber(date.getUTCHours(), { unit: 'hour' })
+ }
+
+ return lightFormatters.H(date, token)
+ },
+
+ // Hour [0-11]
+ K: function(date, token, localize) {
+ var hours = date.getUTCHours() % 12
+
+ if (token === 'Ko') {
+ return localize.ordinalNumber(hours, { unit: 'hour' })
+ }
+
+ return addLeadingZeros(hours, token.length)
+ },
+
+ // Hour [1-24]
+ k: function(date, token, localize) {
+ var hours = date.getUTCHours()
+ if (hours === 0) hours = 24
+
+ if (token === 'ko') {
+ return localize.ordinalNumber(hours, { unit: 'hour' })
+ }
+
+ return addLeadingZeros(hours, token.length)
+ },
+
+ // Minute
+ m: function(date, token, localize) {
+ if (token === 'mo') {
+ return localize.ordinalNumber(date.getUTCMinutes(), { unit: 'minute' })
+ }
+
+ return lightFormatters.m(date, token)
+ },
+
+ // Second
+ s: function(date, token, localize) {
+ if (token === 'so') {
+ return localize.ordinalNumber(date.getUTCSeconds(), { unit: 'second' })
+ }
+
+ return lightFormatters.s(date, token)
+ },
+
+ // Fraction of second
+ S: function(date, token) {
+ return lightFormatters.S(date, token)
+ },
+
+ // Timezone (ISO-8601. If offset is 0, output is always `'Z'`)
+ X: function(date, token, _localize, options) {
+ var originalDate = options._originalDate || date
+ var timezoneOffset = originalDate.getTimezoneOffset()
+
+ if (timezoneOffset === 0) {
+ return 'Z'
+ }
+
+ switch (token) {
+ // Hours and optional minutes
+ case 'X':
+ return formatTimezoneWithOptionalMinutes(timezoneOffset)
+
+ // Hours, minutes and optional seconds without `:` delimiter
+ // Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets
+ // so this token always has the same output as `XX`
+ case 'XXXX':
+ case 'XX': // Hours and minutes without `:` delimiter
+ return formatTimezone(timezoneOffset)
+
+ // Hours, minutes and optional seconds with `:` delimiter
+ // Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets
+ // so this token always has the same output as `XXX`
+ case 'XXXXX':
+ case 'XXX': // Hours and minutes with `:` delimiter
+ default:
+ return formatTimezone(timezoneOffset, ':')
+ }
+ },
+
+ // Timezone (ISO-8601. If offset is 0, output is `'+00:00'` or equivalent)
+ x: function(date, token, _localize, options) {
+ var originalDate = options._originalDate || date
+ var timezoneOffset = originalDate.getTimezoneOffset()
+
+ switch (token) {
+ // Hours and optional minutes
+ case 'x':
+ return formatTimezoneWithOptionalMinutes(timezoneOffset)
+
+ // Hours, minutes and optional seconds without `:` delimiter
+ // Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets
+ // so this token always has the same output as `xx`
+ case 'xxxx':
+ case 'xx': // Hours and minutes without `:` delimiter
+ return formatTimezone(timezoneOffset)
+
+ // Hours, minutes and optional seconds with `:` delimiter
+ // Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets
+ // so this token always has the same output as `xxx`
+ case 'xxxxx':
+ case 'xxx': // Hours and minutes with `:` delimiter
+ default:
+ return formatTimezone(timezoneOffset, ':')
+ }
+ },
+
+ // Timezone (GMT)
+ O: function(date, token, _localize, options) {
+ var originalDate = options._originalDate || date
+ var timezoneOffset = originalDate.getTimezoneOffset()
+
+ switch (token) {
+ // Short
+ case 'O':
+ case 'OO':
+ case 'OOO':
+ return 'GMT' + formatTimezoneShort(timezoneOffset, ':')
+ // Long
+ case 'OOOO':
+ default:
+ return 'GMT' + formatTimezone(timezoneOffset, ':')
+ }
+ },
+
+ // Timezone (specific non-location)
+ z: function(date, token, _localize, options) {
+ var originalDate = options._originalDate || date
+ var timezoneOffset = originalDate.getTimezoneOffset()
+
+ switch (token) {
+ // Short
+ case 'z':
+ case 'zz':
+ case 'zzz':
+ return 'GMT' + formatTimezoneShort(timezoneOffset, ':')
+ // Long
+ case 'zzzz':
+ default:
+ return 'GMT' + formatTimezone(timezoneOffset, ':')
+ }
+ },
+
+ // Seconds timestamp
+ t: function(date, token, _localize, options) {
+ var originalDate = options._originalDate || date
+ var timestamp = Math.floor(originalDate.getTime() / 1000)
+ return addLeadingZeros(timestamp, token.length)
+ },
+
+ // Milliseconds timestamp
+ T: function(date, token, _localize, options) {
+ var originalDate = options._originalDate || date
+ var timestamp = originalDate.getTime()
+ return addLeadingZeros(timestamp, token.length)
+ }
+}
+
+function formatTimezoneShort(offset, dirtyDelimiter) {
+ var sign = offset > 0 ? '-' : '+'
+ var absOffset = Math.abs(offset)
+ var hours = Math.floor(absOffset / 60)
+ var minutes = absOffset % 60
+ if (minutes === 0) {
+ return sign + String(hours)
+ }
+ var delimiter = dirtyDelimiter || ''
+ return sign + String(hours) + delimiter + addLeadingZeros(minutes, 2)
+}
+
+function formatTimezoneWithOptionalMinutes(offset, dirtyDelimiter) {
+ if (offset % 60 === 0) {
+ var sign = offset > 0 ? '-' : '+'
+ return sign + addLeadingZeros(Math.abs(offset) / 60, 2)
+ }
+ return formatTimezone(offset, dirtyDelimiter)
+}
+
+function formatTimezone(offset, dirtyDelimiter) {
+ var delimiter = dirtyDelimiter || ''
+ var sign = offset > 0 ? '-' : '+'
+ var absOffset = Math.abs(offset)
+ var hours = addLeadingZeros(Math.floor(absOffset / 60), 2)
+ var minutes = addLeadingZeros(absOffset % 60, 2)
+ return sign + hours + delimiter + minutes
+}
+
+export default formatters
diff --git a/date-fns/src/_lib/format/lightFormatters/index.ts b/date-fns/src/_lib/format/lightFormatters/index.ts
new file mode 100644
index 0000000..9e7138e
--- /dev/null
+++ b/date-fns/src/_lib/format/lightFormatters/index.ts
@@ -0,0 +1,94 @@
+import addLeadingZeros from '../../addLeadingZeros/index'
+
+/*
+ * | | Unit | | Unit |
+ * |-----|--------------------------------|-----|--------------------------------|
+ * | a | AM, PM | A* | |
+ * | d | Day of month | D | |
+ * | h | Hour [1-12] | H | Hour [0-23] |
+ * | m | Minute | M | Month |
+ * | s | Second | S | Fraction of second |
+ * | y | Year (abs) | Y | |
+ *
+ * Letters marked by * are not implemented but reserved by Unicode standard.
+ */
+
+const formatters = {
+ // Year
+ y(date: Date, token: string): string {
+ // From http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Format_tokens
+ // | Year | y | yy | yyy | yyyy | yyyyy |
+ // |----------|-------|----|-------|-------|-------|
+ // | AD 1 | 1 | 01 | 001 | 0001 | 00001 |
+ // | AD 12 | 12 | 12 | 012 | 0012 | 00012 |
+ // | AD 123 | 123 | 23 | 123 | 0123 | 00123 |
+ // | AD 1234 | 1234 | 34 | 1234 | 1234 | 01234 |
+ // | AD 12345 | 12345 | 45 | 12345 | 12345 | 12345 |
+
+ const signedYear = date.getUTCFullYear()
+ // Returns 1 for 1 BC (which is year 0 in JavaScript)
+ const year = signedYear > 0 ? signedYear : 1 - signedYear
+ return addLeadingZeros(token === 'yy' ? year % 100 : year, token.length)
+ },
+
+ // Month
+ M(date: Date, token: string): string {
+ const month = date.getUTCMonth()
+ return token === 'M' ? String(month + 1) : addLeadingZeros(month + 1, 2)
+ },
+
+ // Day of the month
+ d(date: Date, token: string): string {
+ return addLeadingZeros(date.getUTCDate(), token.length)
+ },
+
+ // AM or PM
+ a(date: Date, token: string): string {
+ const dayPeriodEnumValue = date.getUTCHours() / 12 >= 1 ? 'pm' : 'am'
+
+ switch (token) {
+ case 'a':
+ case 'aa':
+ return dayPeriodEnumValue.toUpperCase()
+ case 'aaa':
+ return dayPeriodEnumValue
+ case 'aaaaa':
+ return dayPeriodEnumValue[0]
+ case 'aaaa':
+ default:
+ return dayPeriodEnumValue === 'am' ? 'a.m.' : 'p.m.'
+ }
+ },
+
+ // Hour [1-12]
+ h(date: Date, token: string): string {
+ return addLeadingZeros(date.getUTCHours() % 12 || 12, token.length)
+ },
+
+ // Hour [0-23]
+ H(date: Date, token: string): string {
+ return addLeadingZeros(date.getUTCHours(), token.length)
+ },
+
+ // Minute
+ m(date: Date, token: string): string {
+ return addLeadingZeros(date.getUTCMinutes(), token.length)
+ },
+
+ // Second
+ s(date: Date, token: string): string {
+ return addLeadingZeros(date.getUTCSeconds(), token.length)
+ },
+
+ // Fraction of second
+ S(date: Date, token: string): string {
+ const numberOfDigits = token.length
+ const milliseconds = date.getUTCMilliseconds()
+ const fractionalSeconds = Math.floor(
+ milliseconds * Math.pow(10, numberOfDigits - 3)
+ )
+ return addLeadingZeros(fractionalSeconds, token.length)
+ },
+}
+
+export default formatters
diff --git a/date-fns/src/_lib/format/longFormatters/index.js b/date-fns/src/_lib/format/longFormatters/index.js
new file mode 100644
index 0000000..ff84163
--- /dev/null
+++ b/date-fns/src/_lib/format/longFormatters/index.js
@@ -0,0 +1,66 @@
+function dateLongFormatter(pattern, formatLong) {
+ switch (pattern) {
+ case 'P':
+ return formatLong.date({ width: 'short' })
+ case 'PP':
+ return formatLong.date({ width: 'medium' })
+ case 'PPP':
+ return formatLong.date({ width: 'long' })
+ case 'PPPP':
+ default:
+ return formatLong.date({ width: 'full' })
+ }
+}
+
+function timeLongFormatter(pattern, formatLong) {
+ switch (pattern) {
+ case 'p':
+ return formatLong.time({ width: 'short' })
+ case 'pp':
+ return formatLong.time({ width: 'medium' })
+ case 'ppp':
+ return formatLong.time({ width: 'long' })
+ case 'pppp':
+ default:
+ return formatLong.time({ width: 'full' })
+ }
+}
+
+function dateTimeLongFormatter(pattern, formatLong) {
+ var matchResult = pattern.match(/(P+)(p+)?/)
+ var datePattern = matchResult[1]
+ var timePattern = matchResult[2]
+
+ if (!timePattern) {
+ return dateLongFormatter(pattern, formatLong)
+ }
+
+ var dateTimeFormat
+
+ switch (datePattern) {
+ case 'P':
+ dateTimeFormat = formatLong.dateTime({ width: 'short' })
+ break
+ case 'PP':
+ dateTimeFormat = formatLong.dateTime({ width: 'medium' })
+ break
+ case 'PPP':
+ dateTimeFormat = formatLong.dateTime({ width: 'long' })
+ break
+ case 'PPPP':
+ default:
+ dateTimeFormat = formatLong.dateTime({ width: 'full' })
+ break
+ }
+
+ return dateTimeFormat
+ .replace('{{date}}', dateLongFormatter(datePattern, formatLong))
+ .replace('{{time}}', timeLongFormatter(timePattern, formatLong))
+}
+
+var longFormatters = {
+ p: timeLongFormatter,
+ P: dateTimeLongFormatter
+}
+
+export default longFormatters
diff --git a/date-fns/src/_lib/getTimezoneOffsetInMilliseconds/index.js b/date-fns/src/_lib/getTimezoneOffsetInMilliseconds/index.js
new file mode 100644
index 0000000..0b637c4
--- /dev/null
+++ b/date-fns/src/_lib/getTimezoneOffsetInMilliseconds/index.js
@@ -0,0 +1,26 @@
+/**
+ * Google Chrome as of 67.0.3396.87 introduced timezones with offset that includes seconds.
+ * They usually appear for dates that denote time before the timezones were introduced
+ * (e.g. for 'Europe/Prague' timezone the offset is GMT+00:57:44 before 1 October 1891
+ * and GMT+01:00:00 after that date)
+ *
+ * Date#getTimezoneOffset returns the offset in minutes and would return 57 for the example above,
+ * which would lead to incorrect calculations.
+ *
+ * This function returns the timezone offset in milliseconds that takes seconds in account.
+ */
+export default function getTimezoneOffsetInMilliseconds(date) {
+ const utcDate = new Date(
+ Date.UTC(
+ date.getFullYear(),
+ date.getMonth(),
+ date.getDate(),
+ date.getHours(),
+ date.getMinutes(),
+ date.getSeconds(),
+ date.getMilliseconds()
+ )
+ )
+ utcDate.setUTCFullYear(date.getFullYear())
+ return date.getTime() - utcDate.getTime()
+}
diff --git a/date-fns/src/_lib/getTimezoneOffsetInMilliseconds/test.js b/date-fns/src/_lib/getTimezoneOffsetInMilliseconds/test.js
new file mode 100644
index 0000000..821e16f
--- /dev/null
+++ b/date-fns/src/_lib/getTimezoneOffsetInMilliseconds/test.js
@@ -0,0 +1,28 @@
+// @flow
+/* eslint-env mocha */
+
+import assert from 'power-assert'
+import getTimezoneOffsetInMilliseconds from '.'
+
+describe('getTimezoneOffsetInMilliseconds', function () {
+ it('works for a modern date', function () {
+ var date = new Date(2018, 0 /* Jan */, 1, 12, 34, 56, 789)
+ var result = date.getTime() - getTimezoneOffsetInMilliseconds(date)
+ var expectedResult = Date.UTC(2018, 0 /* Jan */, 1, 12, 34, 56, 789)
+ assert(result === expectedResult)
+ })
+
+ it('works for a date before standardized timezones', function () {
+ var date = new Date(1800, 0 /* Jan */, 1, 12, 34, 56, 789)
+ var result = date.getTime() - getTimezoneOffsetInMilliseconds(date)
+ var expectedResult = Date.UTC(1800, 0 /* Jan */, 1, 12, 34, 56, 789)
+ assert(result === expectedResult)
+ })
+
+ it('works for a date BC', function () {
+ var date = new Date(-500, 0 /* Jan */, 1, 12, 34, 56, 789)
+ var result = date.getTime() - getTimezoneOffsetInMilliseconds(date)
+ var expectedResult = Date.UTC(-500, 0 /* Jan */, 1, 12, 34, 56, 789)
+ assert(result === expectedResult)
+ })
+})
diff --git a/date-fns/src/_lib/getUTCDayOfYear/index.js b/date-fns/src/_lib/getUTCDayOfYear/index.js
new file mode 100644
index 0000000..37cdc0e
--- /dev/null
+++ b/date-fns/src/_lib/getUTCDayOfYear/index.js
@@ -0,0 +1,18 @@
+import toDate from '../../toDate/index'
+import requiredArgs from '../requiredArgs/index'
+
+var MILLISECONDS_IN_DAY = 86400000
+
+// This function will be a part of public API when UTC function will be implemented.
+// See issue: https://github.com/date-fns/date-fns/issues/376
+export default function getUTCDayOfYear(dirtyDate) {
+ requiredArgs(1, arguments)
+
+ var date = toDate(dirtyDate)
+ var timestamp = date.getTime()
+ date.setUTCMonth(0, 1)
+ date.setUTCHours(0, 0, 0, 0)
+ var startOfYearTimestamp = date.getTime()
+ var difference = timestamp - startOfYearTimestamp
+ return Math.floor(difference / MILLISECONDS_IN_DAY) + 1
+}
diff --git a/date-fns/src/_lib/getUTCDayOfYear/test.js b/date-fns/src/_lib/getUTCDayOfYear/test.js
new file mode 100644
index 0000000..b4f2963
--- /dev/null
+++ b/date-fns/src/_lib/getUTCDayOfYear/test.js
@@ -0,0 +1,36 @@
+// @flow
+/* eslint-env mocha */
+
+import assert from 'power-assert'
+import getUTCDayOfYear from '.'
+
+describe('getUTCDayOfYear', function() {
+ it('returns the day of the year of the given date', function() {
+ var result = getUTCDayOfYear(new Date(Date.UTC(2014, 6 /* Jul */, 2)))
+ assert(result === 183)
+ })
+
+ it('accepts a timestamp', function() {
+ var result = getUTCDayOfYear(
+ new Date(Date.UTC(2014, 0 /* Jan */, 2)).getTime()
+ )
+ assert(result === 2)
+ })
+
+ it('handles dates before 100 AD', function() {
+ var initialDate = new Date(0)
+ initialDate.setUTCFullYear(0, 11 /* Dec */, 31)
+ initialDate.setUTCHours(0, 0, 0, 0)
+ var result = getUTCDayOfYear(initialDate)
+ assert(result === 366)
+ })
+
+ it('returns NaN if the given date is invalid', function() {
+ var result = getUTCDayOfYear(new Date(NaN))
+ assert(isNaN(result))
+ })
+
+ it('throws TypeError exception if passed less than 1 argument', function() {
+ assert.throws(getUTCDayOfYear.bind(null), TypeError)
+ })
+})
diff --git a/date-fns/src/_lib/getUTCISOWeek/index.js b/date-fns/src/_lib/getUTCISOWeek/index.js
new file mode 100644
index 0000000..ab17ea2
--- /dev/null
+++ b/date-fns/src/_lib/getUTCISOWeek/index.js
@@ -0,0 +1,21 @@
+import toDate from '../../toDate/index'
+import startOfUTCISOWeek from '../startOfUTCISOWeek/index'
+import startOfUTCISOWeekYear from '../startOfUTCISOWeekYear/index'
+import requiredArgs from '../requiredArgs/index'
+
+var MILLISECONDS_IN_WEEK = 604800000
+
+// This function will be a part of public API when UTC function will be implemented.
+// See issue: https://github.com/date-fns/date-fns/issues/376
+export default function getUTCISOWeek(dirtyDate) {
+ requiredArgs(1, arguments)
+
+ var date = toDate(dirtyDate)
+ var diff =
+ startOfUTCISOWeek(date).getTime() - startOfUTCISOWeekYear(date).getTime()
+
+ // Round the number of days to the nearest integer
+ // because the number of milliseconds in a week is not constant
+ // (e.g. it's different in the week of the daylight saving time clock shift)
+ return Math.round(diff / MILLISECONDS_IN_WEEK) + 1
+}
diff --git a/date-fns/src/_lib/getUTCISOWeek/test.js b/date-fns/src/_lib/getUTCISOWeek/test.js
new file mode 100644
index 0000000..29dc6b2
--- /dev/null
+++ b/date-fns/src/_lib/getUTCISOWeek/test.js
@@ -0,0 +1,58 @@
+// @flow
+/* eslint-env mocha */
+
+import assert from 'power-assert'
+import getUTCISOWeek from '.'
+
+describe('getUTCISOWeek', function() {
+ it('returns the ISO week of the given date', function() {
+ var result = getUTCISOWeek(new Date(Date.UTC(2005, 0 /* Jan */, 2)))
+ assert(result === 53)
+ })
+
+ it('accepts a timestamp', function() {
+ var result = getUTCISOWeek(
+ new Date(Date.UTC(2008, 11 /* Dec */, 29)).getTime()
+ )
+ assert(result === 1)
+ })
+
+ describe('edge cases', function() {
+ it('returns the ISO week at 1 January 2016', function() {
+ var result = getUTCISOWeek(new Date(Date.UTC(2016, 0 /* Jan */, 1)))
+ assert(result === 53)
+ })
+
+ it('returns the ISO week at 1 May 2016', function() {
+ var result = getUTCISOWeek(new Date(Date.UTC(2016, 4 /* May */, 1)))
+ assert(result === 17)
+ })
+
+ it('returns the ISO week at 2 May 2016', function() {
+ var result = getUTCISOWeek(new Date(Date.UTC(2016, 4 /* May */, 2)))
+ assert(result === 18)
+ })
+
+ it('returns the ISO week at 31 May 2016', function() {
+ var result = getUTCISOWeek(new Date(Date.UTC(2016, 4 /* May */, 31)))
+ assert(result === 22)
+ })
+ })
+
+ it('handles dates before 100 AD', function() {
+ var initialDate = new Date(0)
+ initialDate.setUTCFullYear(7, 11 /* Dec */, 30)
+ initialDate.setUTCHours(0, 0, 0, 0)
+ var result = getUTCISOWeek(initialDate)
+ assert(result === 52)
+ })
+
+ it('returns NaN if the given date is invalid', function() {
+ var result = getUTCISOWeek(new Date(NaN))
+ assert(isNaN(result))
+ })
+
+ it('throws TypeError exception if passed less than 1 argument', function() {
+ assert.throws(getUTCISOWeek.bind(null), TypeError)
+ })
+})
diff --git a/date-fns/src/_lib/getUTCISOWeekYear/index.js b/date-fns/src/_lib/getUTCISOWeekYear/index.js
new file mode 100644
index 0000000..e098159
--- /dev/null
+++ b/date-fns/src/_lib/getUTCISOWeekYear/index.js
@@ -0,0 +1,30 @@
+import toDate from '../../toDate/index'
+import startOfUTCISOWeek from '../startOfUTCISOWeek/index'
+import requiredArgs from '../requiredArgs/index'
+
+// This function will be a part of public API when UTC function will be implemented.
+// See issue: https://github.com/date-fns/date-fns/issues/376
+export default function getUTCISOWeekYear(dirtyDate) {
+ requiredArgs(1, arguments)
+
+ var date = toDate(dirtyDate)
+ var year = date.getUTCFullYear()
+
+ var fourthOfJanuaryOfNextYear = new Date(0)
+ fourthOfJanuaryOfNextYear.setUTCFullYear(year + 1, 0, 4)
+ fourthOfJanuaryOfNextYear.setUTCHours(0, 0, 0, 0)
+ var startOfNextYear = startOfUTCISOWeek(fourthOfJanuaryOfNextYear)
+
+ var fourthOfJanuaryOfThisYear = new Date(0)
+ fourthOfJanuaryOfThisYear.setUTCFullYear(year, 0, 4)
+ fourthOfJanuaryOfThisYear.setUTCHours(0, 0, 0, 0)
+ var startOfThisYear = startOfUTCISOWeek(fourthOfJanuaryOfThisYear)
+
+ if (date.getTime() >= startOfNextYear.getTime()) {
+ return year + 1
+ } else if (date.getTime() >= startOfThisYear.getTime()) {
+ return year
+ } else {
+ return year - 1
+ }
+}
diff --git a/date-fns/src/_lib/getUTCISOWeekYear/test.js b/date-fns/src/_lib/getUTCISOWeekYear/test.js
new file mode 100644
index 0000000..07aab97
--- /dev/null
+++ b/date-fns/src/_lib/getUTCISOWeekYear/test.js
@@ -0,0 +1,36 @@
+// @flow
+/* eslint-env mocha */
+
+import assert from 'power-assert'
+import getUTCISOWeekYear from '.'
+
+describe('getUTCISOWeekYear', function() {
+ it('returns the ISO week-numbering year of the given date', function() {
+ var result = getUTCISOWeekYear(new Date(Date.UTC(2007, 11 /* Dec */, 31)))
+ assert(result === 2008)
+ })
+
+ it('accepts a timestamp', function() {
+ var result = getUTCISOWeekYear(
+ new Date(Date.UTC(2005, 0 /* Jan */, 1)).getTime()
+ )
+ assert(result === 2004)
+ })
+
+ it('handles dates before 100 AD', function() {
+ var initialDate = new Date(0)
+ initialDate.setUTCFullYear(7, 11 /* Dec */, 31)
+ initialDate.setUTCHours(0, 0, 0, 0)
+ var result = getUTCISOWeekYear(initialDate)
+ assert(result === 8)
+ })
+
+ it('returns NaN if the given date is invalid', function() {
+ var result = getUTCISOWeekYear(new Date(NaN))
+ assert(isNaN(result))
+ })
+
+ it('throws TypeError exception if passed less than 1 argument', function() {
+ assert.throws(getUTCISOWeekYear.bind(null), TypeError)
+ })
+})
diff --git a/date-fns/src/_lib/getUTCWeek/index.js b/date-fns/src/_lib/getUTCWeek/index.js
new file mode 100644
index 0000000..0b69ba2
--- /dev/null
+++ b/date-fns/src/_lib/getUTCWeek/index.js
@@ -0,0 +1,22 @@
+import toDate from '../../toDate/index'
+import startOfUTCWeek from '../startOfUTCWeek/index'
+import startOfUTCWeekYear from '../startOfUTCWeekYear/index'
+import requiredArgs from '../requiredArgs/index'
+
+var MILLISECONDS_IN_WEEK = 604800000
+
+// This function will be a part of public API when UTC function will be implemented.
+// See issue: https://github.com/date-fns/date-fns/issues/376
+export default function getUTCWeek(dirtyDate, options) {
+ requiredArgs(1, arguments)
+
+ var date = toDate(dirtyDate)
+ var diff =
+ startOfUTCWeek(date, options).getTime() -
+ startOfUTCWeekYear(date, options).getTime()
+
+ // Round the number of days to the nearest integer
+ // because the number of milliseconds in a week is not constant
+ // (e.g. it's different in the week of the daylight saving time clock shift)
+ return Math.round(diff / MILLISECONDS_IN_WEEK) + 1
+}
diff --git a/date-fns/src/_lib/getUTCWeek/test.js b/date-fns/src/_lib/getUTCWeek/test.js
new file mode 100644
index 0000000..0814368
--- /dev/null
+++ b/date-fns/src/_lib/getUTCWeek/test.js
@@ -0,0 +1,70 @@
+// @flow
+/* eslint-env mocha */
+
+import assert from 'power-assert'
+import getUTCWeek from '.'
+
+describe('getUTCWeek', function() {
+ it('returns the local week of year of the given date', function() {
+ var result = getUTCWeek(new Date(Date.UTC(2005, 0 /* Jan */, 2)))
+ assert(result === 2)
+ })
+
+ it('accepts a timestamp', function() {
+ var result = getUTCWeek(Date.UTC(2008, 11 /* Dec */, 29))
+ assert(result === 1)
+ })
+
+ it('handles dates before 100 AD', function() {
+ var initialDate = new Date(0)
+ initialDate.setUTCFullYear(7, 11 /* Dec */, 30)
+ initialDate.setUTCHours(0, 0, 0, 0)
+ var result = getUTCWeek(initialDate)
+ assert(result === 1)
+ })
+
+ it('returns NaN if the given date is invalid', function() {
+ var result = getUTCWeek(new Date(NaN))
+ assert(isNaN(result))
+ })
+
+ it('allows to specify `weekStartsOn` and `firstWeekContainsDate` in locale', function() {
+ var date = new Date(Date.UTC(2005, 0 /* Jan */, 2))
+ var result = getUTCWeek(date, {
+ locale: {
+ options: { weekStartsOn: 1, firstWeekContainsDate: 4 }
+ }
+ })
+ assert(result === 53)
+ })
+
+ it('`options.weekStartsOn` overwrites the first day of the week specified in locale', function() {
+ var date = new Date(Date.UTC(2005, 0 /* Jan */, 2))
+ var result = getUTCWeek(date, {
+ weekStartsOn: 1,
+ firstWeekContainsDate: 4,
+ locale: {
+ options: { weekStartsOn: 0, firstWeekContainsDate: 1 }
+ }
+ })
+ assert(result === 53)
+ })
+
+ it('throws `RangeError` if `options.weekStartsOn` is not convertable to 0, 1, ..., 6 or undefined', function() {
+ var block = getUTCWeek.bind(null, new Date(2007, 11 /* Dec */, 31), {
+ weekStartsOn: NaN
+ })
+ assert.throws(block, RangeError)
+ })
+
+ it('throws `RangeError` if `options.firstWeekContainsDate` is not convertable to 1, 2, ..., 7 or undefined', function() {
+ var block = getUTCWeek.bind(null, new Date(2007, 11 /* Dec */, 31), {
+ firstWeekContainsDate: NaN
+ })
+ assert.throws(block, RangeError)
+ })
+
+ it('throws TypeError exception if passed less than 1 argument', function() {
+ assert.throws(getUTCWeek.bind(null), TypeError)
+ })
+})
diff --git a/date-fns/src/_lib/getUTCWeekYear/index.js b/date-fns/src/_lib/getUTCWeekYear/index.js
new file mode 100644
index 0000000..1f561c7
--- /dev/null
+++ b/date-fns/src/_lib/getUTCWeekYear/index.js
@@ -0,0 +1,51 @@
+import toInteger from '../toInteger/index'
+import toDate from '../../toDate/index'
+import startOfUTCWeek from '../startOfUTCWeek/index'
+import requiredArgs from '../requiredArgs/index'
+
+// This function will be a part of public API when UTC function will be implemented.
+// See issue: https://github.com/date-fns/date-fns/issues/376
+export default function getUTCWeekYear(dirtyDate, dirtyOptions) {
+ requiredArgs(1, arguments)
+
+ var date = toDate(dirtyDate, dirtyOptions)
+ var year = date.getUTCFullYear()
+
+ var options = dirtyOptions || {}
+ var locale = options.locale
+ var localeFirstWeekContainsDate =
+ locale && locale.options && locale.options.firstWeekContainsDate
+ var defaultFirstWeekContainsDate =
+ localeFirstWeekContainsDate == null
+ ? 1
+ : toInteger(localeFirstWeekContainsDate)
+ var firstWeekContainsDate =
+ options.firstWeekContainsDate == null
+ ? defaultFirstWeekContainsDate
+ : toInteger(options.firstWeekContainsDate)
+
+ // Test if weekStartsOn is between 1 and 7 _and_ is not NaN
+ if (!(firstWeekContainsDate >= 1 && firstWeekContainsDate <= 7)) {
+ throw new RangeError(
+ 'firstWeekContainsDate must be between 1 and 7 inclusively'
+ )
+ }
+
+ var firstWeekOfNextYear = new Date(0)
+ firstWeekOfNextYear.setUTCFullYear(year + 1, 0, firstWeekContainsDate)
+ firstWeekOfNextYear.setUTCHours(0, 0, 0, 0)
+ var startOfNextYear = startOfUTCWeek(firstWeekOfNextYear, dirtyOptions)
+
+ var firstWeekOfThisYear = new Date(0)
+ firstWeekOfThisYear.setUTCFullYear(year, 0, firstWeekContainsDate)
+ firstWeekOfThisYear.setUTCHours(0, 0, 0, 0)
+ var startOfThisYear = startOfUTCWeek(firstWeekOfThisYear, dirtyOptions)
+
+ if (date.getTime() >= startOfNextYear.getTime()) {
+ return year + 1
+ } else if (date.getTime() >= startOfThisYear.getTime()) {
+ return year
+ } else {
+ return year - 1
+ }
+}
diff --git a/date-fns/src/_lib/getUTCWeekYear/test.js b/date-fns/src/_lib/getUTCWeekYear/test.js
new file mode 100644
index 0000000..3b45fc4
--- /dev/null
+++ b/date-fns/src/_lib/getUTCWeekYear/test.js
@@ -0,0 +1,70 @@
+// @flow
+/* eslint-env mocha */
+
+import assert from 'power-assert'
+import getUTCWeekYear from '.'
+
+describe('getUTCWeekYear', function() {
+ it('returns the local week-numbering year of the given date', function() {
+ var result = getUTCWeekYear(new Date(Date.UTC(2004, 11 /* Dec */, 26)))
+ assert(result === 2005)
+ })
+
+ it('accepts a timestamp', function() {
+ var result = getUTCWeekYear(Date.UTC(2000, 11 /* Dec */, 30))
+ assert(result === 2000)
+ })
+
+ it('handles dates before 100 AD', function() {
+ var initialDate = new Date(0)
+ initialDate.setUTCFullYear(7, 11 /* Dec */, 31)
+ initialDate.setUTCHours(0, 0, 0, 0)
+ var result = getUTCWeekYear(initialDate)
+ assert(result === 8)
+ })
+
+ it('returns NaN if the given date is invalid', function() {
+ var result = getUTCWeekYear(new Date(NaN))
+ assert(isNaN(result))
+ })
+
+ it('allows to specify `weekStartsOn` and `firstWeekContainsDate` in locale', function() {
+ var date = new Date(Date.UTC(2004, 11 /* Dec */, 26))
+ var result = getUTCWeekYear(date, {
+ locale: {
+ options: { weekStartsOn: 1, firstWeekContainsDate: 4 }
+ }
+ })
+ assert(result === 2004)
+ })
+
+ it('`options.weekStartsOn` overwrites the first day of the week specified in locale', function() {
+ var date = new Date(Date.UTC(2004, 11 /* Dec */, 26))
+ var result = getUTCWeekYear(date, {
+ weekStartsOn: 1,
+ firstWeekContainsDate: 4,
+ locale: {
+ options: { weekStartsOn: 0, firstWeekContainsDate: 1 }
+ }
+ })
+ assert(result === 2004)
+ })
+
+ it('throws `RangeError` if `options.weekStartsOn` is not convertable to 0, 1, ..., 6 or undefined', function() {
+ var block = getUTCWeekYear.bind(null, new Date(2007, 11 /* Dec */, 31), {
+ weekStartsOn: NaN
+ })
+ assert.throws(block, RangeError)
+ })
+
+ it('throws `RangeError` if `options.firstWeekContainsDate` is not convertable to 1, 2, ..., 7 or undefined', function() {
+ var block = getUTCWeekYear.bind(null, new Date(2007, 11 /* Dec */, 31), {
+ firstWeekContainsDate: NaN
+ })
+ assert.throws(block, RangeError)
+ })
+
+ it('throws TypeError exception if passed less than 1 argument', function() {
+ assert.throws(getUTCWeekYear.bind(null), TypeError)
+ })
+})
diff --git a/date-fns/src/_lib/isSameUTCWeek/index.js b/date-fns/src/_lib/isSameUTCWeek/index.js
new file mode 100644
index 0000000..699806f
--- /dev/null
+++ b/date-fns/src/_lib/isSameUTCWeek/index.js
@@ -0,0 +1,13 @@
+import startOfUTCWeek from '../startOfUTCWeek/index'
+import requiredArgs from '../requiredArgs/index'
+
+// This function will be a part of public API when UTC function will be implemented.
+// See issue: https://github.com/date-fns/date-fns/issues/376
+export default function isSameUTCWeek(dirtyDateLeft, dirtyDateRight, options) {
+ requiredArgs(2, arguments)
+
+ var dateLeftStartOfWeek = startOfUTCWeek(dirtyDateLeft, options)
+ var dateRightStartOfWeek = startOfUTCWeek(dirtyDateRight, options)
+
+ return dateLeftStartOfWeek.getTime() === dateRightStartOfWeek.getTime()
+}
diff --git a/date-fns/src/_lib/isSameUTCWeek/test.js b/date-fns/src/_lib/isSameUTCWeek/test.js
new file mode 100644
index 0000000..909d034
--- /dev/null
+++ b/date-fns/src/_lib/isSameUTCWeek/test.js
@@ -0,0 +1,111 @@
+// @flow
+/* eslint-env mocha */
+
+import assert from 'power-assert'
+import isSameUTCWeek from '.'
+
+describe('isSameUTCWeek', function() {
+ it('returns true if the given dates have the same week', function() {
+ var result = isSameUTCWeek(
+ new Date(Date.UTC(2014, 7 /* Aug */, 31)),
+ new Date(Date.UTC(2014, 8 /* Sep */, 4))
+ )
+ assert(result === true)
+ })
+
+ it('returns false if the given dates have different weeks', function() {
+ var result = isSameUTCWeek(
+ new Date(Date.UTC(2014, 7 /* Aug */, 30)),
+ new Date(Date.UTC(2014, 8 /* Sep */, 4))
+ )
+ assert(result === false)
+ })
+
+ it('allows to specify which day is the first day of the week', function() {
+ var result = isSameUTCWeek(
+ new Date(Date.UTC(2014, 7 /* Aug */, 31)),
+ new Date(Date.UTC(2014, 8 /* Sep */, 4)),
+ { weekStartsOn: 1 }
+ )
+ assert(result === false)
+ })
+
+ it('allows to specify which day is the first day of the week in locale', function() {
+ var result = isSameUTCWeek(
+ new Date(Date.UTC(2014, 7 /* Aug */, 31)),
+ new Date(Date.UTC(2014, 8 /* Sep */, 4)),
+ {
+ locale: {
+ options: { weekStartsOn: 1 }
+ }
+ }
+ )
+ assert(result === false)
+ })
+
+ it('`options.weekStartsOn` overwrites the first day of the week specified in locale', function() {
+ var result = isSameUTCWeek(
+ new Date(Date.UTC(2014, 7 /* Aug */, 31)),
+ new Date(Date.UTC(2014, 8 /* Sep */, 4)),
+ {
+ weekStartsOn: 1,
+ locale: {
+ options: { weekStartsOn: 0 }
+ }
+ }
+ )
+ assert(result === false)
+ })
+
+ it('implicitly converts options', function() {
+ var result = isSameUTCWeek(
+ new Date(Date.UTC(2014, 7 /* Aug */, 31)),
+ new Date(Date.UTC(2014, 8 /* Sep */, 4)),
+ { weekStartsOn: '1' }
+ )
+ assert(result === false)
+ })
+
+ it('accepts a timestamp', function() {
+ var result = isSameUTCWeek(
+ Date.UTC(2014, 7 /* Aug */, 31),
+ Date.UTC(2014, 8 /* Sep */, 4)
+ )
+ assert(result === true)
+ })
+
+ it('returns false if the first date is `Invalid Date`', function() {
+ var result = isSameUTCWeek(
+ new Date(NaN),
+ new Date(Date.UTC(1989, 6 /* Jul */, 10))
+ )
+ assert(result === false)
+ })
+
+ it('returns false if the second date is `Invalid Date`', function() {
+ var result = isSameUTCWeek(
+ new Date(Date.UTC(1987, 1 /* Feb */, 11)),
+ new Date(NaN)
+ )
+ assert(result === false)
+ })
+
+ it('returns false if the both dates are `Invalid Date`', function() {
+ var result = isSameUTCWeek(new Date(NaN), new Date(NaN))
+ assert(result === false)
+ })
+
+ it('throws `RangeError` if `options.weekStartsOn` is not convertable to 0, 1, ..., 6 or undefined', function() {
+ var block = isSameUTCWeek.bind(
+ null,
+ new Date(Date.UTC(2014, 7 /* Aug */, 31)),
+ new Date(Date.UTC(2014, 8 /* Sep */, 4)),
+ { weekStartsOn: NaN }
+ )
+ assert.throws(block, RangeError)
+ })
+
+ it('throws TypeError exception if passed less than 1 argument', function() {
+ assert.throws(isSameUTCWeek.bind(null, 1), TypeError)
+ })
+})
diff --git a/date-fns/src/_lib/protectedTokens/index.js b/date-fns/src/_lib/protectedTokens/index.js
new file mode 100644
index 0000000..c62313f
--- /dev/null
+++ b/date-fns/src/_lib/protectedTokens/index.js
@@ -0,0 +1,30 @@
+var protectedDayOfYearTokens = ['D', 'DD']
+var protectedWeekYearTokens = ['YY', 'YYYY']
+
+export function isProtectedDayOfYearToken(token) {
+ return protectedDayOfYearTokens.indexOf(token) !== -1
+}
+
+export function isProtectedWeekYearToken(token) {
+ return protectedWeekYearTokens.indexOf(token) !== -1
+}
+
+export function throwProtectedError(token, format, input) {
+ if (token === 'YYYY') {
+ throw new RangeError(
+ `Use \`yyyy\` instead of \`YYYY\` (in \`${format}\`) for formatting years to the input \`${input}\`; see: https://git.io/fxCyr`
+ )
+ } else if (token === 'YY') {
+ throw new RangeError(
+ `Use \`yy\` instead of \`YY\` (in \`${format}\`) for formatting years to the input \`${input}\`; see: https://git.io/fxCyr`
+ )
+ } else if (token === 'D') {
+ throw new RangeError(
+ `Use \`d\` instead of \`D\` (in \`${format}\`) for formatting days of the month to the input \`${input}\`; see: https://git.io/fxCyr`
+ )
+ } else if (token === 'DD') {
+ throw new RangeError(
+ `Use \`dd\` instead of \`DD\` (in \`${format}\`) for formatting days of the month to the input \`${input}\`; see: https://git.io/fxCyr`
+ )
+ }
+}
diff --git a/date-fns/src/_lib/requiredArgs/index.ts b/date-fns/src/_lib/requiredArgs/index.ts
new file mode 100644
index 0000000..bdbb950
--- /dev/null
+++ b/date-fns/src/_lib/requiredArgs/index.ts
@@ -0,0 +1,12 @@
+export default function requiredArgs(required: number, args: IArguments) {
+ if (args.length < required) {
+ throw new TypeError(
+ required +
+ ' argument' +
+ (required > 1 ? 's' : '') +
+ ' required, but only ' +
+ args.length +
+ ' present'
+ )
+ }
+}
diff --git a/date-fns/src/_lib/requiredArgs/test.js b/date-fns/src/_lib/requiredArgs/test.js
new file mode 100644
index 0000000..a6cbe4a
--- /dev/null
+++ b/date-fns/src/_lib/requiredArgs/test.js
@@ -0,0 +1,37 @@
+// @flow
+/* eslint-env mocha */
+
+import assert from 'power-assert'
+import requiredArgs from '.'
+
+describe('requiredArgs', function () {
+ function wrapperFn(required) {
+ // $ExpectedMistake
+ return function () {
+ requiredArgs(required, arguments)
+ }
+ }
+ const twoArgsRequired = wrapperFn(2)
+
+ describe('with correct number of passed arguments', function () {
+ it('does not throw an error', function () {
+ assert.doesNotThrow(() => twoArgsRequired(1, 2))
+ })
+ })
+
+ describe('with wrong number of arguments', function () {
+ it('throws correct error message', function () {
+ assert.throws(
+ function () {
+ twoArgsRequired(1)
+ },
+ function (err) {
+ return (
+ err instanceof TypeError &&
+ err.message === '2 arguments required, but only 1 present'
+ )
+ }
+ )
+ })
+ })
+})
diff --git a/date-fns/src/_lib/setUTCDay/index.js b/date-fns/src/_lib/setUTCDay/index.js
new file mode 100644
index 0000000..6e4e472
--- /dev/null
+++ b/date-fns/src/_lib/setUTCDay/index.js
@@ -0,0 +1,38 @@
+import toInteger from '../toInteger/index'
+import toDate from '../../toDate/index'
+import requiredArgs from '../requiredArgs/index'
+
+// This function will be a part of public API when UTC function will be implemented.
+// See issue: https://github.com/date-fns/date-fns/issues/376
+export default function setUTCDay(dirtyDate, dirtyDay, dirtyOptions) {
+ requiredArgs(2, arguments)
+
+ var options = dirtyOptions || {}
+ var locale = options.locale
+ var localeWeekStartsOn =
+ locale && locale.options && locale.options.weekStartsOn
+ var defaultWeekStartsOn =
+ localeWeekStartsOn == null ? 0 : toInteger(localeWeekStartsOn)
+ var weekStartsOn =
+ options.weekStartsOn == null
+ ? defaultWeekStartsOn
+ : toInteger(options.weekStartsOn)
+
+ // Test if weekStartsOn is between 0 and 6 _and_ is not NaN
+ if (!(weekStartsOn >= 0 && weekStartsOn <= 6)) {
+ throw new RangeError('weekStartsOn must be between 0 and 6 inclusively')
+ }
+
+ var date = toDate(dirtyDate)
+ var day = toInteger(dirtyDay)
+
+ var currentDay = date.getUTCDay()
+
+ var remainder = day % 7
+ var dayIndex = (remainder + 7) % 7
+
+ var diff = (dayIndex < weekStartsOn ? 7 : 0) + day - currentDay
+
+ date.setUTCDate(date.getUTCDate() + diff)
+ return date
+}
diff --git a/date-fns/src/_lib/setUTCDay/test.js b/date-fns/src/_lib/setUTCDay/test.js
new file mode 100644
index 0000000..a34074b
--- /dev/null
+++ b/date-fns/src/_lib/setUTCDay/test.js
@@ -0,0 +1,132 @@
+// @flow
+/* eslint-env mocha */
+
+import assert from 'power-assert'
+import setUTCDay from '.'
+
+describe('setUTCDay', function () {
+ it('sets the day of the week', function () {
+ var result = setUTCDay(new Date(Date.UTC(2014, 8 /* Sep */, 1)), 0)
+ assert.deepEqual(result, new Date(Date.UTC(2014, 7 /* Aug */, 31)))
+ })
+
+ it('allows to specify which day is the first day of the week', function () {
+ var result = setUTCDay(new Date(Date.UTC(2014, 8 /* Sep */, 1)), 0, {
+ weekStartsOn: 1,
+ })
+ assert.deepEqual(result, new Date(Date.UTC(2014, 8 /* Sep */, 7)))
+ })
+
+ it('allows to specify which day is the first day of the week in locale', function () {
+ var result = setUTCDay(new Date(Date.UTC(2014, 8 /* Sep */, 1)), 0, {
+ locale: {
+ options: { weekStartsOn: 1 },
+ },
+ })
+ assert.deepEqual(result, new Date(Date.UTC(2014, 8 /* Sep */, 7)))
+ })
+
+ it('`options.weekStartsOn` overwrites the first day of the week specified in locale', function () {
+ var result = setUTCDay(new Date(Date.UTC(2014, 8 /* Sep */, 1)), 0, {
+ weekStartsOn: 1,
+ locale: {
+ options: { weekStartsOn: 0 },
+ },
+ })
+ assert.deepEqual(result, new Date(Date.UTC(2014, 8 /* Sep */, 7)))
+ })
+
+ describe('the day index is more than 6', function () {
+ it('sets the day of the next week', function () {
+ var result = setUTCDay(new Date(Date.UTC(2014, 8 /* Sep */, 1)), 8)
+ assert.deepEqual(result, new Date(Date.UTC(2014, 8 /* Sep */, 8)))
+ })
+
+ it('allows to specify which day is the first day of the week', function () {
+ var result = setUTCDay(new Date(Date.UTC(2014, 8 /* Sep */, 1)), 7, {
+ weekStartsOn: 1,
+ })
+ assert.deepEqual(result, new Date(Date.UTC(2014, 8 /* Sep */, 14)))
+ })
+
+ it('sets the day of another week in the future', function () {
+ var result = setUTCDay(new Date(Date.UTC(2014, 8 /* Sep */, 1)), 14, {
+ weekStartsOn: 1,
+ })
+ assert.deepEqual(result, new Date(Date.UTC(2014, 8 /* Sep */, 21)))
+ })
+ })
+
+ describe('the day index is less than 0', function () {
+ it('sets the day of the last week', function () {
+ var result = setUTCDay(new Date(Date.UTC(2014, 8 /* Sep */, 1)), -6)
+ assert.deepEqual(result, new Date(Date.UTC(2014, 7 /* Aug */, 25)))
+ })
+
+ it('allows to specify which day is the first day of the week', function () {
+ var result = setUTCDay(new Date(Date.UTC(2014, 8 /* Sep */, 1)), -7, {
+ weekStartsOn: 1,
+ })
+ assert.deepEqual(result, new Date(Date.UTC(2014, 7 /* Aug */, 31)))
+ })
+
+ it('set the day of another week in the past', function () {
+ var result = setUTCDay(new Date(Date.UTC(2014, 8 /* Sep */, 1)), -14, {
+ weekStartsOn: 1,
+ })
+ assert.deepEqual(result, new Date(Date.UTC(2014, 7 /* Aug */, 24)))
+ })
+ })
+
+ it('accepts a timestamp', function () {
+ var result = setUTCDay(
+ new Date(Date.UTC(2014, 8 /* Sep */, 1)).getTime(),
+ 3
+ )
+ assert.deepEqual(result, new Date(Date.UTC(2014, 8 /* Sep */, 3)))
+ })
+
+ it('converts a fractional number to an integer', function () {
+ var result = setUTCDay(new Date(Date.UTC(2014, 8 /* Sep */, 1)), 0.9)
+ assert.deepEqual(result, new Date(Date.UTC(2014, 7 /* Aug */, 31)))
+ })
+
+ it('implicitly converts number arguments', function () {
+ var result = setUTCDay(new Date(Date.UTC(2014, 8 /* Sep */, 1)), '0')
+ assert.deepEqual(result, new Date(Date.UTC(2014, 7 /* Aug */, 31)))
+ })
+
+ it('implicitly converts options', function () {
+ var result = setUTCDay(new Date(Date.UTC(2014, 8 /* Sep */, 1)), 0, {
+ weekStartsOn: '1',
+ })
+ assert.deepEqual(result, new Date(Date.UTC(2014, 8 /* Sep */, 7)))
+ })
+
+ it('does not mutate the original date', function () {
+ var date = new Date(Date.UTC(2014, 8 /* Sep */, 1))
+ setUTCDay(date, 3)
+ assert.deepEqual(date, new Date(Date.UTC(2014, 8 /* Sep */, 1)))
+ })
+
+ it('returns `Invalid Date` if the given date is invalid', function () {
+ var result = setUTCDay(new Date(NaN), 0)
+ assert(result instanceof Date && isNaN(result))
+ })
+
+ it('returns `Invalid Date` if the given amount is NaN', function () {
+ var result = setUTCDay(new Date(2014, 8 /* Sep */, 1), NaN)
+ assert(result instanceof Date && isNaN(result))
+ })
+
+ it('throws `RangeError` if `options.weekStartsOn` is not convertable to 0, 1, ..., 6 or undefined', function () {
+ var block = setUTCDay.bind(null, new Date(2014, 8 /* Sep */, 1), 0, {
+ weekStartsOn: NaN,
+ })
+ assert.throws(block, RangeError)
+ })
+
+ it('throws TypeError exception if passed less than 1 argument', function () {
+ assert.throws(setUTCDay.bind(null, 1), TypeError)
+ })
+})
diff --git a/date-fns/src/_lib/setUTCISODay/index.js b/date-fns/src/_lib/setUTCISODay/index.js
new file mode 100644
index 0000000..cbd2fbc
--- /dev/null
+++ b/date-fns/src/_lib/setUTCISODay/index.js
@@ -0,0 +1,27 @@
+import toInteger from '../toInteger/index'
+import toDate from '../../toDate/index'
+import requiredArgs from '../requiredArgs/index'
+
+// This function will be a part of public API when UTC function will be implemented.
+// See issue: https://github.com/date-fns/date-fns/issues/376
+export default function setUTCISODay(dirtyDate, dirtyDay) {
+ requiredArgs(2, arguments)
+
+ var day = toInteger(dirtyDay)
+
+ if (day % 7 === 0) {
+ day = day - 7
+ }
+
+ var weekStartsOn = 1
+ var date = toDate(dirtyDate)
+ var currentDay = date.getUTCDay()
+
+ var remainder = day % 7
+ var dayIndex = (remainder + 7) % 7
+
+ var diff = (dayIndex < weekStartsOn ? 7 : 0) + day - currentDay
+
+ date.setUTCDate(date.getUTCDate() + diff)
+ return date
+}
diff --git a/date-fns/src/_lib/setUTCISODay/test.js b/date-fns/src/_lib/setUTCISODay/test.js
new file mode 100644
index 0000000..11b6019
--- /dev/null
+++ b/date-fns/src/_lib/setUTCISODay/test.js
@@ -0,0 +1,79 @@
+// @flow
+/* eslint-env mocha */
+
+import assert from 'power-assert'
+import setUTCISODay from '.'
+
+describe('setUTCISODay', function () {
+ it('sets the day of the ISO week', function () {
+ var result = setUTCISODay(new Date(Date.UTC(2014, 8 /* Sep */, 1)), 3)
+ assert.deepEqual(result, new Date(Date.UTC(2014, 8 /* Sep */, 3)))
+ })
+
+ it('sets the day to Sunday of this ISO week if the index is 7', function () {
+ var result = setUTCISODay(new Date(Date.UTC(2014, 8 /* Sep */, 1)), 7)
+ assert.deepEqual(result, new Date(Date.UTC(2014, 8 /* Sep */, 7)))
+ })
+
+ describe('the day index is more than 7', function () {
+ it('sets the day of the next ISO week', function () {
+ var result = setUTCISODay(new Date(Date.UTC(2014, 8 /* Sep */, 1)), 8)
+ assert.deepEqual(result, new Date(Date.UTC(2014, 8 /* Sep */, 8)))
+ })
+
+ it('sets the day of another ISO week in the future', function () {
+ var result = setUTCISODay(new Date(Date.UTC(2014, 8 /* Sep */, 1)), 21)
+ assert.deepEqual(result, new Date(Date.UTC(2014, 8 /* Sep */, 21)))
+ })
+ })
+
+ describe('the day index is less than 1', function () {
+ it('sets the day of the last ISO week', function () {
+ var result = setUTCISODay(new Date(Date.UTC(2014, 8 /* Sep */, 1)), 0)
+ assert.deepEqual(result, new Date(Date.UTC(2014, 7 /* Aug */, 31)))
+ })
+
+ it('set the day of another ISO week in the past', function () {
+ var result = setUTCISODay(new Date(Date.UTC(2014, 8 /* Sep */, 1)), -13)
+ assert.deepEqual(result, new Date(Date.UTC(2014, 7 /* Aug */, 18)))
+ })
+ })
+
+ it('accepts a timestamp', function () {
+ var result = setUTCISODay(
+ new Date(Date.UTC(2014, 8 /* Sep */, 1)).getTime(),
+ 3
+ )
+ assert.deepEqual(result, new Date(Date.UTC(2014, 8 /* Sep */, 3)))
+ })
+
+ it('converts a fractional number to an integer', function () {
+ var result = setUTCISODay(new Date(Date.UTC(2014, 8 /* Sep */, 1)), 3.33)
+ assert.deepEqual(result, new Date(Date.UTC(2014, 8 /* Sep */, 3)))
+ })
+
+ it('implicitly converts number arguments', function () {
+ var result = setUTCISODay(new Date(Date.UTC(2014, 8 /* Sep */, 1)), '3')
+ assert.deepEqual(result, new Date(Date.UTC(2014, 8 /* Sep */, 3)))
+ })
+
+ it('does not mutate the original date', function () {
+ var date = new Date(Date.UTC(2014, 8 /* Sep */, 1))
+ setUTCISODay(date, 3)
+ assert.deepEqual(date, new Date(Date.UTC(2014, 8 /* Sep */, 1)))
+ })
+
+ it('returns `Invalid Date` if the given date is invalid', function () {
+ var result = setUTCISODay(new Date(NaN), 3)
+ assert(result instanceof Date && isNaN(result))
+ })
+
+ it('returns `Invalid Date` if the given amount is NaN', function () {
+ var result = setUTCISODay(new Date(2014, 8 /* Sep */, 1), NaN)
+ assert(result instanceof Date && isNaN(result))
+ })
+
+ it('throws TypeError exception if passed less than 1 argument', function () {
+ assert.throws(setUTCISODay.bind(null, 1), TypeError)
+ })
+})
diff --git a/date-fns/src/_lib/setUTCISOWeek/index.js b/date-fns/src/_lib/setUTCISOWeek/index.js
new file mode 100644
index 0000000..99ce6da
--- /dev/null
+++ b/date-fns/src/_lib/setUTCISOWeek/index.js
@@ -0,0 +1,16 @@
+import toInteger from '../toInteger/index'
+import toDate from '../../toDate/index'
+import getUTCISOWeek from '../getUTCISOWeek/index'
+import requiredArgs from '../requiredArgs/index'
+
+// This function will be a part of public API when UTC function will be implemented.
+// See issue: https://github.com/date-fns/date-fns/issues/376
+export default function setUTCISOWeek(dirtyDate, dirtyISOWeek) {
+ requiredArgs(2, arguments)
+
+ var date = toDate(dirtyDate)
+ var isoWeek = toInteger(dirtyISOWeek)
+ var diff = getUTCISOWeek(date) - isoWeek
+ date.setUTCDate(date.getUTCDate() - diff * 7)
+ return date
+}
diff --git a/date-fns/src/_lib/setUTCISOWeek/test.js b/date-fns/src/_lib/setUTCISOWeek/test.js
new file mode 100644
index 0000000..07b7276
--- /dev/null
+++ b/date-fns/src/_lib/setUTCISOWeek/test.js
@@ -0,0 +1,61 @@
+// @flow
+/* eslint-env mocha */
+
+import assert from 'power-assert'
+import setUTCISOWeek from '.'
+
+describe('setUTCISOWeek', function() {
+ it('sets the ISO week', function() {
+ var result = setUTCISOWeek(new Date(Date.UTC(2004, 7 /* Aug */, 7)), 53)
+ assert.deepEqual(result, new Date(Date.UTC(2005, 0 /* Jan */, 1)))
+ })
+
+ it('accepts a timestamp', function() {
+ var result = setUTCISOWeek(
+ new Date(Date.UTC(2009, 11 /* Dec */, 2)).getTime(),
+ 1
+ )
+ assert.deepEqual(result, new Date(Date.UTC(2008, 11 /* Dec */, 31)))
+ })
+
+ it('converts a fractional number to an integer', function() {
+ var result = setUTCISOWeek(new Date(Date.UTC(2004, 7 /* Aug */, 7)), 53.53)
+ assert.deepEqual(result, new Date(Date.UTC(2005, 0 /* Jan */, 1)))
+ })
+
+ it('implicitly converts number arguments', function() {
+ var result = setUTCISOWeek(new Date(Date.UTC(2004, 7 /* Aug */, 7)), '53')
+ assert.deepEqual(result, new Date(Date.UTC(2005, 0 /* Jan */, 1)))
+ })
+
+ it('does not mutate the original date', function() {
+ var date = new Date(Date.UTC(2014, 6 /* Jul */, 2))
+ setUTCISOWeek(date, 52)
+ assert.deepEqual(date, new Date(Date.UTC(2014, 6 /* Jul */, 2)))
+ })
+
+ it('handles dates before 100 AD', function() {
+ var initialDate = new Date(0)
+ initialDate.setUTCFullYear(4, 0 /* Jan */, 4)
+ initialDate.setUTCHours(0, 0, 0, 0)
+ var expectedResult = new Date(0)
+ expectedResult.setUTCFullYear(4, 11 /* Dec */, 26)
+ expectedResult.setUTCHours(0, 0, 0, 0)
+ var result = setUTCISOWeek(initialDate, 52)
+ assert.deepEqual(result, expectedResult)
+ })
+
+ it('returns `Invalid Date` if the given date is invalid', function() {
+ var result = setUTCISOWeek(new Date(NaN), 53)
+ assert(result instanceof Date && isNaN(result))
+ })
+
+ it('returns `Invalid Date` if the given amount is NaN', function() {
+ var result = setUTCISOWeek(new Date(2004, 7 /* Aug */, 7), NaN)
+ assert(result instanceof Date && isNaN(result))
+ })
+
+ it('throws TypeError exception if passed less than 1 argument', function() {
+ assert.throws(setUTCISOWeek.bind(null, 1), TypeError)
+ })
+})
diff --git a/date-fns/src/_lib/setUTCWeek/index.js b/date-fns/src/_lib/setUTCWeek/index.js
new file mode 100644
index 0000000..606d817
--- /dev/null
+++ b/date-fns/src/_lib/setUTCWeek/index.js
@@ -0,0 +1,16 @@
+import toInteger from '../toInteger/index'
+import toDate from '../../toDate/index'
+import getUTCWeek from '../getUTCWeek/index'
+import requiredArgs from '../requiredArgs/index'
+
+// This function will be a part of public API when UTC function will be implemented.
+// See issue: https://github.com/date-fns/date-fns/issues/376
+export default function setUTCWeek(dirtyDate, dirtyWeek, options) {
+ requiredArgs(2, arguments)
+
+ var date = toDate(dirtyDate)
+ var week = toInteger(dirtyWeek)
+ var diff = getUTCWeek(date, options) - week
+ date.setUTCDate(date.getUTCDate() - diff * 7)
+ return date
+}
diff --git a/date-fns/src/_lib/setUTCWeek/test.js b/date-fns/src/_lib/setUTCWeek/test.js
new file mode 100644
index 0000000..58aea10
--- /dev/null
+++ b/date-fns/src/_lib/setUTCWeek/test.js
@@ -0,0 +1,95 @@
+// @flow
+/* eslint-env mocha */
+
+import assert from 'power-assert'
+import setUTCWeek from '.'
+
+describe('setUTCWeek', function() {
+ it('sets the local week', function() {
+ var result = setUTCWeek(new Date(Date.UTC(2005, 0 /* Jan */, 2)), 1)
+ assert.deepEqual(result, new Date(Date.UTC(2004, 11 /* Dec */, 26)))
+ })
+
+ it('accepts a timestamp', function() {
+ var result = setUTCWeek(Date.UTC(2009, 11 /* Dec */, 2), 1)
+ assert.deepEqual(result, new Date(Date.UTC(2008, 11 /* Dec */, 31)))
+ })
+
+ it('converts a fractional number to an integer', function() {
+ var result = setUTCWeek(new Date(Date.UTC(2005, 0 /* Jan */, 2)), 1.1)
+ assert.deepEqual(result, new Date(Date.UTC(2004, 11 /* Dec */, 26)))
+ })
+
+ it('implicitly converts number arguments', function() {
+ var result = setUTCWeek(new Date(Date.UTC(2004, 7 /* Aug */, 7)), '53')
+ assert.deepEqual(result, new Date(Date.UTC(2005, 0 /* Jan */, 1)))
+ })
+
+ it('does not mutate the original date', function() {
+ var date = new Date(2014, 6 /* Jul */, 2)
+ setUTCWeek(date, 52)
+ assert.deepEqual(date, new Date(2014, 6 /* Jul */, 2))
+ })
+
+ it('handles dates before 100 AD', function() {
+ var initialDate = new Date(0)
+ initialDate.setUTCFullYear(4, 0 /* Jan */, 4)
+ initialDate.setUTCHours(0, 0, 0, 0)
+ var expectedResult = new Date(0)
+ expectedResult.setUTCFullYear(4, 11 /* Dec */, 19)
+ expectedResult.setUTCHours(0, 0, 0, 0)
+ var result = setUTCWeek(initialDate, 52)
+ assert.deepEqual(result, expectedResult)
+ })
+
+ it('returns `Invalid Date` if the given date is invalid', function() {
+ var result = setUTCWeek(new Date(NaN), 53)
+ assert(result instanceof Date && isNaN(result))
+ })
+
+ it('returns `Invalid Date` if the given amount is NaN', function() {
+ var result = setUTCWeek(new Date(2004, 7 /* Aug */, 7), NaN)
+ assert(result instanceof Date && isNaN(result))
+ })
+
+ it('allows to specify `weekStartsOn` and `firstWeekContainsDate` in locale', function() {
+ var date = new Date(Date.UTC(2005, 0 /* Jan */, 2))
+ var result = setUTCWeek(date, 1, {
+ locale: {
+ options: { weekStartsOn: 1, firstWeekContainsDate: 4 }
+ }
+ })
+ assert.deepEqual(result, new Date(Date.UTC(2004, 0 /* Jan */, 4)))
+ })
+
+ it('`options.weekStartsOn` overwrites the first day of the week specified in locale', function() {
+ var date = new Date(Date.UTC(2005, 0 /* Jan */, 2))
+ var result = setUTCWeek(date, 1, {
+ weekStartsOn: 1,
+ firstWeekContainsDate: 4,
+ locale: {
+ options: { weekStartsOn: 0, firstWeekContainsDate: 1 }
+ }
+ })
+ assert.deepEqual(result, new Date(Date.UTC(2004, 0 /* Jan */, 4)))
+ })
+
+ it('throws `RangeError` if `options.weekStartsOn` is not convertable to 0, 1, ..., 6 or undefined', function() {
+ var block = setUTCWeek.bind(null, new Date(2004, 7 /* Aug */, 7), 53, {
+ weekStartsOn: NaN
+ })
+ assert.throws(block, RangeError)
+ })
+
+ it('throws `RangeError` if `options.firstWeekContainsDate` is not convertable to 1, 2, ..., 7 or undefined', function() {
+ var block = setUTCWeek.bind(null, new Date(2004, 7 /* Aug */, 7), 53, {
+ firstWeekContainsDate: NaN
+ })
+ assert.throws(block, RangeError)
+ })
+
+ it('throws TypeError exception if passed less than 2 arguments', function() {
+ assert.throws(setUTCWeek.bind(null), TypeError)
+ assert.throws(setUTCWeek.bind(null, 1), TypeError)
+ })
+})
diff --git a/date-fns/src/_lib/startOfUTCISOWeek/index.js b/date-fns/src/_lib/startOfUTCISOWeek/index.js
new file mode 100644
index 0000000..4633c38
--- /dev/null
+++ b/date-fns/src/_lib/startOfUTCISOWeek/index.js
@@ -0,0 +1,18 @@
+import toDate from '../../toDate/index'
+import requiredArgs from '../requiredArgs/index'
+
+// This function will be a part of public API when UTC function will be implemented.
+// See issue: https://github.com/date-fns/date-fns/issues/376
+export default function startOfUTCISOWeek(dirtyDate) {
+ requiredArgs(1, arguments)
+
+ var weekStartsOn = 1
+
+ var date = toDate(dirtyDate)
+ var day = date.getUTCDay()
+ var diff = (day < weekStartsOn ? 7 : 0) + day - weekStartsOn
+
+ date.setUTCDate(date.getUTCDate() - diff)
+ date.setUTCHours(0, 0, 0, 0)
+ return date
+}
diff --git a/date-fns/src/_lib/startOfUTCISOWeek/test.js b/date-fns/src/_lib/startOfUTCISOWeek/test.js
new file mode 100644
index 0000000..1c93535
--- /dev/null
+++ b/date-fns/src/_lib/startOfUTCISOWeek/test.js
@@ -0,0 +1,34 @@
+// @flow
+/* eslint-env mocha */
+
+import assert from 'power-assert'
+import startOfUTCISOWeek from '.'
+
+describe('startOfUTCISOWeek', function() {
+ it('returns the date with the time set to 00:00:00 and the date set to the first day of an ISO week', function() {
+ var date = new Date(Date.UTC(2014, 8 /* Sep */, 2, 11, 55, 0))
+ var result = startOfUTCISOWeek(date)
+ assert.deepEqual(result, new Date(Date.UTC(2014, 8 /* Sep */, 1)))
+ })
+
+ it('accepts a timestamp', function() {
+ var date = new Date(Date.UTC(2014, 1 /* Feb */, 11, 11, 55, 0)).getTime()
+ var result = startOfUTCISOWeek(date)
+ assert.deepEqual(result, new Date(Date.UTC(2014, 1 /* Feb */, 10)))
+ })
+
+ it('does not mutate the original date', function() {
+ var date = new Date(Date.UTC(2014, 8 /* Sep */, 2, 11, 55, 0))
+ startOfUTCISOWeek(date)
+ assert.deepEqual(date, new Date(Date.UTC(2014, 8 /* Sep */, 2, 11, 55, 0)))
+ })
+
+ it('returns `Invalid Date` if the given date is invalid', function() {
+ var result = startOfUTCISOWeek(new Date(NaN))
+ assert(result instanceof Date && isNaN(result))
+ })
+
+ it('throws TypeError exception if passed less than 1 argument', function() {
+ assert.throws(startOfUTCISOWeek.bind(null), TypeError)
+ })
+})
diff --git a/date-fns/src/_lib/startOfUTCISOWeekYear/index.js b/date-fns/src/_lib/startOfUTCISOWeekYear/index.js
new file mode 100644
index 0000000..db3313c
--- /dev/null
+++ b/date-fns/src/_lib/startOfUTCISOWeekYear/index.js
@@ -0,0 +1,16 @@
+import getUTCISOWeekYear from '../getUTCISOWeekYear/index'
+import startOfUTCISOWeek from '../startOfUTCISOWeek/index'
+import requiredArgs from '../requiredArgs/index'
+
+// This function will be a part of public API when UTC function will be implemented.
+// See issue: https://github.com/date-fns/date-fns/issues/376
+export default function startOfUTCISOWeekYear(dirtyDate) {
+ requiredArgs(1, arguments)
+
+ var year = getUTCISOWeekYear(dirtyDate)
+ var fourthOfJanuary = new Date(0)
+ fourthOfJanuary.setUTCFullYear(year, 0, 4)
+ fourthOfJanuary.setUTCHours(0, 0, 0, 0)
+ var date = startOfUTCISOWeek(fourthOfJanuary)
+ return date
+}
diff --git a/date-fns/src/_lib/startOfUTCISOWeekYear/test.js b/date-fns/src/_lib/startOfUTCISOWeekYear/test.js
new file mode 100644
index 0000000..5d0485f
--- /dev/null
+++ b/date-fns/src/_lib/startOfUTCISOWeekYear/test.js
@@ -0,0 +1,58 @@
+// @flow
+/* eslint-env mocha */
+
+import assert from 'power-assert'
+import startOfUTCISOWeekYear from '.'
+
+describe('startOfUTCISOWeekYear', function() {
+ it('returns the date with the time set to 00:00:00 and the date set to the first day of an ISO year', function() {
+ var result = startOfUTCISOWeekYear(
+ new Date(Date.UTC(2009, 0 /* Jan */, 1, 16, 0))
+ )
+ assert.deepEqual(
+ result,
+ new Date(Date.UTC(2008, 11 /* Dec */, 29, 0, 0, 0, 0))
+ )
+ })
+
+ it('accepts a timestamp', function() {
+ var result = startOfUTCISOWeekYear(
+ new Date(Date.UTC(2005, 0 /* Jan */, 1, 6, 0)).getTime()
+ )
+ assert.deepEqual(
+ result,
+ new Date(Date.UTC(2003, 11 /* Dec */, 29, 0, 0, 0, 0))
+ )
+ })
+
+ it('does not mutate the original date', function() {
+ var date = new Date(Date.UTC(2014, 6 /* Jul */, 2))
+ startOfUTCISOWeekYear(date)
+ assert.deepEqual(date, new Date(Date.UTC(2014, 6 /* Jul */, 2)))
+ })
+
+ it('handles dates before 100 AD', function() {
+ var initialDate = new Date(0)
+ initialDate.setUTCFullYear(9, 0 /* Jan */, 1)
+ initialDate.setUTCHours(0, 0, 0, 0)
+ var expectedResult = new Date(0)
+ expectedResult.setUTCFullYear(8, 11 /* Dec */, 29)
+ expectedResult.setUTCHours(0, 0, 0, 0)
+ var result = startOfUTCISOWeekYear(initialDate)
+ assert.deepEqual(result, expectedResult)
+ })
+
+ it('correctly handles years in which 4 January is Sunday', function() {
+ var result = startOfUTCISOWeekYear(new Date(Date.UTC(2009, 6 /* Jul */, 2)))
+ assert.deepEqual(result, new Date(Date.UTC(2008, 11 /* Dec */, 29)))
+ })
+
+ it('returns `Invalid Date` if the given date is invalid', function() {
+ var result = startOfUTCISOWeekYear(new Date(NaN))
+ assert(result instanceof Date && isNaN(result))
+ })
+
+ it('throws TypeError exception if passed less than 1 argument', function() {
+ assert.throws(startOfUTCISOWeekYear.bind(null), TypeError)
+ })
+})
diff --git a/date-fns/src/_lib/startOfUTCWeek/index.js b/date-fns/src/_lib/startOfUTCWeek/index.js
new file mode 100644
index 0000000..fb5db75
--- /dev/null
+++ b/date-fns/src/_lib/startOfUTCWeek/index.js
@@ -0,0 +1,33 @@
+import toInteger from '../toInteger/index'
+import toDate from '../../toDate/index'
+import requiredArgs from '../requiredArgs/index'
+
+// This function will be a part of public API when UTC function will be implemented.
+// See issue: https://github.com/date-fns/date-fns/issues/376
+export default function startOfUTCWeek(dirtyDate, dirtyOptions) {
+ requiredArgs(1, arguments)
+
+ var options = dirtyOptions || {}
+ var locale = options.locale
+ var localeWeekStartsOn =
+ locale && locale.options && locale.options.weekStartsOn
+ var defaultWeekStartsOn =
+ localeWeekStartsOn == null ? 0 : toInteger(localeWeekStartsOn)
+ var weekStartsOn =
+ options.weekStartsOn == null
+ ? defaultWeekStartsOn
+ : toInteger(options.weekStartsOn)
+
+ // Test if weekStartsOn is between 0 and 6 _and_ is not NaN
+ if (!(weekStartsOn >= 0 && weekStartsOn <= 6)) {
+ throw new RangeError('weekStartsOn must be between 0 and 6 inclusively')
+ }
+
+ var date = toDate(dirtyDate)
+ var day = date.getUTCDay()
+ var diff = (day < weekStartsOn ? 7 : 0) + day - weekStartsOn
+
+ date.setUTCDate(date.getUTCDate() - diff)
+ date.setUTCHours(0, 0, 0, 0)
+ return date
+}
diff --git a/date-fns/src/_lib/startOfUTCWeek/test.js b/date-fns/src/_lib/startOfUTCWeek/test.js
new file mode 100644
index 0000000..15680f0
--- /dev/null
+++ b/date-fns/src/_lib/startOfUTCWeek/test.js
@@ -0,0 +1,108 @@
+// @flow
+/* eslint-env mocha */
+
+import assert from 'power-assert'
+import startOfUTCWeek from '.'
+
+describe('startOfUTCWeek', function () {
+ it('returns the date with the time set to 00:00:00 and the date set to the first day of a week', function () {
+ var date = new Date(Date.UTC(2014, 8 /* Sep */, 2, 11, 55, 0))
+ var result = startOfUTCWeek(date)
+ assert.deepEqual(result, new Date(Date.UTC(2014, 7 /* Aug */, 31)))
+ })
+
+ it('allows to specify which day is the first day of the week', function () {
+ var date = new Date(Date.UTC(2014, 8 /* Sep */, 2, 11, 55, 0))
+ var result = startOfUTCWeek(date, { weekStartsOn: 1 })
+ assert.deepEqual(result, new Date(Date.UTC(2014, 8 /* Sep */, 1)))
+ })
+
+ it('allows to specify which day is the first day of the week in locale', function () {
+ var date = new Date(Date.UTC(2014, 8 /* Sep */, 2, 11, 55, 0))
+ var result = startOfUTCWeek(date, {
+ locale: {
+ options: { weekStartsOn: 1 },
+ },
+ })
+ assert.deepEqual(result, new Date(Date.UTC(2014, 8 /* Sep */, 1)))
+ })
+
+ it('`options.weekStartsOn` overwrites the first day of the week specified in locale', function () {
+ var date = new Date(Date.UTC(2014, 8 /* Sep */, 2, 11, 55, 0))
+ var result = startOfUTCWeek(date, {
+ weekStartsOn: 1,
+ locale: {
+ options: { weekStartsOn: 0 },
+ },
+ })
+ assert.deepEqual(result, new Date(Date.UTC(2014, 8 /* Sep */, 1)))
+ })
+
+ it('implicitly converts options', function () {
+ var date = new Date(Date.UTC(2014, 8 /* Sep */, 2, 11, 55, 0))
+ var result = startOfUTCWeek(date, { weekStartsOn: '1' })
+ assert.deepEqual(result, new Date(Date.UTC(2014, 8 /* Sep */, 1)))
+ })
+
+ it('accepts a timestamp', function () {
+ var date = new Date(Date.UTC(2014, 8 /* Sep */, 2, 11, 55, 0)).getTime()
+ var result = startOfUTCWeek(date)
+ assert.deepEqual(result, new Date(Date.UTC(2014, 7 /* Aug */, 31)))
+ })
+
+ it('does not mutate the original date', function () {
+ var date = new Date(Date.UTC(2014, 8 /* Sep */, 2, 11, 55, 0))
+ startOfUTCWeek(date)
+ assert.deepEqual(date, new Date(Date.UTC(2014, 8 /* Sep */, 2, 11, 55, 0)))
+ })
+
+ describe('edge cases', function () {
+ describe('when the given day is before the start of a week', function () {
+ it('it returns the start of a week', function () {
+ var date = new Date(Date.UTC(2014, 9 /* Oct */, 6))
+ var result = startOfUTCWeek(date, { weekStartsOn: 3 })
+ assert.deepEqual(result, new Date(Date.UTC(2014, 9 /* Oct */, 1)))
+ })
+ })
+
+ describe('when the given day is the start of a week', function () {
+ it('it returns the start of a week', function () {
+ var date = new Date(Date.UTC(2014, 9 /* Oct */, 8))
+ var result = startOfUTCWeek(date, { weekStartsOn: 3 })
+ assert.deepEqual(result, new Date(Date.UTC(2014, 9 /* Oct */, 8)))
+ })
+ })
+
+ describe('when the given day is after the start of a week', function () {
+ it('it returns the start of a week', function () {
+ var date = new Date(Date.UTC(2014, 9 /* Oct */, 10))
+ var result = startOfUTCWeek(date, { weekStartsOn: 3 })
+ assert.deepEqual(result, new Date(Date.UTC(2014, 9 /* Oct */, 8)))
+ })
+ })
+
+ it('handles the week at the start of a year', function () {
+ var date = new Date(Date.UTC(2014, 0 /* Jan */, 1))
+ var result = startOfUTCWeek(date)
+ assert.deepEqual(result, new Date(Date.UTC(2013, 11 /* Dec */, 29)))
+ })
+ })
+
+ it('returns `Invalid Date` if the given date is invalid', function () {
+ var result = startOfUTCWeek(new Date(NaN))
+ assert(result instanceof Date && isNaN(result))
+ })
+
+ it('throws `RangeError` if `options.weekStartsOn` is not convertable to 0, 1, ..., 6 or undefined', function () {
+ var block = startOfUTCWeek.bind(
+ null,
+ new Date(Date.UTC(2014, 8 /* Sep */, 2, 11, 55, 0)),
+ { weekStartsOn: NaN }
+ )
+ assert.throws(block, RangeError)
+ })
+
+ it('throws TypeError exception if passed less than 1 argument', function () {
+ assert.throws(startOfUTCWeek.bind(null), TypeError)
+ })
+})
diff --git a/date-fns/src/_lib/startOfUTCWeekYear/index.js b/date-fns/src/_lib/startOfUTCWeekYear/index.js
new file mode 100644
index 0000000..5b505db
--- /dev/null
+++ b/date-fns/src/_lib/startOfUTCWeekYear/index.js
@@ -0,0 +1,30 @@
+import toInteger from '../toInteger/index'
+import getUTCWeekYear from '../getUTCWeekYear/index'
+import startOfUTCWeek from '../startOfUTCWeek/index'
+import requiredArgs from '../requiredArgs/index'
+
+// This function will be a part of public API when UTC function will be implemented.
+// See issue: https://github.com/date-fns/date-fns/issues/376
+export default function startOfUTCWeekYear(dirtyDate, dirtyOptions) {
+ requiredArgs(1, arguments)
+
+ var options = dirtyOptions || {}
+ var locale = options.locale
+ var localeFirstWeekContainsDate =
+ locale && locale.options && locale.options.firstWeekContainsDate
+ var defaultFirstWeekContainsDate =
+ localeFirstWeekContainsDate == null
+ ? 1
+ : toInteger(localeFirstWeekContainsDate)
+ var firstWeekContainsDate =
+ options.firstWeekContainsDate == null
+ ? defaultFirstWeekContainsDate
+ : toInteger(options.firstWeekContainsDate)
+
+ var year = getUTCWeekYear(dirtyDate, dirtyOptions)
+ var firstWeek = new Date(0)
+ firstWeek.setUTCFullYear(year, 0, firstWeekContainsDate)
+ firstWeek.setUTCHours(0, 0, 0, 0)
+ var date = startOfUTCWeek(firstWeek, dirtyOptions)
+ return date
+}
diff --git a/date-fns/src/_lib/startOfUTCWeekYear/test.js b/date-fns/src/_lib/startOfUTCWeekYear/test.js
new file mode 100644
index 0000000..73bb518
--- /dev/null
+++ b/date-fns/src/_lib/startOfUTCWeekYear/test.js
@@ -0,0 +1,95 @@
+// @flow
+/* eslint-env mocha */
+
+import assert from 'power-assert'
+import startOfUTCWeekYear from '.'
+
+describe('startOfUTCWeekYear', function() {
+ it('returns the date with the time set to 00:00:00 and the date set to the first day of a week year', function() {
+ var result = startOfUTCWeekYear(new Date(Date.UTC(2005, 6 /* Jul */, 2)))
+ assert.deepEqual(
+ result,
+ new Date(Date.UTC(2004, 11 /* Dec */, 26, 0, 0, 0, 0))
+ )
+ })
+
+ it('accepts a timestamp', function() {
+ var result = startOfUTCWeekYear(Date.UTC(2005, 0 /* Jan */, 1, 6, 0))
+ assert.deepEqual(
+ result,
+ new Date(Date.UTC(2004, 11 /* Dec */, 26, 0, 0, 0, 0))
+ )
+ })
+
+ it('does not mutate the original date', function() {
+ var date = new Date(Date.UTC(2014, 6 /* Jul */, 2))
+ startOfUTCWeekYear(date)
+ assert.deepEqual(date, new Date(Date.UTC(2014, 6 /* Jul */, 2)))
+ })
+
+ it('handles dates before 100 AD', function() {
+ var initialDate = new Date(0)
+ initialDate.setUTCFullYear(9, 0 /* Jan */, 1)
+ initialDate.setUTCHours(0, 0, 0, 0)
+ var expectedResult = new Date(0)
+ expectedResult.setUTCFullYear(8, 11 /* Dec */, 28)
+ expectedResult.setUTCHours(0, 0, 0, 0)
+ var result = startOfUTCWeekYear(initialDate)
+ assert.deepEqual(result, expectedResult)
+ })
+
+ it('returns `Invalid Date` if the given date is invalid', function() {
+ var result = startOfUTCWeekYear(new Date(NaN))
+ assert(result instanceof Date && isNaN(result))
+ })
+
+ it('allows to specify `weekStartsOn` and `firstWeekContainsDate` in locale', function() {
+ var date = new Date(Date.UTC(2005, 6 /* Jul */, 2))
+ var result = startOfUTCWeekYear(date, {
+ locale: {
+ options: { weekStartsOn: 1, firstWeekContainsDate: 4 }
+ }
+ })
+ assert.deepEqual(
+ result,
+ new Date(Date.UTC(2005, 0 /* Jan */, 3, 0, 0, 0, 0))
+ )
+ })
+
+ it('`options.weekStartsOn` overwrites the first day of the week specified in locale', function() {
+ var date = new Date(2005, 6 /* Jul */, 2)
+ var result = startOfUTCWeekYear(date, {
+ weekStartsOn: 1,
+ firstWeekContainsDate: 4,
+ locale: {
+ options: { weekStartsOn: 0, firstWeekContainsDate: 1 }
+ }
+ })
+ assert.deepEqual(
+ result,
+ new Date(Date.UTC(2005, 0 /* Jan */, 3, 0, 0, 0, 0))
+ )
+ })
+
+ it('throws `RangeError` if `options.weekStartsOn` is not convertable to 0, 1, ..., 6 or undefined', function() {
+ var block = startOfUTCWeekYear.bind(
+ null,
+ new Date(2007, 11 /* Dec */, 31),
+ { weekStartsOn: NaN }
+ )
+ assert.throws(block, RangeError)
+ })
+
+ it('throws `RangeError` if `options.firstWeekContainsDate` is not convertable to 1, 2, ..., 7 or undefined', function() {
+ var block = startOfUTCWeekYear.bind(
+ null,
+ new Date(2007, 11 /* Dec */, 31),
+ { firstWeekContainsDate: NaN }
+ )
+ assert.throws(block, RangeError)
+ })
+
+ it('throws TypeError exception if passed less than 1 argument', function() {
+ assert.throws(startOfUTCWeekYear.bind(null), TypeError)
+ })
+})
diff --git a/date-fns/src/_lib/test/index.ts b/date-fns/src/_lib/test/index.ts
new file mode 100644
index 0000000..ecd8f8c
--- /dev/null
+++ b/date-fns/src/_lib/test/index.ts
@@ -0,0 +1 @@
+export function assertType<T>(_: T) {}
diff --git a/date-fns/src/_lib/toInteger/index.ts b/date-fns/src/_lib/toInteger/index.ts
new file mode 100644
index 0000000..e9a9359
--- /dev/null
+++ b/date-fns/src/_lib/toInteger/index.ts
@@ -0,0 +1,13 @@
+export default function toInteger(dirtyNumber: unknown) {
+ if (dirtyNumber === null || dirtyNumber === true || dirtyNumber === false) {
+ return NaN
+ }
+
+ const number = Number(dirtyNumber)
+
+ if (isNaN(number)) {
+ return number
+ }
+
+ return number < 0 ? Math.ceil(number) : Math.floor(number)
+}
diff --git a/date-fns/src/_lib/toInteger/test.js b/date-fns/src/_lib/toInteger/test.js
new file mode 100644
index 0000000..6542890
--- /dev/null
+++ b/date-fns/src/_lib/toInteger/test.js
@@ -0,0 +1,64 @@
+// @flow
+/* eslint-env mocha */
+
+import assert from 'power-assert'
+import toInteger from '.'
+
+describe('toInteger', function () {
+ it('truncates positive numbers', function () {
+ var result = toInteger(10.99)
+ assert(result === 10)
+ })
+
+ it('truncates negative numbers', function () {
+ var result = toInteger(-5.5)
+ assert(result === -5)
+ })
+
+ it('converts convertable strings', function () {
+ var result = toInteger('-10.75')
+ assert(result === -10)
+ })
+
+ it('returns NaN for non-convertable strings', function () {
+ var result = toInteger('Foobar')
+ assert(typeof result === 'number' && isNaN(result))
+ })
+
+ it('returns NaN for false', function () {
+ var result = toInteger(false)
+ assert(typeof result === 'number' && isNaN(result))
+ })
+
+ it('returns NaN for true', function () {
+ var result = toInteger(true)
+ assert(typeof result === 'number' && isNaN(result))
+ })
+
+ it('returns NaN for null', function () {
+ var result = toInteger(null)
+ assert(typeof result === 'number' && isNaN(result))
+ })
+
+ it('returns NaN for undefined', function () {
+ var result = toInteger(undefined)
+ assert(typeof result === 'number' && isNaN(result))
+ })
+
+ it('returns NaN for NaN', function () {
+ var result = toInteger(NaN)
+ assert(typeof result === 'number' && isNaN(result))
+ })
+
+ it('converts convertable objects', function () {
+ // eslint-disable-next-line no-new-wrappers
+ var result = toInteger(new Number(123))
+ assert(result === 123)
+ })
+
+ it('returns NaN for non-convertable objects', function () {
+ // eslint-disable-next-line no-new-wrappers
+ var result = toInteger({})
+ assert(typeof result === 'number' && isNaN(result))
+ })
+})