diff options
Diffstat (limited to 'indra/newview/lldateutil.cpp')
-rw-r--r-- | indra/newview/lldateutil.cpp | 86 |
1 files changed, 52 insertions, 34 deletions
diff --git a/indra/newview/lldateutil.cpp b/indra/newview/lldateutil.cpp index 040fad3c4a..10b7935caf 100644 --- a/indra/newview/lldateutil.cpp +++ b/indra/newview/lldateutil.cpp @@ -37,52 +37,70 @@ #include "lltrans.h" #include "llui.h" -static S32 age_days_from_date(const std::string& date_string, - const LLDate& now) -{ - // Convert string date to malleable representation - S32 month, day, year; - S32 matched = sscanf(date_string.c_str(), "%d/%d/%d", &month, &day, &year); - if (matched != 3) return S32_MIN; - - // Create ISO-8601 date string - std::string iso8601_date_string = - llformat("%04d-%02d-%02dT00:00:00Z", year, month, day); - LLDate date(iso8601_date_string); - - // Correct for the fact that account creation dates are in Pacific time, - // == UTC - 8 - F64 date_secs_since_epoch = date.secondsSinceEpoch(); - date_secs_since_epoch += 8.0 * 60.0 * 60.0; +static S32 DAYS_PER_MONTH_NOLEAP[] = + { 31, 28, 21, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +static S32 DAYS_PER_MONTH_LEAP[] = + { 31, 29, 21, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - // Convert seconds from epoch to seconds from now - F64 now_secs_since_epoch = now.secondsSinceEpoch(); - F64 age_secs = now_secs_since_epoch - date_secs_since_epoch; - - // We don't care about sub-day times - const F64 SEC_PER_DAY = 24.0 * 60.0 * 60.0; - S32 age_days = lltrunc(age_secs / SEC_PER_DAY); - - return age_days; +static S32 days_from_month(S32 year, S32 month) +{ + if (year % 4 == 0 + && year % 100 != 0) + { + // leap year + return DAYS_PER_MONTH_LEAP[month]; + } + else + { + return DAYS_PER_MONTH_NOLEAP[month]; + } } std::string LLDateUtil::ageFromDate(const std::string& date_string, const LLDate& now) { - S32 age_days = age_days_from_date(date_string, now); - if (age_days == S32_MIN) return "???"; + S32 born_month, born_day, born_year; + S32 matched = sscanf(date_string.c_str(), "%d/%d/%d", &born_month, &born_day, &born_year); + if (matched != 3) return "???"; + LLDate born_date; + born_date.fromYMDHMS(born_year, born_month, born_day); + F64 born_date_secs_since_epoch = born_date.secondsSinceEpoch(); + // Correct for the fact that account creation dates are in Pacific time, + // == UTC - 8 + born_date_secs_since_epoch += 8.0 * 60.0 * 60.0; + born_date.secondsSinceEpoch(born_date_secs_since_epoch); + // explode out to month/day/year again + born_date.split(&born_year, &born_month, &born_day); + + S32 now_year, now_month, now_day; + now.split(&now_year, &now_month, &now_day); + + // Do grade-school subtraction, from right-to-left, borrowing from the left + // when things go negative + S32 age_days = (now_day - born_day); + if (age_days < 0) + { + now_month -= 1; + if (now_month == 0) + { + now_year -= 1; + now_month = 12; + } + age_days += days_from_month(now_year, now_month); + } + S32 age_months = (now_month - born_month); + if (age_months < 0) + { + now_year -= 1; + age_months += 12; + } + S32 age_years = (now_year - born_year); // Noun pluralization depends on language std::string lang = LLUI::getLanguage(); // Try for age in round number of years LLStringUtil::format_map_t args; - S32 age_years = age_days / 365; - age_days = age_days % 365; - // *NOTE: This is wrong. Not all months have 30 days, but we don't have a library - // for relative date arithmetic. :-( JC - S32 age_months = age_days / 30; - age_days = age_days % 30; if (age_months > 0 || age_years > 0) { |