Quelqu'un peut-il connaître une bonne bibliothèque (ou un extrait de code) pour convertir un objet Timespan à une chaîne «amicale» telle que: P>
(C'est pour un système d'expiration de documents, où l'expiration pourrait être quelque chose de quelques jours à plusieurs décennies) P>
Juste pour clarifier, disons que j'avais une période de temps avec 7 jours, qui devrait imprimer "1 semaine", 14 jours "2 semaines", 366 jours "1 an et 1 jour", etc. p>
10 Réponses :
Cela ne fera probablement pas tout ce que vous recherchez, mais dans le V4 Microsoft sera Mise en œuvre iformattable code> sur
. P> Timespan code>
bon de savoir. Voici la page MSDN de .net 4 MSDN.MicRosoft.com /en-us/Library/ddd992632(vs.100).aspx
L'objet Timespan a des journées, des heures, des minutes et des propriétés secondes à ce sujet, il ne serait donc pas trop difficile de faire un extrait qui formule ces valeurs à une chaîne amicale. P>
Malheureusement, les jours sont la plus grande valeur. Quelque chose de plus long que cela et vous devrez commencer à vous inquiéter des jours d'un mois pour chaque année ... etc. Vous ferez mieux de vous arrêter pendant des jours à mon avis (l'effort supplémentaire ne semble pas en valeur). P>
... Je pensais que j'apporterais cela de mon propre commentaire: P>
compréhensible, mais est "Ce document expire dans 10 ans, 3 mois, 21 jours, 2 heures et 30 minutes" vraiment plus utile ou moins stupide? Si c'était à moi, car aucune ne semble que la représentation ne semble très utile ...
Je laisserais hors de l'échange d'expiration jusqu'à ce que la date soit raisonnablement proche (30 ou 60 jours peut-être si vous êtes inquiet. sur l'obtention du document mis à jour).
semble un meilleur choix UX pour moi. P>
blockQuote>
Les jours conviennent bien pour dire "Ce document expire dans 7 jours", mais quand "ce document expire dans 3892 jours", cela a l'air un peu stupide (et inutile). Je peux voir comment j'utiliserais Modulo pour faire cela, mais je suis paresseux et je ne veux pas passer du temps à réintroduire la roue :)
Compréhensible, mais est "Ce document expire dans 10 ans, 3 mois, 21 jours, 2 heures et 30 minutes" vraiment plus utile ou moins stupide? Si c'était à moi, car aucune ne semble que la représentation ne semble très utile ... J'aurais quitté le trajet de l'expiration jusqu'à ce que la date soit raisonnablement proche (30 ou 60 jours peut-être que si vous craignez d'obtenir le document mis à jour). Semble un meilleur choix UX pour moi.
Pour formater n'importe quelle période de plus d'un jour (c'est-à-dire le mois / année / décennie, etc.) Un objet Timespan n'est pas suffisant. P>
Supposons que votre fusil horaire soit de 35 jours, puis à partir du 1 avril, vous obtiendrez un mois et cinq jours, alors que du 1er décembre, vous auriez un mois et quatre jours. P>
Pas une implémentation parfaitement présentée, mais cela devrait vous demander assez près.
DateTime dtNow = DateTime.Now; DateTime dtYesterday = DateTime.Now.AddDays(-435.0); TimeSpan ts = dtNow.Subtract(dtYesterday); int years = ts.Days / 365; //no leap year accounting int months = (ts.Days % 365) / 30; //naive guess at month size int weeks = ((ts.Days % 365) % 30) / 7; int days = (((ts.Days % 365) % 30) % 7); StringBuilder sb = new StringBuilder(); if(years > 0) { sb.Append(years.ToString() + " years, "); } if(months > 0) { sb.Append(months.ToString() + " months, "); } if(weeks > 0) { sb.Append(weeks.ToString() + " weeks, "); } if(days > 0) { sb.Append(days.ToString() + " days."); } string FormattedTimeSpan = sb.ToString();
Smashing! Acclamations pour cela. Oui, je pense que vous avez raison de faire la valeur un peu floue, mais c'est une de ces choses où je devrai le tester sur une variété de valeurs et voir ce qui fonctionne comme un terrain moyen sensible entre trop peu et trop de détails.
Merci Patrick McDonald. J'ai totalement manqué mon erreur de pâte de copie.
@Andy_vulhop Vous perdez certains des avantages du StringBuilder en concaténant les cordes que vous mettez en elle la voie traditionnelle. Vous devez utiliser .append code> deux fois (FYI, chaînes informatiques. I.e.
SB.Append (Année.Tostring ()). Ajoutez ("années", "); code>);
Ou j'aime sb.appendormat ("{0} ans", années);
voir Comment-i-I-Calculez-le relatif-temps , Demandé ( par numéro d'utilisateur 1 ) Il y a un an, quand ce sera jeune et non public. C'était (probablement) la base de l'affichage actuel de l'âge pour des questions et des réponses actuelles. P>
Je viens de tomber sur cette question parce que je voulais faire une chose semblable. Après une certaine google, je n'ai toujours pas trouvé ce que je voulais: afficher une tempier de manière "arrondi". Je veux dire: quand un événement a pris plusieurs jours, il n'a pas toujours de sens d'afficher les millisecondes. Cependant, quand il fallait des minutes, c'est probablement le cas. Et dans ce cas, je ne veux pas 0 jours et 0 heure à afficher. Donc, je veux paramétrer le nombre de pièces temporelles pertinentes à afficher. Cela a abouti à ce bit de code: exemple (linqpad): p> affiche: p> me convient, voyez si cela vous convient. P> p>
Idée intéressante, je vais essayer (tardivement) :)
@Gert, je n'essayais que de votre méthode d'extension. Passé 8 heures en tant que Timespan code> et obtenu cela comme résultat "8 heures, 0 minute, 0 seconde, 0 milliseconde". Ces zéro ne devraient-ils pas être affichés comme vous l'avez dit dans votre message? Merci d'avance!
@YUSTME je voulais dire les principales parties 0. Si vous ne voulez pas N'importe quel i> 0 pièce à afficher, vous pouvez ajouter .where (i => i.item2! = 0 code> après le
prise code >.
Ah d'accord, mon mauvais. C'est exactement ce que je veux, merci!
@YUSTME / @ gert-arnold ne remplacerait pas le .skiwhsile (i => i.item2 <= 0) code> avec
. Où (i => i.item2> 0) Code> Faites la même chose avec quelques cycles de moins (je parle spécifiquement de si vous ne voulez pas n'importe quel i> 0 partie à afficher)? Voir aussi ma réponse concernant le projet Humanizer.
@Mark .skipwhile (i => i.item2 <= 0) code> est efficace mais donne des résultats différents que d'utiliser le
. Où (i => i.item2> 0) code> . Ce dernier supprimera toutes les entrées i> zéro.
.SKIPHILE CODE> ne supprimera que les seules valeurs zéro.
Il y a maintenant aussi le Projet Humanizer qui semble très intéressant qui peut faire cela et beaucoup plus. p>
Voici ma solution à cela. Il est basé sur d'autres réponses dans ce fil, avec un soutien supplémentaire pour l'année et le mois, comme cela a été demandé dans la question initiale (et était ce dont j'avais besoin).
Quant à la discussion, si cela a du sens, je dirais qu'il y a des cas où cela le fait. Dans mon cas, nous voulions montrer la durée des accords que dans certains cas seulement quelques jours, et dans d'autres cas plusieurs années. P>
tests; p>
private class TermAndValue { public TermAndValue(string singular, string plural, int value) { Singular = singular; Plural = plural; Value = value; } public string Singular { get; } public string Plural { get; } public int Value { get; } public string Term => Value > 1 ? Plural : Singular; } public static string ToFriendlyDuration(this DateTime value, DateTime? endDate, int maxNrOfElements = 2) { if (!endDate.HasValue) return "Until further notice"; var extendedTimeSpan = new TimeSpanWithYearAndMonth(value, endDate.Value); maxNrOfElements = Math.Max(Math.Min(maxNrOfElements, 5), 1); var termsAndValues = new[] { new TermAndValue("year", "years", extendedTimeSpan.Years), new TermAndValue("month", "months", extendedTimeSpan.Months), new TermAndValue("day", "days", extendedTimeSpan.Days), new TermAndValue("hour", "hours", extendedTimeSpan.Hours), new TermAndValue("minute", "minutes", extendedTimeSpan.Minutes) }; var parts = termsAndValues.Where(i => i.Value != 0).Take(maxNrOfElements); return string.Join(", ", parts.Select(p => $"{p.Value} {p.Term}")); } internal class TimeSpanWithYearAndMonth { internal TimeSpanWithYearAndMonth(DateTime startDate, DateTime endDate) { var span = endDate - startDate; Months = 12 * (endDate.Year - startDate.Year) + (endDate.Month - startDate.Month); Years = Months / 12; Months -= Years * 12; if (Months == 0 && Years == 0) { Days = span.Days; } else { var startDateExceptYearsAndMonths = startDate.AddYears(Years); startDateExceptYearsAndMonths = startDateExceptYearsAndMonths.AddMonths(Months); Days = (endDate - startDateExceptYearsAndMonths).Days; } Hours = span.Hours; Minutes = span.Minutes; } public int Minutes { get; } public int Hours { get; } public int Days { get; } public int Years { get; } public int Months { get; } }
Oui! J'avais besoin de la même chose si de fois alors je crée mon forfait ONW et je l'ai publié à Nuget. Vous êtes invité à l'utiliser.
Le nom du paquet est est esececeeemplies strong> Il est facile à implémenter: p>
Je sais que c'est vieux, mais je voulais répondre avec un grand paquet Nuget. https://www.nuget.org/packages/humanizer p> https://github.com/mehdik/humanizer p> Exemple de leur lecture_MD p> @Ian -Becker a besoin du crédit p> p>
Dupliqué possible de calcul du temps relatif
Vérifiez Ma réponse avec exemple