ホームページ
2026年5月24日

Umbraco 17の日付選択の冒険

Umbraco
C#

最近、仕事でもっとUmbraco 17を使い始めた。

働いている間に、日付選択を使わなければいけないけど、いろんな日付選択を見つけた。

この新しい日付選択に僕はちょっと混乱した。

それに、プログラムでIContentServiceを使って日付を設定したい。

でも、IContentServiceを使った時、大変な問題を見つけた...

IContentServiceで日付を設定した後で、毎回その日付はnullになっちゃった!

このブログ記事では、新しい日付選択の使い方と、IContentServiceで日付を取得する方法を教えている。


はじめに

Umbraco 17には普通の日付選択がもうあるけど、Umbracoのブログ記事によると、Umbraco 18からその日付選択機能がなくなるらしい。

だから、Umbracoは新しい日付選択機能をおすすめしている。

エディター

使い道

ユースケース

戻り値

Date Only

日付選択

誕生日、締切、日程

DateOnly

Time Only

時間選択

営業時間、スケジュール、タイムテーブル

TimeOnly

Date Time (with Time Zone)

日付、時間、タイムゾーンをサポートする

多言語対応アプリ、タイムゾーン対応スケジュール

DateTimeOffset

Date Time (Unspecified)

タイムゾーンなしの日付と時間

地域イベント

DateTime

Umbraco17以前はたくさん日付を保存しているけど、あまりタイムゾーンがなかった。

だから、すべての日付はどんなタイムゾーンの日付か、わからない。

例えば、ウェブサイトはサーバーを変える時、この新しいサーバーは違う日付の設定があった。

サーバーのローカルタイムかUTCかわからないから、大変な問題になる。

そのために、Umbracoは新しい日付のエディターを追加したから、すべての日付はUTCになった。


IContentServiceでの日付の使い方

Before, if you could set the date on IContent by using IContentSercice

以前は、IContentIContentServiceを使って、日付を設定した場合、これ↓ができた。

node.SetValue("publishDate", DateTime.Now);
_contentService.Save(node);

でも、新しい日付のエディターを使ったら、それはできない。

この新しい日付のエディターを使いたい場合、いろいろなことをしなければいけない。

  1. クラスを作る
  2. オブジェクトを作る
  3. オブジェクトからJSONに変更する
  4. 値を設定し, 保存して公開する

下記の例はDateOnlyのエディターを使っている。

1. クラスを作る

 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; }
}

2. オブジェクトを作る

そして、オブジェクトを作る。

DateOnly dateOnly = DateOnly.FromDateTime(DateTime.Today);
DateTimeOffset dateTimeOffset = dateOnly.ToDateTime(TimeOnly.MinValue);

var value = new DateTimeUnspecified
{
	Date = dateTimeOffset
};

3. オブジェクトからJSONに変更する

そして、DI(依存性注入)でIJsonSerializerを注入して、オブジェクトをJSONに変更する。

string jsonValue = _jsonSerializer.Serialize(value);

4. 値を設定し, 保存して公開する

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年

採用可能