我知道有关此的一些主题,我读了所有这些主题,但是好几天都无法解决。我可能找到了解决方案,但对我来说似乎很肮脏。
因此,与其他用户一样,datePicker也有相同的问题。对我来说是Angular Material Datepicker mat-datepicker
当我记录该值时,我得到正确的结果:
Wed Dec 24 1999 00:00:00 GMT+0100 (Mitteleuropäische Normalzeit)
但在请求中是
1999-12-23T23:00:00.000Z
我尝试过的事情:
我已经将{ provide: MAT_MOMENT_DATE_ADAPTER_OPTIONS, useValue: { useUtc: true } }
添加到了component
和app.module.ts
中。这对我没有任何影响。
我的肮脏解决方案(发送请求之前):
let newDate= new Date(this.personalForm.get("dateOfBirth").value);
newDate.setMinutes(newDate.getMinutes() - newDate.getTimezoneOffset());
当我这样做时,控制台记录:
Wed Dec 24 1999 01:00:00 GMT+0100 (Mitteleuropäische Normalzeit)
请求正确:
1997-12-24T00:00:00.000Z
但是,如果现在有人来自其他时区(例如GMT-0100),这将再次不起作用。如何正确解决此问题?
如果有必要知道的话,我还会动态更改适配器:
this._adapter.setLocale(this.translateService.currentLang);
答案 0 :(得分:2)
选取并显示的值是相同的...它是日期时间的不同格式,向我们显示了不同的结果(日期也会更改)!
例如:
- (默认):2019-06-11T19:00:00.000Z
- 等于(by UTCString):Tue,11 Jun 2019 19:00:00 GMT
- 等于(通过LocaleString):6/12/2019,12:00:00 AM
- 等于(通过LocaleTimeString):12:00:00 AM
我们不需要转换它,因为date对象包含相同的确切时间。
This stackblitz将进一步显示格式可以在表面上产生的变化,但下面的日期是相同的;如果您有任何疑问/意见,可以进行分叉讨论,进行更改并针对该答案发表评论,我将尽力澄清。
相关的 TS :
import {Component} from '@angular/core';
/** @title Basic datepicker */
@Component({
selector: 'datepicker-overview-example',
templateUrl: 'datepicker-overview-example.html',
styleUrls: ['datepicker-overview-example.css'],
})
export class DatepickerOverviewExample {
planModel: any = {start_time: new Date() };
constructor(){}
dateChanged(evt){
let selectedDate = new Date(evt);
console.log("by default:", selectedDate);
console.log("by UTCString:", selectedDate.toUTCString());
console.log("by LocaleString:", selectedDate.toLocaleString());
console.log("by LocaleTimeString:", selectedDate.toLocaleTimeString());
}
}
相关的 HTML :
<mat-form-field>
<input matInput [matDatepicker]="picker" placeholder="Choose a date"
[(ngModel)]="planModel.start_time"
(ngModelChange)='dateChanged($event)'
>
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
</mat-form-field>
<hr/>
<p>By default: {{planModel.start_time}} </p>
<p>Medium date: {{planModel.start_time | date:'medium'}} </p>
<p>Short date: {{planModel.start_time | date:'short'}} </p>
<p>Short time: {{planModel.start_time | date: 'shortTime' }} </p>
<p>Medium time: {{planModel.start_time | date: 'mediumTime' }} </p>
<p>Long time: {{planModel.start_time | date: 'longTime' }} </p>
<p>Full time: {{planModel.start_time | date: 'fullTime' }} </p>
答案 1 :(得分:0)
最后,问题出在我的后端,需要了解发生了什么。
要将日期直接保存到我的Postgres数据库中:
DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH);
LocalDateTime lu = LocalDateTime.parse(lastUpdated, inputFormatter);
LocalDateTime dob = LocalDateTime.parse(dateOfBirth, inputFormatter);
this.dateOfBirth = Date.from(dob.atZone(ZoneOffset.UTC).toInstant());
this.lastUpdated = Date.from(lu.atZone(ZoneOffset.UTC).toInstant());
在我之前
this.dateOfBirth = Date.from(dob.atZone(ZoneId.systemDefault()).toInstant());
这是错误的。我只是收到Angular发出的请求,而Java将其直接保存到数据库中。
1999-12-23T23:00:00.000Z
变成
1997-12-24 00:00:00
答案 2 :(得分:0)
1999年12月24日星期三00:00:00 GMT + 0100(MitteleuropäischeNormalzeit) 但在请求中是
1999-12-23T23:00:00.000Z
这两个字符串表示相同的值。它们是查看同一时刻的两种方式。一个是UTC的晚上11点,另一个是UTC的一个小时,所以它代表了第二天的第一刻。在长达24小时的一天中,23日晚上11点增加一个小时,经过了午夜,直到24日的第一时刻。
将您的输入字符串解析为Instant
。末端的Z表示UTC,发音为“ Zulu”。根据定义,Instant
代表UTC时刻,始终为UTC。
您的输入字符串为标准ISO 8601格式。 java.time 类在解析/生成字符串时默认使用这些标准格式。因此,无需指定格式设置模式。
Instant instant = Instant.parse( "1999-12-23T23:00:00.000Z" ) ;
必须将一个时刻(日期,日期和指定的时区或UTC偏移量)保存到类似于标准SQL类型TIMESTAMP WITH TIME ZONE
的数据库列中。类似于TIMESTAMP WITHOUT TIME ZONE
的列将是错误数据类型。
要写入您的数据库,我们需要从Instant
的基本构建模块类切换到更灵活的OffsetDateTime
类。 JDBC 4.2和更高版本要求在JDBC驱动程序中支持OffsetDateTime
类,而Instant
支持是可选的。
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
通过PreparedStatement
和占位符?
写入数据库。
myPreparedStatement.setObject( … , odt ) ;
检索。
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
关于堆栈溢出的讨论已经很多次了。因此,搜索以了解更多信息。并且在发布之前,请彻底搜索Stack Overflow。
LocalDate
如果您的目标只是跟踪日期,并且您并不真正在意时间和时区,则应在Java中使用LocalDate
,在标准中使用DATE
列SQL。
答案 3 :(得分:0)
哈哈,我对此方法的肮脏解决方案就是这种方法,它的用途是正确的,因为我只想将日期以字符串形式发送回而没有任何其他信息,该信息将映射到后端并保存...
public setDate(date: any): string {
const chosenDate = new Date(date);
return `${chosenDate.getMonth() + 1}/${chosenDate.getDate()}/${chosenDate.getFullYear()}`;
}
,然后在html中设置对象值
<mat-form-field appearance="outline">
<mat-label>Birthdate</mat-label>
<input matInput [matDatepicker]="birthdatePicker" placeholder="Birthdate"
(dateChange)="user.birthdate = setDate($event.value)">
<mat-datepicker-toggle matSuffix [for]="birthdatePicker"></mat-datepicker-toggle>
<mat-datepicker #birthdatePicker></mat-datepicker>
<mat-error>error</mat-error>
</mat-form-field>