JavaScript 编程语言【 数据类型】日期和时间

文章目录

  • 日期和时间
    • 创建
    • 访问日期组件
    • 设置日期组件
    • 自动校准(Autocorrection)
    • 日期转化为数字,日期差值
    • Date.now()
    • 基准测试(Benchmarking)
    • 对字符串调用 Date.parse
    • 总结
    • ✅任务
      • 创建日期
      • 显示星期数
      • 欧洲的星期表示方法
      • 许多天之前是哪个月几号?
      • 某月的最后一天?
      • 今天过去了多少秒?
      • 距离明天还有多少秒?
      • 格式化相对日期

日期和时间

让我们来学习一个新的内建对象:日期(Date)。该对象存储日期和时间,并提供了日期/时间的管理方法。

我们可以使用它来存储创建/修改时间,测量时间,或者仅用来打印当前时间。

创建

调用 new Date() 来创建一个新的 Date 对象。在调用时可以带有一些参数,如下所示:

  • new Date()

    不带参数 —— 创建一个表示当前日期和时间的 Date 对象:let now = new Date(); alert( now ); // 显示当前的日期/时间

  • new Date(milliseconds)

    创建一个 Date 对象,其时间等于 1970 年 1 月 1 日 UTC+0 之后经过的毫秒数(1/1000 秒)。// 0 表示 01.01.1970 UTC+0 let Jan01_1970 = new Date(0); alert( Jan01_1970 ); // 现在增加 24 小时,得到 02.01.1970 UTC+0 let Jan02_1970 = new Date(24 * 3600 * 1000); alert( Jan02_1970 );传入的整数参数代表的是自 1970-01-01 00:00:00 以来经过的毫秒数,该整数被称为 时间戳。这是一种日期的轻量级数字表示形式。我们通常使用 new Date(timestamp) 通过时间戳来创建日期,并可以使用 date.getTime() 将现有的 Date 对象转化为时间戳(下文会讲到)。在 01.01.1970 之前的日期带有负的时间戳,例如:// 31 Dec 1969 let Dec31_1969 = new Date(-24 * 3600 * 1000); alert( Dec31_1969 );

  • new Date(datestring)

    如果只有一个参数,并且是字符串,那么它会被自动解析。该算法与 Date.parse 所使用的算法相同,将在下文中进行介绍。let date = new Date("2017-01-26"); alert(date); // 未指定具体时间,所以假定时间为格林尼治标准时间(GMT)的午夜零点 // 并根据运行代码时的用户的时区进行调整 // 因此,结果可能是 // Thu Jan 26 2017 11:00:00 GMT+1100 (Australian Eastern Daylight Time) // 或 // Wed Jan 25 2017 16:00:00 GMT-0800 (Pacific Standard Time)

  • new Date(year, month, date, hours, minutes, seconds, ms)

    使用当前时区中的给定组件创建日期。只有前两个参数是必须的。year 必须是四位数:2013 是合法的,98 是不合法的。month 计数从 0(一月)开始,到 11(十二月)结束。date 是当月的具体某一天,如果缺失,则为默认值 1。如果 hours/minutes/seconds/ms 缺失,则均为默认值 0。例如:new Date(2011, 0, 1, 0, 0, 0, 0); // 1 Jan 2011, 00:00:00 new Date(2011, 0, 1); // 同样,时分秒等均为默认值 0时间度量最大精确到 1 毫秒(1/1000 秒):let date = new Date(2011, 0, 1, 2, 3, 4, 567); alert( date ); // 1.01.2011, 02:03:04.567

访问日期组件

Date 对象中访问年、月等信息有多种方式:

  • getFullYear()

    获取年份(4 位数)

  • getMonth()

    获取月份,从 0 到 11

  • getDate()

    获取当月的具体日期,从 1 到 31,这个方法名称可能看起来有些令人疑惑。

  • getHours(),getMinutes(),getSeconds(),getMilliseconds()

    获取相应的时间组件。

⚠️不是 getYear(),而是 getFullYear()

很多 JavaScript 引擎都实现了一个非标准化的方法 getYear()。不推荐使用这个方法。它有时候可能会返回 2 位的年份信息。永远不要使用它。要获取年份就使用 getFullYear()

另外,我们还可以获取一周中的第几天:

  • getDay()

    获取一周中的第几天,从 0(星期日)到 6(星期六)。第一天始终是星期日,在某些国家可能不是这样的习惯,但是这不能被改变。

以上的所有方法返回的组件都是基于当地时区的。

当然,也有与当地时区的 UTC 对应项,它们会返回基于 UTC+0 时区的日、月、年等:getUTCFullYear(),getUTCMonth(),getUTCDay()。只需要在 "get" 之后插入 "UTC" 即可。

如果你当地时区相对于 UTC 有偏移,那么下面代码会显示不同的小时数:

//  当前日期
let date = new Date();// 当地时区的小时数
alert( date.getHours() );// 在 UTC+0 时区的小时数(非夏令时的伦敦时间)
alert( date.getUTCHours() );

除了上述给定的方法,还有两个没有 UTC 变体的特殊方法:

  • getTime()

    返回日期的时间戳 —— 从 1970-1-1 00:00:00 UTC+0 开始到现在所经过的毫秒数。

  • getTimezoneOffset()

    返回 UTC 与本地时区之间的时差,以分钟为单位:// 如果你在时区 UTC-1,输出 60 // 如果你在时区 UTC+3,输出 -180 alert( new Date().getTimezoneOffset() );

设置日期组件

下列方法可以设置日期/时间组件:

  • setFullYear(year, [month\], [date])
  • setMonth(month, [date\])
  • setDate(date)
  • setHours(hour, [min\], [sec], [ms])
  • setMinutes(min, [sec\], [ms])
  • setSeconds(sec, [ms\])
  • setMilliseconds(ms)
  • setTime(milliseconds)(使用自 1970-01-01 00:00:00 UTC+0 以来的毫秒数来设置整个日期)

以上方法除了 setTime() 都有 UTC 变体,例如:setUTCHours()

我们可以看到,有些方法可以一次性设置多个组件,比如 setHours。未提及的组件不会被修改。

举个例子:

let today = new Date();today.setHours(0);
alert(today); // 日期依然是今天,但是小时数被改为了 0today.setHours(0, 0, 0, 0);
alert(today); // 日期依然是今天,时间为 00:00:00。

自动校准(Autocorrection)

自动校准Date 对象的一个非常方便的特性。我们可以设置超范围的数值,它会自动校准。

举个例子:

let date = new Date(2013, 0, 32); // 32 Jan 2013 ?!?
alert(date); // ……是 1st Feb 2013!

超出范围的日期组件将会被自动分配。

假设我们要在日期 “28 Feb 2016” 上加 2 天。结果可能是 “2 Mar” 或 “1 Mar”,因为存在闰年。但是我们不需要考虑这些,只需要直接加 2 天,剩下的 Date 对象会帮我们处理:

let date = new Date(2016, 1, 28);
date.setDate(date.getDate() + 2);alert( date ); // 1 Mar 2016

这个特性经常被用来获取给定时间段后的日期。例如,我们想获取“现在 70 秒后”的日期:

let date = new Date();
date.setSeconds(date.getSeconds() + 70);alert( date ); // 显示正确的日期信息

我们还可以设置 0 甚至可以设置负值。例如:

let date = new Date(2016, 0, 2); // 2016 年 1 月 2 日date.setDate(1); // 设置为当月的第一天
alert( date );date.setDate(0); // 天数最小可以设置为 1,所以这里设置的是上一月的最后一天
alert( date ); // 31 Dec 2015

日期转化为数字,日期差值

Date 对象被转化为数字时,得到的是对应的时间戳,与使用 date.getTime() 的结果相同:

let date = new Date();
alert(+date); // 以毫秒为单位的数值,与使用 date.getTime() 的结果相同

有一个重要的副作用:日期可以相减,相减的结果是以毫秒为单位时间差。

这个作用可以用于时间测量:

let start = new Date(); // 开始测量时间// do the job
for (let i = 0; i < 100000; i++) {let doSomething = i * i * i;
}let end = new Date(); // 结束测量时间alert( `The loop took ${end - start} ms` );

Date.now()

如果我们仅仅想要测量时间间隔,我们不需要 Date 对象。

有一个特殊的方法 Date.now(),它会返回当前的时间戳。

它相当于 new Date().getTime(),但它不会创建中间的 Date 对象。因此它更快,而且不会对垃圾回收造成额外的压力。

这种方法很多时候因为方便,又或是因性能方面的考虑而被采用,例如使用 JavaScript 编写游戏或其他的特殊应用场景。

因此这样做可能会更好:

let start = Date.now(); // 从 1 Jan 1970 至今的时间戳// do the job
for (let i = 0; i < 100000; i++) {let doSomething = i * i * i;
}let end = Date.now(); // 完成alert( `The loop took ${end - start} ms` ); // 相减的是时间戳,而不是日期

基准测试(Benchmarking)

在对一个很耗 CPU 性能的函数进行可靠的基准测试(Benchmarking)时,我们需要谨慎一点。

例如,我们想判断以下两个计算日期差值的函数:哪个更快?

这种性能测量通常称为“基准测试(benchmark)”。

// 我们有 date1 和 date2,哪个函数会更快地返回两者的时间差?
function diffSubtract(date1, date2) {return date2 - date1;
}// or
function diffGetTime(date1, date2) {return date2.getTime() - date1.getTime();
}

这两个函数做的事情完全相同,但是其中一个函数使用显式的 date.getTime() 来获取毫秒形式的日期,另一个则依赖于“日期 — 数字”的转换。它们的结果是一样的。

那么,哪个更快呢?

首先想到的方法可能是连续运行两者很多次,并计算所消耗的时间之差。就这个例子而言,函数过于简单,所以我们必须执行至少 100000 次。

让我们开始测量:

function diffSubtract(date1, date2) {return date2 - date1;
}function diffGetTime(date1, date2) {return date2.getTime() - date1.getTime();
}function bench(f) {let date1 = new Date(0);let date2 = new Date();let start = Date.now();for (let i = 0; i < 100000; i++) f(date1, date2);return Date.now() - start;
}alert( 'Time of diffSubtract: ' + bench(diffSubtract) + 'ms' );
alert( 'Time of diffGetTime: ' + bench(diffGetTime) + 'ms' );

看起来使用 getTime() 这种方式快得多,这是因为它没有进行类型转换,对引擎优化来说更加简单。

我们得到了结论,但是这并不是一个很好的度量的例子。

想象一下当运行 bench(diffSubtract) 的同时,CPU 还在并行处理其他事务,并且这也会占用资源。然而,运行 bench(diffGetTime) 的时候,并行处理的事务完成了。

对于现代多进程操作系统来说,这是一个非常常见的场景。

比起第二个函数,第一个函数所能使用的 CPU 资源更少。这可能导致错误的结论。

为了得到更加可靠的度量,整个度量测试包应该重新运行多次。

例如,像下面的代码这样:

function diffSubtract(date1, date2) {return date2 - date1;
}function diffGetTime(date1, date2) {return date2.getTime() - date1.getTime();
}function bench(f) {let date1 = new Date(0);let date2 = new Date();let start = Date.now();for (let i = 0; i < 100000; i++) f(date1, date2);return Date.now() - start;
}let time1 = 0;
let time2 = 0;// 交替运行 bench(diffSubtract) 和 bench(diffGetTime) 各 10 次
for (let i = 0; i < 10; i++) {time1 += bench(diffSubtract);time2 += bench(diffGetTime);
}alert( 'Total time for diffSubtract: ' + time1 );
alert( 'Total time for diffGetTime: ' + time2 );

现代的 JavaScript 引擎的先进优化策略只对执行很多次的 “hot code” 有效(对于执行很少次数的代码没有必要优化)。因此,在上面的例子中,第一次执行的优化程度不高。我们可能需要增加一个预热步骤:

// 在主循环中增加预热环节
bench(diffSubtract);
bench(diffGetTime);// 开始度量
for (let i = 0; i < 10; i++) {time1 += bench(diffSubtract);time2 += bench(diffGetTime);
}

⚠️进行微型基准测试时要小心

现代的 JavaScript 引擎执行了很多优化。与正常编写的代码相比,它们可能会改变“人为编写的专用于测试的代码”的执行流程,特别是在我们对很小的代码片段进行基准测试时,例如某个运算符或内建函数的工作方式。因此,为了深入理解性能问题,请学习 JavaScript 引擎的工作原理。在那之后,你或许再也不需要进行微型基准测试了。

http://mrale.ph 提供了很多 V8 引擎相关的文章。

对字符串调用 Date.parse

Date.parse(str) 方法可以从一个字符串中读取日期。

字符串的格式应该为:YYYY-MM-DDTHH:mm:ss.sssZ,其中:

  • YYYY-MM-DD —— 日期:年-月-日。
  • 字符 "T" 是一个分隔符。
  • HH:mm:ss.sss —— 时间:小时,分钟,秒,毫秒。
  • 可选字符 'Z'+-hh:mm 格式的时区。单个字符 Z 代表 UTC+0 时区。

简短形式也是可以的,比如 YYYY-MM-DDYYYY-MM,甚至可以是 YYYY

Date.parse(str) 调用会解析给定格式的字符串,并返回时间戳(自 1970-01-01 00:00:00 起所经过的毫秒数)。如果给定字符串的格式不正确,则返回 NaN

举个例子:

let ms = Date.parse('2012-01-26T13:51:50.417-07:00');alert(ms); // 1327611110417  (时间戳)

我们可以通过时间戳来立即创建一个 new Date 对象:

let date = new Date( Date.parse('2012-01-26T13:51:50.417-07:00') );alert(date);

总结

  • 在 JavaScript 中,日期和时间使用 Date 对象来表示。我们不能单独创建日期或时间,Date 对象总是同时创建两者。
  • 月份从 0 开始计数(对,一月是 0)。
  • 一周中的某一天 getDay() 同样从 0 开始计算(0 代表星期日)。
  • 当设置了超出范围的组件时,Date 会进行自动校准。这一点对于日/月/小时的加减很有用。
  • 日期可以相减,得到的是以毫秒表示的两者的差值。因为当 Date 被转换为数字时,Date 对象会被转换为时间戳。
  • 使用 Date.now() 可以更快地获取当前时间的时间戳。

和其他系统不同,JavaScript 中时间戳以毫秒为单位,而不是秒。

有时我们需要更加精准的时间度量。JavaScript 自身并没有测量微秒的方法(百万分之一秒),但大多数运行环境会提供。例如:浏览器有 performance.now() 方法来给出从页面加载开始的以毫秒为单位的微秒数(精确到毫秒的小数点后三位):

alert(`Loading started ${performance.now()}ms ago`);
// 类似于 "Loading started 34731.26000000001ms ago"
// .26 表示的是微秒(260 微秒)
// 小数点后超过 3 位的数字是精度错误,只有前三位数字是正确的

Node.js 可以通过 microtime 模块或使用其他方法。从技术上讲,几乎所有的设备和环境都允许获取更高精度的时间数值,只不过不是使用 Date 对象。

✅任务

创建日期

重要程度5️⃣

创建一个 Date 对象,日期是:Feb 20, 2012, 3:12am。时区是当地时区。

使用 alert 显示结果。

解决方案

new Date 构造函数默认使用本地时区。所以唯一需要牢记的就是月份从 0 开始计数。

所以二月对应的数值是 1。

这是一个以数字作为日期参数的示例:

// new Date(year, month, date, hour, minute, second, millisecond)
let d1 = new Date(2012, 1, 20, 3, 12);
alert( d1 );

我们还可以从字符串创建日期,像这样:

// new Date(datestring)
let d2 = new Date("February 20, 2012 03:12:00");
alert( d2 );

显示星期数

重要程度5️⃣

编写一个函数 getWeekDay(date) 以短格式来显示一个日期的星期数:‘MO’,‘TU’,‘WE’,‘TH’,‘FR’,‘SA’,‘SU’。

例如:

let date = new Date(2012, 0, 3);  // 3 Jan 2012
alert( getWeekDay(date) );        // 应该输出 "TU"

打开带有测试的沙箱。

解决方案

date.getDay() 方法返回从星期日开始的星期数。

我们创建一个关于星期的数组,这样我们就可以通过编号获取正确的日期名称:

function getWeekDay(date) {
let days = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'];return days[date.getDay()];
}let date = new Date(2014, 0, 3); // 3 Jan 2014
alert( getWeekDay(date) ); // FR

使用沙箱的测试功能打开解决方案。

欧洲的星期表示方法

重要程度5️⃣

欧洲国家的星期计算是从星期一(数字 1)开始的,然后是星期二(数字 2),直到星期日(数字 7)。编写一个函数 getLocalDay(date),并返回日期的欧洲式星期数。

let date = new Date(2012, 0, 3);  // 3 Jan 2012
alert( getLocalDay(date) );       // 星期二,应该显示 2

打开带有测试的沙箱。

解决方案

function getLocalDay(date) {let day = date.getDay();if (day == 0) { // weekday 0 (sunday) is 7 in europeanday = 7;
}return day;
}

使用沙箱的测试功能打开解决方案。

许多天之前是哪个月几号?

重要程度4️⃣

写一个函数 getDateAgo(date, days),返回特定日期 date 往前 days 天是哪个月的哪一天。

例如,假设今天是 20 号,那么 getDateAgo(new Date(), 1) 的结果应该是 19 号,getDateAgo(new Date(), 2) 的结果应该是 18 号。

跨月、年也应该是正确输出:

let date = new Date(2015, 0, 2);alert( getDateAgo(date, 1) ); // 1, (1 Jan 2015)
alert( getDateAgo(date, 2) ); // 31, (31 Dec 2014)
alert( getDateAgo(date, 365) ); // 2, (2 Jan 2014)

P.S. 函数不应该修改给定的 date 值。

打开带有测试的沙箱。

解决方案

思路很简单:从 date 中减去给定的天数:

function getDateAgo(date, days) {
date.setDate(date.getDate() - days);
return date.getDate();
}

……但是函数不能修改 date。这一点很重要,因为我们提供日期的外部代码不希望它被修改。

要实现这一点,我们可以复制这个日期,就像这样:

function getDateAgo(date, days) {
let dateCopy = new Date(date);dateCopy.setDate(date.getDate() - days);
return dateCopy.getDate();
}let date = new Date(2015, 0, 2);alert( getDateAgo(date, 1) ); // 1, (1 Jan 2015)
alert( getDateAgo(date, 2) ); // 31, (31 Dec 2014)
alert( getDateAgo(date, 365) ); // 2, (2 Jan 2014)

使用沙箱的测试功能打开解决方案。

某月的最后一天?

重要程度5️⃣

写一个函数 getLastDayOfMonth(year, month) 返回 month 月的最后一天。有时候是 30,有时是 31,甚至在二月的时候会是 28/29。

参数:

  • year —— 四位数的年份,比如 2012。
  • month —— 月份,从 0 到 11。

举个例子,getLastDayOfMonth(2012, 1) = 29(闰年,二月)

打开带有测试的沙箱。

解决方案

让我们使用下个月创建日期,但将零作为天数(day)传递:

function getLastDayOfMonth(year, month) {
let date = new Date(year, month + 1, 0);
return date.getDate();
}alert( getLastDayOfMonth(2012, 0) ); // 31
alert( getLastDayOfMonth(2012, 1) ); // 29
alert( getLastDayOfMonth(2013, 1) ); // 28

通常,日期从 1 开始,但从技术上讲,我们可以传递任何数字,日期会自动进行调整。因此,当我们传递 0 时,它的意思是“一个月的第一天的前一天”,换句话说:“上个月的最后一天”。

使用沙箱的测试功能打开解决方案。

今天过去了多少秒?

重要程度5️⃣

写一个函数 getSecondsToday(),返回今天已经过去了多少秒?

例如:如果现在是 10:00 am,并且没有夏令时转换,那么:

getSecondsToday() == 36000 // (3600 * 10)

该函数应该在任意一天都能正确运行。那意味着,它不应具有“今天”的硬编码值。

解决方案

为获取秒数,我们可以使用今天的日期和 00:00:00 这个时间创建一个日期,然后使用当前时间减去该时间。

不同之处在于,从今天之初开始算起的时间是以毫秒计算的,我们应该将其除以 1000,进而得到秒数:

function getSecondsToday() {
let now = new Date();// 使用当前的 day/month/year 创建一个对象
let today = new Date(now.getFullYear(), now.getMonth(), now.getDate());let diff = now - today; // ms difference
return Math.round(diff / 1000); // make seconds
}alert( getSecondsToday() );

另一种解决方法是获取 hours/minutes/seconds,然后把它们转换为秒数:

function getSecondsToday() {
let d = new Date();
return d.getHours() * 3600 + d.getMinutes() * 60 + d.getSeconds();
};alert( getSecondsToday() );

距离明天还有多少秒?

重要程度5️⃣

写一个函数 getSecondsToTomorrow(),返回距离明天的秒数。

例如,现在是 23:00,那么:

getSecondsToTomorrow() == 3600

P.S. 该函数应该在任意一天都能正确运行。那意味着,它不应具有“今天”的硬编码值。

解决方案

为获取距离明天的毫秒数,我们可以用“明天 00:00:00”这个日期减去当前的日期。

首先我们生成“明天”,然后对其进行减法操作:

function getSecondsToTomorrow() {
let now = new Date();// tomorrow date
let tomorrow = new Date(now.getFullYear(), now.getMonth(), now.getDate()+1);let diff = tomorrow - now; // difference in ms
return Math.round(diff / 1000); // convert to seconds
}

另一种解法:

function getSecondsToTomorrow() {
let now = new Date();
let hour = now.getHours();
let minutes = now.getMinutes();
let seconds = now.getSeconds();
let totalSecondsToday = (hour * 60 + minutes) * 60 + seconds;
let totalSecondsInADay = 86400;return totalSecondsInADay - totalSecondsToday;
}

请注意,很多国家有夏令时(DST),因此他们的一天可能有 23 小时或者 25 小时。我们对这些天数要区别对待。

格式化相对日期

重要程度4️⃣

写一个函数 formatDate(date),能够对 date 进行如下格式化:

  • 如果 date 距离现在不到 1 秒,输出 "right now"
  • 否则,如果 date 距离现在不到 1 分钟,输出 "n sec. ago"
  • 否则,如果不到 1 小时,输出 "m min. ago"
  • 否则,以 "DD.MM.YY HH:mm" 格式输出完整日期。即:"day.month.year hours:minutes",全部以两位数格式表示,例如:31.12.16 10:00

举个例子:

alert( formatDate(new Date(new Date - 1)) ); // "right now"alert( formatDate(new Date(new Date - 30 * 1000)) ); // "30 sec. ago"alert( formatDate(new Date(new Date - 5 * 60 * 1000)) ); // "5 min. ago"// 昨天的日期,例如 31.12.16 20:00
alert( formatDate(new Date(new Date - 86400 * 1000)) );

打开带有测试的沙箱。

解决方案

为了获取 date 距离当前时间的间隔 —— 我们将两个日期相减。

function formatDate(date) {
let diff = new Date() - date; // 以毫秒表示的差值if (diff < 1000) { // 少于 1 秒return 'right now';
}let sec = Math.floor(diff / 1000); // 将 diff 转换为秒if (sec < 60) {return sec + ' sec. ago';
}let min = Math.floor(diff / 60000); // 将 diff 转换为分钟
if (min < 60) {return min + ' min. ago';
}// 格式化 date
// 将前置 0 加到一位数 day/month/hours/minutes 前
let d = date;
d = ['0' + d.getDate(),'0' + (d.getMonth() + 1),'' + d.getFullYear(),'0' + d.getHours(),'0' + d.getMinutes()
].map(component => component.slice(-2)); // 得到每个组件的后两位// 将时间信息和日期组合在一起
return d.slice(0, 3).join('.') + ' ' + d.slice(3).join(':');
}alert( formatDate(new Date(new Date - 1)) ); // "right now"alert( formatDate(new Date(new Date - 30 * 1000)) ); // "30 sec. ago"alert( formatDate(new Date(new Date - 5 * 60 * 1000)) ); // "5 min. ago"// 昨天的日期如:31.12.2016 20:00
alert( formatDate(new Date(new Date - 86400 * 1000)) );

另一种解法:

function formatDate(date) {
let dayOfMonth = date.getDate();
let month = date.getMonth() + 1;
let year = date.getFullYear();
let hour = date.getHours();
let minutes = date.getMinutes();
let diffMs = new Date() - date;
let diffSec = Math.round(diffMs / 1000);
let diffMin = diffSec / 60;
let diffHour = diffMin / 60;// 格式化
year = year.toString().slice(-2);
month = month < 10 ? '0' + month : month;
dayOfMonth = dayOfMonth < 10 ? '0' + dayOfMonth : dayOfMonth;
hour = hour < 10 ? '0' + hour : hour;
minutes = minutes < 10 ? '0' + minutes : minutes;if (diffSec < 1) {return 'right now';
} else if (diffMin < 1) {return `${diffSec} sec. ago`
} else if (diffHour < 1) {return `${diffMin} min. ago`
} else {return `${dayOfMonth}.${month}.${year} ${hour}:${minutes}`
}
}

使用沙箱的测试功能打开解决方案。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/25193.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据交换平台_05_ 监控和管理消息队列

数据交换平台_05_ 监控和管理消息队列 目录概述需求:设计思路实现思路分析1.监控和管理消息拓展实现参考资料和推荐阅读Survive by day and develop by night. talk for import biz , show your perfect code,full busy,skip hardness,make a better result,wait for change,…

哈希算法实现

哈希算法概述 哈希算法(Hashing Algorithm)是一种将输入数据映射到固定大小的哈希值的算法,用于高效的查找和插入操作。哈希表(Hash Table)是哈希算法的典型应用,通过哈希函数将键映射到表中的索引位置,从而实现快速的数据存取。 以下是哈希表的一个简单实现,以及如何使…

Linux用户和用户组的管理

目录 前言一、系统环境二、Linux用户组的管理2.1 新增用户组2.2 删除用户组2.3 修改用户组2.4 查看用户组 三、Linux用户的管理3.1 新增用户3.2 删除用户3.3 修改用户3.4 查看用户3.5 用户口令&#xff08;密码&#xff09;的管理 总结 前言 本篇文章介绍如何在Linux系统上实现…

OrangePi Kunpeng Pro深度评测:性能与体验的完美融合

文章目录 一、引言二、硬件开箱与介绍1.硬件清单2.硬件介绍 三、软件介绍四、性能测试1. 功率测试2. cpu测试2.1 单线程cpu测试2.2 多线程cpu测试 五、实际开发体验1. 搭建API服务器2. ONNX推理测试3. 在线推理平台 五、测评总结1. 能与硬件配置2. 系统与软件3. 实际开发体验个…

jQuery:一站式指南

目录 jQuery&#xff1a;一站式指南前言1. jQuery简介1.1 jQuery的历史1.2 jQuery的安装 2. jQuery的核心概念2.1 选择器2.2 操作DOM2.2.1 内容操作2.2.2 属性操作2.2.3 CSS操作2.2.4 DOM结构操作 2.3 事件处理2.3.1 绑定事件2.3.2 事件委托2.3.3 解绑事件 3. jQuery的动画与效…

Unity物体材质属性Offset动态偏移

Unity物体材质属性Offset动态偏移 MeshRenderer mr;float offset;public float scrollSpeed 0.5F;private void Start(){mr GetComponent<MeshRenderer>();}void Update(){offset -Time.time * scrollSpeed;mr.material.mainTextureOffset new Vector2(0, -offset);}…

探索智慧商场的功能架构与应用

在数字化和智能化的浪潮下&#xff0c;智慧商场已经成为零售业的重要发展方向之一。智慧商场系统的功能架构设计与应用&#xff0c;结合了现代信息技术和零售业的实际需求&#xff0c;为商场的管理和运营提供了全新的解决方案。本文将深入探讨智慧商场的功能架构与应用&#xf…

SpringAOP-代理方式-Cglib动态代理

文章目录 cglib动态代理 cglib是基于继承的方式实现的 是继承目标类从而产生代理类 springaop底层使用的就是cglib的动态代理 package com.itheima.cjlibproxy;import net.sf.cglib.proxy.Callback; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodI…

matlab---app

一 基础 标签和信号灯没有回调函数 clc,clear,close all %清理命令区、工作区&#xff0c;关闭显示图形 warning off %消除警告 feature jit off %加速代码运行 ysw{i}i %循环赋值 celldisp(ysw) %显示元胞数组ysw.y1{1}[1,2] …

shaderlab 关键点记录

1.C#获取着色器标签的接口 可以使用 Material.GetTag API 从 C# 脚本中读取子着色器标签&#xff0c; 2.常用的标签 subshader的标签 “RenderPipeline” “[name]” //向 Unity 告知此子着色器是否与 URP 或 HDRP 兼容。 值&#xff1a;UniversalRenderPipeline //此…

leetcode够用之java语法

常用方法 Arrays.sort()排序 import java.util.Arrays;public class Main {public static void main(String[] args) {int[] numbers {9, 2, 5, 1, 7, 3};Arrays.sort(numbers);System.out.println(Arrays.toString(numbers)); // 输出: [1, 2, 3, 5, 7, 9]} }获取str中的第…

《软件定义安全》之二:SDN/NFV环境中的安全问题

第2章 SDN/NFV环境中的安全问题 1.架构安全 SDN强调了控制平面的集中化&#xff0c;从架构上颠覆了原有的网络管理&#xff0c;所以SDN的架构安全就是首先要解决的问题。例如&#xff0c;SDN实现中网络控制器相关的安全问题。 1.1 SDN架构的安全综述 从网络安全的角度&…

@BeforeAll 和 @AfterAll 必须是 static 的原因

BeforeAll 和 AfterAll 必须是 static 的原因 执行时机&#xff1a; BeforeAll 方法在所有测试方法之前运行。AfterAll 方法在所有测试方法之后运行。 实例化前/后的执行&#xff1a; 因为 BeforeAll 是在所有测试方法执行之前运行的&#xff0c;所以它在任何一个测试实例创建…

基于springboot的教学管理系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;教师管理&#xff0c;学生管理&#xff0c;课程管理 教师账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;学生管理&#xff0c;课程管理&#xff0c;课程表…

Oracle 数据库的自动化工具:AWR 和 ASM

Oracle 数据库提供了一系列工具和技术&#xff0c;以提高数据库管理的效率和性能。其中&#xff0c;AWR和 ASM是两个关键组件。本文将详细介绍 AWR 和 ASM 的功能及其在数据库管理中的重要性。 AWR AWR 是 Oracle 数据库的一个核心部分&#xff0c;用于收集、处理和维护数据库…

数据结构---树与二叉树

个人介绍 hello hello~ &#xff0c;这里是 code袁~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的…

【CTF MISC】XCTF GFSJ0290 reverseMe Writeup(图像处理)

reverseMe 暂无 解法 导入 Photoshop。 水平翻转&#xff0c;得到 flag。 Flag flag{4f7548f93c7bef1dc6a0542cf04e796e}声明 本博客上发布的所有关于网络攻防技术的文章&#xff0c;仅用于教育和研究目的。所有涉及到的实验操作都在虚拟机或者专门设计的靶机上进行&#xf…

QField如何打开工程或数据文件

Field有个文件选择器&#xff0c;允许从本地设备打开工程。如果想从云端打开文件&#xff0c;请参阅 QFieldCloud 。 注意&#xff1a;请注意&#xff0c;卸载QField时&#xff0c;应用程序文件夹将被删除&#xff0c;而更新则不会。 导入并打开本地工程 QField界面 当转到 …

了解Synchronized对象头?

1、对象头的结构 Java对象存储在内存中结构为&#xff1a; 对象头&#xff08;Header&#xff09;&#xff1a;实例数据&#xff08;Instance Data&#xff09;&#xff1a;定义类中的成员属性对齐填充字节&#xff08;Padding&#xff09;&#xff1a;由于HotSpot虚拟机的自…

Web Dart前端:探索、挑战与未来展望

Web Dart前端&#xff1a;探索、挑战与未来展望 在数字化浪潮的推动下&#xff0c;Web前端技术日新月异&#xff0c;其中Dart语言作为一种高效且灵活的编程语言&#xff0c;正逐渐在Web前端领域崭露头角。然而&#xff0c;Dart在Web前端的应用仍面临诸多挑战和未知。本文将从四…