ngx-bootstrap timepicker时区偏移导致SQL节省错误的时间

时间:2017-06-01 01:08:23

标签: angular ngx-bootstrap

将timepicker模块与所有默认选项一起使用,除了将minutetep设置为1。

代码行如下

let DailyStartTime =  this.dailyStartTime != null ? 
                         new Date(this.dailyStartTime.getFullYear(),
                               this.dailyStartTime.getMonth(),
                               this.dailyStartTime.getDate(),
                               this.dailyStartTime.getHours(),
                               this.dailyStartTime.getMinutes()) : null

将数据记录为 2017年5月31日星期三19:51:00 GMT-0400(东部夏令时)

最初显示,但一旦保存回SQL,它就会转换为 " 2017-05-31T23:51:00"这是按时间偏移推进的。我怎么能否定这个?

3 个答案:

答案 0 :(得分:3)

尝试使用ngx-bootstrap(3.0)timepicker将反应形式保存到POST(C#WebApi with EntityFramework)时遇到了同样的问题

似乎是UTC和本地计算机的问题。来自datepicker的日期似乎很好,但是在创建POST对象时,javascript似乎调整了UTC和本地计算机之间的时区差异。

解决方法(.ts):

submit() {
  this.dataService.saveOpenHours({ OpensAt: this.fixDate(this.form.value.openHour), ClosesAt: this.fixDate(this.form.value.closeHour) }).subscribe(data => {
    // do something
  });
}

fixDate(d: Date): Date {
  d.setHours(d.getHours() - d.getTimezoneOffset() / 60);
  return d;
}

<强> HTML

<form id="ngForm" [formGroup]="form" (ngSubmit)="submit()">
  <timepicker formControlName="openHour"></timepicker>
  <timepicker formControlName="closeHour"></timepicker>
</form>

希望这对某人有帮助!

答案 1 :(得分:1)

最近几天我一直在遇到同样的“问题”。

我在前端使用Angular 7,在后端使用.Net Core Web API。

Web API正在将JSON有效负载中的日期时间作为字符串以以下格式返回给客户端:

  

2020-04-23T01:00:00

TypeScript / JavaScript对象模型将日期字符串的数据类型保留为字符串类型。

按照下面的示例代码附加了bsDatepicker和timepicker(在这种情况下,使用双向模型绑定)后,模型中日期字符串的类型从字符串类型更改为JavaScript Date类型。 / p>

<input name="AppliesEndDate{{index}}" type="text" class="form-control form-control-sm" bsDatepicker [(ngModel)]="costCentre.appliesEndDate" [disabled]="costCentre.totalActiveAssignments!==0" />
<timepicker [(ngModel)]="costCentre.appliesEndDate" [showMeridian]="showMeridian" [disabled]="costCentre.totalActiveAssignments!==0" [minuteStep]="1"></timepicker>

当通过HTTP POST或PUT将模型发送回Web API服务器时,对象模型上的Date数据类型将被序列化回字符串,以UTC格式的日期表示,如Z后缀所示:

  

2020-04-23T00:00:00.000Z

由此可以得出结论,这是在客户端发生的,并且与Angular无关。可能与JavaScript将Date类型转换为字符串的方式有关。

以这些示例为例。我故意选了两个日期。一个在英国夏令时(GMT + 0000)之外,另一个在英国夏令时(GMT + 0100)之内

var date1 = new Date('2019-02-01T14:14:00');
var date2 = new Date('2019-05-01T14:14:00');
  

2019年2月1日星期五14:14:00 GMT + 0000(格林威治标准时间)

     

2019年5月1日星期三14:14:00 GMT + 0100(英国夏令时)

运行以下语句以转换为ISO字符串:

console.log('toISOString ' + date1.toISOString());
console.log('toISOString ' + date2.toISOString());

产生以下结果:

  

toISOString 2019-02-01T14:14:00.000Z

     

toISOString 2019-05-01T13:14:00.000Z

两个日期都转换为UTC格式。请注意,第二个示例的时间为13:14,而不是14:14。这实际上是正确的,因为01/05/2019在BST内部是GMT + 0100。所以真正的UTC实际上是13:14。

对于任何其他语言环境/时区都是如此。 UTC日期时间将根据客户的语言环境/地区来计算。

在幕后,我相信这是在将模型重新发布到服务器的有效负载中时,Angular客户端所发生的事情。它只是在调用“ toISOString”。

您还可以通过“ JSON.stringify”获得相同的结果,我相信它被称为“ toISOString”。

console.log(JSON.stringify(date1));
console.log(JSON.stringify(date2));

尝试在Chrome来源>代码段或其他JavaScript暂存器中运行其中一些命令。

var date1 = new Date('2019-02-01T14:14:00');
var date2 = new Date('2019-05-01T14:14:00');

console.log(date1);
console.log(date2);

console.log(JSON.stringify(date1));
console.log(JSON.stringify(date2));

console.log('toISOString ' + date1.toISOString());
console.log('toISOString ' + date2.toISOString());

console.log('toGMTString ' + date1.toGMTString());
console.log('toGMTString ' + date2.toGMTString());

console.log('toLocaleString ' + date1.toLocaleString());
console.log('toLocaleString ' + date2.toLocaleString());

console.log('toUTCString ' + date1.toUTCString());
console.log('toUTCString ' + date2.toUTCString());

console.log(date1.getTimezoneOffset());
console.log(date2.getTimezoneOffset());

因此,总而言之,我们从客户那里获得了UTC日期时间。

这绝对是一件好事,它使日期时间的语言环境/区域不可知。

有了这样的了解,如果您想在数据库中存储本地日期时间而不是UTC日期时间,则有一些解决方法。

上面的客户端代码建议当然可以“修复”偏移量,但考虑到数据仍将作为UTC日期字符串序列化回客户端。以这种方式删除偏移量实际上已经打破了UTC日期。在服务器上,Web API仍将收到Z后缀,并将其视为UTC日期。因此,您实际上将调整日期偏移量,但未调整UTC格式的上下文。

fixDate(d: Date): Date {
  d.setHours(d.getHours() - d.getTimezoneOffset() / 60);
  return d;
}

但是,如果您将日期以字符串形式发送回(自己转换并删除Z后缀),则返回为以下格式:

  

2020-04-23T01:00:00

那么您将不会暗示该日期是UTC日期。

考虑到以上所有内容,我的看法(经过几天的研究)是最好让客户端将Date类型序列化为UTC。从一致性的角度来看,接受这是如何工作的,并且始终返回UTC字符串日期是一件好事。

就服务器端(在我的情况下为Web API)而言,该日期可以作为UTC日期接收,也可以作为UTC日期存储在数据库/数据存储中,也可以将其转换为服务器端的任何语言环境/区域你的选择。请记住,UTC与区域无关,这对于全球应用程序来说是一件好事。

就我而言,我选择在存储到数据库之前使用以下代码段将输入的UTC日期时间转换为本地日期时间。

o.AppliesStartDate.ToLocalTime();

我希望这对某人有帮助,并希望能阐明事情的运作方式。两天前我一无所获...但是现在有点道理了。

您还可以在Web API C#上执行以下操作:

TimeZoneInfo ist = TimeZoneInfo.FindSystemTimeZoneById("India Standard Time");
TimeZoneInfo gmt = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");

var a1 = new DateTime(2019, 5, 30, 12, 30, 30, DateTimeKind.Utc);
Console.WriteLine(TimeZoneInfo.ConvertTimeFromUtc(a1, gmt));
Console.WriteLine(TimeZoneInfo.ConvertTimeFromUtc(a1, ist ));

这可能进一步说明,Web API上以UTC日期类型接收日期。如果您在反序列化日期时间结构Web API端选中“ kind”属性,则会看到“ UTC”。

希望对您有帮助。

答案 2 :(得分:0)

1. Import DatePipe in app.module.ts####################
    import { DatePipe } from '@angular/common';
2. Add in provider app.module.ts
    providers: [DatePipe]

3. inject in component.ts#################
   constructor(private datePipe: DatePipe){

   }
serach(search: Inward): void {
        this.date = this.datePipe.transform(this.searchForm.value.createdDate, 'dd/MM/yyyy')
        console.log("SEARCH :" + this.date);
    }


component.html###################
<div class="col-md-4">
            <div class="form-group">
                <label>Date</label>
                <input type="text" class="form-control" formControlName="createdDate" bsDatepicker
                    [bsConfig]="{ isAnimated: true ,dateInputFormat:'DD/MM/YYYY'}">
            </div>
        </div>