如何缩短开关案例块将数字转换为月份名称?

Leo*_*ban 110 javascript date date-format switch-statement

有没有办法在更少的行上写这个,但仍然容易阅读?

var month = '';

switch(mm) {
    case '1':
        month = 'January';
        break;
    case '2':
        month = 'February';
        break;
    case '3':
        month = 'March';
        break;
    case '4':
        month = 'April';
        break;
    case '5':
        month = 'May';
        break;
    case '6':
        month = 'June';
        break;
    case '7':
        month = 'July';
        break;
    case '8':
        month = 'August';
        break;
    case '9':
        month = 'September';
        break;
    case '10':
        month = 'October';
        break;
    case '11':
        month = 'November';
        break;
    case '12':
        month = 'December';
        break;
}
Run Code Online (Sandbox Code Playgroud)

xda*_*azz 198

定义一个数组,然后按索引获取.

var months = ['January', 'February', ...];

var month = months[mm - 1] || '';
Run Code Online (Sandbox Code Playgroud)

  • @ mpez0我想我更愿意知道有人设法提出了第15个月,而不是隐藏可能不好的数据 (77认同)
  • @Touffy我认为这不是品味问题,而是[避免聪明的代码](http://programmers.stackexchange.com/questions/91854/how-to-train-yourself-to-avoid-writing-聪明代码).想象一下你自己在读一些其他的'[undefined,'January','February',...]` - 我最好你的第一反应是_WTF?!_,这通常不是一个好兆头...... (48认同)
  • 你可以将`undefined`设置为第一个值(索引0)而不是'mm - 1`,这样数组索引就会匹配月数 (23认同)
  • @Touffy我想我会坚持使用`mm-1`,所以'months.length == 12`. (21认同)
  • `var month = month [(mm -1)%12]` (9认同)
  • @izkata翻译我25年时间系列的第200个月,模数运作良好. (2认同)

vid*_*uch 81

怎么样不使用数组:)

var objDate = new Date("10/11/2009"),
    locale = "en-us",
    month = objDate.toLocaleString(locale, { month: "long" });

console.log(month);

// or if you want the shorter date: (also possible to use "narrow" for "O"
console.log(objDate.toLocaleString(locale, { month: "short" }));
Run Code Online (Sandbox Code Playgroud)

根据这个答案从David Storey 获取Date的月份名称

  • 只保证``new Date("2009-11-10")``格式被解析(参见本规范:http://www.ecma-international.org/publications/standards/Ecma-262.htm).如果浏览器选择了其他日期格式(包括您的答案中的一个),则可以解析,因此不可移植. (6认同)
  • 请记住包含支持IE <11的代码 (3认同)
  • 鉴于问题陈述的问题,你的答案并不是真正解决这个问题,而是在不同的背景下可能是正确的一些不同的解决方案.选择的答案仍然是最好和最有效的. (2认同)

But*_*ass 58

试试这个:

var months = {'1': 'January', '2': 'February'}; //etc
var month = months[mm];
Run Code Online (Sandbox Code Playgroud)

请注意,它mm可以是整数或字符串,它仍然可以工作.

如果您希望不存在的键导致空字符串''(而不是undefined),则添加以下行:

month = (month == undefined) ? '' : month;
Run Code Online (Sandbox Code Playgroud)

JSFiddle.

  • 在比"一年中的几个月"更大的数据集上,这可能会更有效. (4认同)
  • 这实际上是一个枚举(即使其不可变),将其定义为`var months = Object.freeze({'1':'January','2':'February'}); //等.请参阅[JavaScript中的枚举?](http://stackoverflow.com/a/5040502/1796930) (3认同)

Ale*_*lex 26

您可以改为创建一个数组并查找月份名称:

var months = ['January','February','March','April','May','June','July','August','September','October','November','December']


var month = months[mm-1] || '';
Run Code Online (Sandbox Code Playgroud)

请参阅@CupawnTae的答案,了解代码背后的理性 || ''


Cup*_*Tae 19

小心!

应立即触发警钟的事情是第一行:var month = '';- 为什么这个变量被初始化为空字符串,而不是nullundefined?它可能只是习惯或复制/粘贴代码,但除非您确切知道,否则在您重构代码时忽略它是不安全的.

如果您使用月份名称数组并将代码更改为var month = months[mm-1];您正在更改行为,因为现在对于范围之外的数字或非数字值month将是undefined.你可能知道这没关系,但是在很多情况下这会很糟糕.

例如,假设你switch在一个函数中monthToName(mm),有人正在调用你的函数:

var monthName = monthToName(mm);

if (monthName === '') {
  alert("Please enter a valid month.");
} else {
  submitMonth(monthName);
}
Run Code Online (Sandbox Code Playgroud)

现在,如果您更改为使用数组并返回monthName[mm-1],则调用代码将不再按预期运行,并且它将undefined在应该显示警告时提交值.我不是说这是好的代码,但除非您确切知道代码的使用方式,否则您无法做出假设.

或许原始的初始化就在那里,因为一些代码进一步假定它month总是一个字符串,并做类似的事情month.length- 这将导致异常被抛出无效月份并可能完全杀死调用脚本.

如果您确实知道整个上下文 - 例如,它是您自己的所有代码,并且没有其他人会使用它,并且您相信自己不会忘记您在将来的某个时间进行了更改 - 更改行为可能是安全的像这样,但是很多错误来自于这种假设,即在现实生活中,你在防御性编程和/或彻底记录行为方面要好得多.

Wasmoo的答案是正确的(编辑:其他一些答案,包括已接受的答案,现在已经修复) - 您可以使用months[mm-1] || ''或者如果您希望一目了然地发现它正在发生什么,例如:

var months = ['January', 'February', ...];

var month;

if (mm >= 1 && m <= 12) {
  month = months[mm - 1];
} else {
  month = ''; // empty string when not a valid month
}
Run Code Online (Sandbox Code Playgroud)

  • @LeonGaban它不是关于性能:原始问题将变量初始化为空字符串,如果没有选择有效月份则将其保留在该字符串,而此处的许多其他答案忽略了该事实并通过返回"undefined"来改变行为输入不是"1..12".除了非常特殊的情况外,正确的行为每次都会超过性能. (2认同)

Ger*_*ard 17

为了完整性,我想补充目前的答案.基本上,您可以省略break关键字并直接返回适当的值.如果值无法存储在预先计算的查找表中,则此策略很有用.

function foo(mm) {
    switch(mm) {
        case '1':  return 'January';
        case '2':  return 'February';
        case '3':  return 'March';
        case '4':  return 'April';
        // [...]
        case '12': return 'December';
    }
    return '';
}
Run Code Online (Sandbox Code Playgroud)

再一次,使用查找表或日期函数更简洁,主观上更好.


Stu*_*ner 16

你可以使用数组来做到这一点:

var months = ['January', 'February', 'March', 'April', 
              'May', 'June', 'July', 'August', 
              'September', 'October', 'November', 'December'];

var month = months[mm - 1] || '';
Run Code Online (Sandbox Code Playgroud)


Was*_*moo 12

这是另一个仅使用1个变量的选项,''mm超出范围时仍然应用默认值.

var month = ['January', 'February', 'March',
             'April', 'May', 'June', 'July',
             'August', 'September', 'October',
             'November', 'December'
            ][mm-1] || '';
Run Code Online (Sandbox Code Playgroud)


Guf*_*ffa 9

您可以使用条件运算符将其写为表达式而不是开关:

var month =
  mm == 1 ? 'January' :
  mm == 2 ? 'February' :
  mm == 3 ? 'March' :
  mm == 4 ? 'April' :
  mm == 5 ? 'May' :
  mm == 6 ? 'June' :
  mm == 7 ? 'July' :
  mm == 8 ? 'August' :
  mm == 9 ? 'September' :
  mm == 10 ? 'October' :
  mm == 11 ? 'November' :
  mm == 12 ? 'December' :
  '';
Run Code Online (Sandbox Code Playgroud)

如果您之前没有看到链式条件运算符,那么最初可能看起来更难以阅读.将其作为表达式编写使得一个方面比原始代码更容易看到; 很明显,代码的意图是为变量赋值month.


小智 6

Cupawn Tae回答之前,我将其简化为:

var months = ['January', 'February', ...];
var month = (mm >= 1 && mm <= 12) ? months[mm - 1] : '';
Run Code Online (Sandbox Code Playgroud)

或者,是的,我欣赏,不太可读:

var month = months[mm - 1] || ''; // as mentioned further up
Run Code Online (Sandbox Code Playgroud)


Dir*_*irk 5

和 @vidriduch 一样,我想强调代码的 i20y(“国际化”)在当今环境中的重要性,并建议以下简洁而强大的解决方案以及统一测试。

function num2month(month, locale) {
    if (month != Math.floor(month) || month < 1 || month > 12)
        return undefined;
    var objDate = new Date(Math.floor(month) + "/1/1970");
    return objDate.toLocaleString(locale, {month: "long"});
}

/* Test/demo */
for (mm = 1; mm <= 12; mm++)
    document.writeln(num2month(mm, "en") + " " +
                     num2month(mm, "ar-lb") + "<br/>");
document.writeln(num2month("x", "en") + "<br/>");
document.writeln(num2month(.1, "en") + "<br/>");
document.writeln(num2month(12.5, "en" + "<br/>"));
Run Code Online (Sandbox Code Playgroud)

我尝试尽可能接近原始问题,即将数字 1 到 12 转换为月份名称,不仅针对一种特殊情况,而且undefined在参数无效的情况下返回,使用一些以前添加的批评和其他内容答案。(如果需要精确undefined匹配,从到 的更改是微不足道的。)''