After issues and better understanding of the problem, much of the answer is not for the solution, it's much simpler than it seemed
When you create the difference between two dates ( DateTime
) receives a time interval, that is, a TimeSpan
. From there it is only divide by the number of days.
(int)(timespan.Days/30.436875)
If you want to get the remaining days just get the rest:
timespan.Days - ((int)(timespan.Days/30.436875) * 30.436875)
If you want years:
(int)(timespan.Days/365.2425)
This may not give you the expected result in all situations, but you would need to have clear criteria on how to handle each situation, which you do not have in the question.
If the question was more detailed I would like more.
Or you can use the NodaTime that has everything ready.
You also have a response in the OS where you create a type DateTimeSpan
that computes this according to the criteria adopted by that programmer .
public struct DateTimeSpan
{
private readonly int years;
private readonly int months;
private readonly int days;
private readonly int hours;
private readonly int minutes;
private readonly int seconds;
private readonly int milliseconds;
public DateTimeSpan(int years, int months, int days, int hours, int minutes, int seconds, int milliseconds)
{
this.years = years;
this.months = months;
this.days = days;
this.hours = hours;
this.minutes = minutes;
this.seconds = seconds;
this.milliseconds = milliseconds;
}
public int Years { get { return years; } }
public int Months { get { return months; } }
public int Days { get { return days; } }
public int Hours { get { return hours; } }
public int Minutes { get { return minutes; } }
public int Seconds { get { return seconds; } }
public int Milliseconds { get { return milliseconds; } }
enum Phase { Years, Months, Days, Done }
public static DateTimeSpan CompareDates(DateTime date1, DateTime date2)
{
if (date2 < date1)
{
var sub = date1;
date1 = date2;
date2 = sub;
}
DateTime current = date1;
int years = 0;
int months = 0;
int days = 0;
Phase phase = Phase.Years;
DateTimeSpan span = new DateTimeSpan();
int officialDay = current.Day;
while (phase != Phase.Done)
{
switch (phase)
{
case Phase.Years:
if (current.AddYears(years + 1) > date2)
{
phase = Phase.Months;
current = current.AddYears(years);
}
else
{
years++;
}
break;
case Phase.Months:
if (current.AddMonths(months + 1) > date2)
{
phase = Phase.Days;
current = current.AddMonths(months);
if (current.Day < officialDay && officialDay <= DateTime.DaysInMonth(current.Year, current.Month))
current = current.AddDays(officialDay - current.Day);
}
else
{
months++;
}
break;
case Phase.Days:
if (current.AddDays(days + 1) > date2)
{
current = current.AddDays(days);
var timespan = date2 - current;
span = new DateTimeSpan(years, months, days, timespan.Hours, timespan.Minutes, timespan.Seconds, timespan.Milliseconds);
phase = Phase.Done;
}
else
{
days++;
}
break;
}
}
return span;
}
}
I placed GitHub for future reference .
With issues in the question it became clear that the problem was another. Let's look at the posted code and improve it:
public CalcularValor(decimal ValorASerPago, string pDataVencimento, decimal Juros, decimal Multa){
Does not the code return anything? I could have used variable names in lowercase, right?
Is not there a way to date be of another type? I know the error is already elsewhere, but would not it be the case to fix it?
DateTime.TryParse(pDataVencimento + " "+"23:59:59", out DateVencimento);
What's the use of using TryParse()
if not checking if the conversion worked? Can the data come wrong or is it a guaranteed source that has a valid date?
In C # 7 you can use DateTime.TryParse(pDataVencimento + " "+"23:59:59", out var DateVencimento);
and do not need to declare the variable before.
if (DataAtual > DateVencimento) {
This worries me a little, but in your routine should not cause a problem.
decimal ValorDaMulta = ValoraSerPago / 100 * Multa;
Better this way. I'm considering that multa
is a percentage.
What you need to know is the number of days, not the number of months. The original question did not even make sense. Interest is daily, you have to multiply the number of days that are late.
Worse, this whole account is wrong, it should look something like this:
public decimal CalcularValorTotal(decimal valorAPagar, string dataVencimento, decimal juros, decimal multa) {
var vencimento = DateTime.Parse(dataVencimento);
var hoje = DateTime.Now;
if (hoje > vencimento) {
var valorMulta = valorAPagar / 100 * Multa;
var valorJuros = (hoje.Date - vencimento.Date).Days * juros;
return valorAPagar + valorMulta + valorJuros;
}
return valorAPagar;
}
I placed GitHub for future reference .
If you have to deal with the error, the method needs to be well changed to deal with it, I followed the line you do not need, but I can not state that.