budibase/packages/common/node_modules/date-fns/parse/index.js

333 lines
8.5 KiB
JavaScript

var getTimezoneOffsetInMilliseconds = require('../_lib/getTimezoneOffsetInMilliseconds/index.js')
var isDate = require('../is_date/index.js')
var MILLISECONDS_IN_HOUR = 3600000
var MILLISECONDS_IN_MINUTE = 60000
var DEFAULT_ADDITIONAL_DIGITS = 2
var parseTokenDateTimeDelimeter = /[T ]/
var parseTokenPlainTime = /:/
// year tokens
var parseTokenYY = /^(\d{2})$/
var parseTokensYYY = [
/^([+-]\d{2})$/, // 0 additional digits
/^([+-]\d{3})$/, // 1 additional digit
/^([+-]\d{4})$/ // 2 additional digits
]
var parseTokenYYYY = /^(\d{4})/
var parseTokensYYYYY = [
/^([+-]\d{4})/, // 0 additional digits
/^([+-]\d{5})/, // 1 additional digit
/^([+-]\d{6})/ // 2 additional digits
]
// date tokens
var parseTokenMM = /^-(\d{2})$/
var parseTokenDDD = /^-?(\d{3})$/
var parseTokenMMDD = /^-?(\d{2})-?(\d{2})$/
var parseTokenWww = /^-?W(\d{2})$/
var parseTokenWwwD = /^-?W(\d{2})-?(\d{1})$/
// time tokens
var parseTokenHH = /^(\d{2}([.,]\d*)?)$/
var parseTokenHHMM = /^(\d{2}):?(\d{2}([.,]\d*)?)$/
var parseTokenHHMMSS = /^(\d{2}):?(\d{2}):?(\d{2}([.,]\d*)?)$/
// timezone tokens
var parseTokenTimezone = /([Z+-].*)$/
var parseTokenTimezoneZ = /^(Z)$/
var parseTokenTimezoneHH = /^([+-])(\d{2})$/
var parseTokenTimezoneHHMM = /^([+-])(\d{2}):?(\d{2})$/
/**
* @category Common Helpers
* @summary Convert the given argument to an instance of Date.
*
* @description
* Convert the given argument to an instance of Date.
*
* If the argument is an instance of Date, the function returns its clone.
*
* If the argument is a number, it is treated as a timestamp.
*
* If an argument is a string, the function tries to parse it.
* Function accepts complete ISO 8601 formats as well as partial implementations.
* ISO 8601: http://en.wikipedia.org/wiki/ISO_8601
*
* If all above fails, the function passes the given argument to Date constructor.
*
* @param {Date|String|Number} argument - the value to convert
* @param {Object} [options] - the object with options
* @param {0 | 1 | 2} [options.additionalDigits=2] - the additional number of digits in the extended year format
* @returns {Date} the parsed date in the local time zone
*
* @example
* // Convert string '2014-02-11T11:30:30' to date:
* var result = parse('2014-02-11T11:30:30')
* //=> Tue Feb 11 2014 11:30:30
*
* @example
* // Parse string '+02014101',
* // if the additional number of digits in the extended year format is 1:
* var result = parse('+02014101', {additionalDigits: 1})
* //=> Fri Apr 11 2014 00:00:00
*/
function parse (argument, dirtyOptions) {
if (isDate(argument)) {
// Prevent the date to lose the milliseconds when passed to new Date() in IE10
return new Date(argument.getTime())
} else if (typeof argument !== 'string') {
return new Date(argument)
}
var options = dirtyOptions || {}
var additionalDigits = options.additionalDigits
if (additionalDigits == null) {
additionalDigits = DEFAULT_ADDITIONAL_DIGITS
} else {
additionalDigits = Number(additionalDigits)
}
var dateStrings = splitDateString(argument)
var parseYearResult = parseYear(dateStrings.date, additionalDigits)
var year = parseYearResult.year
var restDateString = parseYearResult.restDateString
var date = parseDate(restDateString, year)
if (date) {
var timestamp = date.getTime()
var time = 0
var offset
if (dateStrings.time) {
time = parseTime(dateStrings.time)
}
if (dateStrings.timezone) {
offset = parseTimezone(dateStrings.timezone) * MILLISECONDS_IN_MINUTE
} else {
var fullTime = timestamp + time
var fullTimeDate = new Date(fullTime)
offset = getTimezoneOffsetInMilliseconds(fullTimeDate)
// Adjust time when it's coming from DST
var fullTimeDateNextDay = new Date(fullTime)
fullTimeDateNextDay.setDate(fullTimeDate.getDate() + 1)
var offsetDiff =
getTimezoneOffsetInMilliseconds(fullTimeDateNextDay) -
getTimezoneOffsetInMilliseconds(fullTimeDate)
if (offsetDiff > 0) {
offset += offsetDiff
}
}
return new Date(timestamp + time + offset)
} else {
return new Date(argument)
}
}
function splitDateString (dateString) {
var dateStrings = {}
var array = dateString.split(parseTokenDateTimeDelimeter)
var timeString
if (parseTokenPlainTime.test(array[0])) {
dateStrings.date = null
timeString = array[0]
} else {
dateStrings.date = array[0]
timeString = array[1]
}
if (timeString) {
var token = parseTokenTimezone.exec(timeString)
if (token) {
dateStrings.time = timeString.replace(token[1], '')
dateStrings.timezone = token[1]
} else {
dateStrings.time = timeString
}
}
return dateStrings
}
function parseYear (dateString, additionalDigits) {
var parseTokenYYY = parseTokensYYY[additionalDigits]
var parseTokenYYYYY = parseTokensYYYYY[additionalDigits]
var token
// YYYY or ±YYYYY
token = parseTokenYYYY.exec(dateString) || parseTokenYYYYY.exec(dateString)
if (token) {
var yearString = token[1]
return {
year: parseInt(yearString, 10),
restDateString: dateString.slice(yearString.length)
}
}
// YY or ±YYY
token = parseTokenYY.exec(dateString) || parseTokenYYY.exec(dateString)
if (token) {
var centuryString = token[1]
return {
year: parseInt(centuryString, 10) * 100,
restDateString: dateString.slice(centuryString.length)
}
}
// Invalid ISO-formatted year
return {
year: null
}
}
function parseDate (dateString, year) {
// Invalid ISO-formatted year
if (year === null) {
return null
}
var token
var date
var month
var week
// YYYY
if (dateString.length === 0) {
date = new Date(0)
date.setUTCFullYear(year)
return date
}
// YYYY-MM
token = parseTokenMM.exec(dateString)
if (token) {
date = new Date(0)
month = parseInt(token[1], 10) - 1
date.setUTCFullYear(year, month)
return date
}
// YYYY-DDD or YYYYDDD
token = parseTokenDDD.exec(dateString)
if (token) {
date = new Date(0)
var dayOfYear = parseInt(token[1], 10)
date.setUTCFullYear(year, 0, dayOfYear)
return date
}
// YYYY-MM-DD or YYYYMMDD
token = parseTokenMMDD.exec(dateString)
if (token) {
date = new Date(0)
month = parseInt(token[1], 10) - 1
var day = parseInt(token[2], 10)
date.setUTCFullYear(year, month, day)
return date
}
// YYYY-Www or YYYYWww
token = parseTokenWww.exec(dateString)
if (token) {
week = parseInt(token[1], 10) - 1
return dayOfISOYear(year, week)
}
// YYYY-Www-D or YYYYWwwD
token = parseTokenWwwD.exec(dateString)
if (token) {
week = parseInt(token[1], 10) - 1
var dayOfWeek = parseInt(token[2], 10) - 1
return dayOfISOYear(year, week, dayOfWeek)
}
// Invalid ISO-formatted date
return null
}
function parseTime (timeString) {
var token
var hours
var minutes
// hh
token = parseTokenHH.exec(timeString)
if (token) {
hours = parseFloat(token[1].replace(',', '.'))
return (hours % 24) * MILLISECONDS_IN_HOUR
}
// hh:mm or hhmm
token = parseTokenHHMM.exec(timeString)
if (token) {
hours = parseInt(token[1], 10)
minutes = parseFloat(token[2].replace(',', '.'))
return (hours % 24) * MILLISECONDS_IN_HOUR +
minutes * MILLISECONDS_IN_MINUTE
}
// hh:mm:ss or hhmmss
token = parseTokenHHMMSS.exec(timeString)
if (token) {
hours = parseInt(token[1], 10)
minutes = parseInt(token[2], 10)
var seconds = parseFloat(token[3].replace(',', '.'))
return (hours % 24) * MILLISECONDS_IN_HOUR +
minutes * MILLISECONDS_IN_MINUTE +
seconds * 1000
}
// Invalid ISO-formatted time
return null
}
function parseTimezone (timezoneString) {
var token
var absoluteOffset
// Z
token = parseTokenTimezoneZ.exec(timezoneString)
if (token) {
return 0
}
// ±hh
token = parseTokenTimezoneHH.exec(timezoneString)
if (token) {
absoluteOffset = parseInt(token[2], 10) * 60
return (token[1] === '+') ? -absoluteOffset : absoluteOffset
}
// ±hh:mm or ±hhmm
token = parseTokenTimezoneHHMM.exec(timezoneString)
if (token) {
absoluteOffset = parseInt(token[2], 10) * 60 + parseInt(token[3], 10)
return (token[1] === '+') ? -absoluteOffset : absoluteOffset
}
return 0
}
function dayOfISOYear (isoYear, week, day) {
week = week || 0
day = day || 0
var date = new Date(0)
date.setUTCFullYear(isoYear, 0, 4)
var fourthOfJanuaryDay = date.getUTCDay() || 7
var diff = week * 7 + day + 1 - fourthOfJanuaryDay
date.setUTCDate(date.getUTCDate() + diff)
return date
}
module.exports = parse