如何在jquery ui datepicker和moment.js使用的日期格式之间进行转换?

时间:2013-11-20 16:36:44

标签: javascript .net typescript jquery-ui-datepicker momentjs

日期格式化字符串在jQuery UI datepicker,moment.js,.Net的DateTime类中有不同的规则。如何在这些不同的格式之间进行转换?

更新:现在在github上:https://github.com/deerchao/dateformats

2 个答案:

答案 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 datepickerTimepickermoment.jsDateTime 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();
    }
}