You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							332 lines
						
					
					
						
							8.5 KiB
						
					
					
				
			
		
		
	
	
							332 lines
						
					
					
						
							8.5 KiB
						
					
					
				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
 | 
						|
 |