7
votes

Afficher l'heure relative en heure, jour, mois et année

J'ai écrit une fonction xxx pré>

qui donnait un epoch code>, renvoie une chaîne qui affichera le temps relatif de l'heure et de la minute p> Par exemple: p> xxx pré>

Je veux maintenant prolonger cette fonction en mois et en année, il sera donc en mesure d'imprimer: P>

function toBeautyString(epochNow, epochNow){
    var secDiff = Math.abs(epochNow - epochNow);
    var milliInDay = 1000 * 60 * 60 * 24;
    var milliInHour = 1000 * 60 * 60;

    var nbDays = Math.round(secDiff/milliInDay);
    var nbHour = Math.round(secDiff/milliInHour);

    var relativeHour = (nbDays === 0) ? nbHour : nbHour-(nbDays*24);
    relativeHour %= 24;

    if(nbHour === 0){
        nbDays += 1;
    }else if(nbHour === (nbDays-1)*24){
        nbDays -= 1;
    }

    var dayS = (nbDays > 1) ? "days" : "day";
    var hourS = (relativeHour > 1) ? "hours" : "hour";

    var fullString = "";

    if(nbDays > 0){
        fullString += nbDays + " " + dayS;
        if(relativeHour > 0)
            fullString += " ";
    }

    if(relativeHour > 0){
        fullString += relativeHour + " " + hourS;
    }

    if(epochDate > epochNow){
        return "Will be in " + fullString;
    }else if ((epochDate === epochNow) 
            || (relativeHour === 0 && nbDays === 0)){
        return "Now";
    }else{
        return fullString + " ago";         
    }
}


2 commentaires

Que diriez-vous de vous montrer votre tobeautysstring code? Je préfère étendre cela puis écrivez-vous une nouvelle fonction de zéro.


S'il vous plaît dites-nous quelle langue vous utilisez. Est-ce que c'est JavaScript?


5 Réponses :


2
votes

Il est utile de reconnaître cela comme deux problèmes distincts: 1) Tranking le temps dans des morceaux individuels d'unités variables; 2) formater les morceaux et les rejoindre avec votre choix de virgules, conjonctions, etc. De cette façon, vous conservez votre logique de formatage de texte séparé de votre logique de calcul de temps.

#converts a time amount into a collection of time amounts of varying size.
#`increments` is a list that expresses the ratio of successive time units
#ex. If you want to split a time into days, hours, minutes, and seconds,
#increments should be [24,60,60]
#because there are 24 hours in a day, 60 minutes in an hour, etc.
#as an example, divideTime(100000, [24,60,60]) returns [1,3,46,40], 
#which is equivalent to 1 day, 3 hours, 46 minutes, 40 seconds
def divideTime(amount, increments):
    #base case: there's no increments, so no conversion is necessary
    if len(increments) == 0:
        return [amount]
    #in all other cases, we slice a bit off of `amount`,
    #give it to the smallest increment,
    #convert the rest of `amount` into the next largest unit, 
    #and solve the rest with a recursive call.
    else:
        conversionRate = increments[-1]
        smallestIncrement = amount % conversionRate
        rest = divideTime(amount / conversionRate, increments[:-1])
        return rest + [smallestIncrement]

def beautifulTime(amount):
    names      = ["year", "month", "day", "hour", "minute", "second"]
    increments = [12,     30,      24,    60,     60]
    ret = []
    times = divideTime(amount, increments)
    for i in range(len(names)):
        time = times[i]
        name = names[i]
        #don't display the unit if the time is zero
        #e.g. we prefer "1 year 1 second" to 
        #"1 year 0 months 0 days 0 hours 0 minutes 1 second"
        if time == 0:
            continue
        #pluralize name if appropriate
        if time != 1:
            name = name + "s"
        ret.append(str(time) + " " + name)
    #there's only one unit worth mentioning, so just return it
    if len(ret) == 1:
        return ret[0]
    #when there are two units, we don't need a comma
    if len(ret) == 2:
        return "{0} and {1}".format(ret[0], ret[1])
    #for all other cases, we want a comma and an "and" before the last unit
    ret[-1] = "and " + ret[-1]
    return ", ".join(ret)

print beautifulTime(100000000)
#output: 3 years, 2 months, 17 days, 9 hours, 46 minutes, and 40 seconds


4 commentaires

Y a-t-il un moyen d'obtenir le nombre exact? Même si c'est très complexe à faire, je serai heureux de comprendre comment cela peut être fait.


Je ne suis pas un expert en temps, je ne sais donc pas comment obtenir le nombre exact. Je ne suis même pas sûr d'un nombre exact possible. Le temps est très difficile à faire, car il y a tellement d'exceptions près et de modifications et d'éléments «Gotcha». C'est presque toujours une meilleure idée de trouver une bibliothèque existante que de faire la vôtre.


D'accord, je suis simplement curieux, quelqu'un sur tellement probablement une bibliothèque existante! J'espère qu'il verra cette question!


Il y a beaucoup de bibliothèques; L'objet de date intégré dans JavaScript permet en fait beaucoup d'abus (par exemple, la date dans le constructeur peut être en dehors de sa plage) et comprend des éléments tels que l'UTC et la lumière du jour, des localisations de temps d'économie d'été ...



-3
votes

Il ne peut pas y avoir un tel algorithme! strong>

fractions d'une journée (heures, minutes, secondes), voire des jours eux-mêmes, ne sont pas un problème. Le problème est que la longueur de "un mois" varie entre 28 et 31 jours. P>

Je vous donne un exemple: P>

permet de dire aujourd'hui est 28 févr. 2013 Et vous souhaitez calculer TOBeauTystring (28 janvier 2013) CODE>: P>

today: 1 Mar 2013
toBeautyString(28 Jan 2013)
expected answer 1 month and 1 days ago


3 commentaires

Hmm tobeautysstring (28 janvier 2013) hier a donné une valeur de 1 mois et il y a 4 jours il y a 1 mois. Aussi aujourd'hui n'est plus 1 mars 2013 est le 2 mars 2013.


La sortie dépend du moment où vous exécutez le code (sur la valeur de maintenant). Ce n'est pas un gros problème, juste une entrée cachée que vous devez prendre en compte.


1 mois à l'avenir, la date sera la même, le mois sera de 1 unité plus élevé (avec une enveloppe éventuelle à janvier). Cela peut signifier 28 jours, 29 ou 30, ou 31, en fonction du / courant / mois. Il y a 1 mois, la date était la même, mais le mois était inférieur de 1 unité (ou enveloppe à décembre). Sa longueur dépend du nombre de jours au / le passé / mois. Où est le problème?.



2
votes

Vous pouvez utiliser la classe datrodiff forte> à partir du Bibliothèque de périodes de temps pour .NET Pour afficher l'heure relative:

// ----------------------------------------------------------------------
public void DateDiffSample( DateTime epoch )
{
  DateDiff dateDiff = new DateDiff( DateTime.Now, epoch );
  Console.WriteLine( "{0} ago", dateDiff.GetDescription( 4 ) );
  // > 1 Year 4 Months 12 Days 12 Hours ago
} // DateDiffSample


0 commentaires

2
votes

Aussi de manière exhaustive dans d'autres réponses, votre code ne peut pas être facilement étendu en raison des longueurs de mois variable. Donc, on ne peut tout simplement pas supposer que le mois soit 30 jours.

Pour avoir une différence lisible par l'homme, vous devez soustraire des dates lisibles humaines. P>

Je le ferais comme Ceci (JavaScript, pour correspondre à la question): P>

function toBeautyString(then) {

    var nowdate = new Date();
    var thendate = new Date(then * 1000);

    //finding the human-readable components of the date.

    var y = nowdate.getFullYear() - thendate.getFullYear();
    var m = nowdate.getMonth() - thendate.getMonth();
    var d = nowdate.getDate() - thendate.getDate();
    var h = nowdate.getHours() - thendate.getHours();
    var mm = nowdate.getMinutes() - thendate.getMinutes();
    var s = nowdate.getSeconds() - thendate.getSeconds();

    //back to second grade math, now we must now 'borrow'.

    if(s < 0) {
            s += 60;
            mm--;
    }
    if(mm < 0) {
            mm += 60;
            h--;
    }
    if(h < 0) {
            h += 24;
            d--;
    }
    if(d < 0) {

            //here's where we take into account variable month lengths.

            var a = thendate.getMonth();
            var b;
            if(a <= 6) {
                    if(a == 1) b = 28;
                    else if(a % 2 == 0) b = 31;
                    else b = 30;
            }
            else if(b % 2 == 0) b = 30;
            else b = 31;

            d += b;
            m--;
    }
    if(m < 0) {
            m += 12;
            y--;
    }

    //return "y years, m months, d days, h hours, mm minutes and s seconds ago."
}


2 commentaires

Il ne prévoit également pas de temps d'économie de jour, ce qui entraînera une heure manquante (ou restes) lorsqu'il va chevaucher la journée dans laquelle vous ajoutez ou soustrayez une heure ...


Évité, aussi plus efficace que ma mise en œuvre; Mais veuillez corriger les fautes de frappe lorsque vous déclarez Nowdate et Thendate ( Var Date Nowdated : mot date non nécessaire). En outre, cela échoue si le thengate n'est pas dans le passé ... Facile à réparer, de même que des années de saut et de sauts de DST.



1
votes

Deux fonctions: une pour calculer la différence, et une autre pour le montrer (inspirée de la réponse de Kevin). Fonctionne pour tous mes tests, prend en compte des durées de mois, facile à traduire et fonctionne également autour du temps d'économie de jour. XXX


1 commentaires

En ce qui concerne le temps d'économie de jour: vous ne devriez probablement pas le prendre en compte pour des périodes plus courtes, par exemple 1 jour ou moins. Vous pouvez également le mentionner dans la jolie chaîne imprimée "plus 1 heure perdue / gagnée à DST".