SE の雑記

SQL Server の情報をメインに Microsoft 製品の勉強内容を日々投稿

PowerApps と SQL Server / Database の日付型データの取り扱い

leave a comment

PowerApps で SQL Server / SQL Database の日付型データを取り扱う際にはいくつかの注意事項があり、それらについては、Working with date/time values and SQL Server でまとめられています。

SQL Server コネクターを使用して PowerAppS から、SQL Server の datetime / datetime2 / datetimeoffset のような日付型ののデータを取得した場合、これらの列については PowerApps の日付/時刻型にダイレクトにマッピングされ、オフセットの問題が発生する可能性があります。

最初から日付のデータをすべて「UTC」または「オフセット付きの日付」で管理している場合は、影響が抑えられるかもしれませんが、日付を現地時刻で格納している場合、SQL Server コネクターで取得した日付型のデータについては、PowerApps で表示した場合に想定していない時間となります。

例としてですが、SQL Server で次のような日付のデータを登録してみます。

DROP TABLE IF EXISTS DateTest
GO
CREATE TABLE DateTest(
	id int identity primary key,
	c_datetime2 datetime2 DEFAULT (GETDATE()),
	c_utc_datetime2 datetime2 DEFAULT (GETUTCDATE()),
	c_tz_datetimeoffset datetimeoffset DEFAULT(GETUTCDATE() AT TIME ZONE 'Tokyo Standard Time')
)
GO
INSERT INTO DateTest DEFAULT VALUES
SELECT * FROM DateTest

これにより、次のようなデータが登録されます。

image

  • c_datetime2 : 日本時間
  • c_utc_datetime2 : UTC 時間
  • c_tz_datetimeoffset : UTC 時間 + 日本時間のオフセット

このデータを PowerApps で表示してみると、次のようになります。

image

  • c_datetime2 : 日本時間で登録したものに対して、9 時間足されている
  • c_utc_datetime2 : UTC 時間で登録されたものに対して、9 時間足されている
  • c_tz_datetimeoffset : UTC 時間の時間 + オフセットの時間に対して、UTC の時間で表示されている

SQL Server コネクターを使用した場合、次のような動作になっています。

  • 絶対値で登録されている日付については、その時間に対して UTC のオフセットが加味された時間で変換される
  • オフセットを持っている日付については、絶対値の部分のみが利用される

日付型のデータについては、UTC で登録するようにしておかないと、時間のずれが発生しそうですね…。

現状、SQL Server コネクターについては「日付を変換せずに利用する」というオプションは存在していないため、登録されているデータをそのまま利用するということができません。

冒頭で記載した記事の解決方法としては、「絶対値 (登録されている日付がそのままの時刻で必要) な場合は、日付型ではなく、文字列データ型 (varchar / nvarchar 等)で登録し、PowerApps側 の DateTimeValue 関数で日付に変換する」で登録を行うということで紹介されています。

PowrApps で、日付型の取り扱い難しいですね…。

SQL Server の日付型をそのまま利用する場合、UTC で登録するようにしておかないと厳しいかもしれないですね。

(datetimeoffset の利用も厳しそうな気が…。)

PowerApps で UTC の時刻を登録する場合は、次のような関数の指定でしょうか。

Patch(
    '[dbo].[DateTest]',
    Defaults('[dbo].[DateTest]'),
    {
        c_datetime2: DateAdd(
            Now(),
            TimeZoneOffset(Now()),
            Minutes
        ),
        c_utc_datetime2: DateAdd(
            Now(),
            TimeZoneOffset(Now()),
            Minutes
        ),
        c_tz_datetimeoffset: DateTimeValue(
            Text(
                Now(),
                DateTimeFormat.UTC
            ),
            "ja-JP"
        )
    }
)

 

先ほどのテーブルを次のようにしてみます。

DROP TABLE IF EXISTS DateTest
GO
CREATE TABLE DateTest(
	id int identity primary key,
	c_datetime2 datetime2 DEFAULT (GETDATE()),
	c_utc_datetime2 datetime2 DEFAULT (GETUTCDATE()),
	c_tz_datetimeoffset datetimeoffset DEFAULT(GETUTCDATE() AT TIME ZONE 'Tokyo Standard Time'),
	c_local_time varchar(27) DEFAULT (GETDATE())
)
GO
INSERT INTO DateTest DEFAULT VALUES
SELECT * FROM DateTest

 

これに対して、データを PowerApps から登録する場合は、次のような Patch 関数を使用することになるのでしょうか。

Patch(
    '[dbo].[DateTest]',
    Defaults('[dbo].[DateTest]'),
    {
        c_datetime2: DateAdd(
            Now(),
            TimeZoneOffset(Now()),
            Minutes
        ),
        c_utc_datetime2: DateAdd(
            Now(),
            TimeZoneOffset(Now()),
            Minutes
        ),
        c_tz_datetimeoffset: DateTimeValue(
            Text(
                Now(),
                DateTimeFormat.UTC
            ),
            "ja-JP"
        ),
        c_local_time: Text(
            Now(),
            "[$-ja-JP]yyyy/mm/dd hh:mm:ss"
        )
    }
)

日付の扱い方、中々難しいですね…。

Written by masayuki.ozawa

8月 11th, 2018 at 8:07 pm

Leave a Reply

*