在Javascript中使用时间跨度



已经在使用Date.js了,但必要时也可以使用其他库。

不确定处理时间增量的最佳方法是什么。具体来说,我想要显示从现在到过去日期时间之间所经过的时间。

所以我需要这样做:

var elapsed_time = new Date() - pastDate;
pastDate.toString('days-hours-minutes-seconds');

得到它的大部分工作使用Date.js,但问题是现在我正在使用一个日期对象,而不是一个时间跨度,所以什么应该是一个23小时的时间跨度,而不是23小时后的日期的第一次:

<>之前var result = (new Date()) - past_date;"result"是数字(可能是毫秒):15452732之前<>之前var result = (new Date() - past_date . var"result"是1969年的日期:Wed Dec 31 1969 23:17:32之前

我需要的是:

<>之前0天23小时17分32秒之前

任何想法?

听起来你需要moment.js

moment().subtract('days', 6).calendar();

=>上周日晚上8:23

moment().startOf('hour').fromNow();

=> 26 minutes ago

编辑:

纯JS日期差异计算:

var date1 = new Date("7/Nov/2012 20:30:00");
var date2 = new Date("20/Nov/2012 19:15:00");
var diff = date2.getTime() - date1.getTime();
var days = Math.floor(diff / (1000 * 60 * 60 * 24));
diff -=  days * (1000 * 60 * 60 * 24);
var hours = Math.floor(diff / (1000 * 60 * 60));
diff -= hours * (1000 * 60 * 60);
var mins = Math.floor(diff / (1000 * 60));
diff -= mins * (1000 * 60);
var seconds = Math.floor(diff / (1000));
diff -= seconds * (1000);
document.write(days + " days, " + hours + " hours, " + mins + " minutes, " + seconds + " seconds");

如果你不太担心几天后的准确性,你可以简单地做数学

function timeSince(when) { // this ignores months
    var obj = {};
    obj._milliseconds = (new Date()).valueOf() - when.valueOf();
    obj.milliseconds = obj._milliseconds % 1000;
    obj._seconds = (obj._milliseconds - obj.milliseconds) / 1000;
    obj.seconds = obj._seconds % 60;
    obj._minutes = (obj._seconds - obj.seconds) / 60;
    obj.minutes = obj._minutes % 60;
    obj._hours = (obj._minutes - obj.minutes) / 60;
    obj.hours = obj._hours % 24;
    obj._days = (obj._hours - obj.hours) / 24;
    obj.days = obj._days % 365;
    // finally
    obj.years = (obj._days - obj.days) / 365;
    return obj;
}

然后是timeSince(pastDate);,并使用您喜欢的属性。

否则您可以使用.getUTC*来计算它,但请注意,计算

可能会稍微慢一些
function timeSince(then) {
    var now = new Date(), obj = {};
    obj.milliseconds = now.getUTCMilliseconds() - then.getUTCMilliseconds();
    obj.seconds = now.getUTCSeconds() - then.getUTCSeconds();
    obj.minutes = now.getUTCMinutes() - then.getUTCMinutes();
    obj.hours = now.getUTCHours() - then.getUTCHours();
    obj.days = now.getUTCDate() - then.getUTCDate();
    obj.months = now.getUTCMonth() - then.getUTCMonth();
    obj.years = now.getUTCFullYear() - then.getUTCFullYear();
    // fix negatives
    if (obj.milliseconds < 0) --obj.seconds, obj.milliseconds = (obj.milliseconds + 1000) % 1000;
    if (obj.seconds < 0) --obj.minutes, obj.seconds = (obj.seconds + 60) % 60;
    if (obj.minutes < 0) --obj.hours, obj.minutes = (obj.minutes + 60) % 60;
    if (obj.hours < 0) --obj.days, obj.hours = (obj.hours + 24) % 24;
    if (obj.days < 0) { // months have different lengths
        --obj.months;
        now.setUTCMonth(now.getUTCMonth() + 1);
        now.setUTCDate(0);
        obj.days = (obj.days + now.getUTCDate()) % now.getUTCDate();
    }
    if (obj.months < 0)  --obj.years, obj.months = (obj.months + 12) % 12;
    return obj;
}

这是一个简单的时间戳格式化程序,它具有自定义模式支持感知区域设置的,使用Intl.RelativeTimeFormat

格式示例:

/** delta: 1234567890, @locale: 'en-US', @style: 'long' */
/* D~ h~ m~ s~ f~ */
14 days 6 hours 56 minutes 7 seconds 890
/* D#"d" h#"h" m#"m" s#"s" f#"ms" */
14d 6h 56m 7s 890ms
/* D~, h:m:s.f */
14 days, 06:56:07.890
/* h~ m~ s~ */
342 hours 56 minutes 7 seconds
   
/* up D~, h:m */
up 14 days, 06:56

用法说明、源代码和实例如下:

/************************** README *************************
Initialize formatter:
    timespan.locale(@locale, @style)
    
      @locale format:
          
          'en-US', 'de-AT', ...
          
              reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#locales_argument
      
      @style format:
      
          'long': e.g., 1 month
          'short': e.g., 1 mo.
      Examples:
          timespan.locale('en-US', 'long');
          timespan.locale('de-AT', 'short');
Get formatted timespan:
    timespan.format(@pattern, @milliseconds)
        @pattern tokens:
        
            D: days, h: hours, m: minutes, s: seconds, f: milliseconds
        @pattern token extension:
        
            h  => '0'-padded value, 
            h# => raw value,
            h~ => locale formatted value
        Examples:
            timespan.format('D~ h~ m~ s~', 1234567890);
            timespan.format('up D~, h:m', 1234567890);
NOTES:
* milliseconds unit have no locale translation
* may encounter declension issues for some locales
* use quoted text for raw inserts
*/

/************************** SOURCE *************************/
const timespan = (() => {
  let rtf, tokensRtf;
  const
  tokens = /[Dhmsf][#~]?|"[^"]*"|'[^']*'/g,
  map = [
      {t: [['D', 1], ['D#'], ['D~', 'day']], u: 86400000},
      {t: [['h', 2], ['h#'], ['h~', 'hour']], u: 3600000},
      {t: [['m', 2], ['m#'], ['m~', 'minute']], u: 60000},
      {t: [['s', 2], ['s#'], ['s~', 'second']], u: 1000},
      {t: [['f', 3], ['f#'], ['f~']], u: 1}
  ],
  locale = (value, style = 'long') => {
      try {
          rtf = new Intl.RelativeTimeFormat(value, {style});
      } catch (e) {
          if (rtf) throw e;
          return;
      }
      const h = rtf.format(1, 'hour').split(' ');
      tokensRtf = new Set(rtf.format(1, 'day').split(' ')
          .filter(t => t != 1 && h.indexOf(t) > -1));
      return true;
  },
  fallback = (t, u) => u + ' ' + t.fmt + (u == 1 ? '' : 's'),
  mapper = {
      number: (t, u) => (u + '').padStart(t.fmt, '0'),
      string: (t, u) => rtf ? rtf.format(u, t.fmt).split(' ')
          .filter(t => !tokensRtf.has(t)).join(' ')
          .trim().replace(/[+-]/g, '') : fallback(t, u),
  },
  replace = (out, t) => out[t] || t.slice(1, t.length - 1),
  format = (pattern, value) => {
      if (typeof pattern !== 'string')
          throw Error('invalid pattern');
      if (!Number.isFinite(value))
          throw Error('invalid value');
      if (!pattern)
          return '';
      const out = {};
      value = Math.abs(value);
      pattern.match(tokens)?.forEach(t => out[t] = null);
      map.forEach(m => {
          let u = null;
          m.t.forEach(t => {
              if (out[t.token] !== null)
                  return;
              if (u === null) {
                  u = Math.floor(value / m.u);
                  value %= m.u;
              }
              out[t.token] = '' + (t.fn ? t.fn(t, u) : u);
          })
      });
      return pattern.replace(tokens, replace.bind(null, out));
  };
  map.forEach(m => m.t = m.t.map(t => ({
      token: t[0], fmt: t[1], fn: mapper[typeof t[1]]
  })));
  locale('en');
  return {format, locale};
})();

/************************** EXAMPLES *************************/
const delta = 1234567890;
console.log(timespan.format('D~ h~ m~ s~ f~', delta));
console.log(timespan.format('s~ m~ h~ D~', delta));
console.log(timespan.format('D#"d" h#"h" m#"m" s#"s" f#"ms"', delta));
console.log(timespan.format('h~ m~ s~', delta));
console.log(timespan.format('D,h:m:s.f', delta));
console.log(timespan.format('D~, h:m:s.f', delta));
console.log(timespan.format('up D~, h:m', delta));
timespan.locale('de-DE', 'long');
console.log(timespan.format('D~ h~ m~ s~', delta));

你可以使用momentjs的duration对象

的例子:

const diff = moment.duration(Date.now() - new Date(2010, 1, 1))
console.log(`${diff.years()} years ${diff.months()} months ${diff.days()} days ${diff.hours()} hours ${diff.minutes()} minutes and ${diff.seconds()} seconds`)

/**
 * 计算时间对象与当前时间的差距,并显示友好的文本 
 * English: Calculating the difference between the given time and the current time and then showing the results.
 */
function date2Text(date) {
    var milliseconds = new Date() - date;
    var timespan = new TimeSpan(milliseconds);
    if (milliseconds < 0) {
        return timespan.toString() + "之后";
    }else{
        return timespan.toString() + "前";
    }
}
/**
 * 用于计算时间间隔的对象
 * English: Using a function to calculate the time interval
 * @param milliseconds 毫秒数
 */
var TimeSpan = function (milliseconds) {
    milliseconds = Math.abs(milliseconds);
    var days = Math.floor(milliseconds / (1000 * 60 * 60 * 24));
    milliseconds -= days * (1000 * 60 * 60 * 24);
    var hours = Math.floor(milliseconds / (1000 * 60 * 60));
    milliseconds -= hours * (1000 * 60 * 60);
    var mins = Math.floor(milliseconds / (1000 * 60));
    milliseconds -= mins * (1000 * 60);
    var seconds = Math.floor(milliseconds / (1000));
    milliseconds -= seconds * (1000);
    return {
        getDays: function () {
            return days;
        },
        getHours: function () {
            return hours;
        },
        getMinuts: function () {
            return mins;
        },
        getSeconds: function () {
            return seconds;
        },
        toString: function () {
            var str = "";
            if (days > 0 || str.length > 0) {
                str += days + "天";
            }
            if (hours > 0 || str.length > 0) {
                str += hours + "小时";
            }
            if (mins > 0 || str.length > 0) {
                str += mins + "分钟";
            }
            if (days == 0 && (seconds > 0 || str.length > 0)) {
                str += seconds + "秒";
            }
            return str;
        }
    }
}

Moment.js提供如下功能:

http://momentjs.com/

有很好的文档和很好的库。

应该像"Duration"one_answers"Humanize of API http://momentjs.com/docs/#/displaying/from/"一样

 var d1, d2; // Timepoints
 var differenceInPlainText = moment(a).from(moment(b), true); // Add true for suffixless text

这里有一个。net c#类似的时间跨度类实现,支持天、小时、分和秒。此实现还支持负时间跨度。

const MILLIS_PER_SECOND = 1000;
const MILLIS_PER_MINUTE = MILLIS_PER_SECOND * 60;   //     60,000
const MILLIS_PER_HOUR = MILLIS_PER_MINUTE * 60;     //  3,600,000
const MILLIS_PER_DAY = MILLIS_PER_HOUR * 24;        // 86,400,000
export class TimeSpan {
    private _millis: number;
    private static interval(value: number, scale: number): TimeSpan {
        if (Number.isNaN(value)) {
            throw new Error("value can't be NaN");
        }
        const tmp = value * scale;
        const millis = TimeSpan.round(tmp + (value >= 0 ? 0.5 : -0.5));
        if ((millis > TimeSpan.maxValue.totalMilliseconds) || (millis < TimeSpan.minValue.totalMilliseconds)) {
            throw new TimeSpanOverflowError("TimeSpanTooLong");
        }
        return new TimeSpan(millis);
    }
    private static round(n: number): number {
        if (n < 0) {
            return Math.ceil(n);
        } else if (n > 0) {
            return Math.floor(n);
        }
        return 0;
    }
    private static timeToMilliseconds(hour: number, minute: number, second: number): number {
        const totalSeconds = (hour * 3600) + (minute * 60) + second;
        if (totalSeconds > TimeSpan.maxValue.totalSeconds || totalSeconds < TimeSpan.minValue.totalSeconds) {
            throw new TimeSpanOverflowError("TimeSpanTooLong");
        }
        return totalSeconds * MILLIS_PER_SECOND;
    }
    public static get zero(): TimeSpan {
        return new TimeSpan(0);
    }
    public static get maxValue(): TimeSpan {
        return new TimeSpan(Number.MAX_SAFE_INTEGER);
    }
    public static get minValue(): TimeSpan {
        return new TimeSpan(Number.MIN_SAFE_INTEGER);
    }
    public static fromDays(value: number): TimeSpan {
        return TimeSpan.interval(value, MILLIS_PER_DAY);
    }
    public static fromHours(value: number): TimeSpan {
        return TimeSpan.interval(value, MILLIS_PER_HOUR);
    }
    public static fromMilliseconds(value: number): TimeSpan {
        return TimeSpan.interval(value, 1);
    }
    public static fromMinutes(value: number): TimeSpan {
        return TimeSpan.interval(value, MILLIS_PER_MINUTE);
    }
    public static fromSeconds(value: number): TimeSpan {
        return TimeSpan.interval(value, MILLIS_PER_SECOND);
    }
    public static fromTime(hours: number, minutes: number, seconds: number): TimeSpan;
    public static fromTime(days: number, hours: number, minutes: number, seconds: number, milliseconds: number): TimeSpan;
    public static fromTime(daysOrHours: number, hoursOrMinutes: number, minutesOrSeconds: number, seconds?: number, milliseconds?: number): TimeSpan {
        if (milliseconds != undefined) {
            return this.fromTimeStartingFromDays(daysOrHours, hoursOrMinutes, minutesOrSeconds, seconds, milliseconds);
        } else {
            return this.fromTimeStartingFromHours(daysOrHours, hoursOrMinutes, minutesOrSeconds);
        }
    }
    private static fromTimeStartingFromHours(hours: number, minutes: number, seconds: number): TimeSpan {
        const millis = TimeSpan.timeToMilliseconds(hours, minutes, seconds);
        return new TimeSpan(millis);
    }
    private static fromTimeStartingFromDays(days: number, hours: number, minutes: number, seconds: number, milliseconds: number): TimeSpan {
        const totalMilliSeconds = (days * MILLIS_PER_DAY) +
            (hours * MILLIS_PER_HOUR) +
            (minutes * MILLIS_PER_MINUTE) +
            (seconds * MILLIS_PER_SECOND) +
            milliseconds;
        if (totalMilliSeconds > TimeSpan.maxValue.totalMilliseconds || totalMilliSeconds < TimeSpan.minValue.totalMilliseconds) {
            throw new TimeSpanOverflowError("TimeSpanTooLong");
        }
        return new TimeSpan(totalMilliSeconds);
    }
    constructor(millis: number) {
        this._millis = millis;
    }
    public get days(): number {
        return TimeSpan.round(this._millis / MILLIS_PER_DAY);
    }
    public get hours(): number {
        return TimeSpan.round((this._millis / MILLIS_PER_HOUR) % 24);
    }
    public get minutes(): number {
        return TimeSpan.round((this._millis / MILLIS_PER_MINUTE) % 60);
    }
    public get seconds(): number {
        return TimeSpan.round((this._millis / MILLIS_PER_SECOND) % 60);
    }
    public get milliseconds(): number {
        return TimeSpan.round(this._millis % 1000);
    }
    public get totalDays(): number {
        return this._millis / MILLIS_PER_DAY;
    }
    public get totalHours(): number {
        return this._millis / MILLIS_PER_HOUR;
    }
    public get totalMinutes(): number {
        return this._millis / MILLIS_PER_MINUTE;
    }
    public get totalSeconds(): number {
        return this._millis / MILLIS_PER_SECOND;
    }
    public get totalMilliseconds(): number {
        return this._millis;
    }
    public add(ts: TimeSpan): TimeSpan {
        const result = this._millis + ts.totalMilliseconds;
        return new TimeSpan(result);
    }
    public subtract(ts: TimeSpan): TimeSpan {
        const result = this._millis - ts.totalMilliseconds;
        return new TimeSpan(result);
    }
}

如何使用

创建新的TimeSpan对象

从零

    const ts = TimeSpan.zero;
从毫秒

    const milliseconds = 10000; // 1 second
    // by using the constructor
    const ts1 = new TimeSpan(milliseconds);
    // or as an alternative you can use the static factory method
    const ts2 = TimeSpan.fromMilliseconds(milliseconds);
从秒

    const seconds = 86400; // 1 day
    const ts = TimeSpan.fromSeconds(seconds);
从分钟

    const minutes = 1440; // 1 day
    const ts = TimeSpan.fromMinutes(minutes);
从小时

    const hours = 24; // 1 day
    const ts = TimeSpan.fromHours(hours);
从天

    const days = 1; // 1 day
    const ts = TimeSpan.fromDays(days);
从给定的小时,分钟和秒的时间

    const hours = 1;
    const minutes = 1;
    const seconds = 1;
    const ts = TimeSpan.fromTime(hours, minutes, seconds);
从time2到给定的日、时、分、秒和毫秒

    const days = 1;
    const hours = 1;
    const minutes = 1;
    const seconds = 1;
    const milliseconds = 1;
    const ts = TimeSpan.fromTime(days, hours, minutes, seconds, milliseconds);
从最大安全整数

    const ts = TimeSpan.maxValue;
从最小安全整数

    const ts = TimeSpan.minValue;
从最小安全整数

    const ts = TimeSpan.minValue;
添加

    const ts1 = TimeSpan.fromDays(1);
    const ts2 = TimeSpan.fromHours(1);
    const ts = ts1.add(ts2);
    console.log(ts.days);               // 1
    console.log(ts.hours);              // 1
    console.log(ts.minutes);            // 0
    console.log(ts.seconds);            // 0
    console.log(ts.milliseconds);           // 0
减去

    const ts1 = TimeSpan.fromDays(1);
    const ts2 = TimeSpan.fromHours(1);
    const ts = ts1.subtract(ts2);
    console.log(ts.days);               // 0
    console.log(ts.hours);              // 23
    console.log(ts.minutes);            // 0
    console.log(ts.seconds);            // 0
    console.log(ts.milliseconds);           // 0
获取间隔

    const days = 1;
    const hours = 1;
    const minutes = 1;
    const seconds = 1;
    const milliseconds = 1;
    const ts = TimeSpan.fromTime2(days, hours, minutes, seconds, milliseconds);
    console.log(ts.days);               // 1
    console.log(ts.hours);              // 1
    console.log(ts.minutes);            // 1
    console.log(ts.seconds);            // 1
    console.log(ts.milliseconds);           // 1
    console.log(ts.totalDays)           // 1.0423726967592593;
    console.log(ts.totalHours)          // 25.016944722222224;
    console.log(ts.totalMinutes)            // 1501.0166833333333;
    console.log(ts.totalSeconds)            // 90061.001;
    console.log(ts.totalMilliseconds);      // 90061001;

参见此处:https://github.com/erdas/timespan

相关内容

  • 没有找到相关文章

最新更新