angular - Ionic 2 beta 11: Initierar datum- och tidskomponent för att ta hänsyn till lokal tidszon


Jag har problem med datetime-komponenten i Ionic 2 beta 11. Från vad jag förstår i Ionic API-dokumentationen bör jag skicka in ett värde från Date.toISOString. Detta fungerar bra, förutom att datumet visas som UTC istället för enhetens aktuella tidszon (PDT för mina ändamål). Till exempel visas datumet som:

09/19/2016 8:46 PM

istället för det förväntade:

09/19/2016 1:46 PM

Här är min backing-klass:

export class TestPage {
  private _date: Date = new Date();
  public get date(): string {
    return this._date.toISOString();
  }
}

All min mallkod för TestPage:

  <ion-datetime 
      displayFormat="MM/DD/YYYY h:mm A" 
      pickerFormat="MM DD YYYY h mm A" 
      [(ngModel)]="date">
  </ion-datetime>

Jag kan arbeta runt detta genom att först tillämpa Date.getTimezoneOffset på datumvärdet, men jag skulle föredra att undvika detta eftersom det verkar som att ramverket borde ta hänsyn till tidszon i användargränssnittet.

  public get date(): string {
    let n: number = this._date.getTime();
    n -= (this._date.getTimezoneOffset() * 60 * 1000);
    let d: string = new Date(n).toISOString();
    return d;
  }

Här är en Plunker som jag har skapat för att demonstrera problemet: http://plnkr.co/edit/2iJRh1zM4pmwcNilWIcG?p=preview

Svar #1

Som du kan se i dokumentationen:

Om datetime-värden behöver parsas från ett visst format, eller manipuleras (som att lägga till 5 dagar till ett datum, subtrahera 30 minuter, etc.), eller till och med formatera data till en specifik lokal, så rekommenderar vi starkt att använda moment.js för att "Parsa, validera, manipulera och visa datum i JavaScript". Moment.js har snabbt blivit vår standardlösning när vi hanterar datummoment i JavaScript, men Ionic inkluderar inte denna beroende som standard eftersom de flesta appar inte kommer att behöva det, och dess lokala konfiguration bör beslutas av slutföraren/developern.

Så istället för att göra det manuellt genom att använda Date.getTimezoneOffset kan du använda tidszonsmetoder från moment-timezone.js på detta sätt:

var jun = moment("2014-06-01T12:00:00Z");
jun.tz('America/Los_Angeles').format('MM/DD/YYYY h:mm a');

eller bara:

var timestamp = 1412144245453; // October 1st, 2014 6:17:25 AM.
moment.tz(timeStamp, 'America/Los_Angeles').format('MM/DD/YYYY h:mm a');  // Output: 09/30/2014 11:17 PM

Du kan kontrollera hur du importerar det till Ionic-projektet här.

Svar #2

Mina scenary odata-tjänster returnerar datum och tider som ISO 8601 UTC

{ExpectedEndDate:"2016-12-01T04:00:00Z"}

Jag använder pipe för att visa i primeng DataTable

<p-column field="ExpectedEndDate" header="F.Prevista">
            <template let-col let-item="rowData" pTemplate type="body">
                <span>{{item[col.field] | date: 'dd/MM/yyyy HH:mm:ss'}}</span>
            </template>
</p-column>

det här visar datumet i min lokala tid som förväntat (GMT+0100)

01/12/2016 05:00:00

Att använda Ionic DateTime över min modells egenskap, visar det redigerade datumet som UTC :( för att lösa detta gör jag så i min form.ts Deklarera 2 funktioner (jag antar att de kan vara någon form av globala)

setIonicDateTime(value: string): Date {
    if (value) {
        let date: Date = new Date(value);
        let ionicDate = new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), date.getUTCMilliseconds());
        return ionicDate;
    }
    return null;
}
getIonicDateTime(value: Date): string {
    if (value) {
        let date: Date = new Date(value);
        let ionicDate = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds()));
        return ionicDate.toISOString();
    }
    return null;
}

sedan omsluta min modell på rätt sätt (edit är min modell)

@Input() set ExpectedEndDate(value: string) {
    this.edit.ExpectedEndDate = this.setIonicDateTime(value);
}
get ExpectedEndDate():string {
   return this.getIonicDateTime(this.edit.ExpectedEndDate);
}

i mallen använd egenskapen istället för modellens kod för datumet.

<ion-item>
    <ion-label floating>F.Prevista</ion-label>
    <ion-datetime formControlName="ExpectedEndDate"   displayFormat="DD/MM/YYYY HH:mm" [(ngModel)]="ExpectedEndDate">
    </ion-datetime>
</ion-item>

Detta sätt fungerar bra för mig, alltid visa och redigera datumen i lokal tid och lagra i UTC. Detta fungerar alltid, datumen är ISO 8601 UTC