Angular 学习笔记 ( timezone + moment + material date-picker + date pipe + asp.net core )
更新 : 2019-06-17
常用 moment
1. Get start of day
moment().startOf('day')
if(date!.isSame(moment(), 'day'))
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 )的更多相关文章
- Angular 学习笔记 (动态组件 & Material Overlay & Dialog 分析)
更新: 2019-11-24 dialog vs router link refer : https://stackoverflow.com/questions/51821766/angular-m ...
- angular学习笔记(三十一)-$location(2)
之前已经介绍了$location服务的基本用法:angular学习笔记(三十一)-$location(1). 这篇是上一篇的进阶,介绍$location的配置,兼容各版本浏览器,等. *注意,这里介绍 ...
- angular学习笔记(三十一)-$location(1)
本篇介绍angular中的$location服务的基本用法,下一篇介绍它的复杂的用法. $location服务的主要作用是用于获取当前url以及改变当前的url,并且存入历史记录. 一. 获取url的 ...
- angular学习笔记(三十)-指令(10)-require和controller
本篇介绍指令的最后两个属性,require和controller 当一个指令需要和父元素指令进行通信的时候,它们就会用到这两个属性,什么意思还是要看栗子: html: <outer‐direct ...
- angular学习笔记(三十)-指令(7)-compile和link(2)
继续上一篇:angular学习笔记(三十)-指令(7)-compile和link(1) 上一篇讲了compile函数的基本概念,接下来详细讲解compile和link的执行顺序. 看一段三个指令嵌套的 ...
- angular学习笔记(三十)-指令(7)-compile和link(1)
这篇主要讲解指令中的compile,以及它和link的微妙的关系. link函数在之前已经讲过了,而compile函数,它和link函数是不能共存的,如果定义了compile属性又定义link属性,那 ...
- angular学习笔记(三十)-指令(6)-transclude()方法(又称linker()方法)-模拟ng-repeat指令
在angular学习笔记(三十)-指令(4)-transclude文章的末尾提到了,如果在指令中需要反复使用被嵌套的那一坨,需要使用transclude()方法. 在angular学习笔记(三十)-指 ...
- angular学习笔记(三十)-指令(5)-link
这篇主要介绍angular指令中的link属性: link:function(scope,iEle,iAttrs,ctrl,linker){ .... } link属性值为一个函数,这个函数有五个参数 ...
- angular学习笔记(三十)-指令(2)-restrice,replace,template
本篇主要讲解指令中的 restrict属性, replace属性, template属性 这三个属性 一. restrict: 字符串.定义指令在视图中的使用方式,一共有四种使用方式: 1. 元素: ...
随机推荐
- 4、pandas的数据筛选之isin和str.contains函数
DataFrame列表: 以>,<,==,>=,<=来进行选择(“等于”一定是用‘==’,如果用‘=’就不是判断大小了): 使用 &(且) 和 |(或) 时每个条件都要 ...
- Vue 旅游网首页开发1-工具安装及码云使用
Vue 旅游网首页开发-工具安装及码云使用 环境安装 安装 node.js node.js 官网:https://nodejs.org/en/ 注册码云,创建私密仓库存储项目 码云:https://g ...
- overture里设置踏板标记
在学习如何设置踏板标记之前,我们先来了解什么是踏板标记.踏板标记一般是使用在乐谱上,众所周知,钢琴有三个踏板,每个踏板的作用都不一样:右边的踏板称为“延音踏板”,是用来延长琴弦振动的时间,使音延长的效 ...
- 【Python029--一个任务】
一.文件编写 任务:将文件(record.txt)中的数据进行分割,并按照以下规律保存起来: --小甲鱼的对话单独保存为boy_*.txt的文件(去掉“小甲鱼:”) --小客服的对话单独保存为girl ...
- HTML <frame> 标签的 src 属性
HTML <frame> 标签 实例 src 属性规定在框架中显示的文档的位置: <html> <frameset cols="50%,50%"> ...
- P4137 Rmq Problem / mex
目录 链接 思路 线段树 莫队 链接 https://www.luogu.org/problemnew/show/P4137 思路 做了好几次,每次都得想一会,再记录一下 可持久化权值线段树 区间出现 ...
- Python之Requests的高级用法
# 高级用法 本篇文档涵盖了Requests的一些更加高级的特性. ## 会话对象 会话对象让你能够跨请求保持某些参数.它也会在同一个Session实例发出的所有请求之间保持cookies. 会话对象 ...
- PL/SQL Developer几个使用小技巧
1.选中sql语句的当前行 鼠标连续点击所在行3次. 2.记住登陆密码 工具 -> 首选项 -> Oracle -> 登录历史,勾选“带口令存储”. 3.查看Oracle的tnsna ...
- [蓝桥] 算法训练 P0505
时间限制:1.0s 内存限制:256.0MB 一个整数n的阶乘可以写成n!,它表示从1到n这n个整数的乘积.阶乘的增长速度非常快,例如,13!就已经比较大了,已经无法存放在一个整型变量中:而35!就更 ...
- parent获取子元素以及自身元素
innerHTML 设置或获取位于对象起始和结束标签内的 HTML outerHTML 设置或获取对象及其内容的 HTML 形式 innerText 设置或获取位于对象起始和结束标签内的文本 oute ...