Având în vedere că lumea și soțul ei par să elaboreze eșantioane de coduri, iată ceea ce am scris acum ceva timp, pe baza unor câteva răspunsuri.
Aveam o nevoie specifică ca acest cod să fie localizabil. Deci am două clase? Grammar
, care specifică termenii localizabili și FuzzyDateExtensions
, care deține o grămadă de metode de extensie. Nu aveam nevoie să mă ocup de viitoare date, așa că nu se face nici o încercare de a se ocupa de acest cod.
Am lăsat o parte din XMLdoc în sursă, dar am eliminat cel mai mult (acolo unde ar fi evident) pentru dragul scurt. De asemenea, nu am inclus nici un membru al clasei aici:
public class Grammar
{
/// Gets or sets the term for "just now".
public string JustNow { get; set; }
/// Gets or sets the term for "X minutes ago".
///
/// This is a pattern, where {0}
/// is the number of minutes.
///
public string MinutesAgo { get; set; }
public string OneHourAgo { get; set; }
public string HoursAgo { get; set; }
public string Yesterday { get; set; }
public string DaysAgo { get; set; }
public string LastMonth { get; set; }
public string MonthsAgo { get; set; }
public string LastYear { get; set; }
public string YearsAgo { get; set; }
/// Gets or sets the term for "ages ago".
public string AgesAgo { get; set; }
///
/// Gets or sets the threshold beyond which the fuzzy date should be
/// considered "ages ago".
///
public TimeSpan AgesAgoThreshold { get; set; }
///
/// Initialises a new instance with the
/// specified properties.
///
private void Initialise(string justNow, string minutesAgo,
string oneHourAgo, string hoursAgo, string yesterday, string daysAgo,
string lastMonth, string monthsAgo, string lastYear, string yearsAgo,
string agesAgo, TimeSpan agesAgoThreshold)
{ ... }
}
Clasa FuzzyDateString
conține:
public static class FuzzyDateExtensions
{
public static string ToFuzzyDateString(this TimeSpan timespan)
{
return timespan.ToFuzzyDateString(new Grammar());
}
public static string ToFuzzyDateString(this TimeSpan timespan,
Grammar grammar)
{
return GetFuzzyDateString(timespan, grammar);
}
public static string ToFuzzyDateString(this DateTime datetime)
{
return (DateTime.Now - datetime).ToFuzzyDateString();
}
public static string ToFuzzyDateString(this DateTime datetime,
Grammar grammar)
{
return (DateTime.Now - datetime).ToFuzzyDateString(grammar);
}
private static string GetFuzzyDateString(TimeSpan timespan,
Grammar grammar)
{
timespan = timespan.Duration();
if (timespan >= grammar.AgesAgoThreshold)
{
return grammar.AgesAgo;
}
if (timespan < new TimeSpan(0, 2, 0)) // 2 minutes
{
return grammar.JustNow;
}
if (timespan < new TimeSpan(1, 0, 0)) // 1 hour
{
return String.Format(grammar.MinutesAgo, timespan.Minutes);
}
if (timespan < new TimeSpan(1, 55, 0)) // 1 hour 55 minutes
{
return grammar.OneHourAgo;
}
if (timespan < new TimeSpan(12, 0, 0) // 12 hours
&& (DateTime.Now - timespan).IsToday())
{
return String.Format(grammar.HoursAgo, timespan.RoundedHours());
}
if ((DateTime.Now.AddDays(1) - timespan).IsToday())
{
return grammar.Yesterday;
}
if (timespan < new TimeSpan(32, 0, 0, 0) // 32 days
&& (DateTime.Now - timespan).IsThisMonth())
{
return String.Format(grammar.DaysAgo, timespan.RoundedDays());
}
if ((DateTime.Now.AddMonths(1) - timespan).IsThisMonth())
{
return grammar.LastMonth;
}
if (timespan < new TimeSpan(365, 0, 0, 0, 0) // 365 days
&& (DateTime.Now - timespan).IsThisYear())
{
return String.Format(grammar.MonthsAgo, timespan.RoundedMonths());
}
if ((DateTime.Now - timespan).AddYears(1).IsThisYear())
{
return grammar.LastYear;
}
return String.Format(grammar.YearsAgo, timespan.RoundedYears());
}
}
Unul dintre lucrurile cheie pe care am vrut să le obțin, precum și localizarea, a fost că "astăzi" ar însemna doar "această zi calendaristică", astfel încât IsToday
, IsThisMonth
code> Metoda IsThisYear arata astfel:
public static bool IsToday(this DateTime date)
{
return date.DayOfYear == DateTime.Now.DayOfYear && date.IsThisYear();
}
și metodele de rotunjire sunt așa (am inclus RoundedMonths
, deoarece asta este un pic diferit):
public static int RoundedDays(this TimeSpan timespan)
{
return (timespan.Hours > 12) ? timespan.Days + 1 : timespan.Days;
}
public static int RoundedMonths(this TimeSpan timespan)
{
DateTime then = DateTime.Now - timespan;
// Number of partial months elapsed since 1 Jan, AD 1 (DateTime.MinValue)
int nowMonthYears = DateTime.Now.Year * 12 + DateTime.Now.Month;
int thenMonthYears = then.Year * 12 + then.Month;
return nowMonthYears - thenMonthYears;
}
Sper că oamenii consideră acest lucru util și / sau interesant: o)