EXT-1743 People inspectors should show Age, not Date born, fixed date math

Changed date math to correctly account for month lengths and leap years.
Extended unit test.
Review pending.
master
James Cook 2009-11-18 19:21:09 -08:00
parent 81eca4a782
commit 7ab6dc37f8
3 changed files with 90 additions and 10 deletions

View File

@ -66,23 +66,82 @@ static S32 age_days_from_date(const std::string& date_string,
return age_days;
}
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 };
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)
{
#define BAD_DATE_MATH 0
#if BAD_DATE_MATH
S32 age_days = age_days_from_date(date_string, now);
if (age_days == S32_MIN) return "???";
// 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;
#else
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);
#endif
// Noun pluralization depends on language
std::string lang = LLUI::getLanguage();
// Try for age in round number of years
LLStringUtil::format_map_t args;
if (age_months > 0 || age_years > 0)
{

View File

@ -39,6 +39,7 @@
#include "llavataractions.h"
#include "llavatarpropertiesprocessor.h"
#include "llcallingcard.h"
#include "lldateutil.h"
#include "llfloaterreporter.h"
#include "llfloaterworldmap.h"
#include "llinspect.h"
@ -351,7 +352,7 @@ void LLInspectAvatar::processAvatarData(LLAvatarData* data)
{
LLStringUtil::format_map_t args;
args["[BORN_ON]"] = data->born_on;
args["[AGE]"] = data->born_on;
args["[AGE]"] = LLDateUtil::ageFromDate(data->born_on, LLDate::now());
args["[SL_PROFILE]"] = data->about_text;
args["[RW_PROFILE"] = data->fl_about_text;
args["[ACCTTYPE]"] = LLAvatarPropertiesProcessor::accountType(data);

View File

@ -60,6 +60,11 @@ std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::
std::string LLTrans::getCountString(const std::string& language, const std::string& xml_desc, S32 count)
{
count_string_t key(xml_desc, count);
if (gCountString.find(key) == gCountString.end())
{
return std::string("Couldn't find ") + xml_desc;
}
return gCountString[ count_string_t(xml_desc, count) ];
}
@ -91,8 +96,11 @@ namespace tut
gCountString[ count_string_t("AgeYears", 2) ] = "2 years";
gCountString[ count_string_t("AgeMonths", 1) ] = "1 month";
gCountString[ count_string_t("AgeMonths", 2) ] = "2 months";
gCountString[ count_string_t("AgeMonths", 11) ]= "11 months";
gCountString[ count_string_t("AgeWeeks", 1) ] = "1 week";
gCountString[ count_string_t("AgeWeeks", 2) ] = "2 weeks";
gCountString[ count_string_t("AgeWeeks", 3) ] = "3 weeks";
gCountString[ count_string_t("AgeWeeks", 4) ] = "4 weeks";
gCountString[ count_string_t("AgeDays", 1) ] = "1 day";
gCountString[ count_string_t("AgeDays", 2) ] = "2 days";
}
@ -113,12 +121,18 @@ namespace tut
ensure_equals("years",
LLDateUtil::ageFromDate("12/31/2007", mNow),
"2 years old" );
ensure_equals("single year",
LLDateUtil::ageFromDate("12/31/2008", mNow),
"1 year old" );
ensure_equals("years",
LLDateUtil::ageFromDate("1/1/2008", mNow),
"1 year 11 months old" );
ensure_equals("single year + one month",
LLDateUtil::ageFromDate("11/30/2008", mNow),
"1 year 1 month old" );
ensure_equals("single year + a bit",
LLDateUtil::ageFromDate("12/12/2008", mNow),
"1 year old" );
ensure_equals("single year",
LLDateUtil::ageFromDate("12/31/2008", mNow),
"1 year old" );
}
template<> template<>
@ -128,6 +142,9 @@ namespace tut
ensure_equals("months",
LLDateUtil::ageFromDate("10/30/2009", mNow),
"2 months old" );
ensure_equals("months 2",
LLDateUtil::ageFromDate("10/31/2009", mNow),
"2 months old" );
ensure_equals("single month",
LLDateUtil::ageFromDate("11/30/2009", mNow),
"1 month old" );
@ -137,6 +154,9 @@ namespace tut
void dateutil_object_t::test<3>()
{
set_test_name("Weeks");
ensure_equals("4 weeks",
LLDateUtil::ageFromDate("12/1/2009", mNow),
"4 weeks old" );
ensure_equals("weeks",
LLDateUtil::ageFromDate("12/17/2009", mNow),
"2 weeks old" );