网赚论坛

 找回密码
 免费注册
查看: 188|回复: 0
打印 上一主题 下一主题

《Nodejs开发加密货币》之十八:关于时间处理的相关问题

[复制链接]

11

主题

74

帖子

46

积分

Ⅰ级财主

Rank: 1

积分
46
跳转到指定楼层
楼主
发表于 2017-11-28 16:14:25 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
前言

时间戳是很多应用系统,特别是加密货币开发设计中非常重要的元素。各种语言都提供了相应的时间处理函数,以前直接拿来就用了,也没有发现什么问题。但是javascript语言里,有一个Date类的函数非常奇葩,网络上很多文档的举例都是错误的,因此简单总结一下,提醒以后别在这个小问题上翻船。

问题再现

请猜想下面的语句应该输出哪一天:

  • ```
  • new Date(Date.UTC(2005,7,8));```

复制代码
结果是: `Mon Aug 08 2005 08:00:00 GMT+0800 (中国标准时间)` , 即: `2005年8月8日`

但是,看看这篇文档的解释 http://www.w3school.com.cn/jsref/jsref_utc.asp

其实,网上还有很多文档犯了这个错误。我本人也是在反复没有获得想要的结果情况下,才着手查询文档的。

这本不是什么大问题,不过自己有点强迫症,担心万一还有更多“非常规”的用法存在,那么这种看似很小的问题,可能就是致命的(逻辑上没问题,意识中没发现)。如果按照前面关于异常和错误的处理要求,这种错误应该是程序员自身的问题了,唯一的解决办法就是提高能力,让自己更加严谨、更加认真。所以,这篇文章就是查缺补漏的。

不同产品对时间处理的需求

我在思考这样一个问题:作为加密货币,亿书对每笔交易都有时间戳,而且对版权保护,时间戳还是非常重要的字段。如果,亿书一个节点在中国,另一个在美国,那么这个时间处理该如何统一,相关的方法该如何选择?

从理论上分析,不同产品可能对时间处理的需求也不相同。

1.对于一般的应用系统,特别是没有国际化要求的产品,时间自然没有特殊要求,前端后台统一是很简单的事,只要避免上面的失误,正确使用时间相关的接口函数即可。

2.对于有国际化需求的产品,特别是加密货币这种去中心化的产品,全世界的用户都在使用,就要考虑两个方面的因素,一个是面向用户的时间本地化问题,另一个是面向产品后台的时间统一性问题。

时间处理基本原理

天下人的时间都是一样的。但是,相同时刻,不同时区的人们,所处的时空是不一样的。不同时区,人们对于时空的感受又是那么惊奇的相似,比如:除了南北极,大多数地方都是早上五六点钟太阳升起,中午12点左右艳阳高照,下午五六点钟日落西山,如果一个中国人去了美国(比中国晚13个小时),原本是中午艳阳高照,一看手表,竟然是午夜0点钟,还不得精神分裂啊,因此为了迎合人类习惯,自然就有了很多的本地化需求。

从编程的角度看,时间具备唯一、均匀和恒定的特点,只要使用统一确定的参考点,就不至于在系统中出现混乱。所以,对应上面的产品需求,对于不需要国际化的产品,只要使用本地化时间处理方法即可(参考点是本地),前后端统一,逻辑简单。而对于国际化的产品,那就使用世界时间(参考点是国际日期变更线,UTC或GMT标准时间),然后在客户端面向用户进行本地化处理即可。

Javascript的Date对象

js提供了操作日期和时间的对象Date。Date对象是js语言的一中内部数据类型(类函数),要使用语法new Date()创建。创建了对象之后,就可以使用多种方法来操作它了。这里列出几个需要熟练掌握的细节供参考。

(1)构造函数

  • ```
  • new Date();
  • new Date(milliseconds);
  • new Date(dateString);
  • new Date(year, month[, day[, hour[, minutes[, seconds[, milliseconds]]]]]);```

复制代码
简单一句话:新建对象可以使用0~7个参数,这些参数可以是字符串或数字。

(2)参数

需要注意的是:


  • - Date时刻面向本地时间,参数代表的是本地时间,新建的对象代表的也是本地时间,输出的结果后面通常有`(某国标准时间)`等字样;
  • - 0参数,代表当前日期和时间;
  • - 1参数,若是数字milliseconds,应该是距离1970年1月1日午夜(UTC)的毫秒数,通常使用Date.UTC()函数来设定;若是字符串dateString,应该是时间格式,如:`new Date('December 17, 1995 03:24:00');`
  • - 2~7参数,只能是数字。*只有`day`从1开始,其他都是从0开始*。因为周期通常采取取模运算,所以如果数值大于合理范围(如月份为13),数值会被自动调整。比如: new Date(2013, 13, 1)等于new Date(2014, 1, 1),它们都表示日期2014-02-01(注意月份是从0开始的)。- 如果需要世界时,要使用 new Date(Date.UTC(...)) 和相同参数。


(3)方法

关于方法要注意两点:


  • 静态方法:3个,都返回距离标准时间的毫秒数,分别对应构建函数三个形式,其中包括 Date.now()、Date.parse()(解析一个表示日期的字符串)、Date.UTC() (从2到7参数)。实例方法:4种,get类查询方法、set类设置方法、to类转换方法、of类,其中每种方法,都提供了本地和世界时两个参考系的方法,比如get[UTC]Date()方法。

特别注意的是:getTime()方法不分时区,返回Date对象的内部毫秒表示,这将是去伪存真的唯一途径,比如:如何判断不同时区是否同时呢,仅仅看这个方法的返回值就是了, 应该说在世界上不同时区,同时运行`(new Date()).getTime()`的返回值是一样的。

实践

编程里,需要处理的问题,无非是这样几个场景(下面的代码来自官方文档和亿书源码):

(1)记录时间

  • ```
  • var today = new Date(); //本地当前日期和时间
  • var birthday = new Date("1995-12-17T03:24:00"); //1995年12月17日
  • var birthday = new Date(1995,11,17); //1995年12月17日```

复制代码
如果需要格式化,就可以使用上面提到的to为前缀的转换方法,例如:toLocaleDateString()、toLocaleString()等,如果不满意,就找找现成的扩展插件,比如moment.js。如果仍不满意,那就自己实现吧,也很简单。

(2)计算时间

主要原则是计算距离标准时间的毫秒数,然后再计算。因为这类方法本身就是基于世界时UTC的,并且在计算过程中可能使用减法处理时间段(差值),因此参考点抵消,可以不去考虑参考点的存在。

这方面被大量用到项目中,也有很多第三方包存在,比如:timeago.js之类的,下面简单举例:

使用 Date 对象:

  • ```
  • var start = Date.now();

  • // 这里进行耗时的方法调用:
  • doSomethingForALongTime();
  • var end = Date.now();
  • var elapsed = end - start; // 运行时间的毫秒值```

复制代码
使用内建的`getTime()`方法(推荐):

  • ```
  • // 设置初始时间
  • var begin = Date.UTC(2016, 6, 1, 0, 0, 0, 0); // 2016年7月1日,月份从0开始

  • // 获得当前时间
  • var now = new Date();
  • var elapsed = now.getTime() - begin.getTime(); // 毫秒值```

复制代码
链接

本系列文章即时更新,若要掌握最新内容,请关注下面的链接

本源文地址: https://github.com/imfly/bitcoin-on-nodejs

电子书阅读: http://bitcoin-on-nodejs.ebookchain.org

官方Q交流群:185046161

参考

[国际日期变更线]:http://baike.baidu.com/link?url=KXEt7IGgVrZmHTpJbDXFHfeJ4O2S7XCmHZiO9EFhAZOMWCaaW0clTFxIHK--M0lZdkLBWvzar7atrtUG9Js-Xq

[JavaScript标准库 Date文档]:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Date

[亿书白皮书]: http://ebookchain.org/ebookchain.pdf

[亿书官方网站]: http://ebookchain.org/
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

广告合作|Archiver|手机版|小黑屋|财富吧

GMT+8, 2024-12-29 14:26 , Processed in 0.171601 second(s), 35 queries , Gzip On.

Powered by Discuz! X3.1

© 2014-2021 财富吧

快速回复 返回顶部 返回列表