From 87391ad9b1686269d07ebf7a6fa1576384fee271 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 31 May 2022 12:30:03 +0500 Subject: [PATCH] Add DateOnly, TimeOnly support --- AsbCloudApp/Data/ScheduleDto.cs | 4 +- AsbCloudApp/Data/TimeDto.cs | 79 +++++++++++++++++++ AsbCloudInfrastructure/DependencyInjection.cs | 7 ++ .../Validators/DependencyInjection.cs | 1 + .../Validators/TimeDtoValidator.cs | 23 ++++++ AsbCloudWebApi/AsbCloudWebApi.csproj | 10 +-- .../Converters/TimeOnlyTypeConverter.cs | 46 +++++++++++ AsbCloudWebApi/Startup.cs | 9 +-- ConsoleApp1/Program.cs | 25 +++++- 9 files changed, 191 insertions(+), 13 deletions(-) create mode 100644 AsbCloudApp/Data/TimeDto.cs create mode 100644 AsbCloudInfrastructure/Validators/TimeDtoValidator.cs create mode 100644 AsbCloudWebApi/Converters/TimeOnlyTypeConverter.cs diff --git a/AsbCloudApp/Data/ScheduleDto.cs b/AsbCloudApp/Data/ScheduleDto.cs index 1790ab41..610cdab7 100644 --- a/AsbCloudApp/Data/ScheduleDto.cs +++ b/AsbCloudApp/Data/ScheduleDto.cs @@ -25,12 +25,12 @@ namespace AsbCloudApp.Data /// /// Начало смены /// - public TimeOnly ShiftStart { get; set; } + public TimeDto ShiftStart { get; set; } /// /// Конец смены /// - public TimeOnly ShiftEnd { get; set; } + public TimeDto ShiftEnd { get; set; } /// /// Начало бурения diff --git a/AsbCloudApp/Data/TimeDto.cs b/AsbCloudApp/Data/TimeDto.cs new file mode 100644 index 00000000..969cf21f --- /dev/null +++ b/AsbCloudApp/Data/TimeDto.cs @@ -0,0 +1,79 @@ +using System; + +namespace AsbCloudApp.Data +{ + /// + /// DTO времени + /// + public class TimeDto + { + private int hour = 0; + private int minute = 0; + private int second = 0; + + /// + /// час + /// + public int Hour { + get => hour; + set { + if (value > 23 || value < 0) + throw new ArgumentOutOfRangeException(nameof(Hour), "hour should be in [0; 23]"); + hour = value; + } + } + + /// + /// минута + /// + public int Minute + { + get => minute; + set + { + if (value > 59 || value < 0) + throw new ArgumentOutOfRangeException(nameof(minute), "minute should be in [0; 59]"); + minute = value; + } + } + + /// + /// секунда + /// + public int Second + { + get => second; + set + { + if (value > 59 || value < 0) + throw new ArgumentOutOfRangeException(nameof(second), "second should be in [0; 59]"); + second = value; + } + } + + /// + public TimeDto() + { } + + /// + public TimeDto(TimeOnly time) + { + hour = time.Hour; + minute = time.Minute; + second = time.Second; + } + + /// + /// Makes System.TimeOnly + /// + /// System.TimeOnly + public TimeOnly MakeTimeOnly() => new(Hour, Minute, Second); + + /// + public override string ToString() + { + var str = $"{Hour:00}:{Minute:00}:{Second:00}"; + return str; + } + } +} diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index 629ac726..48c3cb30 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -40,6 +40,13 @@ namespace AsbCloudInfrastructure .ForType() .MapWith((source) => source == default ? new DateTime(0, DateTimeKind.Utc) : source); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .MapWith((source) => source == default ? default : source.MakeTimeOnly()); + + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .MapWith((source) => new(source)); } public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration) diff --git a/AsbCloudInfrastructure/Validators/DependencyInjection.cs b/AsbCloudInfrastructure/Validators/DependencyInjection.cs index 1af250eb..3ac651aa 100644 --- a/AsbCloudInfrastructure/Validators/DependencyInjection.cs +++ b/AsbCloudInfrastructure/Validators/DependencyInjection.cs @@ -22,6 +22,7 @@ namespace AsbCloudInfrastructure.Validators // services.AddTransient, UserRoleDtoValidator>(); // services.AddTransient, WellDtoValidator>(); // services.AddTransient, WellOperationDtoValidator>(); + // TimeDtoValidator return services; } diff --git a/AsbCloudInfrastructure/Validators/TimeDtoValidator.cs b/AsbCloudInfrastructure/Validators/TimeDtoValidator.cs new file mode 100644 index 00000000..e9c7ba54 --- /dev/null +++ b/AsbCloudInfrastructure/Validators/TimeDtoValidator.cs @@ -0,0 +1,23 @@ +using AsbCloudApp.Data; +using FluentValidation; + +namespace AsbCloudInfrastructure.Validators +{ + public class TimeDtoValidator : AbstractValidator + { + public TimeDtoValidator() + { + RuleFor(x=>x.Hour) + .InclusiveBetween(0,23) + .WithMessage("hour should be in [0; 23]"); + + RuleFor(x => x.Minute) + .InclusiveBetween(0, 59) + .WithMessage("minute should be in [0; 59]"); + + RuleFor(x => x.Second) + .InclusiveBetween(0, 59) + .WithMessage("second should be in [0; 59]"); + } + } +} diff --git a/AsbCloudWebApi/AsbCloudWebApi.csproj b/AsbCloudWebApi/AsbCloudWebApi.csproj index 92304360..492513b3 100644 --- a/AsbCloudWebApi/AsbCloudWebApi.csproj +++ b/AsbCloudWebApi/AsbCloudWebApi.csproj @@ -8,12 +8,12 @@ - - - + + + - - + + diff --git a/AsbCloudWebApi/Converters/TimeOnlyTypeConverter.cs b/AsbCloudWebApi/Converters/TimeOnlyTypeConverter.cs new file mode 100644 index 00000000..484d2f3e --- /dev/null +++ b/AsbCloudWebApi/Converters/TimeOnlyTypeConverter.cs @@ -0,0 +1,46 @@ +using System; +using System.ComponentModel; +using System.Globalization; + +namespace AsbCloudWebApi.Converters +{ +#nullable enable + public class DateOnlyTypeConverter : TypeConverter + { + public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType) + { + if (sourceType == typeof(string)) + { + return true; + } + return base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value) + { + if (value is string str) + { + return TimeOnly.Parse(str); + } + return base.ConvertFrom(context, culture, value); + } + + public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType) + { + if (destinationType == typeof(string)) + { + return true; + } + return base.CanConvertTo(context, destinationType); + } + public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType) + { + if (destinationType == typeof(string) && value is TimeOnly date) + { + return date.ToString("O"); + } + return base.ConvertTo(context, culture, value, destinationType); + } + } +#nullable disable +} diff --git a/AsbCloudWebApi/Startup.cs b/AsbCloudWebApi/Startup.cs index d65805e0..16c286f0 100644 --- a/AsbCloudWebApi/Startup.cs +++ b/AsbCloudWebApi/Startup.cs @@ -20,16 +20,15 @@ namespace AsbCloudWebApi public void ConfigureServices(IServiceCollection services) { services.AddControllers() - .AddJsonOptions(new System.Action(opts => + .AddJsonOptions(new System.Action(options => { - opts.JsonSerializerOptions.NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals | System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString; - })) - .AddProtoBufNet(); //adds mediaType "application/protobuf" + options.JsonSerializerOptions.NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals | System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString; })) + .AddProtoBufNet(); ProtobufModel.EnshureRegistered(); services.AddSwagger(); - + services.AddInfrastructure(Configuration); services.AddJWTAuthentication(); diff --git a/ConsoleApp1/Program.cs b/ConsoleApp1/Program.cs index 33142088..6ecc53aa 100644 --- a/ConsoleApp1/Program.cs +++ b/ConsoleApp1/Program.cs @@ -1,5 +1,7 @@ -using AsbCloudDb.Model; +using AsbCloudApp.Data; +using AsbCloudDb.Model; using AsbCloudInfrastructure.Services.DailyReport; +using Mapster; using Microsoft.EntityFrameworkCore; using System; using System.Linq; @@ -23,6 +25,27 @@ namespace ConsoleApp1 { static void Main(/*string[] args*/) { + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .MapWith((source) => source.DateTime); + + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .MapWith((source) => source == default ? new DateTime(0, DateTimeKind.Utc) : source); + + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .MapWith((source) => source == default? default: source.MakeTimeOnly()); + + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .MapWith((source) => new (source)); + + var sh = new ScheduleDto{ + ShiftStart = new TimeDto { Hour = 11, Minute = 30, } + }; + var en = sh.Adapt(); + var aa = en.Adapt(); // use ServiceFactory to make services var op = ServiceFactory.MakeWellOperationsService(); var d = op.FirstOperationDate(90);