0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

プリザンターのサーバスクリプトで日付を簡単に扱う方法

Posted at

はじめに

プリザンターのサーバスクリプトだと、日付項目などのDateTime型はタイムゾーンはUTCのデータしか取得が出来ません。
これは、サーバスクリプトの実装に使われているClearScriptのライブラリの制約によるもので、C#のDateTime型をJavaScriptのDateTime型に変換をおこなうときに、タイムゾーンがUTCとなってしまうためです。

EnableDateTimeConversion
Specifies that the script engine is to perform automatic conversion between .NET DateTime objects and JavaScript Date objects. This conversion is bidirectional and lossy. A DateTime object constructed from a JavaScript Date object always represents a Coordinated Universal Time (UTC) and has its Kind property set to Utc.

https://microsoft.github.io/ClearScript/Reference/html/T_Microsoft_ClearScript_V8_V8ScriptEngineFlags.htm

ただし、気をつけないといけないことが一つあります。サーバスクリプト内で日付の書き換え行う場合など、DateTimeの更新などを行う場合は、それを実行するユーザーにセットされているタイムゾーンのデータをセットする必要があります。
どこでどのタイムゾーンになるか簡単にまとめてみました。

実行環境 データベース ユーザー設定 API Get/Set1 スクリプトGet/Set2 サーバスクリプトGet サーバスクリプトSet2
JST JST JST JST JST UTC JST
UTC UTC JST JST JST UTC JST

普通に日本向けに運用している場合などは、何をするにしても一旦JSTに変換する必要がありかなりめんどくさい・・・。

解決してみた

サーバスクリプトに実装してみた

サーバスクリプトから取得するときだけ、UTCになるのが不便なので、一括でタイムゾーンを変換してやりましょう。
modelを直接触ると面倒なので、DateTimeなプロパティだけをmodel_jstという変数を作ってそちらにセットしてみます。「画面表示の前」や「秒表示の前」にセットすればOKです。

const regex = new RegExp('(^Date|Time$)');
let model_jst = {};

for (const [key, value] of Object.entries(model)) {
    if (regex.test(key) && value) {
        model_jst[key] = value.toLocaleString("ja-JP", {
             timeZone: "JST"
        });
    }
}

DateA~ZDate001~999UpdateTimeCreatedTimeのうちページに表されているもの(=modelに含まれているもの)だけが、model_jstにセットされます。表示されていないものを触りたいときはview.AlwaysGetColumnsを使って対象を追加する方法も吊しのまま使えるようになっています。
デバッグ用にcontext.Logを追加して実行してみるとこんな感じになります。

model:CreatedTime/Thu Dec 05 2024 06:19:08 GMT+0000 (Coordinated Universal Time)
model:UpdatedTime/Thu Dec 05 2024 06:19:08 GMT+0000 (Coordinated Universal Time)
model:DateY/Wed Dec 04 2024 15:00:00 GMT+0000 (Coordinated Universal Time)
model:DateZ/Wed Dec 04 2024 15:00:00 GMT+0000 (Coordinated Universal Time)
model:Date001/Wed Dec 04 2024 15:00:00 GMT+0000 (Coordinated Universal Time)
model:Date002/Wed Dec 04 2024 15:00:00 GMT+0000 (Coordinated Universal Time)
model_jst:CreatedTime/2024/12/5 15:19:08
model_jst:UpdatedTime/2024/12/5 15:19:08
model_jst:DateY/2024/12/5 0:00:00
model_jst:DateZ/2024/12/5 0:00:00
model_jst:Date001/2024/12/5 0:00:00
model_jst:Date002/2024/12/5 0:00:00

お、いい感じに変換できてますね。

拡張サーバスクリプトにしてみた

それぞれのサイトに追加していくもの面倒なので、拡張サーバスクリプトにして組み込んでみました。

DateTimeTimeZoneConvert.json
{
    "Name": "modelのタイムゾーンを変換する",
    "BeforeOpeningPage": true,
    "BeforeOpeningRow": true,
    "Body": "// Write an arbitrary script."
}
DateTimeTimeZoneConvert.json.js
let model_jst = {};
let success_model_jst = false;
//エラーが出ると面倒なのでtry-catchで囲っておく
try {
    const regex = new RegExp('(^Date|Time$)');
    for (const [key, value] of Object.entries(model)) {
        if (regex.test(key) && value) {
            model_jst[key] = value.toLocaleString("ja-JP", {
                timeZone: "JST"
            });
        }
    }
    success_model_jst = true;
} catch(e) {
    success_model_jst = false;
    context.Error(e.Stack);
}

拡張サーバスクリプトはエラーを吐くと全部が止まってしまって面倒なので、try-catchで囲っています。また、正常に実行されることを確認するために、success_model_jstに実行に成功したかどうかをtrue/falseでセットしています。

まとめ

サーバスクリプトで常に頭を悩ませるタイムゾーン問題を簡単に解決してみました。マルチロケーションで異なるタイムゾーンのユーザーが混在している環境の場合は、user.UserIdで実行ユーザのIDを取得した後にAPIのusers/getでユーザーのTimeZoneLanguage3を取得することで対応が可能です。

  1. APIキーにセットされているユーザーと同じ

  2. 実行したユーザーのタイムゾーンと同じ 2

  3. ロケールはプリザンターでは管理していないので、Languageから類推してセットする必要あり

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?