After editing and better understanding of the problem most of the answer does not serve for the solution, it is much simpler than it seemed
When it creates the difference between two dates (DateTime
) receives an interval of time, ie a TimeSpan
. Then it’s just divided by the number of days.
(int)(timespan.Days/30.436875)
If you want to catch 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 the expected result in all situations, but it would need to have clear criteria of how to deal with each situation, which there is in the question.
If the question were more fancy I would do more fancy.
Or you can use the Nodatime who has everything ready.
Also has a response in the OS where it creates a type DateTimeSpan
which calculates 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 put in the Github for future reference.
With issues in question it became clear that the problem was another. Let’s analyze the code posted and improve it:
public CalcularValor(decimal ValorASerPago, string pDataVencimento, decimal Juros, decimal Multa){
The code does not return anything? Could have used the variable names in lower case, right?
There is no way this date is of another type? I know the mistake is already in another place, but it would not be the case to fix it?
DateTime.TryParse(pDataVencimento + " "+"23:59:59", out DateVencimento);
What’s the point of using the TryParse()
Will not check if the conversion has worked? The data may be wrong or it is guaranteed source that has a valid date?
In C# 7 you can use DateTime.TryParse(pDataVencimento + " "+"23:59:59", out var DateVencimento);
and need not even declare the variable before.
if (DataAtual > DateVencimento) {
It worries me a little, but in your routine should not cause trouble.
decimal ValorDaMulta = ValoraSerPago / 100 * Multa;
Better that way. I’m considering multa
is a percentage.
What you need to know is the number of days and not the number of months. The original question didn’t even make sense. Interest is daily, you have to multiply the day number that is late.
Worse, this whole account is wrong, it should be 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 put in the Github for future reference.
If I have to fix the error, the method needs to be well changed to deal with it, I followed the line I don’t need, but I can’t claim that.
Because in function (int)(timespan.Days/30.436875) the value of 30 has the decimals? this method would return the correct result taking into account that not every month has 30 days?
– Bruno Aparecido da Silva
Correct, depending on the criteria, because it linearizes the months, which is not quite true.
– Maniero
I made an issue in the question, is it clearer to you? With this method it would be possible to solve the problem in question?
– Bruno Aparecido da Silva
Where’s your code? Where’s your specific problem? Putting in more irrelevant information doesn’t make it any clearer. The problem is clear, what you don’t have is details. So the answer has some details, but not as many as you could if you put in the details you’re doing. You just stuffed sausage. But this information shows that your problem is another completely different from what is in the question, this is not how you calculate interest. Even this problem of calculating interest that is another different question has no criteria for knowing the exact way to calculate it.
– Maniero
The start of the interest application is not a problem, but an exact way to return the correct date in months and days.
– Bruno Aparecido da Silva
If you start from the wrong problem, the solution will be wrong.
– Maniero
So you can give me some tutorial or something related so I can solve this issue correctly
– Bruno Aparecido da Silva
There is no such thing, perhaps it is the case to open another question, but you need to give details, show what you are doing. I improved the answer and this is the real solution.
– Maniero