Calculer le temps relatif en C #

Étant donné une valeur spécifique DateTime , comment afficher l'heure relative, par exemple:

  • Il y a 2 heures
  • Il y a 3 jours
  • il y a un mois
0
ajouté édité
Vues: 47
Que faire si vous voulez calculer un temps relatif à partir de maintenant à l'avenir?
ajouté l'auteur Jhonny D. Cano -Leftware-, source
Il y a le paquet .net github.com/NickStrupat/TimeAgo qui fait à peu près ce qu'on demande.
ajouté l'auteur Rossco, source
moment.js est une très belle bibliothèque d'analyse de date .. Vous pouvez envisager d'utiliser cela (côté serveur ou côté client), selon vos besoins. juste parce que personne ne l'a mentionné ici
ajouté l'auteur code ninja, source

32 Réponses

public static string RelativeDate(DateTime theDate)
{
    Dictionary thresholds = new Dictionary();
    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 "";
}

I prefer this version for its conciseness, and ability to add in new tick points. This could be encapsulated with a Latest() extension to Timespan instead of that long 1 liner, but for the sake of brevity in posting, this will do. This fixes the an hour ago, 1 hours ago, by providing an hour until 2 hours have elapsed

0
ajouté
J'obtiens toutes sortes de problèmes en utilisant cette fonction, par exemple si vous simulez 'theDate = DateTime.Now.AddMinutes (-40);' Je reçois '40 heures auparavant ', mais avec la réponse de Michael au code de refactormy, il est correct il y a '40 minutes'?
ajouté l'auteur GONeale, source
Pour résoudre le problème mentionné par @CodeMonkeyKing, vous pouvez utiliser un SortedDictionary au lieu d'un simple Dictionary : l'utilisation est la même, mais cela garantit que les clés sont triées. Mais même alors, l'algorithme a des failles, car RelativeDate (DateTime.Now.AddMonths (-3) .AddDays (-3)) renvoie "il y a 95 mois" , indépendamment quel type de dictionnaire vous utilisez, ce qui est incorrect (il devrait retourner "il y a 3 mois" ou "4 mois" selon le seuil que vous utilisez) - même si -3 ne crée pas de date dans
ajouté l'auteur Matt, source
OP a oublié t.Days> 30? t.Days / 30:
ajouté l'auteur Lars Holm Jensen, source
Hmm, bien que ce code puisse fonctionner, il est incorrect et invalide de supposer que l'ordre des clés dans le dictionnaire sera dans un ordre spécifique. Le dictionnaire utilise le Object.GetHashCode() qui ne retourne pas un long mais un int !. Si vous voulez que ceux-ci soient triés, alors vous devriez utiliser une SortedList . Quel est le problème avec les seuils évalués dans un ensemble de if / else si /.../ else? Vous obtenez le même nombre de comparaisons. FYI le hachage pour long.MaxValue s'avère être le même que int.MinValue!
ajouté l'auteur CodeMonkeyKing, source
Je pense qu'il vous manque un zéro, essayez: depuis longtemps = (DateTime.Now.Ticks - theDate.Ticks) / 10000000;
ajouté l'auteur robnardo, source

Voici comment je le fais

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

Suggestions? Commentaires? Façons d'améliorer cet algorithme?

0
ajouté
Mais actuellement SO ne montre que le format "Time ago" jusqu'à 2 jours. Plus de 2 jours et vous mettez le format d'heure de date standard. Ai-je raison ?
ajouté l'auteur Hugo Hilário, source
Puisque tous ces If..else ne sont que des timeslabs, vous pouvez créer une énumération pour une meilleure lisibilité. Dites enum TimeSlabs {Secondes = 60, Minutes = 60 * 60, Heures = 60 * 60 * 24, Jours = 60 * 60 * 24 * 365,}
ajouté l'auteur Antony Thomas, source
Je pense aussi que c'est une définition assez étrange de "hier", si je vois maintenant (dimanche soir) une réponse le vendredi soir comme "hier".
ajouté l'auteur Paŭlo Ebermann, source
"<48 * 60 * 60s" est une définition plutôt non conventionnelle pour "hier". S'il est 9 heures du matin mercredi, pensez-vous vraiment à 9h01 lundi comme "hier". J'aurais pensé qu'un algorithme pour hier ou "n days ago" devrait prendre en compte avant / après minuit.
ajouté l'auteur Joe, source
J'attribuerais simplement var delta = ts.Duration() pour que vous obteniez la valeur absolue dans un objet TimeSpan , et que vous puissiez faire des choses comme if (delta ou if (delta . Toujours lisible, et pas besoin de chiffres ou de constantes cryptiques.
ajouté l'auteur Rufus L, source
Les compilateurs sont généralement assez bons pour pré-calculer des expressions constantes, comme 24 * 60 * 60, donc vous pouvez directement les utiliser au lieu de les calculer vous-même pour être 86400 et mettre l'expression originale dans les commentaires
ajouté l'auteur zvolkov, source
@bzlm Je pense que je l'ai fait pour un projet sur lequel je travaillais. Ma motivation ici était d'alerter les autres que des semaines ont été omises de cet échantillon de code. Quant à savoir comment faire cela, cela me semblait assez simple.
ajouté l'auteur jray, source
remarqué que cette fonction exclut les semaines
ajouté l'auteur jray, source
Je pense que la meilleure façon d'améliorer l'algorithme est d'afficher 2 unités comme "2 mois 21 jours", "1 heure 40 minutes" pour une précision croissante.
ajouté l'auteur Evgeny Levin, source
@ Jeffy, vous avez manqué le calcul de l'année bissextile et les contrôles connexes
ajouté l'auteur Saboor Awan, source
45 minutes étant affichées comme "il y a une heure" ?! N'est-ce pas un bug? Si ce n'est pas le cas, pourquoi ne pas faire la même chose pour les secondes et les minutes?
ajouté l'auteur Eldritch Conundrum, source

@jeff

IMHO vôtre semble un peu long. Cependant, il semble un peu plus robuste avec le soutien pour "hier" et "années". Mais d'après mon expérience, lorsque la personne est utilisée, la personne est plus susceptible de voir le contenu dans les 30 premiers jours. Ce sont seulement les gens vraiment hardcore qui viennent après ça. C'est pourquoi je choisis d'habitude de garder cela court et simple.

C'est la méthode que j'utilise actuellement sur un de mes sites. Cela ne renvoie qu'un jour relatif, heure, heure. Et puis l'utilisateur doit claquer "il y a" dans la sortie.

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

Jeff, votre code est sympa mais pourrait être plus clair avec des constantes (comme suggéré dans le code complet).

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";
}
0
ajouté
@Atmo: non ce n'est pas possible
ajouté l'auteur André Pena, source
Je ne comprends vraiment pas pourquoi les gens n'utilisent pas TotalMinutes, TotalDays, TotalHours ... Cela raccourcirait pas mal ...
ajouté l'auteur lord.fist, source
Quelqu'un at-il des conseils sur la façon dont cela pourrait être mis en œuvre avec une chaîne de format personnalisé, de sorte que `string.Format (mydate," jj / MM / aaaa (YTT) ") ==" 26/04/2011 (aujourd'hui) "?
ajouté l'auteur Neil Barnwell, source
Je déteste ces constantes avec une passion. Est-ce que cela semble mal à quelqu'un? Thread.Sleep (1 * MINUTE) ? Parce que c'est faux d'un facteur de 1000.
ajouté l'auteur Roman Starkov, source
Un autre bug: Parce que delta est absolu, le chemin pour "pas encore" n'est jamais atteint. Remplacez par: delta = ts.TotalSeconds;
ajouté l'auteur StefanG, source
Je pense que si les constantes étaient renommées pour décrire avec précision la valeur qu'elles contiennent, ce serait plus facile à comprendre. Donc SecondsPerMinute = 60; MinutesPerHour = 60; SecondsPerHour = MinutesPerHour * SecondsPerHour; etc. Le simple fait de l'appeler MINUTE = 60 ne permet pas au lecteur de déterminer la valeur.
ajouté l'auteur slolife, source
Le pépin est en "hier", ce n'est pas tout à fait exact puisque quelque chose que je vois aujourd'hui à 7 heures du matin, qui est arrivé il y a deux jours à 22 heures, cédera "hier", ce qui n'est pas exact.
ajouté l'auteur Ayyash, source
Dans certaines langues, vous pouvez même spécifier n'importe quel type d'opérateur de comparaison pour l'instruction switch (), comme>,> =, <= etc ... n'est-ce pas possible en C #?
ajouté l'auteur Atmocreations, source
Pourquoi pas var ts = DateTime.UtcNow - yourDate; , c'est plus simple? Quelle est la justification de Math.Abs ​​?
ajouté l'auteur Jeppe Stig Nielsen, source
ne devrait pas être si (delta <= 90 * MINUTE)? Quelque part j'ai eu un "il y a 1 heure".
ajouté l'auteur Roberto, source
Pourquoi personne (sauf Joe) ne se soucie de la mauvaise valeur "Hier" ou "jours passés"? Hier n'est pas un calcul d'heure, mais un calcul au jour le jour. Donc oui, c'est un mauvais code au moins dans deux cas fréquents.
ajouté l'auteur CtrlX, source
const int SECOND = 1; Donc une seconde bizarre est une seconde.
ajouté l'auteur seriousdev, source
Ce type de code est presque impossible à localiser. Si votre application n'a besoin que de rester en anglais, alors ça va. Mais si vous faites le saut vers d'autres langues, vous vous détestez pour avoir fait une telle logique. Juste pour que vous sachiez ...
ajouté l'auteur Nik Reiman, source
@romkyns Thread.Sleep (1 * MINUTE) ne me semble pas correct, et c'est parce que MINUTE n'a aucune unité spécifiée. Maintenant, MINUTE_IN_SECONDS , ce serait facile à repérer et à corriger facilement: Thread.Sleep (1 * MINUTE_IN_SECONDS * 1000) ou Thread.Sleep (1 * MINUTE_IN_SECONDS * SECOND_IN_MILLISECONDS) . (Obtenir verbeux, mais mieux que les bogues cachés.)
ajouté l'auteur jpmc26, source
Quand je vois tout le capital, je repense aux styles de codage développés pour le C / C ++. La recommandation de Microsoft est Pascal cased. Vérifiez la réponse à cette question - stackoverflow.com / questions / 242534 / & hellip;
ajouté l'auteur CodeMonkeyKing, source
@nick Si vous placez ceci dans un IValueConverter, il traitera automatiquement le CultureInfo pour vous (en supposant que vous avez défini la culture en premier)
ajouté l'auteur Lance McCarthy, source
Vous pouvez optimiser la solution en utilisant le type const sur DateTime, vous n'avez pas à les définir manuellement.
ajouté l'auteur SOAL ABDELDJALLIL, source

Je pensais que je donnerais un coup de feu en utilisant des classes et le polymorphisme. J'ai eu une itération précédente qui a utilisé le sous-classement qui a fini par avoir trop de frais généraux. Je suis passé à un modèle d'objet de délégation / propriété publique plus flexible, qui est nettement meilleur. Mon code est très légèrement plus précis, j'aimerais pouvoir trouver une meilleure façon de générer des «mois passés» qui ne semblaient pas trop sophistiqués.

Je pense que je resterais fidèle à la cascade si-alors de Jeff parce que c'est moins de code et c'est plus simple (il est certainement plus facile de s'assurer que ça fonctionnera comme prévu).

Pour le code ci-dessous, PrintRelativeTime.GetRelativeTimeMessage (il y a TimeSpan) renvoie le message d'heure relative (par exemple "hier").

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

    static PrintRelativeTime()
    {
        timeRanges = new List{
            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);
    }
}
0
ajouté

Je recommande de calculer cela du côté client aussi. Moins de travail pour le serveur.

Ce qui suit est la version que j'utilise (de 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);
                });
        };
}
0
ajouté
La question est C# tagged Pourquoi code Javascript ?
ajouté l'auteur Kiquenet, source

En PHP, je le fais de cette façon:

<?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";

} ?>
0
ajouté
La question est C# tagged . Pourquoi ce code PHP ? À mon humble avis, applique uniquement le code C#
ajouté l'auteur Kiquenet, source

@Jeff

var ts = nouveau   TimeSpan (DateTime.UtcNow.Ticks -   dt.Ticks);

Faire une soustraction sur DateTime renvoie quand même un TimeSpan .

Donc vous pouvez juste faire

(DateTime.UtcNow - dt).TotalSeconds

Je suis également surpris de voir les constantes multipliées à la main et ensuite les commentaires ajoutés aux multiplications. Est-ce que c'était une optimisation malavisée?

0
ajouté

Ceci, je l'ai obtenu d'un blog de Bill Gates. Je dois le trouver dans l'historique de mon navigateur et je vous donnerai le lien.

Le code Javascript pour faire la même chose (comme demandé):

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

Fondamentalement, vous travaillez en termes de secondes ...

0
ajouté

Vous pouvez utiliser l ' extension TimeAgo à partir de laquelle ressemble:

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

Ou utilisez plugin jQuery avec l'extension Razor de Timeago.

0
ajouté

Je voudrais fournir quelques méthodes d'extensions pratiques pour cela et rendre le code plus lisible. Tout d'abord, quelques méthodes d'extension pour 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;
    }
}

Ensuite, un pour DateTime .

public static class DateTimeExtensions {

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

        return dateTime - delta;
    }
}

Maintenant, vous pouvez faire quelque chose comme ci-dessous:

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
0
ajouté

Voici une réécriture de Jeffs Script pour 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";
    }
}    
0
ajouté
La question est C# tagged Pourquoi code PHP ?
ajouté l'auteur Kiquenet, source

using Fluent 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();
0
ajouté

Voici l'algorithme que stackoverflow utilise mais réécrit de manière plus concise en pseudo-code perlish avec une correction de bogue (pas de "il y a une heure"). La fonction prend un nombre (positif) de secondes et renvoie une chaîne conviviale comme "3 heures" ou "hier".

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";
0
ajouté
using System;
using System.Collections.Generic;
using System.Linq;

public static class RelativeDateHelper
{
    private static Dictionary> sm_Dict = null;

    private static Dictionary> DictionarySetup()
    {
        var dict = new Dictionary>();
        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;
    }
}

Identique à autre réponse à cette question mais en tant qu'extension méthode avec un dictionnaire statique.

0
ajouté
Qu'est-ce que le dictionnaire vous achète ici?
ajouté l'auteur StriplingWarrior, source
Je vois. Je pensais juste, puisque la documentation sur Dictionary indique que "L'ordre dans lequel les éléments sont retournés est indéfini", ( msdn.microsoft.com/en-us/library/xfhwa508.aspx ) peut-être que ce n'est pas la meilleure structure de données à utiliser quand vous ne vous en souciez pas à propos des temps de recherche autant que d'avoir des choses restent en ordre.
ajouté l'auteur StriplingWarrior, source
StriplingWarrior: Facilité de lecture et de modification par rapport à une instruction switch ou à une pile d'instructions if / else. Le dictionnaire étant statique signifie que lui et les objets Func <,> ne doivent pas être créés chaque fois que nous voulons utiliser ToRelativeDate; il est créé une seule fois, comparé à celui que j'ai lié dans ma réponse.
ajouté l'auteur Chris Charabaruk, source
StriplingWarrior: Je crois que LINQ en tient compte lorsqu'il est utilisé avec Dictionary s. Si vous n'êtes toujours pas à l'aise avec cela, vous pouvez utiliser SortedDictionary , mais ma propre expérience montre que cela n'est pas nécessaire.
ajouté l'auteur Chris Charabaruk, source
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";
}

Les valeurs de conversion pour les jours d'un mois et d'une année ont été extraites de Google.

0
ajouté

Quelques années en retard à la fête, mais j'avais l'obligation de le faire pour les dates passées et futures, donc j'ai combiné Jeff et

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;

        /// 
/// Returns a friendly version of the provided DateTime, relative to now. E.g.: "2 days ago", or "in 6 months". ///
 
        /// 
The DateTime to compare to Now
        /// A friendly string
        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";
            }
        }
    }

0
ajouté

Je pense qu'il y a déjà un certain nombre de réponses liées à ce post, mais on peut utiliser ce qui est facile à utiliser comme plugin et aussi facilement lisible pour les programmeurs. Envoyez votre date spécifique, et obtenez sa valeur sous forme de chaîne:

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;
}
0
ajouté

Mon chemin est beaucoup plus simple. Vous pouvez modifier avec les chaînes de retour que vous voulez

    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;
    }
0
ajouté

Sûrement une solution facile pour se débarrasser du problème «il y a 1 heure» serait d'augmenter la fenêtre pour laquelle il y a «une heure». Changement

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

dans

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

Cela signifie que quelque chose qui s'est passé il y a 110 minutes se lira comme «il y a une heure» - ce n'est peut-être pas parfait, mais je dirais que c'est mieux que la situation actuelle «il y a 1 heure».

0
ajouté

Étant donné que le monde et son mari semblent afficher des échantillons de code, voici ce que j'ai écrit il y a un certain temps, basé sur quelques-unes de ces réponses.

J'avais un besoin spécifique pour que ce code soit localisable. Donc j'ai deux cours? Grammar , qui spécifie les termes localisables, et FuzzyDateExtensions , qui contient un tas de méthodes d'extension. Je n'avais pas besoin de gérer les datetime futures, donc aucune tentative n'est faite pour les gérer avec ce code.

J'ai laissé une partie de XMLdoc dans la source, mais j'ai supprimé la plupart (où ils seraient évidents) par souci de brièveté. Je n'ai pas inclus tous les membres de la classe ici:

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)
    { ... }
}

La classe FuzzyDateString contient:

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

L'une des choses clés que je voulais atteindre, ainsi que la localisation, était que "aujourd'hui" signifierait seulement "ce jour de calendrier", donc le IsToday , IsThisMonth , < Les méthodes code> IsThisYear ressemblent à ceci:

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

et les méthodes d'arrondi sont comme ceci (j'ai inclus RoundedMonths , car c'est un peu différent):

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

J'espère que les gens trouvent cela utile et / ou intéressant: o)

0
ajouté

Java pour l'utilisation de gwt côté client:

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

}
0
ajouté
La question est C# tagged . Pourquoi ce code Java ? À mon humble avis, applique uniquement le code C#
ajouté l'auteur Kiquenet, source

Il y a aussi un paquet appelé Humanizer sur Nuget et ça marche vraiment très bien

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 has a writeup on it on his blog

0
ajouté
Tellement utile! Cette réponse doit être beaucoup plus élevée dans cette liste. Si j'avais 100 votes, je le donnerais à ceci. Apparemment (venant de JS-land), la recherche de ce package n'a pas été facile.
ajouté l'auteur kumar_harsh, source
note amicale: Sur .net 4.5 ou ci-dessus ne pas installer complet Humanizer ... seulement installer Humanizer.Core partie de celui-ci .. cause d'autres paquets de langue ne sont pas pris en charge sur cette version
ajouté l'auteur Ahmad, source

Lorsque vous connaissez le fuseau horaire du spectateur, il peut être plus clair d'utiliser les jours calendaires à l'échelle du jour. Je ne suis pas familier avec les bibliothèques .NET, donc je ne sais pas comment vous le feriez en C#, malheureusement.

Sur les sites de consommation, vous pouvez également être hand-wavier moins d'une minute. "Il y a moins d'une minute" ou "tout à l'heure" pourrait suffire.

0
ajouté

plugin jquery.timeago

Jeff, because Stack Overflow uses jQuery extensively, I recommend the plugin jquery.timeago .

Avantages:

  • Evitez les horodatages datés "il y a 1 minute" même si la page a été ouverte il y a 10 minutes; timeago se rafraîchit automatiquement.
  • Vous pouvez tirer pleinement parti de la mise en cache de pages et / ou de fragments dans vos applications Web, car les horodatages ne sont pas calculés sur le serveur.
  • Vous pouvez utiliser des microformats comme les enfants cool.

Il suffit de l'attacher à vos horodatages sur DOM prêt:

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

Cela transformera tous les éléments abbr avec une classe de timeago et un ISO 8601 horodatage dans le titre:

July 17, 2008

en quelque chose comme ça:

4 months ago

ce qui donne: il y a 4 mois. Au fil du temps, les horodatages seront automatiquement mis à jour.

Disclaimer: J'ai écrit ce plugin, donc je suis partial.

0
ajouté
@Rob Fonseca-Ensor - maintenant ça me fait pleurer aussi. Comment est une mise à jour une fois par minute, pour montrer des informations précises, de quelque façon que ce soit concernant le texte clignotant une fois par seconde?
ajouté l'auteur Daniel Earwicker, source
un super plugin - juste pour le plaisir, je l'ai "allégé" en réduisant les fonctionnalités, comme l'autoupdating, et l'ai combiné avec la réponse refactormycode </ a> - jsfiddle.net/drzaus/eMUzF
ajouté l'auteur drzaus, source
Ryan, j'ai suggéré que SO utilise timeago il y a un moment. La réponse de Jeff m'a fait pleurer, je vous suggère de vous asseoir: stackoverflow.uservoice.com/pages/1722-general/suggestions/…
ajouté l'auteur Rob Fonseca-Ensor, source
@RyanMcGeary: C'est probablement le mauvais endroit à demander mais j'ai une question sur l'utilisation de TimeAgo. Je suis au Royaume-Uni (GMT qui inclut DST) et les dates stockées dans ma base de données sont UTC. Si j'insère une date dans mon DB comme UTC en été, évidemment le temps sera dehors par 1 heure. Ainsi, au lieu de l'impression TimeAgo "il y a environ 1 minute", il va dire "il y a environ 1 heure". Le plugin TimeAgo gère-t-il les différences DST?
ajouté l'auteur TheCarver, source
La question concerne C#, je ne vois pas comment un plugin jQuery est pertinent.
ajouté l'auteur BartoszKP, source
Et si l'utilisateur a JavaScript désactivé? jQuery (et JavaScritp en général) ne devraient être utilisés pour améliorer l'expérience côté client, mais vos fonctions d'application ne devraient pas dépendre des technologies du client. Vous pouvez accomplir cela sans utiliser JavaScript.
ajouté l'auteur Seb, source
Une option pour désactiver la mise à jour automatique ne devrait pas être si difficile, n'est-ce pas? Si ce n'est pas déjà fait, c'est ... Il suffit de mettre à jour les horodatages une fois sur pageload et d'en finir avec lui.
ajouté l'auteur Dean Harding, source
Est-ce que ce soutien. C# datetime.utcNow ?? ce serait bien
ajouté l'auteur blackholeearth0_gmail, source
@PaparazzoKid Oui, Timeago gère très bien les fuseaux horaires tant que votre horodatage est un horodatage ISO8601 correct. Mais tu as raison. C'est le mauvais endroit pour poser cette question. Allez ici à la place: github.com/rmm5t/jquery-timeago/issues
ajouté l'auteur Ryan McGeary, source
Seb, Si vous avez désactivé Javascript, la chaîne que vous avez initialement placée entre les balises abbr est affichée. Généralement, il s'agit juste d'une date ou d'une heure dans le format que vous souhaitez. Timeago se dégrade avec élégance. Cela ne devient pas beaucoup plus simple.
ajouté l'auteur Ryan McGeary, source
Hé, merci Rob. C'est bon. C'est à peine perceptible, surtout quand un seul numéro change pendant la transition, bien que les pages SO aient beaucoup d'horodatages. J'aurais pensé qu'il aurait au moins apprécié les avantages de la mise en cache des pages, même s'il choisit d'éviter les mises à jour automatiques. Je suis sûr que Jeff aurait pu fournir des commentaires pour améliorer le plugin aussi. Je prends consolation en sachant que des sites comme arstechnica.com l'utilisent.
ajouté l'auteur Ryan McGeary, source

Voici une implémentation que j'ai ajoutée en tant que méthode d'extension à la classe DateTime qui gère les dates futures et passées et fournit une option d'approximation qui vous permet de spécifier le niveau de détail que vous recherchez ("3 heures" vs "3 heures, Il y a 23 minutes, 12 secondes "):

using System.Text;

/// 
/// Compares a supplied date to the current date and generates a friendly English /// comparison ("5 days ago", "5 days from now") ///
 
/// 
The date to convert
/// 
When off, calculate timespan down to the second.
/// When on, approximate to the largest round unit of time.
/// 
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();
}
0
ajouté

Version iPhone-c

+ (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];
}

}

0
ajouté
var ts = new TimeSpan(DateTime.Now.Ticks - dt.Ticks);
0
ajouté

vous pouvez essayer ceci. Je pense que cela fonctionnera correctement.

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";
}
0
ajouté
/** 
 * {@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";
    }
}
0
ajouté

Si vous voulez avoir un résultat comme "2 jours, 4 heures et 12 minutes", vous avez besoin d'une période de temps:

TimeSpan timeDiff = DateTime.Now-CreatedDate;

Ensuite, vous pouvez accéder aux valeurs que vous aimez:

timeDiff.Days
timeDiff.Hours

etc.

0
ajouté

Ceci est ma fonction, fonctionne comme un charme :)

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;
        }
0
ajouté
codage heureux: D
ajouté l'auteur VnDevil, source
fonctionne comme un charme :)
ajouté l'auteur densityx, source