Answer-ID
  • Întrebări
  • Tag-uri
  • Categorii
Notificări
Recompense
Înregistrare
După înregistrare, veți primi notificări despre răspunsurile și comentariile la întrebările DVS.
Logare
Dacă aveţi deja un cont, autentificaţi-vă pentru a verifica notificările noi.
Aici vor fi recompensele pentru întrebările, răspunsurile și comentariile adăugate sau modificate.
Mai mult
Sursă
Editează
Jeff Atwood
Jeff Atwood

Calcula timp relativ în C#

Având un specific DateTime de valoare, cum pot afișa timp relativ, cum ar fi:

  • 2 ore în urmă
  • 3 zile în urmă
  • o lună în urmă
1453 2008-07-31T23:55:37+00:00 37
Programare
datetime
c#
time
datediff
relative-time-span
Comentarii la întrebare (3)
Soluția
Vincent Robert
Vincent Robert
4 august 2008 в 1:57
2008-08-04T13:57:26+00:00
Mai mult
Sursă
Editează
#8406140

Jeff, codul este frumos, dar ar putea fi mai clare cu constante (cum se sugerează în Cod Complet).

const int MINUTE = 60 * SECOND;
const int HOUR = 60 * MINUTE;
const int DAY = 24 * HOUR;
const int MONTH = 30 * DAY;

var ts = new TimeSpan(DateTime.UtcNow.Ticks - yourDate.Ticks);
double delta = Math.Abs(ts.TotalSeconds);

if (delta < 1 * MINUTE)
  return ts.Seconds == 1 ? "one second ago" : ts.Seconds + " seconds ago";

if (delta < 2 * MINUTE)
  return "a minute ago";

if (delta < 45 * MINUTE)
  return ts.Minutes + " minutes ago";

if (delta < 90 * MINUTE)
  return "an hour ago";

if (delta < 24 * HOUR)
  return ts.Hours + " hours ago";

if (delta < 48 * HOUR)
  return "yesterday";

if (delta < 30 * DAY)
  return ts.Days + " days ago";

if (delta < 12 * MONTH)
{
  int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));
  return months <= 1 ? "one month ago" : months + " months ago";
}
else
{
  int years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));
  return years <= 1 ? "one year ago" : years + " years ago";
}
953
0
Comentarii (20)
Ryan McGeary
Ryan McGeary
21 septembrie 2008 в 4:04
2008-09-21T16:04:55+00:00
Mai mult
Sursă
Editează
#8406149

jquery.timeago plugin

Jeff, pentru că Stack Overflow foloseste jQuery intens, vă recomandăm jquery.timeago plugin.

Beneficii:

  • Evita marcajele de timp datat ", 1 minute în urmă" chiar dacă pagina a fost deschis în urmă cu 10 minute; timeago reîmprospătează automat.
  • Puteți profita din plin de pagină și/sau caching-ul de fragmente în aplicații web, deoarece marcajele de timp sunt't calculată pe server.
  • Veți obține pentru a utiliza microformate ca copiii se răcească.

Doar atașați-l la marcajele de timp pe DOM gata:

    jQuery(&#39;abbr.timeago&#39;).timeago();
});

Acest lucru va transforma toate abbr elemente cu o clasă de timeago și ISO 8601 timestamp în titlu:

în ceva de genul asta:

care produce: 4 luni în urmă. Pe măsură ce trece timpul, marcajele de timp se va actualiza automat.

Disclaimer: am scris acest plugin, deci am'm părtinitoare.

357
0
Comentarii (12)
Jeff Atwood
Jeff Atwood
31 iulie 2008 в 11:56
2008-07-31T23:56:41+00:00
Mai mult
Sursă
Editează
#8406138

Aici's cum o fac

double delta = Math.Abs(ts.TotalSeconds);

if (delta < 60)
{
  return ts.Seconds == 1 ? "one second ago" : ts.Seconds + " seconds ago";
}
if (delta < 120)
{
  return "a minute ago";
}
if (delta < 2700) // 45 * 60
{
  return ts.Minutes + " minutes ago";
}
if (delta < 5400) // 90 * 60
{
  return "an hour ago";
}
if (delta < 86400) // 24 * 60 * 60
{
  return ts.Hours + " hours ago";
}
if (delta < 172800) // 48 * 60 * 60
{
  return "yesterday";
}
if (delta < 2592000) // 30 * 24 * 60 * 60
{
  return ts.Days + " days ago";
}
if (delta < 31104000) // 12 * 30 * 24 * 60 * 60
{
  int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));
  return months <= 1 ? "one month ago" : months + " months ago";
}
int years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));
return years <= 1 ? "one year ago" : years + " years ago";

Sugestii? Comentarii? Modalități de a îmbunătăți acest algoritm?

326
0
Comentarii (11)
 DevelopingChris
DevelopingChris
14 august 2008 в 5:43
2008-08-14T05:43:45+00:00
Mai mult
Sursă
Editează
#8406142
{
    Dictionary<long, string> thresholds = new Dictionary<long, string>();
    int minute = 60;
    int hour = 60 * minute;
    int day = 24 * hour;
    thresholds.Add(60, "{0} seconds ago");
    thresholds.Add(minute * 2, "a minute ago");
    thresholds.Add(45 * minute, "{0} minutes ago");
    thresholds.Add(120 * minute, "an hour ago");
    thresholds.Add(day, "{0} hours ago");
    thresholds.Add(day * 2, "yesterday");
    thresholds.Add(day * 30, "{0} days ago");
    thresholds.Add(day * 365, "{0} months ago");
    thresholds.Add(long.MaxValue, "{0} years ago");
    long since = (DateTime.Now.Ticks - theDate.Ticks) / 10000000;
    foreach (long threshold in thresholds.Keys) 
    {
        if (since < threshold) 
        {
            TimeSpan t = new TimeSpan((DateTime.Now.Ticks - theDate.Ticks));
            return string.Format(thresholds[threshold], (t.Days > 365 ? t.Days / 365 : (t.Days > 0 ? t.Days : (t.Hours > 0 ? t.Hours : (t.Minutes > 0 ? t.Minutes : (t.Seconds > 0 ? t.Seconds : 0))))).ToString());
        }
    }
    return "";
}

Eu prefer această versiune pentru concizie, și capacitatea de a adăuga noi bifați puncte. Acest lucru ar putea fi încapsulate cu o Ultima()` extensie pentru Durata de timp în loc de asta timp de 1 linie, dar pentru concizie în postarea, asta va face. Aceasta stabilește o oră, 1 oră în urmă, prin furnizarea de o oră până la 2 ore s-au scurs

92
0
Comentarii (5)
 Thomaschaaf
Thomaschaaf
1 februarie 2009 в 7:22
2009-02-01T19:22:41+00:00
Mai mult
Sursă
Editează
#8406152

Aici o rescriere de Jeffs Script PHP:

define("MINUTE", 60 * SECOND);
define("HOUR", 60 * MINUTE);
define("DAY", 24 * HOUR);
define("MONTH", 30 * DAY);
function relativeTime($time)
{   
    $delta = time() - $time;

    if ($delta < 1 * MINUTE)
    {
        return $delta == 1 ? "one second ago" : $delta . " seconds ago";
    }
    if ($delta < 2 * MINUTE)
    {
      return "a minute ago";
    }
    if ($delta < 45 * MINUTE)
    {
        return floor($delta / MINUTE) . " minutes ago";
    }
    if ($delta < 90 * MINUTE)
    {
      return "an hour ago";
    }
    if ($delta < 24 * HOUR)
    {
      return floor($delta / HOUR) . " hours ago";
    }
    if ($delta < 48 * HOUR)
    {
      return "yesterday";
    }
    if ($delta < 30 * DAY)
    {
        return floor($delta / DAY) . " days ago";
    }
    if ($delta < 12 * MONTH)
    {
      $months = floor($delta / DAY / 30);
      return $months <= 1 ? "one month ago" : $months . " months ago";
    }
    else
    {
        $years = floor($delta / DAY / 365);
        return $years <= 1 ? "one year ago" : $years . " years ago";
    }
}    
71
0
Comentarii (1)
Utilizator anonim
17 septembrie 2008 в 3:19
2008-09-17T03:19:19+00:00
Mai mult
Sursă
Editează
#8406148
{
    TimeSpan oSpan = DateTime.Now.Subtract(input);
    double TotalMinutes = oSpan.TotalMinutes;
    string Suffix = " ago";

    if (TotalMinutes < 0.0)
    {
        TotalMinutes = Math.Abs(TotalMinutes);
        Suffix = " from now";
    }

    var aValue = new SortedList<double, Func<string>>();
    aValue.Add(0.75, () => "less than a minute");
    aValue.Add(1.5, () => "about a minute");
    aValue.Add(45, () => string.Format("{0} minutes", Math.Round(TotalMinutes)));
    aValue.Add(90, () => "about an hour");
    aValue.Add(1440, () => string.Format("about {0} hours", Math.Round(Math.Abs(oSpan.TotalHours)))); // 60 * 24
    aValue.Add(2880, () => "a day"); // 60 * 48
    aValue.Add(43200, () => string.Format("{0} days", Math.Floor(Math.Abs(oSpan.TotalDays)))); // 60 * 24 * 30
    aValue.Add(86400, () => "about a month"); // 60 * 24 * 60
    aValue.Add(525600, () => string.Format("{0} months", Math.Floor(Math.Abs(oSpan.TotalDays / 30)))); // 60 * 24 * 365 
    aValue.Add(1051200, () => "about a year"); // 60 * 24 * 365 * 2
    aValue.Add(double.MaxValue, () => string.Format("{0} years", Math.Floor(Math.Abs(oSpan.TotalDays / 365))));

    return aValue.First(n => TotalMinutes < n.Key).Value.Invoke() + Suffix;
}

http://refactormycode.com/codes/493-twitter-esque-relative-dates

C# 6 versiune:

   new SortedList<double, Func<TimeSpan, string>>
{
    { 0.75, _ => "less than a minute"},
    { 1.5, _ => "about a minute"},
    { 45, x => $"{x.TotalMinutes:F0} minutes"},
    { 90, x => "about an hour"},
    { 1440, x => $"about {x.TotalHours:F0} hours"},
    { 2880, x => "a day"},
    { 43200, x => $"{x.TotalDays:F0} days"},
    { 86400, x => "about a month"},
    { 525600, x => $"{x.TotalDays / 30:F0} months"},
    { 1051200, x => "about a year"},
    { double.MaxValue, x => $"{x.TotalDays / 365:F0} years"}
};

public static string ToRelativeDate(this DateTime input)
{
    TimeSpan x = DateTime.Now - input;
    string Suffix = x.TotalMinutes > 0 ? " ago" : " from now";
    x = new TimeSpan(Math.Abs(x.Ticks));
    return offsets.First(n => x.TotalMinutes < n.Key).Value(x) + Suffix;
}
65
0
Comentarii (4)
 neuracnu
neuracnu
9 martie 2009 в 10:02
2009-03-09T22:02:29+00:00
Mai mult
Sursă
Editează
#8406154

Aici's o implementare am adăugat ca o metodă de prelungire a DateTime clasa care se ocupă de ambele viitor și date din trecut și oferă o aproximare opțiune care vă permite să specificați nivelul de detaliu're în căutarea pentru ("3 ore în urmă" vs "3 ore, 23 minute, 12 secunde în urmă"):


/// <summary>
/// Compares a supplied date to the current date and generates a friendly English 
/// comparison ("5 days ago", "5 days from now")
/// </summary>
/// <param name="date">The date to convert</param>
/// <param name="approximate">When off, calculate timespan down to the second.
/// When on, approximate to the largest round unit of time.</param>
/// <returns></returns>
public static string ToRelativeDateString(this DateTime value, bool approximate)
{
    StringBuilder sb = new StringBuilder();

    string suffix = (value > DateTime.Now) ? " from now" : " ago";

    TimeSpan timeSpan = new TimeSpan(Math.Abs(DateTime.Now.Subtract(value).Ticks));

    if (timeSpan.Days > 0)
    {
        sb.AppendFormat("{0} {1}", timeSpan.Days,
          (timeSpan.Days > 1) ? "days" : "day");
        if (approximate) return sb.ToString() + suffix;
    }
    if (timeSpan.Hours > 0)
    {
        sb.AppendFormat("{0}{1} {2}", (sb.Length > 0) ? ", " : string.Empty,
          timeSpan.Hours, (timeSpan.Hours > 1) ? "hours" : "hour");
        if (approximate) return sb.ToString() + suffix;
    }
    if (timeSpan.Minutes > 0)
    {
        sb.AppendFormat("{0}{1} {2}", (sb.Length > 0) ? ", " : string.Empty, 
          timeSpan.Minutes, (timeSpan.Minutes > 1) ? "minutes" : "minute");
        if (approximate) return sb.ToString() + suffix;
    }
    if (timeSpan.Seconds > 0)
    {
        sb.AppendFormat("{0}{1} {2}", (sb.Length > 0) ? ", " : string.Empty, 
          timeSpan.Seconds, (timeSpan.Seconds > 1) ? "seconds" : "second");
        if (approximate) return sb.ToString() + suffix;
    }
    if (sb.Length == 0) return "right now";

    sb.Append(suffix);
    return sb.ToString();
}
50
0
Comentarii (0)
Jauder Ho
Jauder Ho
23 octombrie 2008 в 10:44
2008-10-23T10:44:13+00:00
Mai mult
Sursă
Editează
#8406151

Mi-ar recomanda calcul acest lucru pe partea de client prea. Mai puțin de lucru pentru server.

Următoarele este versiunea care o folosesc eu (de la Zach Leatherman)

 * Javascript Humane Dates
 * Copyright (c) 2008 Dean Landolt (deanlandolt.com)
 * Re-write by Zach Leatherman (zachleat.com)
 * 
 * Adopted from the John Resig&#39;s pretty.js
 * at http://ejohn.org/blog/javascript-pretty-date
 * and henrah&#39;s proposed modification 
 * at http://ejohn.org/blog/javascript-pretty-date/#comment-297458
 * 
 * Licensed under the MIT license.
 */

function humane_date(date_str){
        var time_formats = [
                [60, &#39;just now&#39;],
                [90, &#39;1 minute&#39;], // 60*1.5
                [3600, &#39;minutes&#39;, 60], // 60*60, 60
                [5400, &#39;1 hour&#39;], // 60*60*1.5
                [86400, &#39;hours&#39;, 3600], // 60*60*24, 60*60
                [129600, &#39;1 day&#39;], // 60*60*24*1.5
                [604800, &#39;days&#39;, 86400], // 60*60*24*7, 60*60*24
                [907200, &#39;1 week&#39;], // 60*60*24*7*1.5
                [2628000, &#39;weeks&#39;, 604800], // 60*60*24*(365/12), 60*60*24*7
                [3942000, &#39;1 month&#39;], // 60*60*24*(365/12)*1.5
                [31536000, &#39;months&#39;, 2628000], // 60*60*24*365, 60*60*24*(365/12)
                [47304000, &#39;1 year&#39;], // 60*60*24*365*1.5
                [3153600000, &#39;years&#39;, 31536000], // 60*60*24*365*100, 60*60*24*365
                [4730400000, &#39;1 century&#39;] // 60*60*24*365*100*1.5
        ];

        var time = (&#39;&#39; + date_str).replace(/-/g,"/").replace(/[TZ]/g," "),
                dt = new Date,
                seconds = ((dt - new Date(time) + (dt.getTimezoneOffset() * 60000)) / 1000),
                token = &#39; ago&#39;,
                i = 0,
                format;

        if (seconds < 0) {
                seconds = Math.abs(seconds);
                token = &#39;&#39;;
        }

        while (format = time_formats[i++]) {
                if (seconds < format[0]) {
                        if (format.length == 2) {
                                return format[1] + (i > 1 ? token : &#39;&#39;); // Conditional so we don&#39;t return Just Now Ago
                        } else {
                                return Math.round(seconds / format[2]) + &#39; &#39; + format[1] + (i > 1 ? token : &#39;&#39;);
                        }
                }
        }

        // overflow for centuries
        if(seconds > 4730400000)
                return Math.round(seconds / 4730400000) + &#39; centuries&#39; + token;

        return date_str;
};

if(typeof jQuery != &#39;undefined&#39;) {
        jQuery.fn.humane_dates = function(){
                return this.each(function(){
                        var date = humane_date(this.title);
                        if(date && jQuery(this).text() != date) // don&#39;t modify the dom if we don&#39;t have to
                                jQuery(this).text(date);
                });
        };
}
39
0
Comentarii (1)
 Karl-Henrik
Karl-Henrik
9 aprilie 2014 в 11:50
2014-04-09T11:50:10+00:00
Mai mult
Sursă
Editează
#8406167

Există, de asemenea, un pachet numit Humanizer pe Nuget și este de fapt, funcționează foarte bine

DateTime.UtcNow.AddHours(-2).Humanize() => "2 hours ago"

DateTime.UtcNow.AddHours(30).Humanize() => "tomorrow"
DateTime.UtcNow.AddHours(2).Humanize() => "2 hours from now"

TimeSpan.FromMilliseconds(1299630020).Humanize() => "2 weeks"
TimeSpan.FromMilliseconds(1299630020).Humanize(3) => "2 weeks, 1 day, 1 hour"

Scott Hanselman are o writeup pe pe blog

36
0
Comentarii (2)
Nick Berardi
Nick Berardi
1 august 2008 в 12:17
2008-08-01T12:17:19+00:00
Mai mult
Sursă
Editează
#8406139

@jeff

IMHO ta pare un pic cam lung. Cu toate acestea se pare un pic mai robust, cu suport pentru "ieri" și "de ani". Dar, în experiența mea, atunci când acest lucru este folosit de persoana este cel mai probabil pentru a vizualiza conținutul în primele 30 de zile. Acesta este doar într-adevăr hardcore oameni care vin după aceea. De aceea, de obicei, am ales să fiu scurt și simplu.

Aceasta este metoda pe care eu sunt în prezent, folosind pe unul dintre site-urile mele. Aceasta returnează numai o rudă zi, oră, timp. Și apoi utilizatorul trebuie să palmă pe "acum" la ieșire.

{
    string output = String.Empty;

    if (time.Days > 0)
        output += time.Days + " days ";

    if ((time.Days == 0 || time.Days == 1) && time.Hours > 0)
        output += time.Hours + " hr ";

    if (time.Days == 0 && time.Minutes > 0)
        output += time.Minutes + " min ";

    if (output.Length == 0)
        output += time.Seconds + " sec";

    return output.Trim();
}
29
0
Comentarii (0)
 Town
Town
25 martie 2011 в 12:21
2011-03-25T00:21:04+00:00
Mai mult
Sursă
Editează
#8406160

Un cuplu de ani mai târziu la petrecere, dar am avut o cerință pentru a face acest lucru pentru atât trecutul cât și viitorul date, așa că am combinat Jeff's și Vincent's în acest sens. L's o ternarytastic extravaganta! :)

    {
        private const int SECOND = 1;
        private const int MINUTE = 60 * SECOND;
        private const int HOUR = 60 * MINUTE;
        private const int DAY = 24 * HOUR;
        private const int MONTH = 30 * DAY;

        /// <summary>
        /// Returns a friendly version of the provided DateTime, relative to now. E.g.: "2 days ago", or "in 6 months".
        /// </summary>
        /// <param name="dateTime">The DateTime to compare to Now</param>
        /// <returns>A friendly string</returns>
        public static string GetFriendlyRelativeTime(DateTime dateTime)
        {
            if (DateTime.UtcNow.Ticks == dateTime.Ticks)
            {
                return "Right now!";
            }

            bool isFuture = (DateTime.UtcNow.Ticks < dateTime.Ticks);
            var ts = DateTime.UtcNow.Ticks < dateTime.Ticks ? new TimeSpan(dateTime.Ticks - DateTime.UtcNow.Ticks) : new TimeSpan(DateTime.UtcNow.Ticks - dateTime.Ticks);

            double delta = ts.TotalSeconds;

            if (delta < 1 * MINUTE)
            {
                return isFuture ? "in " + (ts.Seconds == 1 ? "one second" : ts.Seconds + " seconds") : ts.Seconds == 1 ? "one second ago" : ts.Seconds + " seconds ago";
            }
            if (delta < 2 * MINUTE)
            {
                return isFuture ? "in a minute" : "a minute ago";
            }
            if (delta < 45 * MINUTE)
            {
                return isFuture ? "in " + ts.Minutes + " minutes" : ts.Minutes + " minutes ago";
            }
            if (delta < 90 * MINUTE)
            {
                return isFuture ? "in an hour" : "an hour ago";
            }
            if (delta < 24 * HOUR)
            {
                return isFuture ? "in " + ts.Hours + " hours" : ts.Hours + " hours ago";
            }
            if (delta < 48 * HOUR)
            {
                return isFuture ? "tomorrow" : "yesterday";
            }
            if (delta < 30 * DAY)
            {
                return isFuture ? "in " + ts.Days + " days" : ts.Days + " days ago";
            }
            if (delta < 12 * MONTH)
            {
                int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));
                return isFuture ? "in " + (months <= 1 ? "one month" : months + " months") : months <= 1 ? "one month ago" : months + " months ago";
            }
            else
            {
                int years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));
                return isFuture ? "in " + (years <= 1 ? "one year" : years + " years") : years <= 1 ? "one year ago" : years + " years ago";
            }
        }
    }
24
0
Comentarii (0)
Utilizator anonim
20 februarie 2009 в 3:17
2009-02-20T15:17:43+00:00
Mai mult
Sursă
Editează
#8406153

Există o modalitate ușoară de a face acest lucru în Java? La java.util.Data clasa pare destul de limitate.

Aici este meu rapid și murdar Java soluție:

import javax.management.timer.Timer;

String getRelativeDate(Date date) {     
  long delta = new Date().getTime() - date.getTime();
  if (delta < 1L * Timer.ONE_MINUTE) {
    return toSeconds(delta) == 1 ? "one second ago" : toSeconds(delta) + " seconds ago";
  }
  if (delta < 2L * Timer.ONE_MINUTE) {
    return "a minute ago";
  }
  if (delta < 45L * Timer.ONE_MINUTE) {
    return toMinutes(delta) + " minutes ago";
  }
  if (delta < 90L * Timer.ONE_MINUTE) {
    return "an hour ago";
  }
  if (delta < 24L * Timer.ONE_HOUR) {
    return toHours(delta) + " hours ago";
  }
  if (delta < 48L * Timer.ONE_HOUR) {
    return "yesterday";
  }
  if (delta < 30L * Timer.ONE_DAY) {
    return toDays(delta) + " days ago";
  }
  if (delta < 12L * 4L * Timer.ONE_WEEK) { // a month
    long months = toMonths(delta); 
    return months <= 1 ? "one month ago" : months + " months ago";
  }
  else {
    long years = toYears(delta);
    return years <= 1 ? "one year ago" : years + " years ago";
  }
}

private long toSeconds(long date) {
  return date / 1000L;
}

private long toMinutes(long date) {
  return toSeconds(date) / 60L;
}

private long toHours(long date) {
  return toMinutes(date) / 60L;
}

private long toDays(long date) {
  return toHours(date) / 24L;
}

private long toMonths(long date) {
  return toDays(date) / 30L;
}

private long toYears(long date) {
  return toMonths(date) / 365L;
}
22
0
Comentarii (1)
 ollie
ollie
11 februarie 2010 в 12:23
2010-02-11T12:23:32+00:00
Mai mult
Sursă
Editează
#8406159

iPhone Objective-C Versiunea

    int delta = -(int)[date timeIntervalSinceNow];

    if (delta < 60)
    {
        return delta == 1 ? @"one second ago" : [NSString stringWithFormat:@"%i seconds ago", delta];
    }
    if (delta < 120)
    {
        return @"a minute ago";
    }
    if (delta < 2700)
    {
        return [NSString stringWithFormat:@"%i minutes ago", delta/60];
    }
    if (delta < 5400)
    {
        return @"an hour ago";
    }
    if (delta < 24 * 3600)
    {
        return [NSString stringWithFormat:@"%i hours ago", delta/3600];
    }
    if (delta < 48 * 3600)
    {
        return @"yesterday";
    }
    if (delta < 30 * 24 * 3600)
    {
        return [NSString stringWithFormat:@"%i days ago", delta/(24*3600)];
    }
    if (delta < 12 * 30 * 24 * 3600)
    {
        int months = delta/(30*24*3600);
        return months <= 1 ? @"one month ago" : [NSString stringWithFormat:@"%i months ago", months];
    }
    else
    {
        int years = delta/(12*30*24*3600);
        return years <= 1 ? @"one year ago" : [NSString stringWithFormat:@"%i years ago", years];
    }
}
20
0
Comentarii (0)
Owen Blacker
Owen Blacker
29 aprilie 2011 в 6:31
2011-04-29T18:31:37+00:00
Mai mult
Sursă
Editează
#8406161

Dat lumii și soțul ei par a fi postarea mostre de cod, aici este ceea ce am scris acum ceva timp, bazat pe câteva dintre aceste răspunsuri.

Am avut o nevoie specifică pentru acest cod pentru a fi localisable. Așa că am două clase — "Gramatică", care specifică localisable termeni, și FuzzyDateExtensions, care deține o grămadă de metode de extensie. Am avut nevoie să se ocupe de viitorul datetimes, deci este făcut nici o încercare să le ocupe cu acest cod.

Am'am lăsat o parte din XMLdoc în sursă, dar eliminat cele mai multe (în cazul în care acestea'd evident) pentru concizie's sake. Am'am, de asemenea, nu sunt incluse în fiecare membru al clasei aici:

{
    /// <summary> Gets or sets the term for "just now". </summary>
    public string JustNow { get; set; }
    /// <summary> Gets or sets the term for "X minutes ago". </summary>
    /// <remarks>
    ///     This is a <see cref="String.Format"/> pattern, where <c>{0}</c>
    ///     is the number of minutes.
    /// </remarks>
    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; }
    /// <summary> Gets or sets the term for "ages ago". </summary>
    public string AgesAgo { get; set; }

    /// <summary>
    ///     Gets or sets the threshold beyond which the fuzzy date should be
    ///     considered "ages ago".
    /// </summary>
    public TimeSpan AgesAgoThreshold { get; set; }

    /// <summary>
    ///     Initialises a new <see cref="Grammar"/> instance with the
    ///     specified properties.
    /// </summary>
    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)
    { ... }
}

Anii `FuzzyDateString clasa conține:

{
    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 principalele lucruri pe care am vrut să realizeze, precum și a localizării, a fost "astazi" ar însemna doar "acest calendar zi", deci IsToday, IsThisMonth, `IsThisYear metodele arata astfel:

{
    return date.DayOfYear == DateTime.Now.DayOfYear && date.IsThisYear();
}

și rotunjirea metode sunt de genul asta (m-am'am inclus RoundedMonths, ca's un pic diferit):

{
    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 vor găsi acest util și/sau interesante :o)

19
0
Comentarii (0)
 Simon
Simon
4 septembrie 2009 в 1:15
2009-09-04T13:15:59+00:00
Mai mult
Sursă
Editează
#8406156

folosind Fluent DateTime

var dateTime2 = 3.Days().Ago();
var dateTime3 = 1.Months().Ago();
var dateTime4 = 5.Hours().FromNow();
var dateTime5 = 2.Weeks().FromNow();
var dateTime6 = 40.Seconds().FromNow();
18
0
Comentarii (0)
 icco
icco
20 august 2008 в 5:26
2008-08-20T17:26:49+00:00
Mai mult
Sursă
Editează
#8406146

În PHP, am face în acest fel:

function timesince($original) {
    // array of time period chunks
    $chunks = array(
        array(60 * 60 * 24 * 365 , &#39;year&#39;),
        array(60 * 60 * 24 * 30 , &#39;month&#39;),
        array(60 * 60 * 24 * 7, &#39;week&#39;),
        array(60 * 60 * 24 , &#39;day&#39;),
        array(60 * 60 , &#39;hour&#39;),
        array(60 , &#39;minute&#39;),
    );

    $today = time(); /* Current unix time  */
    $since = $today - $original;

    if($since > 604800) {
    $print = date("M jS", $original);

    if($since > 31536000) {
        $print .= ", " . date("Y", $original);
    }

    return $print;
}

// $j saves performing the count function each time around the loop
for ($i = 0, $j = count($chunks); $i < $j; $i++) {

    $seconds = $chunks[$i][0];
    $name = $chunks[$i][1];

    // finding the biggest chunk (if the chunk fits, break)
    if (($count = floor($since / $seconds)) != 0) {
        break;
    }
}

$print = ($count == 1) ? &#39;1 &#39;.$name : "$count {$name}s";

return $print . " ago";

} ?>
17
0
Comentarii (1)
 Wedge
Wedge
5 august 2008 в 12:42
2008-08-05T00:42:56+00:00
Mai mult
Sursă
Editează
#8406141

Am crezut că am'd dea o șansă folosind clase și polimorfism. Am avut un predecesor care a folosit sub-clasarea care a sfârșit prin a avea prea mult deasupra capului. Am'am trecut la un sistem mai flexibil delega / proprietate publică model de obiect care este semnificativ mai bun. Codul meu este foarte ușor, mai precis, aș vrea să pot veni cu o modalitate mai bună de a genera "luni" nu't par prea over-engineered.

Cred că m-am'd încă stick cu Jeff's dacă-atunci cascadă, deoarece's mai puțin cod și l's mai simple (it's cu siguranță mai ușor pentru a se asigura că'll lucreze cum era de așteptat).

Pentru codul de mai jos PrintRelativeTime.GetRelativeTimeMessage(Durata de timp în urmă) returnează timp relativ mesaj (de exemplu, "ieri").

{
    public TimeSpan UpperBound { get; set; }

    public delegate string RelativeTimeTextDelegate(TimeSpan timeDelta);

    public RelativeTimeTextDelegate MessageCreator { get; set; }

    public int CompareTo(object obj)
    {
        if (!(obj is RelativeTimeRange))
        {
            return 1;
        }
        // note that this sorts in reverse order to the way you&#39;d expect, 
        // this saves having to reverse a list later
        return (obj as RelativeTimeRange).UpperBound.CompareTo(UpperBound);
    }
}

public class PrintRelativeTime
{
    private static List<RelativeTimeRange> timeRanges;

    static PrintRelativeTime()
    {
        timeRanges = new List<RelativeTimeRange>{
            new RelativeTimeRange
            {
                UpperBound = TimeSpan.FromSeconds(1),
                MessageCreator = (delta) => 
                { return "one second ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = TimeSpan.FromSeconds(60),
                MessageCreator = (delta) => 
                { return delta.Seconds + " seconds ago"; }

            }, 
            new RelativeTimeRange
            {
                UpperBound = TimeSpan.FromMinutes(2),
                MessageCreator = (delta) => 
                { return "one minute ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = TimeSpan.FromMinutes(60),
                MessageCreator = (delta) => 
                { return delta.Minutes + " minutes ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = TimeSpan.FromHours(2),
                MessageCreator = (delta) => 
                { return "one hour ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = TimeSpan.FromHours(24),
                MessageCreator = (delta) => 
                { return delta.Hours + " hours ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = TimeSpan.FromDays(2),
                MessageCreator = (delta) => 
                { return "yesterday"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = DateTime.Now.Subtract(DateTime.Now.AddMonths(-1)),
                MessageCreator = (delta) => 
                { return delta.Days + " days ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = DateTime.Now.Subtract(DateTime.Now.AddMonths(-2)),
                MessageCreator = (delta) => 
                { return "one month ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = DateTime.Now.Subtract(DateTime.Now.AddYears(-1)),
                MessageCreator = (delta) => 
                { return (int)Math.Floor(delta.TotalDays / 30) + " months ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = DateTime.Now.Subtract(DateTime.Now.AddYears(-2)),
                MessageCreator = (delta) => 
                { return "one year ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = TimeSpan.MaxValue,
                MessageCreator = (delta) => 
                { return (int)Math.Floor(delta.TotalDays / 365.24D) + " years ago"; }
            }
        };

        timeRanges.Sort();
    }

    public static string GetRelativeTimeMessage(TimeSpan ago)
    {
        RelativeTimeRange postRelativeDateRange = timeRanges[0];

        foreach (var timeRange in timeRanges)
        {
            if (ago.CompareTo(timeRange.UpperBound) <= 0)
            {
                postRelativeDateRange = timeRange;
            }
        }

        return postRelativeDateRange.MessageCreator(ago);
    }
}
14
0
Comentarii (0)
Premdeep Mohanty
Premdeep Mohanty
15 octombrie 2013 в 9:36
2013-10-15T09:36:10+00:00
Mai mult
Sursă
Editează
#8406166

puteți încerca acest lucru.Cred că va funcționa corect.

const int SECOND = 1;
const int MINUTE = 60 * SECOND;
const int HOUR = 60 * MINUTE;
const int DAY = 24 * HOUR;
const int MONTH = 30 * DAY;

if (delta < 0L)
{
  return "not yet";
}
if (delta < 1L * MINUTE)
{
  return ts.Seconds == 1 ? "one second ago" : ts.Seconds + " seconds ago";
}
if (delta < 2L * MINUTE)
{
  return "a minute ago";
}
if (delta < 45L * MINUTE)
{
  return ts.Minutes + " minutes ago";
}
if (delta < 90L * MINUTE)
{
  return "an hour ago";
}
if (delta < 24L * HOUR)
{
  return ts.Hours + " hours ago";
}
if (delta < 48L * HOUR)
{
  return "yesterday";
}
if (delta < 30L * DAY)
{
  return ts.Days + " days ago";
}
if (delta < 12L * MONTH)
{
  int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));
  return months <= 1 ? "one month ago" : months + " months ago";
}
else
{
  int years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));
  return years <= 1 ? "one year ago" : years + " years ago";
}
12
0
Comentarii (0)
 markpasc
markpasc
15 august 2008 в 10:42
2008-08-15T22:42:33+00:00
Mai mult
Sursă
Editează
#8406144

Atunci când știi viewer's de fus orar, s-ar putea fi mai clar de a utiliza zile calendaristice de la zi la scară. Am'm nu sunt familiarizați cu .NET biblioteci deci eu nu't știu cum ai'd face asta in C#, din păcate.

Pe site-uri de consum, ai putea fi, de asemenea, de mână-valurile sub un minut. "mai Puțin de un minut în urmă" sau "acum" ar putea fi destul de bun.

12
0
Comentarii (0)
Chris Charabaruk
Chris Charabaruk
17 iulie 2009 в 2:47
2009-07-17T02:47:42+00:00
Mai mult
Sursă
Editează
#8406155
using System.Collections.Generic;
using System.Linq;

public static class RelativeDateHelper
{
    private static Dictionary<double, Func<double, string>> sm_Dict = null;

    private static Dictionary<double, Func<double, string>> DictionarySetup()
    {
        var dict = new Dictionary<double, Func<double, string>>();
        dict.Add(0.75, (mins) => "less than a minute");
        dict.Add(1.5, (mins) => "about a minute");
        dict.Add(45, (mins) => string.Format("{0} minutes", Math.Round(mins)));
        dict.Add(90, (mins) => "about an hour");
        dict.Add(1440, (mins) => string.Format("about {0} hours", Math.Round(Math.Abs(mins / 60)))); // 60 * 24
        dict.Add(2880, (mins) => "a day"); // 60 * 48
        dict.Add(43200, (mins) => string.Format("{0} days", Math.Floor(Math.Abs(mins / 1440)))); // 60 * 24 * 30
        dict.Add(86400, (mins) => "about a month"); // 60 * 24 * 60
        dict.Add(525600, (mins) => string.Format("{0} months", Math.Floor(Math.Abs(mins / 43200)))); // 60 * 24 * 365 
        dict.Add(1051200, (mins) => "about a year"); // 60 * 24 * 365 * 2
        dict.Add(double.MaxValue, (mins) => string.Format("{0} years", Math.Floor(Math.Abs(mins / 525600))));

        return dict;
    }

    public static string ToRelativeDate(this DateTime input)
    {
        TimeSpan oSpan = DateTime.Now.Subtract(input);
        double TotalMinutes = oSpan.TotalMinutes;
        string Suffix = " ago";

        if (TotalMinutes < 0.0)
        {
            TotalMinutes = Math.Abs(TotalMinutes);
            Suffix = " from now";
        }

        if (null == sm_Dict)
            sm_Dict = DictionarySetup();

        return sm_Dict.First(n => TotalMinutes < n.Key).Value.Invoke(TotalMinutes) + Suffix;
    }
}

La fel ca un alt răspuns la această întrebare dar ca o metodă de prelungire cu un dicționar static.

12
0
Comentarii (4)
Adăugati o întrebare
Categorii
Toate
Tehnologii
Cultură
Viață / Artă
Stiință
Profesii
Afaceri
ID
KO
RO
RU
© Answer-ID 2021
Sursă
https://stackoverflow.com
în cadrul licenței cc by-sa 3.0 cu atribuire