你好我已经实现了这个解决方案,以便从生日日期输入获得用户的生日: Calculate age in C#
这很好但是我需要解释生日不到一年的年龄(婴儿,婴儿)。如果bdate和当前日期之间的时间少于365天,那么现在只给我一个“0”的年龄。
我在想的是这样的:
public string calculateAge(DateTime birthDate, DateTime now)
{
//BDay is in different year (age > 1)
int age = now.Year - birthDate.Year;
if (now.Month < birthDate.Month || (now.Month == birthDate.Month && now.Day < birthDate.Day)) age--;
if (age == 0)
{
//Bday is in same year
age = now.Month - birthDate.Month;
if (now.Month < birthDate.Month || (now.Month == birthDate.Month && now.Day < birthDate.Day)) age--;
return age.ToString() + " months";
}
if (age == 0)
{
//Bday is in the same month
age = now.Day - birthDate.Day;
if (now.Month < birthDate.Month || (now.Month == birthDate.Month && now.Day < birthDate.Day)) age--;
return age.ToString() + " days";
}
return age.ToString();
}
然而,我的一些测试Bday给了我这个:
(Today's date: 3/6/2012)
Bday1 = 3/5/2012
Age result = -1
Expected result = 1 day
Bday2 = 3/1/2012
Age result = 0 months
Expected result = 5 days
Bday3 = 1/1/2012
Age result = 2 months
Expected result = 2 months (this is fine)
Bday4 = 3/7/2011
Age result = -1 months
Expected result = 11 months
Bday5 = 3/1/2011
Age result = 1
Expected result = 1 (this is fine)
您可以看到,由于当前设置的方式,问题源于bday月份小于当前月份时可能会产生一些负数。
我也看到了关于无法进入“天”循环的错误,但我认为现在这是一个有争议的问题。如果您对我能做些什么来获得理想的结果有任何见解,请告诉我。此外,如果您还需要更多信息,如测试bdays。谢谢!
答案 0 :(得分:2)
static public string calculateAge(DateTime birthDate, DateTime now)
{
birthDate = birthDate.Date;
now = now.Date;
var days = now.Day - birthDate.Day;
if (days < 0)
{
var newNow = now.AddMonths(-1);
days += (int)(now - newNow).TotalDays;
now = newNow;
}
var months = now.Month - birthDate.Month;
if (months < 0)
{
months += 12;
now = now.AddYears(-1);
}
var years = now.Year - birthDate.Year;
if (years == 0)
{
if (months == 0)
return days.ToString() + " days";
else
return months.ToString() + " months";
}
return years.ToString();
}
结果(目前 - 2012年3月7日):
3/5/2012: 2 days
3/1/2012: 6 days
1/1/2012: 2 months
3/8/2011: 11 months
3/1/2011: 1
答案 1 :(得分:2)
您可以使用Time Period Library for .NET的 DateDiff 类:
// ----------------------------------------------------------------------
public void DateDiffSample()
{
DateTime date1 = new DateTime( 2009, 11, 8, 7, 13, 59 );
Console.WriteLine( "Date1: {0}", date1 );
// > Date1: 08.11.2009 07:13:59
DateTime date2 = new DateTime( 2011, 3, 20, 19, 55, 28 );
Console.WriteLine( "Date2: {0}", date2 );
// > Date2: 20.03.2011 19:55:28
DateDiff dateDiff = new DateDiff( date1, date2 );
// elapsed
Console.WriteLine( "DateDiff.ElapsedYears: {0}", dateDiff.ElapsedYears );
// > DateDiff.ElapsedYears: 1
Console.WriteLine( "DateDiff.ElapsedMonths: {0}", dateDiff.ElapsedMonths );
// > DateDiff.ElapsedMonths: 4
Console.WriteLine( "DateDiff.ElapsedDays: {0}", dateDiff.ElapsedDays );
// > DateDiff.ElapsedDays: 12
} // DateDiffSample
答案 2 :(得分:1)
我们实际上有一个&#34; DateSpan&#34;在我们的框架中进行类似计算的结构......它与你所追求的内容相关的关键点在于定义的&#34;开始&#34;和&#34;结束&#34; DateTime
变量具有以下属性:
public int WholeMonths
{
get
{
var startInEndsYear = Start.AddYears(End.Year - Start.Year);
// Are within a month of each other if EITHER:
// 1. Month is the same
// 2. Month period is within 1
// AND
// The difference between days of the year is less than the number of days in the start's month
var sameMonth = End.Month == startInEndsYear.Month || (End.Month - 1 == Start.Month && (End.DayOfYear - startInEndsYear.DayOfYear) / (double)DateTime.DaysInMonth(startInEndsYear.Year, startInEndsYear.Month) < 1.0d );
var sameMonthAndDay = sameMonth && End.Day == Start.Day;
var res = (End.Year - Start.Year) * 12;
if (sameMonth && !sameMonthAndDay)
{
res -= (startInEndsYear > End) ? 1 : 0;
}
else if (sameMonthAndDay)
{
res -= (End.TimeOfDay < Start.TimeOfDay ? 1 : 0);
}
else
{
res -= Start.Month;
res += End.Month;
}
return res;
}
}
依赖属性:
public int WholeYears
{
get
{
return (int) Math.Floor(WholeMonths/12d);
}
}
public int PartMonths
{
get
{
return WholeMonths % 12;
}
}
我会将其作为进一步练习,让您根据这些属性转换为单词。
编辑:以下是天数的计算结果:
public TimeSpan PartDays
{
get
{
var startInEndsMonth = Start.AddMonths(WholeMonths);
return End.Subtract(startInEndsMonth);
}
}
答案 3 :(得分:1)
这是一种方式,它计算西方文化中正常人为CE dates做这件事的年龄。不同的文化和日历以不同的方式估计年龄。例如,China and other countries in Asia估计一个新生婴儿在他出生的那天是1岁,并且在中国历法的每个农历新年中他的年龄都会上升。因此,如果一个孩子在农历新年前一个月出生,那么他将在那个月成为1岁,然后在他出生后一个月就会达到2岁。
此算法不适用于BCE日期或跨越从Julian到Gregorian日历的过渡日期。无论如何,无论你如何分割,这都是冒险的命题,因为不同的地点,即使在同一个国家,也在不同的时间切换:俄罗斯在布尔什维克革命之后没有改为公历。
因此,除非你有开始日期的语言环境和结束日期的语言环境,否则你不能准确计算Julian / Gregorian鸿沟的时间跨度。
算法是:
找到参考日期,即当前日期或之前的最近一个月生日。
如果当前的日期早于实际出生日期,请使用前一个月。如果实际出生日期晚于该月的最后一天,请将其限制在该月的最后一天。
例如,如果当前日期是2012年3月7日,实际生日是'1990年3月31日',那么参考日期是2012年2月29日。
计算您的参考日期与出生日期之间的差异,以年和月为单位。这很容易,因为在西历中,年份具有一致的月数。您可以使用整数除法:
int totalMonths =(12 * endYear + endMonth) - (12 * startYear + startMonth); int years = totalMonths / 12; int months = totalMonths%12;
或者你可以在必要时减去并携带。
int years = endYear - startYear ;
int months = endMonth - startMonth ;
if ( months < 0 )
{
months += 12 ;
years -= 1 ;
}
在任何一种情况下,结果都应该相同。
days组件是从参考日期到当前日期的天数。
使用此算法,出生当天就有0天。
这是我的代码:
static class HumanAgeFactory
{
public static HumanAge ComputeAge( this DateTime dob )
{
return dob.ComputeAgeAsOf( DateTime.Now ) ;
}
public static HumanAge ComputeAgeAsOf( this DateTime dob , DateTime now )
{
dob = dob.Date ; // toss the time component
now = now.Date ; // toss the time component
if ( dob > now ) throw new ArgumentOutOfRangeException( "dob" , "'now' must be on or after 'dob'" ) ;
DateTime mostRecentBirthDay = MostRecentNthDayOfTheMonthOnOrBefore( dob.Day , now ) ;
int years = mostRecentBirthDay.Year - dob.Year ;
int months = mostRecentBirthDay.Month - dob.Month ;
int days = (int) ( now - mostRecentBirthDay ).TotalDays ;
if ( months < 0 )
{
months += 12 ;
years -= 1 ;
}
if ( days < 0 ) throw new InvalidOperationException() ;
if ( months < 0 ) throw new InvalidOperationException() ;
if ( years < 0 ) throw new InvalidOperationException() ;
HumanAge instance = new HumanAge( years , months , days ) ;
return instance ;
}
private static DateTime MostRecentNthDayOfTheMonthOnOrBefore( int nthDay , DateTime now )
{
if ( nthDay < 1 ) throw new ArgumentOutOfRangeException( "dayOfBirth" ) ;
int year = now.Year ;
int month = now.Month ;
if ( nthDay > now.Day )
{
--month ;
if ( month < 1 )
{
month += 12 ;
year -= 1 ;
}
}
int daysInMonth = CultureInfo.CurrentCulture.Calendar.GetDaysInMonth( year , month ) ;
int day = ( nthDay > daysInMonth ? daysInMonth : nthDay ) ;
DateTime instance = new DateTime( year , month , day ) ;
return instance ;
}
}
public class HumanAge
{
public int Years { get ; private set ; }
public int Months { get ; private set ; }
public int Days { get ; private set ; }
public override string ToString()
{
string instance = string.Format( "{0} {1} , {2} {3} , {4} {5}" ,
Years , Years == 1 ? "year" : "years" ,
Months , Months == 1 ? "month" : "months" ,
Days , Days == 1 ? "day" : "days"
) ;
return instance ;
}
public HumanAge( int years , int months , int days )
{
if ( years < 0 ) throw new ArgumentOutOfRangeException( "years" ) ;
if ( months < 0 || months > 12 ) throw new ArgumentOutOfRangeException( "months" ) ;
if ( days < 0 || days > 31 ) throw new ArgumentOutOfRangeException( "days" ) ;
this.Years = years ;
this.Months = months ;
this.Days = days ;
return ;
}
}
答案 4 :(得分:0)
我发现这个功能你可以稍微接近:
/// <summary>
/// Converts a timespan value to a string representation.
/// </summary>
/// <param name="time_span">the amount of time to convert to words</param>
/// <param name="whole_seconds">round up the seconds</param>
/// <returns>4 minutes, 58 seconds, etc</returns>
/// <remarks>If it can't convert to a string, it returns "Calculating time remaining..."</remarks>
public string TimespanToWords(TimeSpan time_span, bool whole_seconds = true)
{
TimeSpan span;
string str2 = "";
if (time_span.Days > 0)
{
str2 = str2 + ", " + time_span.Days.ToString() + " days";
span = new TimeSpan(time_span.Days, 0, 0, 0);
time_span = time_span.Subtract(span);
}
if (time_span.Hours > 0)
{
str2 = str2 + ", " + time_span.Hours.ToString() + " hours";
span = new TimeSpan(0, time_span.Hours, 0, 0);
time_span = time_span.Subtract(span);
}
if (time_span.Minutes > 0)
{
str2 = str2 + ", " + time_span.Minutes.ToString() + " minutes";
span = new TimeSpan(0, 0, time_span.Minutes, 0);
time_span = time_span.Subtract(span);
}
if (whole_seconds)
{
if (time_span.Seconds > 0)
{
str2 = str2 + ", " + time_span.Seconds.ToString() + " seconds";
}
}
else
{
str2 = str2 + ", " + time_span.TotalSeconds.ToString() + " seconds";
}
if (str2.Length > 0)
{
str2 = str2.Substring(2);
}
if (string.IsNullOrEmpty(str2))
{
return "Calculating time remaining...";
}
return str2;
}
以下是如何使用它:
var date1 = System.DateTime.Parse("01/01/1999");
var date2 = System.DateTime.Parse("03/07/2012");
var ts = date2 - date1;
var timeString = TimespanToWords(ts, true);
答案 5 :(得分:0)
int[] getAge(DateTime dt)
{
DateTime today = DateTime.Now;
int years = 0;
int days = 0;
int months = 0;
int[] age = new int[3];
while (dt.Year != today.Year || dt.Month != today.Month || dt.Day != today.Day)
{
if (dt.AddYears(1).CompareTo(today) <= 0)
{
years++;
dt = dt.AddYears(1);
}
else
{
if (dt.AddMonths(1).CompareTo(today) <= 0)
{
months++;
dt = dt.AddMonths(1);
}
else
{
if (dt.AddDays(1).CompareTo(today) <= 0)
{
days++;
dt = dt.AddDays(1);
}
else
{
dt = today;
}
}
}
}
age[0] = years;
age[1] = months;
age[2] = days;
return age;
}