Skip to content

Instantly share code, notes, and snippets.

@lucasteles
Last active February 28, 2024 15:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lucasteles/177149302c4713380e4114222e5028e6 to your computer and use it in GitHub Desktop.
Save lucasteles/177149302c4713380e4114222e5028e6 to your computer and use it in GitHub Desktop.
Force UTC AspNet Core
using System.Text.Json;
using System.Text.Json.Serialization;
/// <summary>
/// Json converter for DateTime forcing local time
/// </summary>
public sealed class DateTimeForceLocalJsonConverter : JsonConverter<DateTime>
{
readonly TimeSpan offset;
/// <summary>
/// Convert DateTime always in local time Kind
/// </summary>
/// <param name="offset">Custom timespan offset for DateTimeKind.Unspecified</param>
public DateTimeForceLocalJsonConverter(TimeSpan offset) => this.offset = offset;
/// <summary>
/// Convert DateTime always in local time Kind
/// </summary>
/// <param name="timeZone">time zone to use when DateTimeKind.Unspecified</param>
public DateTimeForceLocalJsonConverter(TimeZoneInfo? timeZone = null) =>
offset = timeZone?.BaseUtcOffset ?? TimeZoneInfo.Local.BaseUtcOffset;
/// <inheritdoc />
public override DateTime
Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) =>
reader.GetDateTime() switch
{
{Kind: DateTimeKind.Utc} utcDate => utcDate.ToLocalTime(),
{Kind: DateTimeKind.Local} localDate => localDate,
var date => new DateTimeOffset(date.Ticks, offset).LocalDateTime,
};
/// <inheritdoc />
public override void
Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) =>
writer.WriteStringValue(value.ToLocalTime());
}
using System.Text.Json;
using System.Text.Json.Serialization;
/// <summary>
/// Json converter for DateTime forcing UTC
/// </summary>
public sealed class DateTimeForceTimeZoneJsonConverter : JsonConverter<DateTime>
{
readonly TimeZoneInfo timeZone;
/// <summary>
/// Convert DateTime always on a timezone
/// </summary>
/// <param name="timeZone">time zone to use when DateTimeKind.Unspecified</param>
public DateTimeForceTimeZoneJsonConverter(TimeZoneInfo? timeZone = null) =>
this.timeZone = timeZone ?? TimeZoneInfo.Local;
/// <inheritdoc />
public override DateTime
Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) =>
TimeZoneInfo.ConvertTimeFromUtc(
reader.GetDateTime() switch
{
{Kind: DateTimeKind.Utc} utcDate => utcDate,
{Kind: DateTimeKind.Local} localDate => localDate.ToUniversalTime(),
var justDate => DateTime.SpecifyKind(justDate, DateTimeKind.Utc),
},
timeZone
);
/// <inheritdoc />
public override void
Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) =>
writer.WriteStringValue(TimeZoneInfo.ConvertTimeFromUtc(value.ToUniversalTime(), timeZone));
}
using System.Text.Json;
using System.Text.Json.Serialization;
/// <summary>
/// Json converter for DateTime forcing UTC
/// </summary>
public sealed class DateTimeForceUtcJsonConverter : JsonConverter<DateTime>
{
readonly TimeSpan offset;
/// <summary>
/// Convert DateTime always in UTC Kind
/// </summary>
/// <param name="offset">Custom timespan offset for DateTimeKind.Unspecified</param>
public DateTimeForceUtcJsonConverter(TimeSpan offset) => this.offset = offset;
/// <summary>
/// Convert DateTime always in UTC Kind
/// </summary>
/// <param name="timeZone">time zone to use when DateTimeKind.Unspecified</param>
public DateTimeForceUtcJsonConverter(TimeZoneInfo? timeZone = null) =>
offset = timeZone?.BaseUtcOffset ?? TimeZoneInfo.Utc.BaseUtcOffset;
/// <inheritdoc />
public override DateTime
Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) =>
reader.GetDateTime() switch
{
{Kind: DateTimeKind.Utc} utcDate => utcDate,
{Kind: DateTimeKind.Local} localDate => localDate.ToUniversalTime(),
var date => new DateTimeOffset(date.Ticks, offset).UtcDateTime,
};
/// <inheritdoc />
public override void
Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) =>
writer.WriteStringValue(value.ToUniversalTime());
}
using System.Globalization;
using System.Text.Json;
CultureInfo.CurrentCulture = new CultureInfo("pt-BR");
// assim que pega um timezone especifico
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Pacific SA Standard Time");
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Configura as opcoes de json do aspnet
// são dois pra funcioar tanto MVC/Swagger quanto web api
builder.Services
.Configure<Microsoft.AspNetCore.Http.Json.JsonOptions>(o =>
ConfigureJsonOptions(o.SerializerOptions))
.Configure<Microsoft.AspNetCore.Mvc.JsonOptions>(o =>
ConfigureJsonOptions(o.JsonSerializerOptions));
//
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
// Funcao helper pra configurar os json options
static void ConfigureJsonOptions(JsonSerializerOptions options)
{
options.WriteIndented = false;
options.Converters.Add(new DateTimeForceUtcJsonConverter());
}
using Microsoft.AspNetCore.Mvc;
namespace WebApplication2.Controllers;
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
[HttpGet]
public IActionResult Get(DateTime date)
{
return Ok(date.ToString("o"));
}
[HttpPost]
public IActionResult Post(WeatherForecast body) =>
Ok(new
{
RequestDate = body.Date.ToString("o"),
ResponseDate = body.Date,
LocalDate = body.Date.ToLocalTime().ToString("o"),
UtcDate = body.Date.ToUniversalTime().ToString("o"),
TimeZone = TimeZoneInfo.Local.DisplayName,
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment