日期格式化字符串在jQuery UI datepicker,moment.js,.Net的DateTime类中有不同的规则。如何在这些不同的格式之间进行转换?
更新:现在在github上:https://github.com/deerchao/dateformats
答案 0 :(得分:9)
使用TypeScript版本:
var j = dateFormat.convert('YYYY-MM-DD', dateFormat.momentJs, dateFormat.datepicker);
以下是TypeScript版本:
module dateFormat {
export interface formatRules {
DayOfMonthShort : string;
DayOfMonthLong : string;
DayOfWeekShort : string;
DayOfWeekLong : string;
DayOfYearShort : string;
DayOfYearLong : string;
MonthOfYearShort : string;
MonthOfYearLong : string;
MonthNameShort : string;
MonthNameLong : string;
YearShort : string;
YearLong : string;
AmPm : string;
Hour24Short : string;
Hour24Long : string;
Hour12Short : string;
Hour12Long : string;
MinuteShort : string;
MinuteLong : string;
SecondShort : string;
SecondLong : string;
FractionalSecond1 : string;
FractionalSecond2 : string;
FractionalSecond3 : string;
TimeZone : string;
UnixTimestamp : string;
MakeLiteral(literal: string): string;
ReadEscapedPart(format: string, startIndex: number) : escapedPart;
}
export interface escapedPart {
value: string;
length: number;
}
interface tokenLocateResult {
nextBegin: number;
literal: string;
token: string;
}
export function convert(format: string, sourceRules: formatRules, destRules: formatRules) {
if(sourceRules == destRules)
return format;
var result = '';
var index = 0;
var destTokens = getTokens(destRules);
var sourceMap = getTokenMap(getTokens(sourceRules));
while(index < format.length) {
var part = locateNextToken(sourceRules, format, index);
if(part.literal.length > 0)
result += destRules.MakeLiteral(part.literal);
if(part.token.length > 0)
result += destTokens[sourceMap[part.token]];
index = part.nextBegin;
}
return result;
}
function locateNextToken(rules: formatRules, format: string, begin: number) {
var literal = '';
var index = begin;
var sequence = getTokenSequence(getTokenMap(getTokens(rules)));
while(index < format.length) {
var escaped = rules.ReadEscapedPart(format, index);
if(escaped.length > 0) {
literal += escaped.value;
index += escaped.length;
continue;
}
var token = sequence.first(x => format.indexOf(x, index) == index);
if(!token) {
literal += format.charAt(index);
index++;
continue;
}
return {
token: token,
literal: literal,
nextBegin: index + token.length
}
}
return {
token: '',
literal: literal,
nextBegin: index
}
}
function getTokens(rules: formatRules) {
return [rules.DayOfMonthShort, rules. DayOfMonthLong,
rules.DayOfWeekShort, rules. DayOfWeekLong,
rules.DayOfYearShort, rules. DayOfYearLong,
rules.MonthOfYearShort, rules. MonthOfYearLong,
rules.MonthNameShort, rules. MonthNameLong,
rules.YearShort, rules. YearLong,
rules.AmPm,
rules.Hour24Short, rules. Hour24Long,
rules.Hour12Short, rules. Hour12Long,
rules.MinuteShort, rules. MinuteLong,
rules.SecondShort, rules. SecondLong,
rules.FractionalSecond1, rules. FractionalSecond2, rules. FractionalSecond3,
rules.TimeZone,
rules.UnixTimestamp
].map(x => x || '');
}
function getTokenMap(tokens: string[]) {
var map = {};
for(var i=0; i<tokens.length; i++) {
var token = tokens[i];
if(token) {
map[token] = i;
}
}
return map;
}
function getTokenSequence(map: any) {
var tokens = Object.keys(map);
tokens.sort((a, b) => b.length - a.length);
return tokens;
}
function indexOfAny(s: string, chars: string) {
for(var i=0; i<s.length; i++) {
var c = s.charAt(i);
for(var j=0; j<chars.length; j++) {
if(c === chars.charAt(j))
return i;
}
}
return -1;
}
export var standard : formatRules = {
DayOfMonthShort : 'd',
DayOfMonthLong : 'dd',
DayOfWeekShort : 'ddd',
DayOfWeekLong : 'dddd',
DayOfYearShort : 'D',
DayOfYearLong : 'DD',
MonthOfYearShort : 'M',
MonthOfYearLong : 'MM',
MonthNameShort : 'MMM',
MonthNameLong : 'MMMM',
YearShort : 'yy',
YearLong : 'yyyy',
AmPm : 'tt',
Hour24Short : 'H',
Hour24Long : 'HH',
Hour12Short : 'h',
Hour12Long : 'hh',
MinuteShort : 'm',
MinuteLong : 'mm',
SecondShort : 's',
SecondLong : 'ss',
FractionalSecond1 : 'f',
FractionalSecond2 : 'ff',
FractionalSecond3 : 'fff',
TimeZone : 'Z',
UnixTimestamp : 'X',
MakeLiteral: function(literal: string) {
var reserved = 'dDMytHhmsfZX';
if(indexOfAny(literal, reserved) < 0)
return literal;
var result = '';
for(var i=0; i< literal.length; i++) {
var c = literal.charAt(i);
if(reserved.contains(c))
result += '\\';
result += c;
}
return result;
},
ReadEscapedPart: function(format: string, startIndex: number) {
var result = '';
var index = startIndex;
while(index < format.length) {
var c = format.charAt(index);
if(c == '\\') {
result += index == format.length - 1 ? '\\' : format[++index];
index++;
continue;
}
break;
}
return {
value: result,
length: index - startIndex
}
},
}
export var dotNet : formatRules = {
DayOfMonthShort : 'd',
DayOfMonthLong : 'dd',
DayOfWeekShort : 'ddd',
DayOfWeekLong : 'dddd',
DayOfYearShort : null,
DayOfYearLong : null,
MonthOfYearShort : 'M',
MonthOfYearLong : 'MM',
MonthNameShort : 'MMM',
MonthNameLong : 'MMMM',
YearShort : 'yy',
YearLong : 'yyyy',
AmPm : 'tt',
Hour24Short : 'H',
Hour24Long : 'HH',
Hour12Short : 'h',
Hour12Long : 'hh',
MinuteShort : 'm',
MinuteLong : 'mm',
SecondShort : 's',
SecondLong : 'ss',
FractionalSecond1 : 'f',
FractionalSecond2 : 'ff',
FractionalSecond3 : 'fff',
TimeZone : 'zzz',
UnixTimestamp : null,
MakeLiteral: function(literal: string) {
var reserved = 'dfFghHKmMstyz\'"';
if(indexOfAny(literal, reserved) < 0)
return literal;
var result = '';
for(var i=0; i< literal.length; i++) {
var c = literal.charAt(i);
if(reserved.contains(c))
result += '\\';
result += c;
}
return result;
},
ReadEscapedPart: function(format: string, startIndex: number) {
var result = '';
var index = startIndex;
while(index < format.length) {
var c = format.charAt(index);
if(c == '\\') {
result += index == format.length - 1 ? '\\' : format[++index];
index++;
continue;
}
if(c == '"') {
while(++index < format.length) {
var cc = format.charAt(index);
if(cc == '"')
break;
if(cc == '\\') {
result += index == format.length - 1 ? '\\' : format[++index];
} else {
result += cc;
}
}
index++;
continue;
}
if(c == "'") {
while(++index < format.length) {
var cc = format.charAt(index);
if(cc == "'")
break;
if(cc == '\\') {
result += index == format.length - 1 ? '\\' : format[++index];
} else {
result += cc;
}
}
index++;
continue;
}
break;
}
return {
value: result,
length: index - startIndex
}
},
}
export var momentJs : formatRules = {
DayOfMonthShort : 'D',
DayOfMonthLong : 'DD',
DayOfWeekShort : 'ddd',
DayOfWeekLong : 'dddd',
DayOfYearShort : 'DDD',
DayOfYearLong : 'DDDD',
MonthOfYearShort : 'M',
MonthOfYearLong : 'MM',
MonthNameShort : 'MMM',
MonthNameLong : 'MMMM',
YearShort : 'YY',
YearLong : 'YYYY',
AmPm : 'A',
Hour24Short : 'H',
Hour24Long : 'HH',
Hour12Short : 'h',
Hour12Long : 'hh',
MinuteShort : 'm',
MinuteLong : 'mm',
SecondShort : 's',
SecondLong : 'ss',
FractionalSecond1 : 'S',
FractionalSecond2 : 'SS',
FractionalSecond3 : 'SSS',
TimeZone : 'Z',
UnixTimestamp : 'X',
MakeLiteral: function(literal: string) {
var reserved = 'MoDdeEwWYgGAaHhmsSzZX';
literal = literal.replaceAll("[", "(").replaceAll("]", ")");
if(indexOfAny(literal, reserved) < 0)
return literal;
return '[' + literal + ']';
},
ReadEscapedPart: function(format: string, startIndex: number) {
if(format.charAt(startIndex) != '[')
return {value: '', length: 0};
var result = '';
var index = startIndex;
while(index < format.length) {
var c = format.charAt(index);
if(c == ']') {
break;
}
result += c;
}
return {
value: result,
length: index - startIndex
}
},
}
export var datepicker : formatRules = {
DayOfMonthShort : 'd',
DayOfMonthLong : 'dd',
DayOfWeekShort : 'D',
DayOfWeekLong : 'DD',
DayOfYearShort : 'o',
DayOfYearLong : 'oo',
MonthOfYearShort : 'm',
MonthOfYearLong : 'mm',
MonthNameShort : 'M',
MonthNameLong : 'MM',
YearShort : 'y',
YearLong : 'yy',
AmPm : null,
Hour24Short : null,
Hour24Long : null,
Hour12Short : null,
Hour12Long : null,
MinuteShort : null,
MinuteLong : null,
SecondShort : null,
SecondLong : null,
FractionalSecond1 : null,
FractionalSecond2 : null,
FractionalSecond3 : null,
TimeZone : null,
UnixTimestamp : '@',
MakeLiteral: function(literal: string) {
var reserved = "dDomMy@'";
if(indexOfAny(literal, reserved) < 0)
return literal;
return "'" + literal.replaceAll("'", "''") + "'";
},
ReadEscapedPart: function(format: string, startIndex: number) {
if(format.charAt(startIndex) != "'")
return {value: '', length: 0};
var result = '';
var index = startIndex;
while(++index < format.length) {
var c = format.charAt(index);
if(c == "'") {
index++;
if(index == format.length)
break;
if(format[index] == "'") {
result += c;
} else {
break;
}
} else {
result += c;
}
}
return {
value: result,
length: index - startIndex
}
},
}
export var timepicker : formatRules = {
DayOfMonthShort : null,
DayOfMonthLong : null,
DayOfWeekShort : null,
DayOfWeekLong : null,
DayOfYearShort : null,
DayOfYearLong : null,
MonthOfYearShort : null,
MonthOfYearLong : null,
MonthNameShort : null,
MonthNameLong : null,
YearShort : null,
YearLong : null,
AmPm : 'TT',
Hour24Short : 'H',
Hour24Long : 'HH',
Hour12Short : 'h',
Hour12Long : 'hh',
MinuteShort : 'm',
MinuteLong : 'mm',
SecondShort : 's',
SecondLong : 'ss',
FractionalSecond1 : null,
FractionalSecond2 : null,
FractionalSecond3 : 'l',
TimeZone : 'Z',
UnixTimestamp : null,
MakeLiteral: function(literal: string) {
var reserved = "HhmslctTzZ'";
if(indexOfAny(literal, reserved) < 0)
return literal;
return "'" + literal.replaceAll("'", '"') + "'";
},
ReadEscapedPart: function(format: string, startIndex: number) {
if(format.charAt(startIndex) != "'")
return {value: '', length: 0};
var result = '';
var index = startIndex;
while(++index < format.length) {
var c = format.charAt(index);
if(c == "'") {
index++;
if(index == format.length)
break;
if(format.charAt(index) == "'")
result += c;
else
break;
} else {
result += c;
}
}
return {
value: result,
length: index - startIndex
}
},
}
}
interface String {
replaceAll(search: string, replacement: string): string;
contains(part: string): boolean;
}
interface Array<T> {
first(callbackfn?: (value: T) => boolean, thisArg?: any): T;
}
JavaScript版本:
var dateFormat;
(function (dateFormat) {
function convert(format, sourceRules, destRules) {
if (sourceRules == destRules)
return format;
var result = '';
var index = 0;
var destTokens = getTokens(destRules);
var sourceMap = getTokenMap(getTokens(sourceRules));
while (index < format.length) {
var part = locateNextToken(sourceRules, format, index);
if (part.literal.length > 0)
result += destRules.MakeLiteral(part.literal);
if (part.token.length > 0)
result += destTokens[sourceMap[part.token]];
index = part.nextBegin;
}
return result;
}
dateFormat.convert = convert;
function locateNextToken(rules, format, begin) {
var literal = '';
var index = begin;
var sequence = getTokenSequence(getTokenMap(getTokens(rules)));
while (index < format.length) {
var escaped = rules.ReadEscapedPart(format, index);
if (escaped.length > 0) {
literal += escaped.value;
index += escaped.length;
continue;
}
var token = sequence.first(function (x) {
return format.indexOf(x, index) == index;
});
if (!token) {
literal += format.charAt(index);
index++;
continue;
}
return {
token: token,
literal: literal,
nextBegin: index + token.length
};
}
return {
token: '',
literal: literal,
nextBegin: index
};
}
function getTokens(rules) {
return [
rules.DayOfMonthShort,
rules.DayOfMonthLong,
rules.DayOfWeekShort,
rules.DayOfWeekLong,
rules.DayOfYearShort,
rules.DayOfYearLong,
rules.MonthOfYearShort,
rules.MonthOfYearLong,
rules.MonthNameShort,
rules.MonthNameLong,
rules.YearShort,
rules.YearLong,
rules.AmPm,
rules.Hour24Short,
rules.Hour24Long,
rules.Hour12Short,
rules.Hour12Long,
rules.MinuteShort,
rules.MinuteLong,
rules.SecondShort,
rules.SecondLong,
rules.FractionalSecond1,
rules.FractionalSecond2,
rules.FractionalSecond3,
rules.TimeZone,
rules.UnixTimestamp
].map(function (x) {
return x || '';
});
}
function getTokenMap(tokens) {
var map = {};
for (var i = 0; i < tokens.length; i++) {
var token = tokens[i];
if (token) {
map[token] = i;
}
}
return map;
}
function getTokenSequence(map) {
var tokens = Object.keys(map);
tokens.sort(function (a, b) {
return b.length - a.length;
});
return tokens;
}
function indexOfAny(s, chars) {
for (var i = 0; i < s.length; i++) {
var c = s.charAt(i);
for (var j = 0; j < chars.length; j++) {
if (c === chars.charAt(j))
return i;
}
}
return -1;
}
dateFormat.standard = {
DayOfMonthShort: 'd',
DayOfMonthLong: 'dd',
DayOfWeekShort: 'ddd',
DayOfWeekLong: 'dddd',
DayOfYearShort: 'D',
DayOfYearLong: 'DD',
MonthOfYearShort: 'M',
MonthOfYearLong: 'MM',
MonthNameShort: 'MMM',
MonthNameLong: 'MMMM',
YearShort: 'yy',
YearLong: 'yyyy',
AmPm: 'tt',
Hour24Short: 'H',
Hour24Long: 'HH',
Hour12Short: 'h',
Hour12Long: 'hh',
MinuteShort: 'm',
MinuteLong: 'mm',
SecondShort: 's',
SecondLong: 'ss',
FractionalSecond1: 'f',
FractionalSecond2: 'ff',
FractionalSecond3: 'fff',
TimeZone: 'Z',
UnixTimestamp: 'X',
MakeLiteral: function (literal) {
var reserved = 'dDMytHhmsfZX';
if (indexOfAny(literal, reserved) < 0)
return literal;
var result = '';
for (var i = 0; i < literal.length; i++) {
var c = literal.charAt(i);
if (reserved.contains(c))
result += '\\';
result += c;
}
return result;
},
ReadEscapedPart: function (format, startIndex) {
var result = '';
var index = startIndex;
while (index < format.length) {
var c = format.charAt(index);
if (c == '\\') {
result += index == format.length - 1 ? '\\' : format[++index];
index++;
continue;
}
break;
}
return {
value: result,
length: index - startIndex
};
}
};
dateFormat.dotNet = {
DayOfMonthShort: 'd',
DayOfMonthLong: 'dd',
DayOfWeekShort: 'ddd',
DayOfWeekLong: 'dddd',
DayOfYearShort: null,
DayOfYearLong: null,
MonthOfYearShort: 'M',
MonthOfYearLong: 'MM',
MonthNameShort: 'MMM',
MonthNameLong: 'MMMM',
YearShort: 'yy',
YearLong: 'yyyy',
AmPm: 'tt',
Hour24Short: 'H',
Hour24Long: 'HH',
Hour12Short: 'h',
Hour12Long: 'hh',
MinuteShort: 'm',
MinuteLong: 'mm',
SecondShort: 's',
SecondLong: 'ss',
FractionalSecond1: 'f',
FractionalSecond2: 'ff',
FractionalSecond3: 'fff',
TimeZone: 'zzz',
UnixTimestamp: null,
MakeLiteral: function (literal) {
var reserved = 'dfFghHKmMstyz\'"';
if (indexOfAny(literal, reserved) < 0)
return literal;
var result = '';
for (var i = 0; i < literal.length; i++) {
var c = literal.charAt(i);
if (reserved.contains(c))
result += '\\';
result += c;
}
return result;
},
ReadEscapedPart: function (format, startIndex) {
var result = '';
var index = startIndex;
while (index < format.length) {
var c = format.charAt(index);
if (c == '\\') {
result += index == format.length - 1 ? '\\' : format[++index];
index++;
continue;
}
if (c == '"') {
while (++index < format.length) {
var cc = format.charAt(index);
if (cc == '"')
break;
if (cc == '\\') {
result += index == format.length - 1 ? '\\' : format[++index];
} else {
result += cc;
}
}
index++;
continue;
}
if (c == "'") {
while (++index < format.length) {
var cc = format.charAt(index);
if (cc == "'")
break;
if (cc == '\\') {
result += index == format.length - 1 ? '\\' : format[++index];
} else {
result += cc;
}
}
index++;
continue;
}
break;
}
return {
value: result,
length: index - startIndex
};
}
};
dateFormat.momentJs = {
DayOfMonthShort: 'D',
DayOfMonthLong: 'DD',
DayOfWeekShort: 'ddd',
DayOfWeekLong: 'dddd',
DayOfYearShort: 'DDD',
DayOfYearLong: 'DDDD',
MonthOfYearShort: 'M',
MonthOfYearLong: 'MM',
MonthNameShort: 'MMM',
MonthNameLong: 'MMMM',
YearShort: 'YY',
YearLong: 'YYYY',
AmPm: 'A',
Hour24Short: 'H',
Hour24Long: 'HH',
Hour12Short: 'h',
Hour12Long: 'hh',
MinuteShort: 'm',
MinuteLong: 'mm',
SecondShort: 's',
SecondLong: 'ss',
FractionalSecond1: 'S',
FractionalSecond2: 'SS',
FractionalSecond3: 'SSS',
TimeZone: 'Z',
UnixTimestamp: 'X',
MakeLiteral: function (literal) {
var reserved = 'MoDdeEwWYgGAaHhmsSzZX';
literal = literal.replaceAll("[", "(").replaceAll("]", ")");
if (indexOfAny(literal, reserved) < 0)
return literal;
return '[' + literal + ']';
},
ReadEscapedPart: function (format, startIndex) {
if (format.charAt(startIndex) != '[')
return { value: '', length: 0 };
var result = '';
var index = startIndex;
while (index < format.length) {
var c = format.charAt(index);
if (c == ']') {
break;
}
result += c;
}
return {
value: result,
length: index - startIndex
};
}
};
dateFormat.datepicker = {
DayOfMonthShort: 'd',
DayOfMonthLong: 'dd',
DayOfWeekShort: 'D',
DayOfWeekLong: 'DD',
DayOfYearShort: 'o',
DayOfYearLong: 'oo',
MonthOfYearShort: 'm',
MonthOfYearLong: 'mm',
MonthNameShort: 'M',
MonthNameLong: 'MM',
YearShort: 'y',
YearLong: 'yy',
AmPm: null,
Hour24Short: null,
Hour24Long: null,
Hour12Short: null,
Hour12Long: null,
MinuteShort: null,
MinuteLong: null,
SecondShort: null,
SecondLong: null,
FractionalSecond1: null,
FractionalSecond2: null,
FractionalSecond3: null,
TimeZone: null,
UnixTimestamp: '@',
MakeLiteral: function (literal) {
var reserved = "dDomMy@'";
if (indexOfAny(literal, reserved) < 0)
return literal;
return "'" + literal.replaceAll("'", "''") + "'";
},
ReadEscapedPart: function (format, startIndex) {
if (format.charAt(startIndex) != "'")
return { value: '', length: 0 };
var result = '';
var index = startIndex;
while (++index < format.length) {
var c = format.charAt(index);
if (c == "'") {
index++;
if (index == format.length)
break;
if (format[index] == "'") {
result += c;
} else {
break;
}
} else {
result += c;
}
}
return {
value: result,
length: index - startIndex
};
}
};
dateFormat.timepicker = {
DayOfMonthShort: null,
DayOfMonthLong: null,
DayOfWeekShort: null,
DayOfWeekLong: null,
DayOfYearShort: null,
DayOfYearLong: null,
MonthOfYearShort: null,
MonthOfYearLong: null,
MonthNameShort: null,
MonthNameLong: null,
YearShort: null,
YearLong: null,
AmPm: 'TT',
Hour24Short: 'H',
Hour24Long: 'HH',
Hour12Short: 'h',
Hour12Long: 'hh',
MinuteShort: 'm',
MinuteLong: 'mm',
SecondShort: 's',
SecondLong: 'ss',
FractionalSecond1: null,
FractionalSecond2: null,
FractionalSecond3: 'l',
TimeZone: 'Z',
UnixTimestamp: null,
MakeLiteral: function (literal) {
var reserved = "HhmslctTzZ'";
if (indexOfAny(literal, reserved) < 0)
return literal;
return "'" + literal.replaceAll("'", '"') + "'";
},
ReadEscapedPart: function (format, startIndex) {
if (format.charAt(startIndex) != "'")
return { value: '', length: 0 };
var result = '';
var index = startIndex;
while (++index < format.length) {
var c = format.charAt(index);
if (c == "'") {
index++;
if (index == format.length)
break;
if (format.charAt(index) == "'")
result += c;
else
break;
} else {
result += c;
}
}
return {
value: result,
length: index - startIndex
};
}
};
})(dateFormat || (dateFormat = {}));
以下是字符串和数组的一些实用方法:
if (!String.prototype.replaceAll) {
String.prototype.replaceAll = function (pattern, replacement) {
return this.split(pattern).join(replacement);
};
}
if (!String.prototype.contains) {
String.prototype.contains = function (part) {
return this.indexOf(part) >= 0;
};
}
if (!Array.prototype.first) {
Array.prototype.first = function (callback) {
if (!callback)
return this.length ? this[0] : null;
for (var i = 0; i < this.length; i++) {
var item = this[i];
if (callback(item)) {
return item;
}
}
return null;
};
}
答案 1 :(得分:1)
我编写了一些代码,可以根据我的要求在这些格式(jQuery UI datepicker,Timepicker,moment.js,DateTime class in.Net)之间进行转换。基本思想是将源格式字符串解析为具有特殊含义的文字和标记,然后根据目标规则生成另一个格式字符串。
我的代码有C#和typescript,你可以使用其中一个或两个。由于大多数其他规则缺乏支持,因此忽略了一些语法,例如moment.js中的一周中的一周,但我认为剩下的内容足以满足我的需求。我还创建了自己的标准规则,我将在未来的项目中坚持使用它,并且只在最后一刻转换为本地格式。如果您不喜欢它,请将其删除。如果需要,您还可以轻松创建其他规则。
C#版本的测试比打字稿版本更多,但我不能说没有任何错误。使用它需要您自担风险。
以下是使用C#版本的方法:
var j = @"literal d dd D DD o oo m mm M MM y yy @' d dd'";
var m = "[literal ]D DD ddd dddd DDD DDDD M MM MMM MMMM YY YYYY X[ d dd]";
Assert.AreEqual(m, DateTimeFormatRules.Convert(j, DateTimeFormatRules.JqueryDatePicker, DateTimeFormatRules.MomentJs));
Assert.AreEqual(j, DateTimeFormatRules.Convert(m, DateTimeFormatRules.MomentJs, DateTimeFormatRules.JqueryDatePicker));
和C#源代码:
/// <summary>
/// <para>Represents a set of date/time formatting rules.</para>
/// <para>Properties could be null if the rule is not supported.</para>
/// </summary>
public abstract class DateTimeFormatRules
{
/// <summary>
/// 1 ~ 31
/// </summary>
public abstract string DayOfMonthShort { get; }
/// <summary>
/// 01 ~ 31
/// </summary>
public abstract string DayOfMonthLong { get; }
/// <summary>
/// Mon ~ Sun
/// </summary>
public abstract string DayOfWeekShort { get; }
/// <summary>
/// Monday ~ Sunday
/// </summary>
public abstract string DayOfWeekLong { get; }
/// <summary>
/// 1 ~ 366
/// </summary>
public abstract string DayOfYearShort { get; }
/// <summary>
/// 001 ~ 366
/// </summary>
public abstract string DayOfYearLong { get; }
/// <summary>
/// 1 ~ 12
/// </summary>
public abstract string MonthOfYearShort { get; }
/// <summary>
/// 01 ~ 12
/// </summary>
public abstract string MonthOfYearLong { get; }
/// <summary>
/// Jan ~ Dec
/// </summary>
public abstract string MonthNameShort { get; }
/// <summary>
/// January ~ December
/// </summary>
public abstract string MonthNameLong { get; }
/// <summary>
/// 00 ~ 99
/// </summary>
public abstract string YearShort { get; }
/// <summary>
/// 0000 ~ 9999
/// </summary>
public abstract string YearLong { get; }
/// <summary>
/// AM ~ PM
/// </summary>
public abstract string AmPm { get; }
/// <summary>
/// 0 ~ 23
/// </summary>
public abstract string Hour24Short { get; }
/// <summary>
/// 00 ~ 23
/// </summary>
public abstract string Hour24Long { get; }
/// <summary>
/// 1 ~ 12
/// </summary>
public abstract string Hour12Short { get; }
/// <summary>
/// 01 ~ 12
/// </summary>
public abstract string Hour12Long { get; }
/// <summary>
/// 0 ~ 59
/// </summary>
public abstract string MinuteShort { get; }
/// <summary>
/// 00 ~ 59
/// </summary>
public abstract string MinuteLong { get; }
/// <summary>
/// 0 ~ 59
/// </summary>
public abstract string SecondShort { get; }
/// <summary>
/// 00 ~ 59
/// </summary>
public abstract string SecondLong { get; }
/// <summary>
/// 0 ~ 9
/// </summary>
public abstract string FractionalSecond1 { get; }
/// <summary>
/// 00 ~ 99
/// </summary>
public abstract string FractionalSecond2 { get; }
/// <summary>
/// 000 ~ 999
/// </summary>
public abstract string FractionalSecond3 { get; }
/// <summary>
/// +08:00
/// </summary>
public abstract string TimeZone { get; }
/// <summary>
/// 1384935963160
/// </summary>
public abstract string UnixTimestamp { get; }
public abstract string MakeLiteral(string literal);
public abstract string ReadEscapedPart(string format, int startIndex, out int length);
public static DateTimeFormatRules Standard
{
get { return StandardDateTimeFormatRules.Instance; }
}
public static DateTimeFormatRules DotNet
{
get { return DotNetDateTimeFormatRules.Instance; }
}
public static DateTimeFormatRules MomentJs
{
get { return MomentJsDateTimeFormatRules.Instance; }
}
public static DateTimeFormatRules JqueryDatePicker
{
get { return JQueryUIDatePickerFormatRules.Instance; }
}
public static DateTimeFormatRules JqueryTimePicker
{
get { return JQueryUITimePickerFormatRules.Instance; }
}
public static string Convert(string format, DateTimeFormatRules sourceRules, DateTimeFormatRules destRules)
{
if (sourceRules == destRules)
return format;
var sb = new StringBuilder(format.Length);
var index = 0;
while (index < format.Length)
{
string literal;
int next;
var token = sourceRules.LocateNextToken(format, index, out next, out literal);
if (literal.Length > 0)
sb.Append(destRules.MakeLiteral(literal));
if (token.Length > 0)
sb.Append(destRules.AllTokens[sourceRules.TokenMap[token]]);
index = next;
}
return sb.ToString();
}
/// <summary>
/// Locate next token in the format string
/// </summary>
/// <param name="format">The input format string</param>
/// <param name="begin">The beginning index in format string to search</param>
/// <param name="nextBegin">where to search next time</param>
/// <param name="literal">literal string before the token</param>
/// <returns>The token, if any; otherwise string.Empty</returns>
private string LocateNextToken(string format, int begin, out int nextBegin, out string literal)
{
var sb = new StringBuilder(format.Length);
var index = begin;
while (index < format.Length)
{
int length;
var escaped = ReadEscapedPart(format, index, out length);
if (length > 0)
{
sb.Append(escaped);
index += length;
continue;
}
var token = TryingSequence
.FirstOrDefault(x => format.IndexOf(x, index, StringComparison.Ordinal) == index);
if (token == null)
{
sb.Append(format[index]);
index++;
continue;
}
nextBegin = index + token.Length;
literal = sb.ToString();
return token;
}
nextBegin = index;
literal = sb.ToString();
return "";
}
private string[] _tokens;
private string[] AllTokens
{
get
{
return _tokens ?? (_tokens = new[]
{
DayOfMonthShort, DayOfMonthLong,
DayOfWeekShort, DayOfWeekLong,
DayOfYearShort, DayOfYearLong,
MonthOfYearShort, MonthOfYearLong,
MonthNameShort, MonthNameLong,
YearShort, YearLong,
AmPm,
Hour24Short, Hour24Long,
Hour12Short, Hour12Long,
MinuteShort, MinuteLong,
SecondShort, SecondLong,
FractionalSecond1, FractionalSecond2, FractionalSecond3,
TimeZone,
UnixTimestamp,
});
}
}
private Dictionary<string, int> _tokenMap;
private Dictionary<string, int> TokenMap
{
get
{
return _tokenMap ?? (_tokenMap = AllTokens
.Select((token, index) => new
{
index,
token,
})
.Where(x => x.token != null)
.ToDictionary(x => x.token, x => x.index));
}
}
private string[] _tryingSequence;
private string[] TryingSequence
{
get
{
return _tryingSequence ?? (_tryingSequence = TokenMap.Keys
.OrderByDescending(x => x.Length)
.ToArray());
}
}
}
/// <summary>
/// My own standard date time format rules
/// </summary>
internal class StandardDateTimeFormatRules : DateTimeFormatRules
{
private StandardDateTimeFormatRules()
{
}
public static StandardDateTimeFormatRules Instance = new StandardDateTimeFormatRules();
public override string DayOfMonthShort
{
get { return "d"; }
}
public override string DayOfMonthLong
{
get { return "dd"; }
}
public override string DayOfWeekShort
{
get { return "ddd"; }
}
public override string DayOfWeekLong
{
get { return "dddd"; }
}
public override string DayOfYearShort
{
get { return "D"; }
}
public override string DayOfYearLong
{
get { return "DD"; }
}
public override string MonthOfYearShort
{
get { return "M"; }
}
public override string MonthOfYearLong
{
get { return "MM"; }
}
public override string MonthNameShort
{
get { return "MMM"; }
}
public override string MonthNameLong
{
get { return "MMMM"; }
}
public override string YearShort
{
get { return "yy"; }
}
public override string YearLong
{
get { return "yyyy"; }
}
public override string AmPm
{
get { return "tt"; }
}
public override string Hour24Short
{
get { return "H"; }
}
public override string Hour24Long
{
get { return "HH"; }
}
public override string Hour12Short
{
get { return "h"; }
}
public override string Hour12Long
{
get { return "hh"; }
}
public override string MinuteShort
{
get { return "m"; }
}
public override string MinuteLong
{
get { return "mm"; }
}
public override string SecondShort
{
get { return "s"; }
}
public override string SecondLong
{
get { return "ss"; }
}
public override string FractionalSecond1
{
get { return "f"; }
}
public override string FractionalSecond2
{
get { return "ff"; }
}
public override string FractionalSecond3
{
get { return "fff"; }
}
public override string TimeZone
{
get { return "Z"; }
}
public override string UnixTimestamp
{
get { return "X"; }
}
public char[] ReservedChars
{
get { return "dDMytHhmsfZX\\".ToCharArray(); }
}
public override string MakeLiteral(string literal)
{
if (literal.IndexOfAny(ReservedChars) < 0)
return literal;
var sb = new StringBuilder(literal.Length * 2);
foreach (char c in literal)
{
if (ReservedChars.Contains(c))
sb.Append('\\');
sb.Append(c);
}
return sb.ToString();
}
public override string ReadEscapedPart(string format, int startIndex, out int length)
{
var sb = new StringBuilder();
var index = startIndex;
while (index < format.Length)
{
var c = format[index];
if (c == '\\')
{
sb.Append(index == format.Length - 1 ? '\\' : format[++index]);
index++;
continue;
}
break;
}
length = index - startIndex;
return sb.ToString();
}
}
/// <summary>
/// Formating rules for .net DateTime.ToString(format)
/// </summary>
internal class DotNetDateTimeFormatRules : DateTimeFormatRules
{
private DotNetDateTimeFormatRules()
{
}
public static DotNetDateTimeFormatRules Instance = new DotNetDateTimeFormatRules();
public override string DayOfMonthShort
{
get { return "d"; }
}
public override string DayOfMonthLong
{
get { return "dd"; }
}
public override string DayOfWeekShort
{
get { return "ddd"; }
}
public override string DayOfWeekLong
{
get { return "dddd"; }
}
public override string DayOfYearShort
{
get { return null; }
}
public override string DayOfYearLong
{
get { return null; }
}
public override string MonthOfYearShort
{
get { return "M"; }
}
public override string MonthOfYearLong
{
get { return "MM"; }
}
public override string MonthNameShort
{
get { return "MMM"; }
}
public override string MonthNameLong
{
get { return "MMMM"; }
}
public override string YearShort
{
get { return "yy"; }
}
public override string YearLong
{
get { return "yyyy"; }
}
public override string AmPm
{
get { return "tt"; }
}
public override string Hour24Short
{
get { return "H"; }
}
public override string Hour24Long
{
get { return "HH"; }
}
public override string Hour12Short
{
get { return "h"; }
}
public override string Hour12Long
{
get { return "hh"; }
}
public override string MinuteShort
{
get { return "m"; }
}
public override string MinuteLong
{
get { return "mm"; }
}
public override string SecondShort
{
get { return "s"; }
}
public override string SecondLong
{
get { return "ss"; }
}
public override string FractionalSecond1
{
get { return "f"; }
}
public override string FractionalSecond2
{
get { return "ff"; }
}
public override string FractionalSecond3
{
get { return "fff"; }
}
public override string TimeZone
{
get { return "zzz"; }
}
public override string UnixTimestamp
{
get { return null; }
}
public char[] ReservedChars
{
get { return "dfFghHKmMstyz'\"".ToCharArray(); }
}
public override string MakeLiteral(string literal)
{
if (literal.IndexOfAny(ReservedChars) < 0)
return literal;
var sb = new StringBuilder(literal.Length * 2);
foreach (char c in literal)
{
if (ReservedChars.Contains(c))
sb.Append('\\');
sb.Append(c);
}
return sb.ToString();
}
public override string ReadEscapedPart(string format, int startIndex, out int length)
{
var sb = new StringBuilder();
var index = startIndex;
while (index < format.Length)
{
var c = format[index];
if (c == '\\')
{
sb.Append(index == format.Length - 1 ? '\\' : format[++index]);
index++;
continue;
}
if (c == '"')
{
while (++index < format.Length)
{
var cc = format[index];
if (cc == '"')
break;
if (cc == '\\')
{
sb.Append(index == format.Length - 1 ? '\\' : format[++index]);
}
else
{
sb.Append(cc);
}
}
index++;
continue;
}
if (c == '\'')
{
while (++index < format.Length)
{
var cc = format[index];
if (cc == '\'')
break;
if (cc == '\\')
{
sb.Append(index == format.Length - 1 ? '\\' : format[++index]);
}
else
{
sb.Append(cc);
}
}
index++;
continue;
}
break;
}
length = index - startIndex;
return sb.ToString();
}
}
internal class MomentJsDateTimeFormatRules : DateTimeFormatRules
{
private MomentJsDateTimeFormatRules()
{
}
public static MomentJsDateTimeFormatRules Instance = new MomentJsDateTimeFormatRules();
public override string DayOfMonthShort
{
get { return "D"; }
}
public override string DayOfMonthLong
{
get { return "DD"; }
}
public override string DayOfWeekShort
{
get { return "ddd"; }
}
public override string DayOfWeekLong
{
get { return "dddd"; }
}
public override string DayOfYearShort
{
get { return "DDD"; }
}
public override string DayOfYearLong
{
get { return "DDDD"; }
}
public override string MonthOfYearShort
{
get { return "M"; }
}
public override string MonthOfYearLong
{
get { return "MM"; }
}
public override string MonthNameShort
{
get { return "MMM"; }
}
public override string MonthNameLong
{
get { return "MMMM"; }
}
public override string YearShort
{
get { return "YY"; }
}
public override string YearLong
{
get { return "YYYY"; }
}
public override string AmPm
{
get { return "A"; }
}
public override string Hour24Short
{
get { return "H"; }
}
public override string Hour24Long
{
get { return "HH"; }
}
public override string Hour12Short
{
get { return "h"; }
}
public override string Hour12Long
{
get { return "hh"; }
}
public override string MinuteShort
{
get { return "m"; }
}
public override string MinuteLong
{
get { return "mm"; }
}
public override string SecondShort
{
get { return "s"; }
}
public override string SecondLong
{
get { return "ss"; }
}
public override string FractionalSecond1
{
get { return "S"; }
}
public override string FractionalSecond2
{
get { return "SS"; }
}
public override string FractionalSecond3
{
get { return "SSS"; }
}
public override string TimeZone
{
get { return "Z"; }
}
public override string UnixTimestamp
{
get { return "X"; }
}
public char[] ReservedChars
{
get { return "MoDdeEwWYgGAaHhmsSzZX".ToCharArray(); }
}
public override string MakeLiteral(string literal)
{
literal = literal.Replace("[", "(").Replace("]", ")");
if (literal.IndexOfAny(ReservedChars) < 0)
return literal;
return '[' + literal + ']';
}
public override string ReadEscapedPart(string format, int startIndex, out int length)
{
if (format[startIndex] != '[')
{
length = 0;
return "";
}
var sb = new StringBuilder();
var index = startIndex + 1;
while (index < format.Length)
{
var c = format[index++];
if (c == ']')
break;
sb.Append(c);
}
length = index - startIndex;
return sb.ToString();
}
}
internal class JQueryUIDatePickerFormatRules : DateTimeFormatRules
{
private JQueryUIDatePickerFormatRules()
{
}
public static JQueryUIDatePickerFormatRules Instance = new JQueryUIDatePickerFormatRules();
public override string DayOfMonthShort
{
get { return "d"; }
}
public override string DayOfMonthLong
{
get { return "dd"; }
}
public override string DayOfWeekShort
{
get { return "D"; }
}
public override string DayOfWeekLong
{
get { return "DD"; }
}
public override string DayOfYearShort
{
get { return "o"; }
}
public override string DayOfYearLong
{
get { return "oo"; }
}
public override string MonthOfYearShort
{
get { return "m"; }
}
public override string MonthOfYearLong
{
get { return "mm"; }
}
public override string MonthNameShort
{
get { return "M"; }
}
public override string MonthNameLong
{
get { return "MM"; }
}
public override string YearShort
{
get { return "y"; }
}
public override string YearLong
{
get { return "yy"; }
}
public override string AmPm
{
get { return null; }
}
public override string Hour24Short
{
get { return null; }
}
public override string Hour24Long
{
get { return null; }
}
public override string Hour12Short
{
get { return null; }
}
public override string Hour12Long
{
get { return null; }
}
public override string MinuteShort
{
get { return null; }
}
public override string MinuteLong
{
get { return null; }
}
public override string SecondShort
{
get { return null; }
}
public override string SecondLong
{
get { return null; }
}
public override string FractionalSecond1
{
get { return null; }
}
public override string FractionalSecond2
{
get { return null; }
}
public override string FractionalSecond3
{
get { return null; }
}
public override string TimeZone
{
get { return null; }
}
public override string UnixTimestamp
{
get { return "@"; }
}
public char[] ReservedChars
{
get { return "dDomMy@'".ToCharArray(); }
}
public override string MakeLiteral(string literal)
{
if (literal.IndexOfAny(ReservedChars) < 0)
return literal;
return "'" + literal.Replace("'", "''") + "'";
}
public override string ReadEscapedPart(string format, int startIndex, out int length)
{
if (format[startIndex] != '\'')
{
length = 0;
return "";
}
var sb = new StringBuilder();
var index = startIndex;
while (++index < format.Length)
{
var c = format[index];
if (c == '\'')
{
index++;
if (index == format.Length)
{
break;
}
if (format[index] == '\'')
{
sb.Append(c);
}
else
{
break;
}
}
else
{
sb.Append(c);
}
}
length = index - startIndex;
return sb.ToString();
}
}
/// <summary>
/// <para>Formating rules for jQuery UI datepicker.</para>
/// <para>The time part is for timepicker (http://trentrichardson.com/examples/timepicker/)</para>
/// </summary>
internal class JQueryUITimePickerFormatRules : DateTimeFormatRules
{
private JQueryUITimePickerFormatRules()
{
}
public static JQueryUITimePickerFormatRules Instance = new JQueryUITimePickerFormatRules();
public override string DayOfMonthShort
{
get { return null; }
}
public override string DayOfMonthLong
{
get { return null; }
}
public override string DayOfWeekShort
{
get { return null; }
}
public override string DayOfWeekLong
{
get { return null; }
}
public override string DayOfYearShort
{
get { return null; }
}
public override string DayOfYearLong
{
get { return null; }
}
public override string MonthOfYearShort
{
get { return null; }
}
public override string MonthOfYearLong
{
get { return null; }
}
public override string MonthNameShort
{
get { return null; }
}
public override string MonthNameLong
{
get { return null; }
}
public override string YearShort
{
get { return null; }
}
public override string YearLong
{
get { return null; }
}
public override string AmPm
{
get { return "TT"; }
}
public override string Hour24Short
{
get { return "H"; }
}
public override string Hour24Long
{
get { return "HH"; }
}
public override string Hour12Short
{
get { return "h"; }
}
public override string Hour12Long
{
get { return "hh"; }
}
public override string MinuteShort
{
get { return "m"; }
}
public override string MinuteLong
{
get { return "mm"; }
}
public override string SecondShort
{
get { return "s"; }
}
public override string SecondLong
{
get { return "ss"; }
}
public override string FractionalSecond1
{
get { return null; }
}
public override string FractionalSecond2
{
get { return null; }
}
public override string FractionalSecond3
{
get { return "l"; }
}
public override string TimeZone
{
get { return "Z"; }
}
public override string UnixTimestamp
{
get { return null; }
}
public char[] ReservedChars
{
get { return "HhmslctTzZ'".ToCharArray(); }
}
public override string MakeLiteral(string literal)
{
if (literal.IndexOfAny(ReservedChars) < 0)
return literal;
return "'" + literal.Replace("'", "''") + "'";
}
public override string ReadEscapedPart(string format, int startIndex, out int length)
{
if (format[startIndex] != '\'')
{
length = 0;
return "";
}
var sb = new StringBuilder();
var index = startIndex;
while (++index < format.Length)
{
var c = format[index];
if (c == '\'')
{
index++;
if (index == format.Length)
{
break;
}
if (format[index] == '\'')
{
sb.Append(c);
}
else
{
break;
}
}
else
{
sb.Append(c);
}
}
length = index - startIndex;
return sb.ToString();
}
}