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-DD 或 YYYY-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}` } }使用沙箱的测试功能打开解决方案。
相关文章:
JavaScript 编程语言【 数据类型】日期和时间
文章目录 日期和时间创建访问日期组件设置日期组件自动校准(Autocorrection)日期转化为数字,日期差值Date.now()基准测试(Benchmarking)对字符串调用 Date.parse总结✅任务创建日期显示星期数欧洲的星期表示方法许多天…...
RabbitMQ简单使用方法,以异步处理日志为例:
在RabbitMQ中异步记录日志的实现可以分为生产者将日志消息发送到队列,以及消费者从队列中取出消息并记录日志。当搭建好消息队列后,需要确保消费者持续运行,以便随时处理新进入的日志消息。 步骤一:设置生产者发送日志消息到Rabb…...
二分+模拟,CF1461D - Divide and Summarize
一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 Problem - 1461D - Codeforces 二、解题报告 1、思路分析 我们发现每次分裂操作结果都是固定的 我们从初始序列分裂出两个确定的子序列,两个确定的子序列又分裂出4个确定的子序列 那么也就是说…...
C#操作MySQL从入门到精通(16)——使用子查询
前言: 我们在查询数据的过程中有时候查询的数据不是从数据库中来的,而是从另一个查询的结果来的,这时候就需要使用子查询,本文使用的测试数据如下: 1、子查询 下面的代码就是先查询地址是安徽和广西的学生年龄,然后获取年龄对应的姓名 private void button__SubQuery…...
【vue实战项目】通用管理系统:图表功能
目录 前言 1.概述 2.数据概览页 2.1.柱状图 2.2.折线图 2.3.地图 前言 本文是博主前端Vue实战系列中的一篇文章,本系列将会带大家一起从0开始一步步完整的做完一个小项目,让你找到Vue实战的技巧和感觉。 专栏地址: https://blog.csd…...
第99天:权限提升-数据库提权口令获取MYSQLMSSQLOracleMSF
案例一:提权条件-数据库帐号密码获取方式 提权条件 - 数据库帐号密码获取方式 0 、网站存在高权限 SQL 注入点 1 、数据库的存储文件或备份文件 2 、网站应用源码中的数据库配置文件 3 、采用工具或脚本爆破 ( 需解决外联问题 ) sql注入点 xhcms后台管理系统…...
Java 环境配置 -- Java 语言的安装、配置、编译与运行
大家好,我是栗筝i,这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 002 篇文章,在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验,并希望进…...
升级最新版openssh-9.7p1及openssl-1.1.1h详细步骤及常见问题总结
近期因为openssh相继被漏洞扫描工具扫出存在漏洞,所以考虑升级操作系统中的openssh和openssl为最新版本,来避免漏洞风险。期间的升级过程及遇到的疑难问题,特此记录下来,供有需要的人参考。 本次目标是升级 openssh 为 9.7p1 版本…...
学习使用 Frida 过程中出现的问题
一、adb shell命令报错:error: no devices found 目前该问题解决方法仅供参考,可先看看再选择试试!!!!! 查看此电脑也会发现没有出现手机型号文件夹。 第一步: 检查一下手机开了u…...
Java实现简单词法、语法分析器
1、词法分析器实现 词法分析器是编译器中的一个关键组件,用于将源代码解析成词法单元。 词法分析器的结构与组件: 通常,词法分析器由两个主要组件构成:扫描器(Scanner)和记号流(Token Stream&a…...
Python实现半双工的实时通信SSE(Server-Sent Events)
Python实现半双工的实时通信SSE(Server-Sent Events) 1 简介 实现实时通信一般有WebSocket、Socket.IO和SSE(Server-Sent Events)三种方法。WebSocket和Socket.IO是全双工的实时双向通信技术,适合用于聊天和会话等&a…...
python中的解包操作(*和**)
在Python中,* 和 ** 用于函数定义和函数调用时的参数解包和传递,它们有不同的用途和作用。以下是它们的详细解释和区别: 单星号 (*) 1. 位置参数解包(函数调用) 在函数调用时,* 用于将列表或元组解包成位…...
Lua 时间工具类
目录 一、前言 二、函数介绍 1.DayOfWeek 枚举定义 2.GetTimeUntilNextTarget 3.GetSpecificWeekdayTime 三、完整代码 四、总结 一、前言 当我们编写代码时,我们经常会遇到需要处理日期和时间的情况。为了更方便地处理这些需求,我们可以创建一个…...
Qt——Qt网络编程之TCP通信客户端的实现(使用QTcpSocket实现一个TCP客户端例程)
【系列专栏】:博主结合工作实践输出的,解决实际问题的专栏,朋友们看过来! 《项目案例分享》 《极客DIY开源分享》 《嵌入式通用开发实战》 《C++语言开发基础总结》 《从0到1学习嵌入式Linux开发》 《QT开发实战》 《Android开发实战》 《实用硬件方案设计》 《结构建模设…...
Qt信号槽与函数直接调用性能对比
1. 测试方法 定义一个类Recv,其中包含一个成员变量num和一个成员函数add(),add()实现num的递增。 另一个类Send通过信号槽或直接调用的方法调用Recv的add函数。 单独开一个线程Watcher,每秒计算num变量的增长数值,作为add函数被调…...
Python中的异常处理:try-except-finally详解与自定义异常类
Python中的异常处理:try-except-finally详解与自定义异常类 在Python编程中,异常处理是确保程序健壮性和可靠性的重要部分。当程序遇到无法预料的错误时,异常处理机制能够防止程序崩溃,并允许我们采取适当的措施来解决问题。本文…...
vscode软件上安装 Fitten Code插件及使用
一. 简介 前面几篇文章学习了 Pycharm开发工具上安装 Fitten Code插件,以及 Fitten Code插件的使用。 Fitten Code插件是是一款由非十大模型驱动的 AI 编程助手,它可以自动生成代码,提升开发效率,帮您调试 Bug,节省…...
人工智能小作业
1.问题 将下列句子用一阶谓词形式表示: (1)雪是白的。 (2)数a和数b之和大于数c。 (3)201班的学生每人都有一台笔记本电脑。 2.答案 句子(1)“雪是白的”可以表示为: White(雪)。 句子(2)“数a和数b…...
程序员搞副业一些会用到的工具
微信号采集(爬虫)技术的选型 那么,我们应该使用什么技术来从庞大的网页内容中自动筛选和提取微信号呢?答案就是:数据采集技术,也就是爬虫技术。 然而,数据采集技术种类繁多,我们具体应该采用哪一个呢&…...
k8s更改master节点IP
背景 搭建集群的同事未规划网络,导致其中有一台master ip是192.168.7.173,和其他集群节点的IP192.168.0.x或192.168.1.x相隔太远,现在需要对网络做整改,方便管理配置诸如绑定限速等操作。 master节点是3节点的。此博客属于事后记…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...
【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...
windows系统MySQL安装文档
概览:本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容,为学习者提供全面的操作指导。关键要点包括: 解压 :下载完成后解压压缩包,得到MySQL 8.…...
