5

Say I have 678 days, how to calculate how many years, months and days are there from that moment?

Duration duration = Duration.FromStandardDays(678);
Instant now = SystemClock.Instance.Now;
Instant future = now + duration;

// I have to convert NodaTime.Instant to NodaTime.LocalDate but don't know how

Period period = Period.Between(now, future);
Console.WriteLine("{0} years, {1} months, {2} days", period.Years, period.Months, period.Days);
  • 3
    Do you mean you have 678 days left to calculate when the end of time occurs? On a more serious note, see [How to convert number of days to years,months and days](http://stackoverflow.com/questions/19632069/how-to-convert-number-of-days-to-years-months-and-days), [Calculate days in years and months?](http://stackoverflow.com/questions/3884971/calculate-days-in-years-and-months), [Calculating Day, Month, Year](http://stackoverflow.com/questions/3766817/calculating-day-month-year) or try using the search. – CodeCaster Apr 01 '14 at 20:13
  • 5
    You can't without a point of reference. A year is variable length, as is a month. So the answer depends on the date that you ask it. – spender Apr 01 '14 at 20:15
  • @Code 678 days = 1 years, 10 months, x days. That's what I need. – user3473957 Apr 01 '14 at 20:16
  • @spender Exactly, the starting date is the moment of calculation. – user3473957 Apr 01 '14 at 20:18
  • It depends. Are there leap years? We need more info. – Julian J. Tejera Apr 01 '14 at 20:19
  • See http://stackoverflow.com/questions/1916358/a-real-timespan-object-with-years-months – kol Apr 01 '14 at 20:20
  • @JulianJ.Tejera How could I know? If I calculate it now I'll use 01.04.2014 if I calculate it after one year I'll have to use 01.04.2015. – user3473957 Apr 01 '14 at 20:22

2 Answers2

10

You can indeed do this with Noda Time.

First, you need a starting point. This uses the current day in the local time zone. You may wish to use a different day, or a different time zone, depending on your scenario.

Instant now = SystemClock.Instance.Now;
DateTimeZone timeZone = DateTimeZoneProviders.Bcl.GetSystemDefault();
LocalDate today = now.InZone(timeZone).Date;

Then just add the number of days:

int days = 678;
LocalDate future = today.PlusDays(days);

Then you can obtain a period with the units desired:

Period period = Period.Between(today, future, PeriodUnits.YearMonthDay);
Console.WriteLine("{0} years, {1} months, {2} days",
                  period.Years, period.Months, period.Days);

It's important to recognize that the result represents "time from now". Or if you substitute a different starting point, it's "time from (the starting point)". Under no circumstances should you just think that the result is X days = Y years + M months + D days. That would be nonsensical, since the number of days in a year and the number of days in a month depend on which year and month you're talking about.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • Thanks for your answer! Excuse my ignorance... I added Noda Time reference but getting an error "Error 1 'NodaTime.DateTimeZoneProviders' does not contain a definition for 'Bcl'" – user3473957 Apr 02 '14 at 16:24
  • That's been there since the first release. Not sure why you'd get an error unless it's a simple typo. ([docs here](http://nodatime.org/1.2.x/api/html/T_NodaTime_DateTimeZoneProviders.htm)). Of course, you can use the `Tzdb` provider, or pick whatever time zone is relevant for your use case. You *do* need a time zone, because answering the question "What day is today" is time-zone dependent, even if you just care about the date and not the time. – Matt Johnson-Pint Apr 02 '14 at 16:50
  • 1
    The BCL provider isn't available in the PCL version of Noda Time; that might also explain the error. – Malcolm Rowe Apr 02 '14 at 23:35
0

You just need to add the number of days to the current time:

var now = DateTime.Now;
var future = now.AddDays(678);

int years = future.Year - now.Year;
int months = future.Month - now.Month;
if (months < 0)
{
    years--;
    months += 12;
}
int days = future.Day + DateTime.DaysInMonth(now.Year, now.Month) - now.Day;
itsme86
  • 19,266
  • 4
  • 41
  • 57
  • 1
    If I add 365 days the result is 1 year(s), 0 month(s) and 30 day(s)! If I add 60 days the result is 0 year(s), 2 month(s) and 29 day(s)! Something is wrong! How can I fix it? – user3473957 Apr 01 '14 at 22:14