getDateTimeInstance(): Different Behavior for Different Locale

109 views Asked by At

I am doing date format using this function

// DateFormat required from "sap/ui/core/format/DateFormat"
DateFormat.getDateTimeInstance({ pattern: "yyyy-MM-dd HH:mm" });

The format is working fine in "DE" but it is returning wrong value in "EN". In both languages, the time is 24 hour. What I need is:

  • In English, the time text should contain AM or PM.
  • In German, the time text should be in the 24h format.

How can this be achieved?

Target UI5 version: 1.108

1

There are 1 answers

0
Boghyon Hoffmann On

According to the Unicode's Date Field Symbol table:

  • HH corresponds to the "24-hour-cycle format"
  • hh corresponds to the "12-hour-cycle format"
  • jj "is the only way to [...] request a locale's preferred time cycle type (12-hour or 24-hour)."

If not required otherwise, I'd strongly discourage from hardcoding the pattern in the format options in order to let the framework format the date and time depending on the user locale. You can use the format option instead to specify which symbol to incorporate (e.g. jj instead of hh or HH) when formatting the date time value.

Run this snippet to see the result:

globalThis.onUI5Init = () => sap.ui.require([
  "sap/ui/core/format/DateFormat",
  "sap/ui/core/Locale",
  "sap/ui/core/Configuration",
  "sap/m/VBox",
  "sap/m/ObjectStatus",
], (DateFormat, Locale, Configuration, VBox, ObjectStatus) => {
  "use strict";
  const currentUserLocale = Configuration.getLanguageTag();
  const control = new VBox({
    items: [
      new ObjectStatus({
        title: "Locale \"de-DE\"",
        text: DateFormat.getDateTimeInstance({
          format: "yMdjjmm",
          UTC: true,
        }, new Locale("de-DE"))
          .format(new Date(new Date().setUTCHours(23, 0)))
      }),
      new ObjectStatus({
        title: "Locale \"en-US\"",
        text: DateFormat.getDateTimeInstance({
          format: "yMdjjmm",
          UTC: true,
        }, new Locale("en-US"))
          .format(new Date(new Date().setUTCHours(23, 0)))
      }),
      new ObjectStatus({
        title: `Your Preferred Locale ("${currentUserLocale}")`, // Detected locale as per https://sdk.openui5.org/topic/91f21f176f4d1014b6dd926db0e91070
        text: DateFormat.getDateTimeInstance({
          format: "yMdjjmm",
          UTC: true,
        }).format(new Date(new Date().setUTCHours(23, 0)))
      })
    ],
    renderType: "Bare",
  });

  control.addStyleClass("sapUiTinyMargin").placeAt("content");
});
<script id="sap-ui-bootstrap"
  src="https://sdk.openui5.org/nightly/resources/sap-ui-core.js"
  data-sap-ui-libs="sap.ui.core,sap.m,sap.ui.layout,sap.ui.unified"
  data-sap-ui-async="true"
  data-sap-ui-oninit="onUI5Init"
  data-sap-ui-compatversion="edge"
  data-sap-ui-excludejquerycompat="true"
  data-sap-ui-xx-waitfortheme="init"
></script>
<body id="content" class="sapUiBody sapUiSizeCompact"></body>

Given today at 23:00:00Z:

Locale "de-DE": 28.4.2023, 23:00
Locale "en-US": 4/28/2023, 11:00 PM

API reference: sap/ui/core/format/DateFormat.getDateTimeInstance


Same can be achieved in property binding within XML declaratively via type and formatOptions.

<SomeControl xmlns="..."
  xmlns:core="sap.ui.core"
  core:require="{ DateTimeOffset: 'sap/ui/model/odata/type/DateTimeOffset' }"
  someControlProperty="{
    path: 'myODataModel>...',
    type: 'DateTimeOffset',
    formatOptions: {
      format: 'yMdjjmm'
    },
    ...
  }"
/>

API reference: sap/ui/model/odata/type/DateTimeOffset
Documentation (must-read): Dates, Times, Timestamps, and Time Zones
Documentation: Formatting, Parsing, and Validating Data — Data Binding (in XML)