没有时间的Moment.calendar()

moment.calendar() without the time

本文关键字:calendar Moment 没有时间      更新时间:2023-09-26

我想使用moment.calendar()选项而不包含时间…所以与其"上周二下午5点"我想要"上周二"。有人知道moment现在是否有解决方案吗?我发现这个小提琴http://jsfiddle.net/nawxZ/,这显然显示了一个解决方案,但我看不出这是如何工作的?谢谢卡尔

function log(str) {
    $('body').append('<p>' + str + '</p>');
}
log(moment().calendar());
log(moment().calendar(true));

从第2.10.5分钟开始,你可以做:

moment(/*your date*/).calendar(null,{
    lastDay : '[Yesterday]',
    sameDay : '[Today]',
    nextDay : '[Tomorrow]',
    lastWeek : '[last] dddd',
    nextWeek : 'dddd',
    sameElse : 'L'
})

参见:http://momentjs.com/docs/#/displaying/calendar-time/

moment().calendar()支持自定义格式化字符串和格式化函数。

moment().calendar();
>> "Today at 9:06 AM"

然后设置你的格式化字符串

moment.locale('yourlang', {
    calendar: {
        lastDay: function () {
            return '[last]';
        },
        sameDay: function () {
            return '[Today]';
        }
    }
});
moment().calendar();
// Will now output
>> "Today"

就可以了。文档是非常宝贵的资源

效果很好。试试。

(时刻(时间).calendar()。分裂("的")[0]

从Moment 2.25.0开始,现在可以调用 Moment .calendar(formats)而不需要参考时间值

https://momentjs.com/docs//显示/日历时间/

此代码部分工作。问题在于将单词at[Today at]分开。

在下面的示例中,(在英语中表示at)是结果的一部分。

moment().locale()
// "es"
moment().calendar(null, {
    sameDay: function (now) {
        var sameDay = now._locale._calendar.sameDay
        if (typeof sameDay === 'function') {
            sameDay = sameDay.call(this)
        }
        return sameDay.replace(' LT', '')
    }
})
// "hoy a las"

如果翻译是"[Today] [at] LL",我们将能够分离单词at

我也有同样的需求,不幸的是这目前不支持(版本2.24.0)。

如果您查看任意语言文件,如en-gb.js,您可以看到所有日历变体都包含时间。
没有办法遗漏时间。这就需要一个没有每种语言时间的日历变体。

我创建了一个angular指令,它提供了一个只有日期的日历。如果不用angular,就用函数。

 app.filter('amCalendarDate', function($translate) {
    return function(dt) {
        var md = moment(dt), key = '';
        if (!dt || !md || (md + '').toLowerCase() == 'invalid date')
            return '';
        var today = moment();
        var diff = today.diff(md, 'days');
        if (!diff)
            key = 'Today';
        else if (diff == -1)
            key = 'Tomorrow';
        else if (diff == 1)
            key = 'Yesterday';
        else if (Math.abs(diff) <= 6) {
            if (diff < 0)
                key = 'Next';
            else
                key = 'Last';
            var days = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
            today.day(diff);
            key += ' ' + days[today.day()];
        }
        if (key) {
            // if you don't have translate, just return the key
            return $translate.amCalendarDate[key];
        } else
            return md.format('L');
    }
});

如果您没有自定义时间设置,并且只在一天的基础上工作,您可以使用这个简单的多语言(针对EN/DE/FR/IT进行了测试)解决方案。(整天总是用00:00时间标签保存)

let dateParts = moment(DATE).calendar().split(' '),
    index = dateParts.indexOf('00:00');
// ['Yesterday', 'at', '00:00', 'PM'] -> ['Yesterday']
dateParts.length = (index !== -1 ? (index - 1) : dateParts.length);

假设moment.js区域设置不会改变,我为moment().calendar()编写了一个简单的包装函数,用于我使用的以下语言:

en、ar、bg、cs、da、de、el、es、et、fi、fr-ca、fr、he、hr、hu、hy-am、it、ja、kk、ko、lt、nl、nb、pl、pt、ro、ru、sk、sl、sr、sv、th、tr、uk、vi、zh-cn、zh-tw

您可以根据需要在switch语句中添加新的或删除现有的用例,它应该仍然可以正常工作。

const timeRegExp = /[0-9:,]/g;
const dateRegExp = /[0-9.-/]/g;
const removeLastNWords = (str, n, separator) => {
  return `${str.split(' ').splice(0, n).join(separator)}`;
}
const removeDigitsAndTimeChars = (str) => {
  return `${str.replace(timeRegExp, '').trimEnd()}`;
}
const removeLastNWordsStripped = (str, n, separator) => {
  return removeDigitsAndTimeChars(removeLastNWords(str, n, separator));
}
const calendarNoTime = (inp, strict) => {
  const originalCalendarDate = moment(inp, strict).calendar();
  const parts = originalCalendarDate.split(' ');
    
  /**
   * Most languages use the 'L' format for calendar: { sameElse },
   * these have parts of length 1. zh-cn does not use a space to separate 
   * the time from the date, so remove it if present otherwise keep 
   * the 'L' format. If `cn` not needed, simply return parts[0]. 
   * `sr/sl` uses spaces to separate day, month, year.  
   * 
   */
  if (parts.length === 1 || dateRegExp.test(parts[0])) {
    return parts[0].includes(':') ? removeDigitsAndTimeChars(parts[0]) : parts.join(' ');
  }
  switch (moment.locale()) {
    /**
     * These languages have a preposition with a length of < 3 
     * before the time. Find that preposition and keep the words
     * till that preposition. If `ru` not needed,
     * use removeLastNWords(originalCalendarDate, prepositionIndex, ' ')
     * 
     */
    case 'bg':
    case 'cs':
    case 'de':
    case 'es':
    case 'en':
    case 'fr':
    case 'fr-ca':
    case 'hr':
    case 'nl':
    case 'pl':
    case 'pt':
    case 'ro':
    case 'ru':
    case 'sk':
    case 'sl':
    case 'sr':
    case 'uk':
      const prepositionIndex = parts.findIndex((part, i) => i !== 0 && part.length < 3);
      return removeLastNWordsStripped(originalCalendarDate, prepositionIndex, ' ');
      /**
       * Less strict than the above, these languages put their preposition at
       * next to last index inside the `parts` array to every wording.
       * 
       */
    case 'da':
    case 'fi':
    case 'it':
    case 'kk':
    case 'nb':
    case 'th':
    case 'vi':
      return removeLastNWords(originalCalendarDate, parts.length - 2, ' ');
      // Uses [dddd, XX:XX] format, remove digits and special characters
    case 'et':
    case 'ja':
    case 'ko':
    case 'lt':
    case 'sv':
    case 'zh-tw':
    case 'zh-cn':
      return removeDigitsAndTimeChars(originalCalendarDate);
      // Same as above expect the preposition is at parts.length - 3
    case 'el':
      return removeLastNWords(originalCalendarDate, parts.length - 3, ' ');
      // Same as above + [dddd LT] format for some days
    case 'hy-am':
      return parts.length < 3 ? parts[0] : removeLastNWords(originalCalendarDate, parts.length - 3, ' ');
      // Same as above, preposition is at parts.length - 2
    case 'tr':
      return parts.length < 3 ? parts[0] : removeLastNWords(originalCalendarDate, parts.length - 2, ' ');
      // Appends `kor` to time, remove the word that contains this substring
    case 'hu':
      return originalCalendarDate.replace(/ *'b'S*?kor'S*'b/g, '');
      // Custom formats 
      // https://momentjs.com/docs/#/displaying/calendar-time/
    case 'ar':
      return moment(inp).calendar({
        sameDay: '[اليوم]',
        nextDay: '[غدًا]',
        nextWeek: 'dddd',
        lastDay: '[أمس]',
        lastWeek: 'dddd',
        sameElse: 'L',
      });
    case 'he':
      return moment(inp).calendar({
        sameDay: '[היום]',
        nextDay: '[מחר]',
        nextWeek: 'dddd',
        lastDay: '[אתמול]',
        lastWeek: 'dddd',
        sameElse: 'L',
      });
      // Unsupported language, use default format with time
    default:
      return originalCalendarDate;
  }
}

const today = new Date();
const yesterday = (new Date()).setDate((new Date()).getDate() - 1);
const coupleDaysAgo = (new Date()).setDate((new Date()).getDate() - 2);
const fewDaysAgo = (new Date()).setDate((new Date()).getDate() - 4);
const manyDaysAgo = (new Date()).setDate((new Date()).getDate() - 7);
const supportedLanguages = ['en', 'ar', 'bg', 'cs', 'da', 'de', 'el', 'es', 'et', 'fi', 'fr-ca', 'fr', 'he', 'hr', 'hu', 'hy-am', 'it', 'ja', 'kk', 'ko', 'lt', 'nl', 'nb', 'pl', 'pt', 'ro', 'ru', 'sk', 'sl', 'sr', 'sv', 'th', 'tr', 'uk', 'vi', 'zh-cn', 'zh-tw'];
let allDays = [];
supportedLanguages.forEach((lang) => {
  moment.locale(lang);
  allDays = [calendarNoTime(today), calendarNoTime(yesterday), calendarNoTime(coupleDaysAgo), calendarNoTime(fewDaysAgo), calendarNoTime(manyDaysAgo)];
  document.write(`${lang}: `);
  document.write(allDays.join(', '));
  document.write('</br>');
});

对于TypeScript爱好者:

const removeLastNWords = (str: string, n: number, separator: string): string => {}
const removeDigitsAndDateChars = (str: string): string => {}
const removeLastNWordsStripped = (str: string, n: number, separator: string): string => {}
const calendarNoTime = (inp?: moment.MomentInput, strict?: boolean): string => {}

小提琴

编辑1
修正了、sr、sl语言。更新小提琴显示所有支持的语言日期。