最近、仕事でもっとUmbraco 17を使い始めた。
働いている間に、日付選択を使わなければいけないけど、いろんな日付選択を見つけた。
この新しい日付選択に僕はちょっと混乱した。
それに、プログラムでIContentServiceを使って日付を設定したい。
でも、IContentServiceを使った時、大変な問題を見つけた...
IContentServiceで日付を設定した後で、毎回その日付はnullになっちゃった!
このブログ記事では、新しい日付選択の使い方と、IContentServiceで日付を取得する方法を教えている。
Umbraco 17には普通の日付選択がもうあるけど、Umbracoのブログ記事によると、Umbraco 18からその日付選択機能がなくなるらしい。
だから、Umbracoは新しい日付選択機能をおすすめしている。
エディター | 使い道 | ユースケース | 戻り値 |
|---|---|---|---|
日付選択 | 誕生日、締切、日程 |
| |
時間選択 | 営業時間、スケジュール、タイムテーブル |
| |
日付、時間、タイムゾーンをサポートする | 多言語対応アプリ、タイムゾーン対応スケジュール |
| |
タイムゾーンなしの日付と時間 | 地域イベント |
|
Umbraco17以前はたくさん日付を保存しているけど、あまりタイムゾーンがなかった。
だから、すべての日付はどんなタイムゾーンの日付か、わからない。
例えば、ウェブサイトはサーバーを変える時、この新しいサーバーは違う日付の設定があった。
サーバーのローカルタイムかUTCかわからないから、大変な問題になる。
そのために、Umbracoは新しい日付のエディターを追加したから、すべての日付はUTCになった。
Before, if you could set the date on IContent by using IContentSercice
以前は、IContentでIContentServiceを使って、日付を設定した場合、これ↓ができた。
node.SetValue("publishDate", DateTime.Now);
_contentService.Save(node);でも、新しい日付のエディターを使ったら、それはできない。
この新しい日付のエディターを使いたい場合、いろいろなことをしなければいけない。
下記の例はDateOnlyのエディターを使っている。
Umbracoは新しいクラスを作ることをお勧めしている。
using System.Text.Json.Serialization;
namespace UmbracoProject
{
public class DateTimeUnspecified
{
[JsonPropertyName("date")]
public DateTimeOffset Date { get; init; }
}
}Umbracoのソースコードを見たら、Umbraco.Cms.Core.PropertyEditors.ValueConverters.DateTimeValueConverterBaseネームスペースでDateTimeDtoオブジェクトを見つけられる。
自分のオブジェクトを作りたくなかったら、DateTimeDtoを使える。
public class DateTimeDto
{
[JsonPropertyName("date")]
public DateTimeOffset Date { get; init; }
[JsonPropertyName("timeZone")]
public string? TimeZone { get; init; }
}そして、オブジェクトを作る。
DateOnly dateOnly = DateOnly.FromDateTime(DateTime.Today);
DateTimeOffset dateTimeOffset = dateOnly.ToDateTime(TimeOnly.MinValue);
var value = new DateTimeUnspecified
{
Date = dateTimeOffset
};そして、DI(依存性注入)でIJsonSerializerを注入して、オブジェクトをJSONに変更する。
string jsonValue = _jsonSerializer.Serialize(value);node.SetValue("publishDate", jsonValue);
_contentService.Save(node);
_contentService.Publish(node, Array.Empty<string>());重要!
Umbraco 13には
.SaveAndPublish()があったけど、Umbraco 17では、まずは.Save()そして、.Publish()をしなければいけない。
ビューではこれ↓が使われている。
@{
var date = Model.Value<DateOnly?>("publishDate");
}
@date?.ToString("yyyy-MM-dd")IPublishedContentを使えば、通常の方法でDateOnlyを取得できるけど、IContentは本当に違う。
(これ↓が通常の方法)
node.GetValue<DateOnly?>("publishDate")これ↑を使うと、値がnullになってしまう。
だから、これ↓をしなければいけない。
string jsonValue = node.GetValue<string>("publishDate")
DateOnly publishDate = _jsonSerializer.Serialize<DateOnly?>(value);
date?.ToString("yyyy-MM-dd")Umbracoによると、これ↑は正常に動作した。
IPublishedContentはプロパティの値コンバーターを使うけど、IContentは使わない。
だから、JSONを自分でデシリアライズしなければいけない。
Umbracoにはたくさん日付を保存されているけど、あまりタイムゾーンがなかった。
そのために、Umbracoは新しい日付のエディター4を作った。
IContentServiceで日付を取得したら、まず、日付の値をstringとして取得して、その後、IJsonSerializerを使わなければいけないから、stringからDateOnlyに変更する。

ヨハネス・ランツ
ウェブ開発者・経験8年