必要なタイムゾーンで DateTime を取得するために、System.Text.Json でカスタム JsonConverter を使用しています
/// <summary>
/// Converts a string to/from DateTime, requiring the timezone
/// </summary>
public class JsonDateTimeWithTimezoneConverter : JsonConverter<DateTime>
{
//
// FOR EXPLANATIONS
//
// see https://stackoverflow.com/a/58103218/1545567 and https://stackoverflow.com/a/17752389/1545567
//
private readonly string[] FORMATS = {
// Basic formats
"yyyyMMddTHHmmsszzz",
"yyyyMMddTHHmmsszz",
"yyyyMMddTHHmmssZ",
// Extended formats
"yyyy-MM-ddTHH:mm:sszzz",
"yyyy-MM-ddTHH:mm:sszz",
"yyyy-MM-ddTHH:mm:ssZ",
// All of the above with reduced accuracy to minutes
"yyyyMMddTHHmmzzz",
"yyyyMMddTHHmmzz",
"yyyyMMddTHHmmZ",
"yyyy-MM-ddTHH:mmzzz",
"yyyy-MM-ddTHH:mmzz",
"yyyy-MM-ddTHH:mmZ",
};
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
//TODO: 400 BadRequest instead of error 500 InternalServerError when format not respected
Debug.Assert(typeToConvert == typeof(DateTime));
return DateTime.ParseExact(reader.GetString(), FORMATS, CultureInfo.InvariantCulture, DateTimeStyles.None);
}
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:sszzz"));
}
}
このように登録しますConfigureServices
services.AddControllers()
.AddJsonOptions(options => {
options.JsonSerializerOptions.Converters.Add(new JsonDateTimeWithTimezoneConverter());
});
コードでわかるように、日付がタイムゾーンなしで受信されると、エラー 500 InternalServerError の原因となる例外でクラッシュします。
app.UseExceptionHandler の使用に触れずに 400 を返すために例外をスローするにはどうすればよいですか (コードがライブラリ内にあるため)。
スローされる例外は FormatException であるため、私にとっては BadRequest に変換する必要があることに注意してください...