| /* |
| Copyright (c) 2004-2006, The Dojo Foundation |
| All Rights Reserved. |
| |
| Licensed under the Academic Free License version 2.1 or above OR the |
| modified BSD license. For more information on Dojo licensing, see: |
| |
| http://dojotoolkit.org/community/licensing.shtml |
| */ |
| |
| |
| |
| dojo.provide("dojo.date.format"); |
| dojo.require("dojo.date.common"); |
| dojo.require("dojo.date.supplemental"); |
| dojo.require("dojo.lang.array"); |
| dojo.require("dojo.lang.common"); |
| dojo.require("dojo.lang.func"); |
| dojo.require("dojo.string.common"); |
| dojo.require("dojo.i18n.common"); |
| dojo.requireLocalization("dojo.i18n.calendar", "gregorian", null, "ko,zh-cn,zh,sv,ja,en,zh-tw,it,hu,nl,fi,zh-hk,fr,pt,ROOT,es,de,pt-br"); |
| dojo.requireLocalization("dojo.i18n.calendar", "gregorianExtras", null, "zh,ROOT,ja"); |
| (function () { |
| dojo.date.format = function (dateObject, options) { |
| if (typeof options == "string") { |
| dojo.deprecated("dojo.date.format", "To format dates with POSIX-style strings, please use dojo.date.strftime instead", "0.5"); |
| return dojo.date.strftime(dateObject, options); |
| } |
| function formatPattern(dateObject, pattern) { |
| return pattern.replace(/([a-z])\1*/ig, function (match) { |
| var s; |
| var c = match.charAt(0); |
| var l = match.length; |
| var pad; |
| var widthList = ["abbr", "wide", "narrow"]; |
| switch (c) { |
| case "G": |
| if (l > 3) { |
| dojo.unimplemented("Era format not implemented"); |
| } |
| s = info.eras[dateObject.getFullYear() < 0 ? 1 : 0]; |
| break; |
| case "y": |
| s = dateObject.getFullYear(); |
| switch (l) { |
| case 1: |
| break; |
| case 2: |
| s = String(s).substr(-2); |
| break; |
| default: |
| pad = true; |
| } |
| break; |
| case "Q": |
| case "q": |
| s = Math.ceil((dateObject.getMonth() + 1) / 3); |
| switch (l) { |
| case 1: |
| case 2: |
| pad = true; |
| break; |
| case 3: |
| case 4: |
| dojo.unimplemented("Quarter format not implemented"); |
| } |
| break; |
| case "M": |
| case "L": |
| var m = dateObject.getMonth(); |
| var width; |
| switch (l) { |
| case 1: |
| case 2: |
| s = m + 1; |
| pad = true; |
| break; |
| case 3: |
| case 4: |
| case 5: |
| width = widthList[l - 3]; |
| break; |
| } |
| if (width) { |
| var type = (c == "L") ? "standalone" : "format"; |
| var prop = ["months", type, width].join("-"); |
| s = info[prop][m]; |
| } |
| break; |
| case "w": |
| var firstDay = 0; |
| s = dojo.date.getWeekOfYear(dateObject, firstDay); |
| pad = true; |
| break; |
| case "d": |
| s = dateObject.getDate(); |
| pad = true; |
| break; |
| case "D": |
| s = dojo.date.getDayOfYear(dateObject); |
| pad = true; |
| break; |
| case "E": |
| case "e": |
| case "c": |
| var d = dateObject.getDay(); |
| var width; |
| switch (l) { |
| case 1: |
| case 2: |
| if (c == "e") { |
| var first = dojo.date.getFirstDayOfWeek(options.locale); |
| d = (d - first + 7) % 7; |
| } |
| if (c != "c") { |
| s = d + 1; |
| pad = true; |
| break; |
| } |
| case 3: |
| case 4: |
| case 5: |
| width = widthList[l - 3]; |
| break; |
| } |
| if (width) { |
| var type = (c == "c") ? "standalone" : "format"; |
| var prop = ["days", type, width].join("-"); |
| s = info[prop][d]; |
| } |
| break; |
| case "a": |
| var timePeriod = (dateObject.getHours() < 12) ? "am" : "pm"; |
| s = info[timePeriod]; |
| break; |
| case "h": |
| case "H": |
| case "K": |
| case "k": |
| var h = dateObject.getHours(); |
| switch (c) { |
| case "h": |
| s = (h % 12) || 12; |
| break; |
| case "H": |
| s = h; |
| break; |
| case "K": |
| s = (h % 12); |
| break; |
| case "k": |
| s = h || 24; |
| break; |
| } |
| pad = true; |
| break; |
| case "m": |
| s = dateObject.getMinutes(); |
| pad = true; |
| break; |
| case "s": |
| s = dateObject.getSeconds(); |
| pad = true; |
| break; |
| case "S": |
| s = Math.round(dateObject.getMilliseconds() * Math.pow(10, l - 3)); |
| break; |
| case "v": |
| case "z": |
| s = dojo.date.getTimezoneName(dateObject); |
| if (s) { |
| break; |
| } |
| l = 4; |
| case "Z": |
| var offset = dateObject.getTimezoneOffset(); |
| var tz = [(offset <= 0 ? "+" : "-"), dojo.string.pad(Math.floor(Math.abs(offset) / 60), 2), dojo.string.pad(Math.abs(offset) % 60, 2)]; |
| if (l == 4) { |
| tz.splice(0, 0, "GMT"); |
| tz.splice(3, 0, ":"); |
| } |
| s = tz.join(""); |
| break; |
| case "Y": |
| case "u": |
| case "W": |
| case "F": |
| case "g": |
| case "A": |
| dojo.debug(match + " modifier not yet implemented"); |
| s = "?"; |
| break; |
| default: |
| dojo.raise("dojo.date.format: invalid pattern char: " + pattern); |
| } |
| if (pad) { |
| s = dojo.string.pad(s, l); |
| } |
| return s; |
| }); |
| } |
| options = options || {}; |
| var locale = dojo.hostenv.normalizeLocale(options.locale); |
| var formatLength = options.formatLength || "full"; |
| var info = dojo.date._getGregorianBundle(locale); |
| var str = []; |
| var sauce = dojo.lang.curry(this, formatPattern, dateObject); |
| if (options.selector != "timeOnly") { |
| var datePattern = options.datePattern || info["dateFormat-" + formatLength]; |
| if (datePattern) { |
| str.push(_processPattern(datePattern, sauce)); |
| } |
| } |
| if (options.selector != "dateOnly") { |
| var timePattern = options.timePattern || info["timeFormat-" + formatLength]; |
| if (timePattern) { |
| str.push(_processPattern(timePattern, sauce)); |
| } |
| } |
| var result = str.join(" "); |
| return result; |
| }; |
| dojo.date.parse = function (value, options) { |
| options = options || {}; |
| var locale = dojo.hostenv.normalizeLocale(options.locale); |
| var info = dojo.date._getGregorianBundle(locale); |
| var formatLength = options.formatLength || "full"; |
| if (!options.selector) { |
| options.selector = "dateOnly"; |
| } |
| var datePattern = options.datePattern || info["dateFormat-" + formatLength]; |
| var timePattern = options.timePattern || info["timeFormat-" + formatLength]; |
| var pattern; |
| if (options.selector == "dateOnly") { |
| pattern = datePattern; |
| } else { |
| if (options.selector == "timeOnly") { |
| pattern = timePattern; |
| } else { |
| if (options.selector == "dateTime") { |
| pattern = datePattern + " " + timePattern; |
| } else { |
| var msg = "dojo.date.parse: Unknown selector param passed: '" + options.selector + "'."; |
| msg += " Defaulting to date pattern."; |
| dojo.debug(msg); |
| pattern = datePattern; |
| } |
| } |
| } |
| var groups = []; |
| var dateREString = _processPattern(pattern, dojo.lang.curry(this, _buildDateTimeRE, groups, info, options)); |
| var dateRE = new RegExp("^" + dateREString + "$"); |
| var match = dateRE.exec(value); |
| if (!match) { |
| return null; |
| } |
| var widthList = ["abbr", "wide", "narrow"]; |
| var result = new Date(1972, 0); |
| var expected = {}; |
| for (var i = 1; i < match.length; i++) { |
| var grp = groups[i - 1]; |
| var l = grp.length; |
| var v = match[i]; |
| switch (grp.charAt(0)) { |
| case "y": |
| if (l != 2) { |
| result.setFullYear(v); |
| expected.year = v; |
| } else { |
| if (v < 100) { |
| v = Number(v); |
| var year = "" + new Date().getFullYear(); |
| var century = year.substring(0, 2) * 100; |
| var yearPart = Number(year.substring(2, 4)); |
| var cutoff = Math.min(yearPart + 20, 99); |
| var num = (v < cutoff) ? century + v : century - 100 + v; |
| result.setFullYear(num); |
| expected.year = num; |
| } else { |
| if (options.strict) { |
| return null; |
| } |
| result.setFullYear(v); |
| expected.year = v; |
| } |
| } |
| break; |
| case "M": |
| if (l > 2) { |
| if (!options.strict) { |
| v = v.replace(/\./g, ""); |
| v = v.toLowerCase(); |
| } |
| var months = info["months-format-" + widthList[l - 3]].concat(); |
| for (var j = 0; j < months.length; j++) { |
| if (!options.strict) { |
| months[j] = months[j].toLowerCase(); |
| } |
| if (v == months[j]) { |
| result.setMonth(j); |
| expected.month = j; |
| break; |
| } |
| } |
| if (j == months.length) { |
| dojo.debug("dojo.date.parse: Could not parse month name: '" + v + "'."); |
| return null; |
| } |
| } else { |
| result.setMonth(v - 1); |
| expected.month = v - 1; |
| } |
| break; |
| case "E": |
| case "e": |
| if (!options.strict) { |
| v = v.toLowerCase(); |
| } |
| var days = info["days-format-" + widthList[l - 3]].concat(); |
| for (var j = 0; j < days.length; j++) { |
| if (!options.strict) { |
| days[j] = days[j].toLowerCase(); |
| } |
| if (v == days[j]) { |
| break; |
| } |
| } |
| if (j == days.length) { |
| dojo.debug("dojo.date.parse: Could not parse weekday name: '" + v + "'."); |
| return null; |
| } |
| break; |
| case "d": |
| result.setDate(v); |
| expected.date = v; |
| break; |
| case "a": |
| var am = options.am || info.am; |
| var pm = options.pm || info.pm; |
| if (!options.strict) { |
| v = v.replace(/\./g, "").toLowerCase(); |
| am = am.replace(/\./g, "").toLowerCase(); |
| pm = pm.replace(/\./g, "").toLowerCase(); |
| } |
| if (options.strict && v != am && v != pm) { |
| dojo.debug("dojo.date.parse: Could not parse am/pm part."); |
| return null; |
| } |
| var hours = result.getHours(); |
| if (v == pm && hours < 12) { |
| result.setHours(hours + 12); |
| } else { |
| if (v == am && hours == 12) { |
| result.setHours(0); |
| } |
| } |
| break; |
| case "K": |
| if (v == 24) { |
| v = 0; |
| } |
| case "h": |
| case "H": |
| case "k": |
| if (v > 23) { |
| dojo.debug("dojo.date.parse: Illegal hours value"); |
| return null; |
| } |
| result.setHours(v); |
| break; |
| case "m": |
| result.setMinutes(v); |
| break; |
| case "s": |
| result.setSeconds(v); |
| break; |
| case "S": |
| result.setMilliseconds(v); |
| break; |
| default: |
| dojo.unimplemented("dojo.date.parse: unsupported pattern char=" + grp.charAt(0)); |
| } |
| } |
| if (expected.year && result.getFullYear() != expected.year) { |
| dojo.debug("Parsed year: '" + result.getFullYear() + "' did not match input year: '" + expected.year + "'."); |
| return null; |
| } |
| if (expected.month && result.getMonth() != expected.month) { |
| dojo.debug("Parsed month: '" + result.getMonth() + "' did not match input month: '" + expected.month + "'."); |
| return null; |
| } |
| if (expected.date && result.getDate() != expected.date) { |
| dojo.debug("Parsed day of month: '" + result.getDate() + "' did not match input day of month: '" + expected.date + "'."); |
| return null; |
| } |
| return result; |
| }; |
| function _processPattern(pattern, applyPattern, applyLiteral, applyAll) { |
| var identity = function (x) { |
| return x; |
| }; |
| applyPattern = applyPattern || identity; |
| applyLiteral = applyLiteral || identity; |
| applyAll = applyAll || identity; |
| var chunks = pattern.match(/(''|[^'])+/g); |
| var literal = false; |
| for (var i = 0; i < chunks.length; i++) { |
| if (!chunks[i]) { |
| chunks[i] = ""; |
| } else { |
| chunks[i] = (literal ? applyLiteral : applyPattern)(chunks[i]); |
| literal = !literal; |
| } |
| } |
| return applyAll(chunks.join("")); |
| } |
| function _buildDateTimeRE(groups, info, options, pattern) { |
| return pattern.replace(/([a-z])\1*/ig, function (match) { |
| var s; |
| var c = match.charAt(0); |
| var l = match.length; |
| switch (c) { |
| case "y": |
| s = "\\d" + ((l == 2) ? "{2,4}" : "+"); |
| break; |
| case "M": |
| s = (l > 2) ? "\\S+" : "\\d{1,2}"; |
| break; |
| case "d": |
| s = "\\d{1,2}"; |
| break; |
| case "E": |
| s = "\\S+"; |
| break; |
| case "h": |
| case "H": |
| case "K": |
| case "k": |
| s = "\\d{1,2}"; |
| break; |
| case "m": |
| case "s": |
| s = "[0-5]\\d"; |
| break; |
| case "S": |
| s = "\\d{1,3}"; |
| break; |
| case "a": |
| var am = options.am || info.am || "AM"; |
| var pm = options.pm || info.pm || "PM"; |
| if (options.strict) { |
| s = am + "|" + pm; |
| } else { |
| s = am; |
| s += (am != am.toLowerCase()) ? "|" + am.toLowerCase() : ""; |
| s += "|"; |
| s += (pm != pm.toLowerCase()) ? pm + "|" + pm.toLowerCase() : pm; |
| } |
| break; |
| default: |
| dojo.unimplemented("parse of date format, pattern=" + pattern); |
| } |
| if (groups) { |
| groups.push(match); |
| } |
| return "\\s*(" + s + ")\\s*"; |
| }); |
| } |
| })(); |
| dojo.date.strftime = function (dateObject, format, locale) { |
| var padChar = null; |
| function _(s, n) { |
| return dojo.string.pad(s, n || 2, padChar || "0"); |
| } |
| var info = dojo.date._getGregorianBundle(locale); |
| function $(property) { |
| switch (property) { |
| case "a": |
| return dojo.date.getDayShortName(dateObject, locale); |
| case "A": |
| return dojo.date.getDayName(dateObject, locale); |
| case "b": |
| case "h": |
| return dojo.date.getMonthShortName(dateObject, locale); |
| case "B": |
| return dojo.date.getMonthName(dateObject, locale); |
| case "c": |
| return dojo.date.format(dateObject, {locale:locale}); |
| case "C": |
| return _(Math.floor(dateObject.getFullYear() / 100)); |
| case "d": |
| return _(dateObject.getDate()); |
| case "D": |
| return $("m") + "/" + $("d") + "/" + $("y"); |
| case "e": |
| if (padChar == null) { |
| padChar = " "; |
| } |
| return _(dateObject.getDate()); |
| case "f": |
| if (padChar == null) { |
| padChar = " "; |
| } |
| return _(dateObject.getMonth() + 1); |
| case "g": |
| break; |
| case "G": |
| dojo.unimplemented("unimplemented modifier 'G'"); |
| break; |
| case "F": |
| return $("Y") + "-" + $("m") + "-" + $("d"); |
| case "H": |
| return _(dateObject.getHours()); |
| case "I": |
| return _(dateObject.getHours() % 12 || 12); |
| case "j": |
| return _(dojo.date.getDayOfYear(dateObject), 3); |
| case "k": |
| if (padChar == null) { |
| padChar = " "; |
| } |
| return _(dateObject.getHours()); |
| case "l": |
| if (padChar == null) { |
| padChar = " "; |
| } |
| return _(dateObject.getHours() % 12 || 12); |
| case "m": |
| return _(dateObject.getMonth() + 1); |
| case "M": |
| return _(dateObject.getMinutes()); |
| case "n": |
| return "\n"; |
| case "p": |
| return info[dateObject.getHours() < 12 ? "am" : "pm"]; |
| case "r": |
| return $("I") + ":" + $("M") + ":" + $("S") + " " + $("p"); |
| case "R": |
| return $("H") + ":" + $("M"); |
| case "S": |
| return _(dateObject.getSeconds()); |
| case "t": |
| return "\t"; |
| case "T": |
| return $("H") + ":" + $("M") + ":" + $("S"); |
| case "u": |
| return String(dateObject.getDay() || 7); |
| case "U": |
| return _(dojo.date.getWeekOfYear(dateObject)); |
| case "V": |
| return _(dojo.date.getIsoWeekOfYear(dateObject)); |
| case "W": |
| return _(dojo.date.getWeekOfYear(dateObject, 1)); |
| case "w": |
| return String(dateObject.getDay()); |
| case "x": |
| return dojo.date.format(dateObject, {selector:"dateOnly", locale:locale}); |
| case "X": |
| return dojo.date.format(dateObject, {selector:"timeOnly", locale:locale}); |
| case "y": |
| return _(dateObject.getFullYear() % 100); |
| case "Y": |
| return String(dateObject.getFullYear()); |
| case "z": |
| var timezoneOffset = dateObject.getTimezoneOffset(); |
| return (timezoneOffset > 0 ? "-" : "+") + _(Math.floor(Math.abs(timezoneOffset) / 60)) + ":" + _(Math.abs(timezoneOffset) % 60); |
| case "Z": |
| return dojo.date.getTimezoneName(dateObject); |
| case "%": |
| return "%"; |
| } |
| } |
| var string = ""; |
| var i = 0; |
| var index = 0; |
| var switchCase = null; |
| while ((index = format.indexOf("%", i)) != -1) { |
| string += format.substring(i, index++); |
| switch (format.charAt(index++)) { |
| case "_": |
| padChar = " "; |
| break; |
| case "-": |
| padChar = ""; |
| break; |
| case "0": |
| padChar = "0"; |
| break; |
| case "^": |
| switchCase = "upper"; |
| break; |
| case "*": |
| switchCase = "lower"; |
| break; |
| case "#": |
| switchCase = "swap"; |
| break; |
| default: |
| padChar = null; |
| index--; |
| break; |
| } |
| var property = $(format.charAt(index++)); |
| switch (switchCase) { |
| case "upper": |
| property = property.toUpperCase(); |
| break; |
| case "lower": |
| property = property.toLowerCase(); |
| break; |
| case "swap": |
| var compareString = property.toLowerCase(); |
| var swapString = ""; |
| var j = 0; |
| var ch = ""; |
| while (j < property.length) { |
| ch = property.charAt(j); |
| swapString += (ch == compareString.charAt(j)) ? ch.toUpperCase() : ch.toLowerCase(); |
| j++; |
| } |
| property = swapString; |
| break; |
| default: |
| break; |
| } |
| switchCase = null; |
| string += property; |
| i = index; |
| } |
| string += format.substring(i); |
| return string; |
| }; |
| (function () { |
| var _customFormats = []; |
| dojo.date.addCustomFormats = function (packageName, bundleName) { |
| _customFormats.push({pkg:packageName, name:bundleName}); |
| }; |
| dojo.date._getGregorianBundle = function (locale) { |
| var gregorian = {}; |
| dojo.lang.forEach(_customFormats, function (desc) { |
| var bundle = dojo.i18n.getLocalization(desc.pkg, desc.name, locale); |
| gregorian = dojo.lang.mixin(gregorian, bundle); |
| }, this); |
| return gregorian; |
| }; |
| })(); |
| dojo.date.addCustomFormats("dojo.i18n.calendar", "gregorian"); |
| dojo.date.addCustomFormats("dojo.i18n.calendar", "gregorianExtras"); |
| dojo.date.getNames = function (item, type, use, locale) { |
| var label; |
| var lookup = dojo.date._getGregorianBundle(locale); |
| var props = [item, use, type]; |
| if (use == "standAlone") { |
| label = lookup[props.join("-")]; |
| } |
| props[1] = "format"; |
| return (label || lookup[props.join("-")]).concat(); |
| }; |
| dojo.date.getDayName = function (dateObject, locale) { |
| return dojo.date.getNames("days", "wide", "format", locale)[dateObject.getDay()]; |
| }; |
| dojo.date.getDayShortName = function (dateObject, locale) { |
| return dojo.date.getNames("days", "abbr", "format", locale)[dateObject.getDay()]; |
| }; |
| dojo.date.getMonthName = function (dateObject, locale) { |
| return dojo.date.getNames("months", "wide", "format", locale)[dateObject.getMonth()]; |
| }; |
| dojo.date.getMonthShortName = function (dateObject, locale) { |
| return dojo.date.getNames("months", "abbr", "format", locale)[dateObject.getMonth()]; |
| }; |
| dojo.date.toRelativeString = function (dateObject) { |
| var now = new Date(); |
| var diff = (now - dateObject) / 1000; |
| var end = " ago"; |
| var future = false; |
| if (diff < 0) { |
| future = true; |
| end = " from now"; |
| diff = -diff; |
| } |
| if (diff < 60) { |
| diff = Math.round(diff); |
| return diff + " second" + (diff == 1 ? "" : "s") + end; |
| } |
| if (diff < 60 * 60) { |
| diff = Math.round(diff / 60); |
| return diff + " minute" + (diff == 1 ? "" : "s") + end; |
| } |
| if (diff < 60 * 60 * 24) { |
| diff = Math.round(diff / 3600); |
| return diff + " hour" + (diff == 1 ? "" : "s") + end; |
| } |
| if (diff < 60 * 60 * 24 * 7) { |
| diff = Math.round(diff / (3600 * 24)); |
| if (diff == 1) { |
| return future ? "Tomorrow" : "Yesterday"; |
| } else { |
| return diff + " days" + end; |
| } |
| } |
| return dojo.date.format(dateObject); |
| }; |
| dojo.date.toSql = function (dateObject, noTime) { |
| return dojo.date.strftime(dateObject, "%F" + !noTime ? " %T" : ""); |
| }; |
| dojo.date.fromSql = function (sqlDate) { |
| var parts = sqlDate.split(/[\- :]/g); |
| while (parts.length < 6) { |
| parts.push(0); |
| } |
| return new Date(parts[0], (parseInt(parts[1], 10) - 1), parts[2], parts[3], parts[4], parts[5]); |
| }; |
| |