年末感慨


转眼之间,一年的最后一天来了。

2017,技术界貌似正在飞跃。多年的量变终于引起了质变。

人工智能,区块链。对此,我很激动,激动着有点害怕,害怕中有点紧张,还有点渴望。未来的至高点,未来的风口,自己作为一个小小的菜鸟程序员,能够抢占呢?能否参与吗?改变世界?

火车上,回家后,看完了《神们自己》,想起以前囫囵吞枣看的《北京折叠》,这些科幻,离我们,真的很远吗?也曾看过一些历史穿越装逼小说,活了21个年岁,终于也渐渐感受到历史和人类的伟大。从倾向于文采的那个时代,到实业兴邦的近代,甚至到如今支付宝、比特币刷新实体货币。

中国现在很强。


不过下面还是来说说时间的format函数吧

实业兴邦啊(互联网当然也是实业啦,当时的虚业我猜应该是写诗之类的吧,这里就先不百度了)

一.目标程序

一个时间format函数,用法 format(date,"yyyy-MM-dd hh-mm-ss"),参数可变

  1. const format = (value, format = "yyyy-MM-dd hh:mm:ss") => {
  2. const date = new Date(value);
  3. const o = {
  4. "M+": date.getMonth() + 1, // 月份
  5. "d+": date.getDate(), // 日
  6. "h+": date.getHours(), // 小时
  7. "m+": date.getMinutes(), // 分
  8. "s+": date.getSeconds(), // 秒
  9. "q+": Math.floor((date.getMonth() + 3) / 3), // 季度
  10. "S": date.getMilliseconds() // 毫秒
  11. };
  12. let fmt = format;
  13. if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1,
  14. (`${date.getFullYear()}`).substr(4 - RegExp.$1.length));
  15. Object.keys(o).forEach((k) => {
  16. if (new RegExp(`(${k})`).test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ?
  17. (o[k]) :
  18. ((`00${o[k]}`).substr((`${o[k]}`).length)));
  19. });
  20. return fmt;
  21. };

二.不要小看上面的函数,用到的知识点其实还是不少的

现在的技术真是一环扣一环,所以要重视基础啊。

1.关于Date对象方法

getDate,getDay,getMonth,getFullYear(getYear已经被弃用了)

getHours,getMinutes,getSeconds

2. substr的运用 --- 一个Array对象的方法(我们来跟 substring 比较下)

substr(start, length) "slfjlsjf".substr(0,4) => "slfj"

"slfjlsjf".substr(1,4) => "lfjl"

substring(start, end) "slfjlsjf".substring(0,4) => "slfj"

"slfjlsjf".substring(1,4) => "lfj"

  • `上面两个方法不改变原数组

3.RegExp的$

RegExp.$1-$9:MDN上的解释是,该特性是非标准的,尽量不要在生产环境使用。

==貌似已经使用了。

该属性是只读的,而且只有在正确匹配的情况才会改变.

括号匹配项是无限的,但是RegExp对象能捕获的只有9个。

这些属性可以在 String.replace 方法中替换字符串,在这种情况下,不用在前面加上RegExp

  1. const reg = /(\w+)\s(\w+)/;
  2. const str = "hello haha";
  3. console.log("pre:", RegExp.$1, RegExp.$2); // test.js
  4. const a = reg.test(str);
  5. console.log("after:", RegExp.$1, RegExp.$2); // hello haha

我们发现一件非常有趣的事情。node环境下,默认的 RegExp.$1 竟然是文件的名字

此后的 RegExp.$1 为第一个括号所匹配的 hello

RegExp.$2 为第二个括号所匹配的 haha


4.Object.keys(o)

  1. Object.keys() 方法会返回一个给定对象自身可枚举属性组成的数组。

数组中属性名的排列顺序和使用 for ... in 循环遍历该对象返回的顺序一致。

(两者的主要区别是 一个 for ... in 循环还会枚举 其原型链上的属性

  • 根据MDN的解释,该方法在 ES5 和 ES2015(原名ES6) 的解释是不同的

Object.keys("foo"); // TypeError: "foo" is not an object (ES5 code)

Object.keys("foo"); // ["0", "1", "2"]

我自己在我电脑的 Node 6 环境下即为后者的结果

Node.js 是针对V8引擎的现代版本而构建的。根据其文档来看,Node 已经对 ES2015的许多东西进行了实现。

  • 该方法的正常使用

const o = { "one": 1, "two": 2 }

console.log(Object.keys(o)); // ['one', 'two']

  • 该方法和它的兄弟们的区别:for in / Object.keys / Object.getOwnPropertyNames

共同点:三者皆可遍历对象。

不同点:摘自:https://www.cnblogs.com/37sky/articles/5324105.html

  1. const parent = Object.create(Object.prototype, {
  2. a: {
  3. value: 1,
  4. writable: true, // 可写
  5. enumerable: true, // 可枚举
  6. configurable: true // 能否使用访问器, 能够delete
  7. }
  8. });
  9. // 上面的 parent - a可以被枚举
  10. const child = Object.create(parent, {
  11. b: {
  12. value: 2,
  13. writable: true,
  14. enumerable: true,
  15. configurable: true
  16. },
  17. c: {
  18. value: 3,
  19. writable: true,
  20. enumerable: false,
  21. configurable: true
  22. }
  23. });
  24. // b可枚举,c不可枚举
  25. // TEST 1 --- es3 for...in
  26. for (const attr in child) {
  27. console.log(attr); // ------------> b,a
  28. }
  29. // Result: for in 会输出自身以及原型链上可枚举的可见的属性
  30. // TEST 2 --- es5 Object.keys
  31. console.log(Object.keys(child)); // ----------> ['b']
  32. // Result: Object.keys 会输出 自身(仅自身,不包括原型链)可枚举的可见属性
  33. // TEST 3 --- es5 Object.getOwnPropertyNames
  34. console.log(Object.getOwnPropertyNames(child)); // ------> ['b', 'c']
  35. // Result:Object.getOwnProperyNames 会输出 自身(不包括原型链)所有的可见属性
  36. // TEST 4 --- es6 for ... of
  37. for(var i of child) {
  38. console.log(i);
  39. }
  40. // Result: 很遗憾,node 6.10.0 还不支持它
这里做个总结:
  • Object.keys可以输出自身(不包括原型链)的可枚举的可见属性。
  • Object.getOwnPropertyNames可以输出(不包括原型链的)的所有可见属性。
  • for in 可以输出自身和原型链 可枚举(不可枚举则不行)的可见属性。
Object.keys 可以说是要求最严格的,严谨。

5.同时引出JS Object的几个属性

学习链接:http://blog.csdn.net/qq_17335153/article/details/52584727

  • Configurable
  • Enumerable
  • Writable
  • Value
  • Getter
  • Setter
数据属性
  1. const obj = {};
  2. Object.defineProperty(obj, 'name', {
  3. configurable: false,
  4. enumerable: false,
  5. writable: false,
  6. value: 'test'
  7. });
  8. console.log(obj.name);
  9. obj.name = 'write';
  10. console.log(obj.name); // test ,修改失败
  11. console.log("用delete", delete obj.name); // false, delete失败
  12. console.log(obj.name); // 完好如初
  13. Object.defineProperty(obj, 'name', {
  14. configurable: true // 不可修改,将抛出错误
  15. });
访问器属性:C# ???
  1. const book = {
  2. _year: 2004, // 加 _ ,代表属性只能通过对象方法访问
  3. edition: 0
  4. }
  5. Object.defineProperty(book, 'year', {
  6. get: function () {
  7. return this._year;
  8. },
  9. set: function (newValue) {
  10. this._year = newValue;
  11. this.edition += newValue - 2004;
  12. }
  13. });
  14. console.log(book.year); // 2004
  15. book.year = 2006;
  16. console.log(book.year); // 2006 若无 set,则依旧为 2004

三.最后的难点

  1. fmt = fmt.replace(RegExp.$1,
  2. (`${date.getFullYear()}`).substr(4 - RegExp.$1.length));

此句话的作用主要是:当我们写的是 'yyy' 的时候,只会返回年份值的后三个数

  1. Object.keys(o).forEach((k) => {
  2. if (new RegExp(`(${k})`).test(fmt)) fmt = fmt.replace(RegExp.$1,
  3. (RegExp.$1.length === 1) ?
  4. (o[k]) :
  5. ((`00${o[k]}`).substr((`${o[k]}`).length)));
  6. });

使用ES6的模板引擎语法 将属性字符串变为一个个正则表达式

最后使用 replace 一一替换

重点注意,以下两句话是不一样的

http://blog.csdn.net/u010552788/article/details/51019367

  1. console.log("test", new RegExp(`${k}`));
  2. console.log("test2", new RegExp(`(${k})`));

看似只是一句括号之差,但是我们这里需要用到 RegExp.$1

如若用第一种,$ 是没有办法匹配到的

此后依次匹配到 MM hh 等,之后采用 replace 的方法 分别将 MM hh 等替换为

我们的 o[k] 对象。

其后的三元运算符又是什么意思呢?

原来是这样:

假设我们返回的秒数o[k] = 1 ,那么这里我们应该给它显示 01 不是吗?

所以我们这里使用 (00${o[k]}).substr((${o[k]}).length) 来替换

根据是 1 位 还是 2 位 来决定使用 (008).substr(1) = 08 // 8秒

还是 (0018).substr(2) = 18 // 18秒

  1. 对于length = 1 的情况。
  2. 1.此句为了 当分钟数或者秒数或者..... 个位数的时候 显示 '01', '02', '08'之类的
  3. 2.一般情况下,没有 "q+" "S" 的匹配了。具体看 fmt 是否有东西。
  4. 3.对于秒来说,这里的判断其实不会走 RegExp.$1.length === 1 (true)
  5. 4.对于毫秒 S 来说,会走这步。所以 = 1的情况是为了毫秒而准备的。

四.至此,大功告成

一段小小的程序,却能发掘出这么多我不懂的东西。还是差的太远了我,基础。

时间format函数引爆的知识点和年末有话说的更多相关文章

  1. Javascript扩展Date的prototype实现时间format函数 2017-06-29T09:10:00.000Z日期转换

    /*时间格式化 公用方法*/ Date.prototype.format = function(fmt) { // var o = { "M+": this.getMonth() ...

  2. 利用Format函数格式化时间和日期

    在做机房收费系统的时候,因为需要使用到日期进行查询,所以在数据表中没有使用自动添加日期的功能,而是采用了自定义的格式插入.但由于事先没有对时间转换的格式进行统一,导致后面查询时出现的问题不断. 插入时 ...

  3. sql server中format函数的yyyyMMddHHmmssffff时间格式兼容旧版sql写法

    问题:博主看到项目脚本,有些地方使用了format函数来把当前日期转换成yyyyMMddHHmmssffff的格式,但在测试环境数据库是sql 2008 r2,是不支持format这个函数的.脚本会报 ...

  4. Format 函数示例

    Format 函数示例本示例显示用 Format 函数做格式化输出的不同用法.对于日期分隔号(/),时间分隔号(:),以及 AM/ PM 等文本而言,其真正的显示格式会因计算机上的国际标准不同而有所差 ...

  5. MySQL 日期、时间转换函数

    MySQL 日期.时间转换函数:date_format(date,format), time_format(time,format) 能够把一个日期/时间转换成各种各样的字符串格式.它是 str_to ...

  6. PHP的日期和时间处理函数

    1. 将日期和时间转变为时间戳 1.1 time() 原型:time(void) 作用:返回当前时间的 UNIX时间戳. 参数:void,可选(即无参数) 1.2 mktime() 原型:int mk ...

  7. DATEADD和DATEDIFF函数、其他日期处理方法 、已打开的端口、FORMAT函数

    DATEADD和DATEDIFF函数.其他日期处理方法 .已打开的端口.FORMAT函数 DATEADD和DATEDIFF函数.其他日期处理方法 .已打开的端口.Format函数 KeyLife富翁笔 ...

  8. MySQL 获得当前日期时间\时间戳 函数 ( 转自传智播客)

    MySQL 获得当前日期时间 函数 1.1 获得当前日期+时间(date + time)函数:now() mysql> select now(); +-------+ | now() | +-- ...

  9. JS 时间格式化函数

    //时间格式化函数 Date.prototype.format = function (format) { var o = { "M+": this.getMonth() + 1, ...

随机推荐

  1. OpenCV - Windows(win10)编译opencv + opencv_contrib

    在之前的几篇文章中,我提到了在Android.Linux中编译opencv + opencv_contrib,这篇文章主要讲在Windows中编译opencv + opencv_contrib. 首先 ...

  2. Gym - 100570E:Palindrome Query (hash+BIT+二分维护回文串长度)

    题意:给定字符串char[],以及Q个操作,操作有三种: 1:pos,chr:把pos位置的字符改为chr 2:pos:问以pos为中心的回文串长度为多长. 3:pos:问以pos,pos+1为中心的 ...

  3. SparkWriteToHFile

    1. HFile的LoadIncrement卡住 原来是因为权限,我一直以为,load函数之后是要删除文件的,但是hdfs://slave1:8020/test/info文件夹所有的是只读权限,而且考 ...

  4. C#分词算法

    本文用到的库下载:点此下载 词库下载:点此下载 将词库直接放到项目根目录 词库设置如下: 类库说明 词库查看程序:点此下载 可以在上面的程序中添加常用行业词库 还可以通过下面的类在程序中实现 完整的盘 ...

  5. PopupWindow-----listview item的点击出现PopupWindow

    /** * 设置listview item的点击事件 */ lv_app_manager.setOnItemClickListener(new OnItemClickListener() { @Ove ...

  6. 一个自动修改本地IP地址的BAT

    set /a num1=%random%%%200+1+1  //生成随机数set ip=192.168.1.//ip 主体set ip1=%ip%%num1% //拼接两部分cmd /c netsh ...

  7. Spring pom配置详解(转)

    转载至http://blog.csdn.net/ithomer/article/details/9332071# 原博主注释的很详细 <project xmlns="http://ma ...

  8. oracle上课 学习2 oracle 游标 存储过程 有用

    1.1. 训练描述 使用游标,打印emp中20号部门的所有员工的信息 操作步骤答案 declare cursor c_emp  is select * from emp where deptno=10 ...

  9. 文件格式——gff格式

    Gff文件格式 gff格式是Sanger研究所定义,是一种简单的.方便的对于DNA.RNA以及蛋白质序列的特征进行描述的一种数据格式,已经成为序列注释的通用格式,比如基因组的基因预测,许多软件都支持输 ...

  10. java多态和强制类型转换

    子类可以赋值给超类,称之为向上转型,这个是自动的. 超类不可以赋值给子类,这个是向下转型,需要我们手动实现. 赋值给超类的子类引用在运行期间将表现出不同的特性,这就是多态. 小类型    可转换为   ...