تايبسكريبت - منتج اختيار التاريخ في أنجولار: مشكلة تحليل التاريخ UTC قبل يوم واحد
أعلم أن هناك عدة موضوعات حول هذا وقد قرأتها كلها لكنني لم أتمكن من حل ذلك لأيام. ربما وجدت حلاً لكنه يبدو قذرًا بالنسبة لي.
تمامًا مثل المستخدمين الآخرين، لدي نفس المشكلة مع منتقي التاريخ. بالنسبة لي، إنه منتقي تاريخ Angular Material 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);
الإجابة رقم 1
القيمة التي يتم اختيارها وعرضها هي نفسها... إنها تنسيقات التاريخ والوقت المختلفة التي تظهر لنا نتيجة مختلفة (حيث يتغير التاريخ أيضًا)!!
على سبيل المثال:
- (افتراضيًا): 2019-06-11T19:00:00.000Z
- يساوي (بواسطة UTCString): الثلاثاء، 11 يونيو 2019 19:00:00 بتوقيت غرينتش
- يساوي (وفقًا لسلسلة الموقع): 6/12/2019، 12:00:00 ص
- يساوي (حسب LocaleTimeString): 12:00:00 ص
لسنا بحاجة إلى تحويله، لأن كائن التاريخ يحتوي على نفس الوقت بالضبط.
ستُظهر لك هذه الـ Stackblitz بشكل أكبر الفرق الذي يمكن أن يصنعه التنسيق على السطح ولكن التاريخ هو نفسه في الأساس؛ إذا كان لديك أسئلة/تعليقات، يمكنك تفرع هذا الـ 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>
الإجابة رقم 2
ردًا على إجابتك الخاطئة...
الساعة 11 مساءً بتوقيت UTC=00:00+01:00 في اليوم التالي (نفس اللحظة)
الأربعاء 24 ديسمبر 1999 00:00:00 توقيت غرينتش +0100 (التوقيت القياسي لأوروبا الوسطى) لكن في الطلب هو
1999-12-23T23:00:00.000Z
هاتان السلسلتان تمثلان نفس القيمة. هما طريقتان لرؤية نفس اللحظة. إحداهما الساعة 11 مساءً بتوقيت UTC، والأخرى ساعة واحدة أمام UTC، لذا فهي تمثل اللحظة الأولى من اليوم التالي. إضافة ساعة واحدة إلى الساعة 11 مساءً في اليوم 23 في يوم مدته 24 ساعة تؤدي إلى ما بعد دقات منتصف الليل، إلى اللحظة الأولى من اليوم 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. دعم فئة OffsetDateTime في برامج تشغيل JDBC مطلوب بواسطة JDBC 4.2 وما بعدها، بينما دعم Instant اختياري.
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
اكتب إلى قاعدة البيانات عبر PreparedStatement باستخدام عنصر نائب ?.
myPreparedStatement.setObject( … , odt ) ;
استرجاع.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
تم مناقشة هذا مرات عديدة جدًا على Stack Overflow. لذا ابحث لتعرف المزيد. ويرجى البحث في Stack Overflow جيدًا قبل النشر.
تاريخ_محلي
إذا كان هدفك هو تتبع التاريخ فقط، ولا تهتم حقًا بوقت اليوم والمنطقة الزمنية، فيجب عليك استخدام LocalDate في جافا وDATE في عمود SQL القياسي.
