En mi C# ASP.NET Core, estoy tratando de obtener Meses, Trimestres, Bianuales (cantidad de 6 meses) y Años entre dos fechas (StartDate y EndDate).
He hecho TotalMonths, TotalQuarters, TotalYears como se muestra a continuación y funciona:
public static int GetTotalMonth(DateTime startDate, DateTime endDate) { int totalMonth = 12 * (startDate.Year - endDate.Year) + startDate.Month - endDate.Month; return Convert.ToInt32(Math.Abs(totalMonth)); } public static int GetTotalQuarter(DateTime startDate, DateTime endDate) { int firstQuarter = getQuarter(startDate); int secondQuarter = getQuarter(endDate); return 1 + Math.Abs(firstQuarter - secondQuarter); } private static int getQuarter(DateTime date) { return (date.Year * 4) + ((date.Month - 1) / 3); } public static int GetTotalYear(DateTime startDate, DateTime endDate) { int years = endDate.Year - startDate.Year; if (startDate.Month == endDate.Month && endDate.Day < startDate.Day) { years--; } else if (endDate.Month < startDate.Month) { years--; } return Math.Abs(years); }Donde tengo un problema es cómo obtener BiAnnual:
public static int GetTotalBiAnnual(DateTime startDate, DateTime endDate) { return; }¿Cómo lo hago?
Tratar
Math.Floor(GetTotalMonth(startDate, endDate) / 6)también has codificado una función que hace la mitad de tu trabajo, úsala;)
Sugeriría que, en lugar de calcular esto usted mismo, use la biblioteca NodaTime en su lugar.
Entonces puedes hacer algo como esto:
Period period = Period.Between(start, end, PeriodUnits.Months);Esto funcionará durante varios períodos de tiempo diferentes. Puede envolver esto en su propia clase si le resulta más fácil.
Para su bienal, puede expandir esto para tomar el valor del mes del período y redondear hacia abajo para períodos de 6 meses.
Al calcular las diferencias entre dos fechas, normalmente usa la clase TimeSpan . Sin embargo, esta clase no tiene mes ni año, lo que me llevó a crear una clase llamada TimeSpanWithYearAndMonth .
public TimeSpanWithYearAndMonth(DateTime startDate, DateTime endDate) { var span = endDate - startDate; TotalMonths = 12 * (endDate.Year - startDate.Year) + (endDate.Month - startDate.Month); Years = TotalMonths / 12; Months = TotalMonths - (Years * 12); if (Months == 0 && Years == 0) { Days = span.Days; } else { var startDateExceptYearsAndMonths = startDate.AddYears(Years); startDateExceptYearsAndMonths = startDateExceptYearsAndMonths.AddMonths(Months); Days = (endDate - startDateExceptYearsAndMonths).Days; } Hours = span.Hours; Minutes = span.Minutes; Seconds = span.Seconds; } public int Minutes { get; } public int Hours { get; } public int Days { get; } public int Years { get; } public int Months { get; } public int Seconds { get; } public int TotalMonths { get; } public int TotalHalfYears => TotalMonths / 6; Lo amplié con TotalHalfYears ("bianual") usando una división entera simple (por supuesto, puede usar solo esta parte con su cálculo de TotalMonths existente si lo desea).
Aquí hay algunas pruebas unitarias para demostrar cómo funciona;
[TestFixture] public class TimeSpanWithYearAndMonthTests { [Test] public void Calculates_correctly() { new TimeSpanWithYearAndMonth(new DateTime(2019, 5, 1), new DateTime(2019, 5, 2)).Days.Should().Be(1); new TimeSpanWithYearAndMonth(new DateTime(2019, 5, 28), new DateTime(2020, 5, 28)).Years.Should().Be(1); new TimeSpanWithYearAndMonth(new DateTime(2019, 5, 28), new DateTime(2021, 5, 28)).Years.Should().Be(2); new TimeSpanWithYearAndMonth(new DateTime(2019, 5, 28), new DateTime(2021, 5, 28)).Years.Should().Be(2); new TimeSpanWithYearAndMonth(new DateTime(2019, 1, 1), new DateTime(2021, 1, 1)).TotalHalfYears.Should().Be(4); new TimeSpanWithYearAndMonth(new DateTime(2019, 1, 1), new DateTime(2021, 1, 2)).TotalHalfYears.Should().Be(4); new TimeSpanWithYearAndMonth(new DateTime(2019, 1, 1), new DateTime(2021, 6, 1)).TotalHalfYears.Should().Be(4); new TimeSpanWithYearAndMonth(new DateTime(2019, 1, 1), new DateTime(2021, 7, 1)).TotalHalfYears.Should().Be(5); var span = new TimeSpanWithYearAndMonth(new DateTime(2019, 5, 28), new DateTime(2021, 8, 28)); span.Years.Should().Be(2); span.Months.Should().Be(3); span.TotalMonths.Should().Be(27); span = new TimeSpanWithYearAndMonth(new DateTime(2010, 5, 28), new DateTime(2020, 5, 29)); span.Years.Should().Be(10); span.Months.Should().Be(0); span.Days.Should().Be(1); span.TotalMonths.Should().Be(120); } }Asumo a partir de su código existente que necesita calcular a partir de qué semestral están la fecha de startDate y la fecha de endDate y calcular la diferencia. El código puede ser similar a GetTotalQuarter así
public static int GetTotalBiannual(DateTime startDate, DateTime endDate) { int first = GetBiannual(startDate); int second = GetBiannual(endDate); return 1 + Math.Abs(first - second); } private static int GetBiannual(DateTime date) { return (date.Year * 2) + ((date.Month - 1) / 6); }