summaryrefslogtreecommitdiff
path: root/indra/newview/lldateutil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/lldateutil.cpp')
-rw-r--r--indra/newview/lldateutil.cpp86
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)
{