更新 : 2019-06-17

常用 moment

1. Get start of day

moment().startOf('day')
 
2. Check same day
if(date!.isSame(moment(), 'day'))
 
3. Parse string by format
moment('2019-01-02', 'ha')  

4. to age

const language = this.languageService.match({
'en-US' : 'en-US',
'zh' : 'zh-CN'
});
return moment(date).locale(language).fromNow();

5. start of week 是星期天, isoWeek 是星期一

moment().startOf('isoWeek')
 
 
 

提醒

记得放 SetTimeZoneInfo, 不然 response Date value 会依据 local machine, 这是不对的.

app.UseMvc(config =>
{
// OData
config.SetTimeZoneInfo(TimeZoneInfo.Utc);
config.Select().Expand().Filter().OrderBy().MaxTop(null).Count();
config.EnableDependencyInjection();
config.MapODataServiceRoute("WebApi", "api", ODataBuilder.GetEdmModel());
});

http://192.168.1.152:61547/api/orders?$filter=datetime eq 2019-05-18T09:29:27.019%2B08:00

+08.00 在 query 要记得 encode 成 %2B 哦

参考 :

https://stackoverflow.com/questions/29979609/time-conversion-with-timezoneinfo-for-past-years

https://nodatime.org/

不常出国的人对 timezone 可能感到陌生.

这篇特地做了一些整理.

首先说说准备的资料 :

1. offset != timezone

offset 是说 +08:00, -03:00, 它表示某个时间和 UTC 的时差.

timezone 是说 Singapore Standard Time (SST), Greenwich Mean Time (GMT), 它表示某个时间规范.

举个例子就明白了,Singapore Standard Time 这个 timezone 在过去 100 年里,修改了 offset 不下 5 次.

比如 1905 年, offset 是 +07:30 而如今却是 +08:00, 所以如果我问你, 1905-10-15 03:00:00 PM 英国是新加坡的几点... 你用现在的 offset 来算, 就会计算错误了.

2. javascript 自带了 timezone (历史所有 offset 调整计入都有)

当我们 new Date 时, 会依据当前的 timezone 去创建时间. 比如 new Date(1905,0,1) 和 new Date(2018,0,1) 在新加坡的话, 它们的 offset 是不一样的.

3. 当我们想表达一个时间的时候,,我们一定要记得有 timezone 的概念,比如我说 18年3月16日 旁玩5点...这个就不对了,因为你说的是美国的 5 点还是中国呢 ?

但也有一种例外, 比如我说圣诞节是在 12 月 15 日, 那么我想表达并不是任何一个 timezone, 而是每一个 timezone 都不一样的时间. 就好像我们倒数跨年一样.

4. angular material datepicker moment 选择日期是 local 的, 可以通过设置调成 utc. 但是无法设置任意 timezone, 要嘛 local 要嘛 utc, 不能指定说我要选美国的 timezone. (目前不行, 可以通过覆盖 adapter + moment timezone 自己扩展)

5. asp.net core 没有 timezone history, 只有某个 timezone 当今的 offset. 所以我们无法向 javascipt 那样任意的去创建一个准确 offset 很久以前的日子。

需要通过插件 nodatime 去实现. https://nodatime.org  (就是 java 的 jodatime 啦, 也支持 asp.net core 哦).

6. 服务端是没有办法通过 request 获取到 user 的 timezone 的, 网上很多方法使用 js 拿 offset 其实是不准确的, 记得上面说的吗, offset != timezone.

最好的方式是要求用户选择一个 timezone.

7. javascript Date to Json 会转换成 utc 时间.

8. 前后端沟通 :

utc 格式 : 2018-12-31T16:30:07.000z

offset 格式: 2018-12-31T16:30:07.000+08:00

unknown 格式 2018-12-31T16:30:07.000

一般上前 -> 后, 我们都会做一次 to json, 那么 js 自带的逻辑是 to json 后就用 utc 格式了.

但是上面 3 种格式都是可以传的, 直接传 string 不经过 json 的话, asp.net core 都可以处理.

一一举例,以后不要乱 : 前 -> 后

后是 datetimeoffset

utc = +00:00

offset = +xx:xx

unknown = +08.00 <-- 依据后端的 timezone offset

后是 datetime

utc = 时间不变, kind = utc

offset = 时间会调整到后端的 offset, kund = local

unknown = 时间不变, kind = unknown

一一举例,以后不要乱 : 后 -> 前

DateTimeOffset 输出 offset 格式

DateTime kind utc 输出 utc 格式

DateTime kind local 输出 offset 格式

DateTime kind unknown 输出 unknown 格式

js new Date() 对不同格式有不同处理哦.

new Date(utc 格式) = 时间会转换成 local

new Date(offset 格式) = 时间会转换成 local

new Date(unknow 格式) = 时间会保留, 但是它属于 local 时间了. 如果你要转来转去这个是会跑掉的哦,要注意.

9. 日期的 locale 说的是语言展现, 并不是 timezone offset.

10. sql = date, c# = datetime

c# -> sql 不过你什么 kind 只看年月日存

sql -> c# 出来肯定是 kind unknown

我的规范和对应场景 :

如果是要计入 birthday 或者是圣诞节这种不管 timezone 的日期的话

sql 使用 date, c# 用 datetime, js 用 date

后端 -> 前端, new Date + substring 前一部分的日期, 然后设置 0点0分0秒. 让它变成 local 的当天.

前段 -> 后端 , 创建 Date.utc 只拿年月日.

所以 js 是 local date, c# 和 sql 是 utc.

其余场景, date 也好,datetime 也好一律用 DateTimeOffset, sql server 也是 DateTimeOffset

后端 -> 前端 就 parse json new Date 就好了

前段 -> 后端 转换成 datetimeoffset 的格式, 而不要使用原本的 utc 格式.

搞清楚格式后, 剩下的就是沟通时的转换而已了, 比如我要 filter datetimeoffset 我可以很随意.

如果 filter date 就要小心, 记得 sql 是 utc date.

下面是参考代码

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core'; import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatMomentDateModule, MAT_MOMENT_DATE_ADAPTER_OPTIONS } from '@angular/material-moment-adapter';
import * as _moment from 'moment';
import { MatInputModule, MAT_DATE_LOCALE } from '@angular/material'; @NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
ReactiveFormsModule,
MatDatepickerModule,
MatFormFieldModule,
MatMomentDateModule,
MatInputModule
],
providers: [
// { provide: MAT_DATE_LOCALE, useValue: 'ja-JP' },
{ provide: MAT_DATE_LOCALE, useValue: 'en-US' },
{ provide: MAT_MOMENT_DATE_ADAPTER_OPTIONS, useValue: { useUtc: true } }
],
bootstrap: [AppComponent]
})
export class AppModule { }

基本设置是这样.

这里有 2 个点要注意。

第一个是 MAT_DATE_LOCALE, 这个和 timezone 一点关系也没有, 它就是表示了展现语言而已...千万不要被骗了

第二个是 MAT_MOMENT_DATE_ADAPTER_OPTIONS  useUtc, 下面是源码

  private _createMoment(...args: any[]): Moment {
return (this.options && this.options.useUtc) ? moment.utc(...args) : moment(...args);
}

如果自己想要实现的话, 可以自己实现 MomentDateAdapter 配上 moment timezone

import * as _momentTimezone from 'moment-timezone';
_momentTimezone().tz('America/Los_Angeles')

nodatime 使用

1. 创建某个 timezone 的 某个时间, 这个类似于 js 的 new Date(1934,0,1) 更强大的是 js 只能设置 local timezone, 这个还能自己选 timezone.

var timeZone = DateTimeZoneProviders.Tzdb["Asia/Kuala_Lumpur"];
var standardDate = new DateTime(, , , , , );
LocalDateTime nodaDate = LocalDateTime.FromDateTime(standardDate);
ZonedDateTime dateWithZone = nodaDate.InZoneLeniently(timeZone);
var datetimeoffset = dateWithZone.ToDateTimeOffset();

2. 把 utc 或 datetimeoffset 转换成另一个 timezone 的时间.

var timeZone = DateTimeZoneProviders.Tzdb["Asia/Kuala_Lumpur"];
var utc = new DateTime(, , , , , , DateTimeKind.Utc);
var instant1 = Instant.FromDateTimeUtc(utc);
var result1 = instant1.InZone(timeZone).ToOffsetDateTime(); var offset = new DateTimeOffset(new DateTime(, , , , , ), TimeSpan.FromHours());
var instant2 = Instant.FromDateTimeOffset(offset);
var result2 = instant2.InZone(timeZone).ToOffsetDateTime();

3. 获取所有 timezone Id

 var allTimeZones = TzdbDateTimeZoneSource.Default.ZoneLocations.ToList();

Angular 学习笔记 ( timezone + moment + material date-picker + date pipe + asp.net core )的更多相关文章

  1. Angular 学习笔记 (动态组件 & Material Overlay & Dialog 分析)

    更新: 2019-11-24  dialog vs router link refer : https://stackoverflow.com/questions/51821766/angular-m ...

  2. angular学习笔记(三十一)-$location(2)

    之前已经介绍了$location服务的基本用法:angular学习笔记(三十一)-$location(1). 这篇是上一篇的进阶,介绍$location的配置,兼容各版本浏览器,等. *注意,这里介绍 ...

  3. angular学习笔记(三十一)-$location(1)

    本篇介绍angular中的$location服务的基本用法,下一篇介绍它的复杂的用法. $location服务的主要作用是用于获取当前url以及改变当前的url,并且存入历史记录. 一. 获取url的 ...

  4. angular学习笔记(三十)-指令(10)-require和controller

    本篇介绍指令的最后两个属性,require和controller 当一个指令需要和父元素指令进行通信的时候,它们就会用到这两个属性,什么意思还是要看栗子: html: <outer‐direct ...

  5. angular学习笔记(三十)-指令(7)-compile和link(2)

    继续上一篇:angular学习笔记(三十)-指令(7)-compile和link(1) 上一篇讲了compile函数的基本概念,接下来详细讲解compile和link的执行顺序. 看一段三个指令嵌套的 ...

  6. angular学习笔记(三十)-指令(7)-compile和link(1)

    这篇主要讲解指令中的compile,以及它和link的微妙的关系. link函数在之前已经讲过了,而compile函数,它和link函数是不能共存的,如果定义了compile属性又定义link属性,那 ...

  7. angular学习笔记(三十)-指令(6)-transclude()方法(又称linker()方法)-模拟ng-repeat指令

    在angular学习笔记(三十)-指令(4)-transclude文章的末尾提到了,如果在指令中需要反复使用被嵌套的那一坨,需要使用transclude()方法. 在angular学习笔记(三十)-指 ...

  8. angular学习笔记(三十)-指令(5)-link

    这篇主要介绍angular指令中的link属性: link:function(scope,iEle,iAttrs,ctrl,linker){ .... } link属性值为一个函数,这个函数有五个参数 ...

  9. angular学习笔记(三十)-指令(2)-restrice,replace,template

    本篇主要讲解指令中的 restrict属性, replace属性, template属性 这三个属性 一. restrict: 字符串.定义指令在视图中的使用方式,一共有四种使用方式: 1. 元素: ...

随机推荐

  1. 怎样理解测试指标 :TPS和HPS

    TPS(Transaction per second) 是估算应用系统性能的重要依据.其意义是应用系统每秒钟处理完成的交易数量. 一般的,评价系统性能均以每秒钟完成的技术交易的数量来衡量. 系统整体处 ...

  2. hog cython

    pip安装cython之后,将下面代码写入hogtest2.pyx文件(我通过改文件后缀新建) import numpy as np from PIL import Image cimport num ...

  3. Lottie的json动画

    我们的设计如是说: Lottie的json动画,优缺点有 优点: 1.开发成本低,动画的还原度高.设计师导出 json 文件后,交付开发.原本要1天甚至更久的动画实现,现在只要不到一小时甚至更少时间了 ...

  4. python ---12 生成器 推导式

    一.生成器 函数中有yield 的就是生成器函数(替代了return) 本质就是迭代器   一个一个的创建对象     节省内存 1.创建生成器 最后以yield结束 1. 通过⽣成器函数   2. ...

  5. springboot项目打包部署在指定的tomcat容器中

    1.首先需要修改项目的打包方式,将package改为war <packaging>war</packaging> 2.移除spring boot web中的嵌入式tomcat ...

  6. JSON(JavaScript Object Notation, JS 对象标记)

    JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式.它基于 ECMAScript (w3c制定的js规范)的一个子集,采用完全独立于编程语言 ...

  7. ODAC(V9.5.15) 学习笔记(四)TCustomDADataSet(2)

    2.连接相关 名称 类型 说明 Connection 指向一个数据库连接对象 Disconnected 设置为True将在数据库关闭后继续保持数据集的开启状态. 3. 数据获取 名称 类型 说明 Fe ...

  8. 101. Symmetric对称 Tree

    Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). For e ...

  9. Codeforces 808G Anthem of Berland(KMP+基础DP)

    题意 给定一个字符串 \(s\) ,一个字符串 \(t\) ,其中 \(s\) 包含小写字母和 "?" ,\(t\) 只包含小写字母,现在把 \(s\) 中的问号替换成任意的小写字 ...

  10. 洛谷p1732 活蹦乱跳的香穗子 二维DP

    今天不BB了,直接帖原题吧  地址>>https://www.luogu.org/problem/show?pid=1732<< 题目描述 香穗子在田野上调蘑菇!她跳啊跳,发现 ...