Υπολογίστε σχετικό χρόνο σε C #

ψήφοι
1k

Με δεδομένη μια συγκεκριμένη DateTimeτιμή, πώς μπορώ να εμφανίσει σχετικό χρόνο, όπως:

  • πριν 2 ώρες
  • πριν από 3 ημέρες
  • ένα μήνα πριν
Δημοσιεύθηκε 01/08/2008 στις 00:55
πηγή χρήστη
Σε άλλες γλώσσες...                            


36 απαντήσεις

ψήφοι
875

Jeff, ο κώδικάς σας είναι ωραία, αλλά θα μπορούσε να είναι πιο σαφής με σταθερές (όπως προτείνεται στο κώδικα Πλήρης).

const int SECOND = 1;
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";
}
Απαντήθηκε 04/08/2008 στις 14:57
πηγή χρήστη

ψήφοι
343

jquery.timeago plugin

Jeff, επειδή Υπερχείλιση στοίβας χρησιμοποιεί jQuery εκτενώς, ήθελα να συστήσω το plugin jquery.timeago .

Οφέλη:

  • Αποφύγετε χρονικές σημάνσεις της «Πριν από 1 λεπτό», ακόμη και αν η σελίδα άνοιξε πριν από 10 λεπτά? TIMEAGO ανανεώνεται αυτόματα.
  • Μπορείτε να επωφεληθούν πλήρως από τη σελίδα ή / και τμήμα προσωρινή αποθήκευση στο web εφαρμογές σας, επειδή οι χρονικές σφραγίδες δεν υπολογίζονται στο διακομιστή.
  • Μπορείτε να πάρετε για να χρησιμοποιήσετε microformats όπως τα δροσερά παιδιά.

Απλά το συνδέσετε με χρονικές σφραγίδες σας DOM έτοιμο:

jQuery(document).ready(function() {
    jQuery('abbr.timeago').timeago();
});

Αυτό θα μετατρέψει όλα τα abbrστοιχεία με την κατηγορία της TIMEAGO και ένα ISO 8601 timestamp στον τίτλο:

<abbr class="timeago" title="2008-07-17T09:24:17Z">July 17, 2008</abbr>

σε κάτι σαν αυτό:

<abbr class="timeago" title="July 17, 2008">4 months ago</abbr>

η οποία δίδει: 4 μήνες πριν. Όσο περνάει ο καιρός, οι χρονικές σφραγίδες θα ενημερώνεται αυτόματα.

Αποποίηση: Έγραψα αυτό το plugin, έτσι είμαι προκατειλημμένη.

Απαντήθηκε 21/09/2008 στις 17:04
πηγή χρήστη

ψήφοι
318

Εδώ είναι πώς το κάνω

var ts = new TimeSpan(DateTime.UtcNow.Ticks - dt.Ticks);
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";

Προτάσεις; Σχόλια? Τρόποι για να βελτιώσει αυτόν τον αλγόριθμο;

Απαντήθηκε 01/08/2008 στις 00:56
πηγή χρήστη

ψήφοι
84
public static string RelativeDate(DateTime theDate)
{
    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 "";
}

Προτιμώ αυτή την έκδοση για την περιεκτικότητα της, και την ικανότητα να προσθέσει στην νέα σημεία τσιμπούρι. Αυτό θα μπορούσε να είναι έγκλειστα με Latest()επέκταση Timespan αντί της μακράς 1 επένδυση, αλλά για λόγους συντομίας στην απόσπαση, αυτό θα κάνουμε. Αυτό καθορίζει το πριν από μία ώρα, 1 ώρες πριν, παρέχοντας μια ώρα μέχρις ότου παρέλθουν δύο ώρες

Απαντήθηκε 14/08/2008 στις 06:43
πηγή χρήστη

ψήφοι
68

Εδώ ένα ξαναγράψει από Jeffs Σενάριο για PHP:

define("SECOND", 1);
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";
    }
}    
Απαντήθηκε 01/02/2009 στις 20:22
πηγή χρήστη

ψήφοι
60
public static string ToRelativeDate(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";
    }

    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 έκδοση:

static readonly SortedList<double, Func<TimeSpan, string>> offsets = 
   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;
}
Απαντήθηκε 17/09/2008 στις 04:19
πηγή χρήστη

ψήφοι
48

Εδώ είναι μια εφαρμογή που προστίθεται ως μέθοδος επέκτασης στην κατηγορία DateTime που χειρίζεται τόσο το μέλλον και το παρελθόν ημερομηνίες και προσφέρει μια επιλογή προσέγγιση που σας επιτρέπει να καθορίσετε το επίπεδο λεπτομέρειας που ψάχνετε ( «πριν από 3 ώρες» vs «3 ώρες, 23 λεπτά, πριν από 12 δευτερόλεπτα »):

using System.Text;

/// <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();
}
Απαντήθηκε 09/03/2009 στις 23:02
πηγή χρήστη

ψήφοι
38

Θα πρότεινα τον υπολογισμό αυτό από την πλευρά του πελάτη πάρα πολύ. Λιγότερη εργασία για το διακομιστή.

Το παρακάτω είναι η έκδοση που χρησιμοποιώ (από Zach Leatherman)

/*
 * Javascript Humane Dates
 * Copyright (c) 2008 Dean Landolt (deanlandolt.com)
 * Re-write by Zach Leatherman (zachleat.com)
 * 
 * Adopted from the John Resig's pretty.js
 * at http://ejohn.org/blog/javascript-pretty-date
 * and henrah'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, 'just now'],
                [90, '1 minute'], // 60*1.5
                [3600, 'minutes', 60], // 60*60, 60
                [5400, '1 hour'], // 60*60*1.5
                [86400, 'hours', 3600], // 60*60*24, 60*60
                [129600, '1 day'], // 60*60*24*1.5
                [604800, 'days', 86400], // 60*60*24*7, 60*60*24
                [907200, '1 week'], // 60*60*24*7*1.5
                [2628000, 'weeks', 604800], // 60*60*24*(365/12), 60*60*24*7
                [3942000, '1 month'], // 60*60*24*(365/12)*1.5
                [31536000, 'months', 2628000], // 60*60*24*365, 60*60*24*(365/12)
                [47304000, '1 year'], // 60*60*24*365*1.5
                [3153600000, 'years', 31536000], // 60*60*24*365*100, 60*60*24*365
                [4730400000, '1 century'] // 60*60*24*365*100*1.5
        ];

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

        if (seconds < 0) {
                seconds = Math.abs(seconds);
                token = '';
        }

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

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

        return date_str;
};

if(typeof jQuery != 'undefined') {
        jQuery.fn.humane_dates = function(){
                return this.each(function(){
                        var date = humane_date(this.title);
                        if(date && jQuery(this).text() != date) // don't modify the dom if we don't have to
                                jQuery(this).text(date);
                });
        };
}
Απαντήθηκε 23/10/2008 στις 11:44
πηγή χρήστη

ψήφοι
29

Υπάρχουν, επίσης, ένα πακέτο που ονομάζεται Humanizer για Nuget και λειτουργεί πραγματικά πολύ καλά

DateTime.UtcNow.AddHours(-30).Humanize() => "yesterday"
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 έχει writeup σε αυτό για του blog

Απαντήθηκε 09/04/2014 στις 12:50
πηγή χρήστη

ψήφοι
28

@jeff

IMHO δική σας φαίνεται λίγο καιρό. Ωστόσο, φαίνεται λίγο πιο ισχυρή με την υποστήριξη για «χθες» και «χρόνια». Αλλά από την εμπειρία μου, όταν αυτή χρησιμοποιείται το άτομο είναι πιο πιθανό να δείτε το περιεχόμενο κατά τις πρώτες 30 ημέρες. Είναι μόνο τα πραγματικά hardcore ανθρώπους που έρχονται μετά από αυτό. Έτσι, γι 'αυτό συνήθως να επιλέξει να κρατήσει αυτό το σύντομο και απλό.

Αυτή είναι η μέθοδος που είμαι σήμερα χρησιμοποιούν σε μία από τις ιστοσελίδες μου. Αυτό επιστρέφει μόνο μια σχετική ημέρα, την ώρα, την ώρα. Και τότε ο χρήστης πρέπει να χαστούκι στο «πριν» στην έξοδο.

public static string ToLongString(this TimeSpan time)
{
    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();
}
Απαντήθηκε 01/08/2008 στις 13:17
πηγή χρήστη

ψήφοι
22

Μερικά χρόνια αργότερα στο κόμμα, αλλά είχα την απαίτηση να το κάνετε αυτό, τόσο για το παρελθόν και το μέλλον ημερομηνίες, γι 'αυτό σε συνδυασμό Jeff «s και Βίνσεντ σε αυτό. Είναι ένα ternarytastic υπερβολή! :)

public static class DateTimeHelper
    {
        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";
            }
        }
    }
Απαντήθηκε 25/03/2011 στις 01:21
πηγή χρήστη

ψήφοι
21

Είναι ένας εύκολος τρόπος για να γίνει αυτό σε Java εκεί; Η java.util.Dateτάξη φαίνεται μάλλον περιορισμένη.

Εδώ είναι γρήγορη και βρώμικη λύση Java μου:

import java.util.Date;
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;
}
Απαντήθηκε 20/02/2009 στις 16:17
πηγή χρήστη

ψήφοι
19

iPhone obj-γ Έκδοση

+ (NSString *)timeAgoString:(NSDate *)date {
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];
}

}

Απαντήθηκε 11/02/2010 στις 13:23
πηγή χρήστη

ψήφοι
18

Δεδομένου του κόσμου και ο σύζυγός της φαίνεται να απόσπαση δείγματα κώδικα, εδώ είναι ό, τι έγραψα πριν από λίγο καιρό, βασίζεται σε ένα ζευγάρι από αυτές τις απαντήσεις.

Είχα μια συγκεκριμένη ανάγκη για αυτό τον κωδικό για να είναι εντοπίσιμα. Γι 'αυτό και έχουμε δύο κατηγορίες - Grammar, η οποία καθορίζει τους όρους εντοπίσιμα, και FuzzyDateExtensions, η οποία κατέχει ένα σωρό μεθόδους επέκτασης. Δεν είχα καμία ανάγκη να ασχοληθεί με το μέλλον datetimes, οπότε δεν γίνεται καμία προσπάθεια να τους χειριστεί με αυτόν τον κωδικό.

Έχω μείνει μερικές από τις XMLdoc στην πηγή, αλλά αφαιρούνται οι περισσότεροι (όπου θα ήθελα να είναι εμφανής) για λόγους συντομίας. Έχω, επίσης, δεν συμπεριλαμβάνεται κάθε μέλος της κατηγορίας εδώ:

public class Grammar
{
    /// <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)
    { ... }
}

Η FuzzyDateStringκατηγορία περιλαμβάνει:

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());
    }
}

Ένα από τα βασικά πράγματα που ήθελα να επιτευχθούν, καθώς και εντοπισμού, ήταν ότι «σήμερα» θα σήμαινε μόνο «αυτό το ημερολόγιο μέρα», έτσι ώστε η IsToday, IsThisMonth, IsThisYearμέθοδοι μοιάζει κάπως έτσι:

public static bool IsToday(this DateTime date)
{
    return date.DayOfYear == DateTime.Now.DayOfYear && date.IsThisYear();
}

και οι μέθοδοι στρογγυλοποίησης είναι σαν αυτό (έχω περιλαμβάνονται RoundedMonths, όπως αυτό είναι λίγο διαφορετικό):

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;
}

Ελπίζω ότι οι άνθρωποι βρίσκουν αυτό χρήσιμο ή / και ενδιαφέροντα: o)

Απαντήθηκε 29/04/2011 στις 19:31
πηγή χρήστη

ψήφοι
18

Στην PHP, το κάνω με αυτόν τον τρόπο:

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

    $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) ? '1 '.$name : "$count {$name}s";

return $print . " ago";

} ?>
Απαντήθηκε 20/08/2008 στις 18:26
πηγή χρήστη

ψήφοι
17

χρησιμοποιώντας άριστα DateTime https://github.com/FluentDateTime

var dateTime1 = 2.Hours().Ago();
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();
Απαντήθηκε 04/09/2009 στις 14:15
πηγή χρήστη

ψήφοι
14

Νόμιζα ότι είχα δώσει σε αυτό έναν πυροβολισμό, χρησιμοποιώντας τις κατηγορίες και πολυμορφισμός. Είχα μια προηγούμενη επανάληψη που χρησιμοποιείται υπο-χαρακτηρίστηκε η οποία κατέληξε με τον τρόπο πάρα πολύ γενικά. Έχω περάσει σε ένα πιο ευέλικτο μοντέλο αντικειμένου του εκπροσώπου / δημόσια περιουσία η οποία είναι σημαντικά καλύτερη. κωδικός μου είναι πολύ λίγο πιο ακριβή, θα ήθελα να μπορούσα να καταλήξουμε σε ένα καλύτερο τρόπο για τη δημιουργία «μήνες» που δεν φαίνεται πάρα πάνω-μηχανικής.

Νομίζω ότι θα εξακολουθεί να κολλήσει με το εάν-τότε καταρράκτη του Jeff επειδή είναι λιγότερο κώδικα και είναι πιο απλό (αυτό είναι σίγουρα πιο εύκολο να διασφαλιστεί ότι θα λειτουργήσει όπως αναμένεται).

Για τον παρακάτω κώδικα PrintRelativeTime.GetRelativeTimeMessage (TimeSpan πριν) επιστρέφει το σχετικό μήνυμα χρόνου (π.χ. «χθες»).

public class RelativeTimeRange : IComparable
{
    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'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);
    }
}
Απαντήθηκε 05/08/2008 στις 01:42
πηγή χρήστη

ψήφοι
11

μπορείτε να δοκιμάσετε this.I πιστεύω ότι θα λειτουργήσει σωστά.

long delta = new Date().getTime() - date.getTime();
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";
}
Απαντήθηκε 15/10/2013 στις 10:36
πηγή χρήστη

ψήφοι
11
using System;
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;
    }
}

Το ίδιο όπως και μια άλλη απάντηση στο ερώτημα αυτό , αλλά ως μια μέθοδο επέκτασης με μια στατική λεξικό.

Απαντήθηκε 17/07/2009 στις 03:47
πηγή χρήστη

ψήφοι
11

Όταν γνωρίζουμε τη ζώνη ώρας του θεατή, θα μπορούσε να είναι σαφέστερο να χρησιμοποιήσετε ημερολογιακές ημέρες στην κλίμακα ημέρα. Δεν είμαι εξοικειωμένος με τις βιβλιοθήκες .NET έτσι δεν ξέρω πώς θα το κάνουμε αυτό σε C #, δυστυχώς.

Σε ιστοσελίδες των καταναλωτών, θα μπορούσε επίσης να είναι χέρι-αποποίηση λιγότερο από ένα λεπτό. «Λιγότερο από ό, τι πριν από ένα λεπτό» ή «μόλις τώρα» θα μπορούσε να είναι αρκετά καλό.

Απαντήθηκε 15/08/2008 στις 23:42
πηγή χρήστη

ψήφοι
8

Java για τη χρήση gwt πλευρά του πελάτη:

import java.util.Date;

public class RelativeDateFormat {

 private static final long ONE_MINUTE = 60000L;
 private static final long ONE_HOUR = 3600000L;
 private static final long ONE_DAY = 86400000L;
 private static final long ONE_WEEK = 604800000L;

 public static String format(Date date) {

  long delta = new Date().getTime() - date.getTime();
  if (delta < 1L * ONE_MINUTE) {
   return toSeconds(delta) == 1 ? "one second ago" : toSeconds(delta)
     + " seconds ago";
  }
  if (delta < 2L * ONE_MINUTE) {
   return "one minute ago";
  }
  if (delta < 45L * ONE_MINUTE) {
   return toMinutes(delta) + " minutes ago";
  }
  if (delta < 90L * ONE_MINUTE) {
   return "one hour ago";
  }
  if (delta < 24L * ONE_HOUR) {
   return toHours(delta) + " hours ago";
  }
  if (delta < 48L * ONE_HOUR) {
   return "yesterday";
  }
  if (delta < 30L * ONE_DAY) {
   return toDays(delta) + " days ago";
  }
  if (delta < 12L * 4L * ONE_WEEK) {
   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 static long toSeconds(long date) {
  return date / 1000L;
 }

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

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

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

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

 private static long toYears(long date) {
  return toMonths(date) / 365L;
 }

}
Απαντήθηκε 14/11/2009 στις 19:44
πηγή χρήστη

ψήφοι
8

Μπορείτε να μειώσετε την πλευρά του διακομιστή φορτίο εκτελώντας αυτή τη λογική πλευρά του πελάτη. Προβολή πηγής σε ορισμένες σελίδες Digg για την αναφορά. Έχουν ο διακομιστής εκπέμπουν μια τιμή χρόνου εποχή που παίρνει επεξεργασία από το Javascript. Με αυτό τον τρόπο δεν χρειάζεται να διαχειριστούν τη ζώνη ώρας του τελικού χρήστη. Το νέο server-side κώδικα θα ήταν κάτι σαν:

public string GetRelativeTime(DateTime timeStamp)
{
    return string.Format("<script>printdate({0});</script>", timeStamp.ToFileTimeUtc());
}

Θα μπορούσατε ακόμη και να προσθέσετε ένα μπλοκ NOSCRIPT εκεί και απλά να εκτελέσει μια toString ().

Απαντήθηκε 17/08/2008 στις 16:56
πηγή χρήστη

ψήφοι
8

@Jeff

ts var = νέα TimeSpan (DateTime.UtcNow.Ticks - dt.Ticks)?

Κάνοντας μια αφαίρεση για DateTimeεπιστροφές ένα TimeSpanούτως ή άλλως.

Έτσι, το μόνο που μπορούμε να κάνουμε

(DateTime.UtcNow - dt).TotalSeconds

Είμαι επίσης έκπληκτος για να δείτε τις σταθερές επί-με το χέρι και στη συνέχεια σχόλια που έχουν προστεθεί με τις πολλαπλασιασμών in. Ήταν ότι μερικές άστοχες βελτιστοποίηση;

Απαντήθηκε 15/08/2008 στις 15:20
πηγή χρήστη

ψήφοι
7

Μπορείτε να χρησιμοποιήσετε την επέκταση TIMEAGO από το οποίο μοιάζει με το ακόλουθο:

public static string TimeAgo(this DateTime dateTime)
{
    string result = string.Empty;
    var timeSpan = DateTime.Now.Subtract(dateTime);

    if (timeSpan <= TimeSpan.FromSeconds(60))
    {
        result = string.Format("{0} seconds ago", timeSpan.Seconds);
    }
    else if (timeSpan <= TimeSpan.FromMinutes(60))
    {
        result = timeSpan.Minutes > 1 ? 
            String.Format("about {0} minutes ago", timeSpan.Minutes) :
            "about a minute ago";
    }
    else if (timeSpan <= TimeSpan.FromHours(24))
    {
        result = timeSpan.Hours > 1 ? 
            String.Format("about {0} hours ago", timeSpan.Hours) : 
            "about an hour ago";
    }
    else if (timeSpan <= TimeSpan.FromDays(30))
    {
        result = timeSpan.Days > 1 ? 
            String.Format("about {0} days ago", timeSpan.Days) : 
            "yesterday";
    }
    else if (timeSpan <= TimeSpan.FromDays(365))
    {
        result = timeSpan.Days > 30 ? 
            String.Format("about {0} months ago", timeSpan.Days / 30) : 
            "about a month ago";
    }
    else
    {
        result = timeSpan.Days > 365 ? 
            String.Format("about {0} years ago", timeSpan.Days / 365) : 
            "about a year ago";
    }

    return result;
}

Ή χρησιμοποιήστε jQuery plugin με την επέκταση Ξυράφι από TIMEAGO.

Απαντήθηκε 08/09/2015 στις 14:02
πηγή χρήστη

ψήφοι
7

Αυτό, πήρα από ένα από τα blog Bill Gates'. Πρέπει να το βρείτε στο ιστορικό του προγράμματος περιήγησης μου και εγώ θα σας δώσω το link.

Ο κώδικας Javascript για να κάνουν το ίδιο πράγμα (όπως ζητήθηκε):

function posted(t) {
    var now = new Date();
    var diff = parseInt((now.getTime() - Date.parse(t)) / 1000);
    if (diff < 60) { return 'less than a minute ago'; }
    else if (diff < 120) { return 'about a minute ago'; }
    else if (diff < (2700)) { return (parseInt(diff / 60)).toString() + ' minutes ago'; }
    else if (diff < (5400)) { return 'about an hour ago'; }
    else if (diff < (86400)) { return 'about ' + (parseInt(diff / 3600)).toString() + ' hours ago'; }
    else if (diff < (172800)) { return '1 day ago'; } 
    else {return (parseInt(diff / 86400)).toString() + ' days ago'; }
}

Βασικά, εργάζεστε σε όρους δευτερόλεπτα ...

Απαντήθηκε 01/02/2010 στις 20:51
πηγή χρήστη

ψήφοι
7

Εδώ είναι ο αλγόριθμος StackOverflow χρήσεις αλλά ξαναγραφεί πιο συνοπτικά σε perlish ψευδοκώδικα με μια λύση bug (όχι «πριν από μία ώρα»). Η συνάρτηση παίρνει ένα (θετικό) αριθμός των δευτερολέπτων πριν και επιστρέφει μια ανθρώπινη φιλική προς συμβολοσειρά όπως «3 ώρες πριν» ή «χθες».

agoify($delta)
  local($y, $mo, $d, $h, $m, $s);
  $s = floor($delta);
  if($s<=1)            return "a second ago";
  if($s<60)            return "$s seconds ago";
  $m = floor($s/60);
  if($m==1)            return "a minute ago";
  if($m<45)            return "$m minutes ago";
  $h = floor($m/60);
  if($h==1)            return "an hour ago";
  if($h<24)            return "$h hours ago";
  $d = floor($h/24);
  if($d<2)             return "yesterday";
  if($d<30)            return "$d days ago";
  $mo = floor($d/30);
  if($mo<=1)           return "a month ago";
  $y = floor($mo/12);
  if($y<1)             return "$mo months ago";
  if($y==1)            return "a year ago";
  return "$y years ago";
Απαντήθηκε 23/09/2008 στις 02:09
πηγή χρήστη

ψήφοι
5

Αν θέλετε να έχετε μια έξοδο όπως «2 ημέρες, 4 ώρες και 12 λεπτά πριν», θα πρέπει να έχετε μια χρονικού διαστήματος:

TimeSpan timeDiff = DateTime.Now-CreatedDate;

Στη συνέχεια, μπορείτε να έχετε πρόσβαση στις τιμές που σας αρέσει:

timeDiff.Days
timeDiff.Hours

και τα λοιπα.

Απαντήθηκε 08/09/2015 στις 14:02
πηγή χρήστη

ψήφοι
5
/** 
 * {@code date1} has to be earlier than {@code date2}.
 */
public static String relativize(Date date1, Date date2) {
    assert date2.getTime() >= date1.getTime();

    long duration = date2.getTime() - date1.getTime();
    long converted;

    if ((converted = TimeUnit.MILLISECONDS.toDays(duration)) > 0) {
        return String.format("%d %s ago", converted, converted == 1 ? "day" : "days");
    } else if ((converted = TimeUnit.MILLISECONDS.toHours(duration)) > 0) {
        return String.format("%d %s ago", converted, converted == 1 ? "hour" : "hours");
    } else if ((converted = TimeUnit.MILLISECONDS.toMinutes(duration)) > 0) {
        return String.format("%d %s ago", converted, converted == 1 ? "minute" : "minutes");
    } else if ((converted = TimeUnit.MILLISECONDS.toSeconds(duration)) > 0) {
        return String.format("%d %s ago", converted, converted == 1 ? "second" : "seconds");
    } else {
        return "just now";
    }
}
Απαντήθηκε 05/09/2014 στις 02:11
πηγή χρήστη

ψήφοι
5

Νομίζω ότι υπάρχει ήδη μια σειρά από απαντήσεις που σχετίζονται με αυτή τη θέση, αλλά μπορεί κανείς να χρησιμοποιήσει αυτό που είναι εύκολο στη χρήση όπως plugin και εύκολα αναγνώσιμο για τους προγραμματιστές. Αποστολή συγκεκριμένη ημερομηνία σας, και να πάρετε την αξία του σε μορφή συμβολοσειράς:

public string RelativeDateTimeCount(DateTime inputDateTime)
{
    string outputDateTime = string.Empty;
    TimeSpan ts = DateTime.Now - inputDateTime;

    if (ts.Days > 7)
    { outputDateTime = inputDateTime.ToString("MMMM d, yyyy"); }

    else if (ts.Days > 0)
    {
        outputDateTime = ts.Days == 1 ? ("about 1 Day ago") : ("about " + ts.Days.ToString() + " Days ago");
    }
    else if (ts.Hours > 0)
    {
        outputDateTime = ts.Hours == 1 ? ("an hour ago") : (ts.Hours.ToString() + " hours ago");
    }
    else if (ts.Minutes > 0)
    {
        outputDateTime = ts.Minutes == 1 ? ("1 minute ago") : (ts.Minutes.ToString() + " minutes ago");
    }
    else outputDateTime = "few seconds ago";

    return outputDateTime;
}
Απαντήθηκε 16/03/2013 στις 07:36
πηγή χρήστη

ψήφοι
4
public string getRelativeDateTime(DateTime date)
{
    TimeSpan ts = DateTime.Now - date;
    if (ts.TotalMinutes < 1)//seconds ago
        return "just now";
    if (ts.TotalHours < 1)//min ago
        return (int)ts.TotalMinutes == 1 ? "1 Minute ago" : (int)ts.TotalMinutes + " Minutes ago";
    if (ts.TotalDays < 1)//hours ago
        return (int)ts.TotalHours == 1 ? "1 Hour ago" : (int)ts.TotalHours + " Hours ago";
    if (ts.TotalDays < 7)//days ago
        return (int)ts.TotalDays == 1 ? "1 Day ago" : (int)ts.TotalDays + " Days ago";
    if (ts.TotalDays < 30.4368)//weeks ago
        return (int)(ts.TotalDays / 7) == 1 ? "1 Week ago" : (int)(ts.TotalDays / 7) + " Weeks ago";
    if (ts.TotalDays < 365.242)//months ago
        return (int)(ts.TotalDays / 30.4368) == 1 ? "1 Month ago" : (int)(ts.TotalDays / 30.4368) + " Months ago";
    //years ago
    return (int)(ts.TotalDays / 365.242) == 1 ? "1 Year ago" : (int)(ts.TotalDays / 365.242) + " Years ago";
}

τιμές μετατροπής για μέρες σε ένα μήνα και έτος ελήφθησαν από το Google.

Απαντήθηκε 06/08/2013 στις 08:54
πηγή χρήστη

ψήφοι
4

Θα παρέχει μερικές χρήσιμες μεθόδους επεκτάσεις για αυτό και κάνει τον κώδικα πιο ευανάγνωστο. Κατ 'αρχάς, δύο μεθόδων επέκτασης για Int32.

public static class TimeSpanExtensions {

    public static TimeSpan Days(this int value) {

        return new TimeSpan(value, 0, 0, 0);
    }

    public static TimeSpan Hours(this int value) {

        return new TimeSpan(0, value, 0, 0);
    }

    public static TimeSpan Minutes(this int value) {

        return new TimeSpan(0, 0, value, 0);
    }

    public static TimeSpan Seconds(this int value) {

        return new TimeSpan(0, 0, 0, value);
    }

    public static TimeSpan Milliseconds(this int value) {

        return new TimeSpan(0, 0, 0, 0, value);
    }

    public static DateTime Ago(this TimeSpan value) {

        return DateTime.Now - value;
    }
}

Στη συνέχεια, ένα για DateTime.

public static class DateTimeExtensions {

    public static DateTime Ago(this DateTime dateTime, TimeSpan delta) {

        return dateTime - delta;
    }
}

Τώρα, μπορείτε να κάνετε κάτι όπως παρακάτω:

var date = DateTime.Now;
date.Ago(2.Days()); // 2 days ago
date.Ago(7.Hours()); // 7 hours ago
date.Ago(567.Milliseconds()); // 567 milliseconds ago
Απαντήθηκε 13/09/2012 στις 13:15
πηγή χρήστη

ψήφοι
4
var ts = new TimeSpan(DateTime.Now.Ticks - dt.Ticks);
Απαντήθηκε 27/05/2012 στις 18:30
πηγή χρήστη

ψήφοι
2

Σίγουρα μια εύκολη λύση για να απαλλαγούμε από το «1 ώρες πριν» το πρόβλημα θα ήταν να αυξηθεί το παράθυρο που «πριν από μία ώρα» ισχύει για. Αλλαγή

if (delta < 5400) // 90 * 60
{
    return "an hour ago";
}

σε

if (delta < 7200) // 120 * 60
{
    return "an hour ago";
}

Αυτό σημαίνει ότι κάτι που συνέβη πριν από 110 λεπτά θα διαβάσει ως «πριν από μία ώρα» - αυτό μπορεί να μην είναι τέλεια, αλλά θα έλεγα ότι είναι καλύτερη από την τρέχουσα κατάσταση της «1 ώρες πριν».

Απαντήθηκε 25/08/2008 στις 07:12
πηγή χρήστη

ψήφοι
1

Αυτή είναι η λειτουργία μου, λειτουργεί σαν μια γοητεία :)

public static string RelativeDate(DateTime theDate)
        {
            var span = DateTime.Now - theDate;
            if (span.Days > 365)
            {
                var years = (span.Days / 365);
                if (span.Days % 365 != 0)
                    years += 1;
                return $"about {years} {(years == 1 ? "year" : "years")} ago";
            }
            if (span.Days > 30)
            {
                var months = (span.Days / 30);
                if (span.Days % 31 != 0)
                    months += 1;
                return $"about {months} {(months == 1 ? "month" : "months")} ago";
            }
            if (span.Days > 0)
                return $"about {span.Days} {(span.Days == 1 ? "day" : "days")} ago";
            if (span.Hours > 0)
                return $"about {span.Hours} {(span.Hours == 1 ? "hour" : "hours")} ago";
            if (span.Minutes > 0)
                return $"about {span.Minutes} {(span.Minutes == 1 ? "minute" : "minutes")} ago";
            if (span.Seconds > 5)
                return $"about {span.Seconds} seconds ago";

            return span.Seconds <= 5 ? "about 5 seconds ago" : string.Empty;
        }
Απαντήθηκε 04/09/2017 στις 01:27
πηγή χρήστη

ψήφοι
0

Τουρκική μεταφρασμένη έκδοση του Vincents απάντηση.

    const int SECOND = 1;
    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 + " saniye önce";

    if (delta < 45 * MINUTE)
        return ts.Minutes + " dakika önce";

    if (delta < 24 * HOUR)
        return ts.Hours + " saat önce";

    if (delta < 48 * HOUR)
        return "dün";

    if (delta < 30 * DAY)
        return ts.Days + " gün önce";

    if (delta < 12 * MONTH)
    {
        int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));
        return months + " ay önce";
    }
    else
    {
        int years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));
        return years + " yıl önce";
    }
Απαντήθηκε 03/01/2019 στις 08:03
πηγή χρήστη

ψήφοι
0

Ο δικός μου τρόπος είναι πολύ πιο απλή. Μπορείτε να τροποποιήσετε τις χορδές επιστροφή, όπως θέλετε

    public static string TimeLeft(DateTime utcDate)
    {
        TimeSpan timeLeft = DateTime.UtcNow - utcDate;
        string timeLeftString = "";
        if (timeLeft.Days > 0)
        {
            timeLeftString += timeLeft.Days == 1 ? timeLeft.Days + " day" : timeLeft.Days + " days";
        }
        else if (timeLeft.Hours > 0)
        {
            timeLeftString += timeLeft.Hours == 1 ? timeLeft.Hours + " hour" : timeLeft.Hours + " hours";
        }
        else
        {
            timeLeftString += timeLeft.Minutes == 1 ? timeLeft.Minutes+" minute" : timeLeft.Minutes + " minutes";
        }
        return timeLeftString;
    }
Απαντήθηκε 15/03/2018 στις 13:03
πηγή χρήστη

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more