Last active
February 7, 2018 11:07
-
-
Save jfbueno/6ca90f23da1b3dc7e92959acfb049444 to your computer and use it in GitHub Desktop.
SimpleDateTimeApi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Globalization; | |
namespace JefersonBueno | |
{ | |
public class Program | |
{ | |
public static string ChangeDate(string date, char op, long value) | |
{ | |
var toAdd = Math.Abs(value); | |
if(op == '-') | |
toAdd *= -1; | |
var dt = CwiSimpleDateTimeExtensions.FromDateTimeString(date); | |
var newDate = dt.AddMinutes(toAdd); | |
return newDate.ToString(); | |
} | |
public static void Main() | |
{ | |
var testes = new[] | |
{ | |
new { Input = "01/03/2010 23:00", Op = '+', Val = 4_000L }, | |
new { Input = "01/01/0030 00:00", Op = '+', Val = 18_000L }, | |
new { Input = "01/05/2018 14:00", Op = '+', Val = 50L }, | |
new { Input = "02/08/2014 00:08", Op = '-', Val = -8L }, | |
new { Input = "01/05/0001 00:50", Op = '-', Val = 50L } | |
}; | |
foreach(var teste in testes) | |
{ | |
var result = ChangeDate(teste.Input, teste.Op, teste.Val); | |
var toAdd = Math.Abs(teste.Val); | |
if(teste.Op == '-') | |
toAdd *= -1; | |
var expected = DateTime.ParseExact(teste.Input, "dd/MM/yyyy HH:mm", CultureInfo.InvariantCulture).AddMinutes(toAdd).ToString("dd/MM/yyyy HH:mm"); | |
Console.WriteLine($"Input: {teste.Input} {teste.Op} {teste.Val}\nResult: {result}\nExpected: {expected} | {result == expected}\n"); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
namespace JefersonBueno | |
{ | |
/* | |
** Estrutura que representa uma data simples. Sem anos bissextos e fusos horários. | |
** Cada objeto deste tipo tem um campo chamado 'dateMillis', que contém a data e o tempo | |
** (horas e minutos apenas) contando em milissegundos a partir do dia 01/01/0001 às 00:00. | |
*/ | |
public struct CwiSimpleDateTime | |
{ | |
private enum DatePortion | |
{ | |
Year, Month, Day | |
} | |
private static readonly int[] MaxDaysOfMonths = { 30, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; | |
private static readonly int[] DaysToMonth = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; | |
private const int DaysPerYear = 365; | |
private const int MillisPerSecond = 1000; | |
private const int MillisPerMinute = 60 * MillisPerSecond; | |
private const int MillisPerHour = 60 * MillisPerMinute; | |
private const int MillisPerDay = 24 * MillisPerHour; | |
private ulong dateMillis; | |
public int Year => GetDateFraction(DatePortion.Year); | |
public int Month => GetDateFraction(DatePortion.Month); | |
public int Day => GetDateFraction(DatePortion.Day); | |
public int Hour => (int)((dateMillis / MillisPerHour) % 24); | |
public int Minute => (int)((dateMillis / MillisPerMinute) % 60); | |
private CwiSimpleDateTime(ulong millis) => dateMillis = millis; | |
public CwiSimpleDateTime(int year, int month, int day, int hour, int minute) => dateMillis = DateToMillis(year, month, day) + (ulong)TimeToMillis(hour, minute); | |
public CwiSimpleDateTime(int year, int month, int day) : this(year, month, day, 0, 0) { } | |
public CwiSimpleDateTime AddMinutes(long minutes) => Add(minutes, MillisPerMinute); | |
private CwiSimpleDateTime Add(long value, int multiplier) => AddMilliseconds(value * multiplier); | |
private CwiSimpleDateTime AddMilliseconds(long millis) => new CwiSimpleDateTime((ulong)millis + dateMillis); | |
public override string ToString() => $"{Day:d2}/{Month:d2}/{Year:d4} {Hour:d2}:{Minute:d2}"; | |
private int GetDateFraction(DatePortion part) | |
{ | |
var qtDays = (int)(dateMillis / MillisPerDay); | |
var qtYears = qtDays / DaysPerYear; | |
if(part == DatePortion.Year) | |
return qtYears + 1; | |
qtDays -= qtYears * DaysPerYear; // n = dia do ano subtraindo 1, por ex.: 2018/03/03 => 62º dia; n => 61 | |
int month = 0; | |
while (qtDays >= DaysToMonth[month]) { | |
month++; | |
} | |
if(part == DatePortion.Month) | |
return month; | |
return qtDays - DaysToMonth[month - 1] + 1; | |
} | |
private static ulong DateToMillis(int year, int month, int day) | |
{ | |
if(year < 1 || year > 9999 || month < 1 || month > 12) { | |
throw new ArgumentOutOfRangeException("O ano precisa estar entre 1 e 9999 e o mês entre 1 e 12"); | |
} | |
if(day > MaxDaysOfMonths[month - 1]) { | |
throw new ArgumentOutOfRangeException($"Quantidade de dias ({day}) inválida para o mês {month}"); | |
} | |
int y = year - 1; | |
int m = month - 1; | |
ulong n = (ulong)((day - 1) + DaysToMonth[month - 1] + ((year - 1) * DaysPerYear)); | |
return n * MillisPerDay; | |
} | |
private static long TimeToMillis(int hour, int minute) | |
{ | |
if(hour < 0 || hour > 23 || minute < 0 || minute > 59) { | |
throw new ArgumentOutOfRangeException($"Intervalo inválido para horas e minutos ({hour}:{minute})"); | |
} | |
int qt = (hour) * MillisPerHour + minute * MillisPerMinute; | |
return qt; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
namespace JefersonBueno | |
{ | |
public static class CwiSimpleDateTimeExtensions | |
{ | |
public static CwiSimpleDateTime FromDateTimeString(string data) | |
{ | |
var split = data.Split(' '); | |
var (year, month, day) = FromDateString(split[0]); | |
var (hour, minute) = FromTimeString(split[1]); | |
return new CwiSimpleDateTime(year, month, day, hour, minute); | |
} | |
private static (int year, int month, int day) FromDateString(string date) | |
{ | |
var splittedDate = date.Split('/'); | |
if(splittedDate.Length != 3) | |
return (0, 0, 0); | |
return (Convert.ToInt32(splittedDate[2]), Convert.ToInt32(splittedDate[1]), Convert.ToInt32(splittedDate[0])); | |
} | |
private static (int hour, int minute) FromTimeString(string time) | |
{ | |
var splittedTime = time.Split(':'); | |
if(splittedTime.Length != 2) | |
return (0, 0); | |
return (Convert.ToInt32(splittedTime[0]), Convert.ToInt32(splittedTime[1])); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment