Abrufen des Tagessuffix bei Verwendung von DateTime.ToString ()

78

Ist es möglich, das Tagessuffix beim Formatieren eines Datums mit DateTime.ToString () einzuschließen?

Zum Beispiel möchte ich das Datum im folgenden Format drucken - Montag, 27. Juli 2009. Das nächste Beispiel, das ich mit DateTime.ToString () finden kann, ist Montag, 27. Juli 2009.

Kann ich dies mit DateTime.ToString () tun oder muss ich auf meinen eigenen Code zurückgreifen?

Craig Bovis
quelle
7
Hat jemand NodaTime gesagt?
Granate
2
Zu Ihrer Information, "[Datum] Ordnungssuffix" werden diese genannt. "Tag" bezieht sich normalerweise auf Montag-Sonntag
Richard Szalay
@ Granate Ich möchte, dass dies die Antwort so schlecht ist. Ich habe fast eine Stunde lang gesucht, um NodaTime wie in der Frage erwähnt zu formatieren, aber soweit ich das beurteilen kann, funktioniert es nicht: nodatime.org/2.3.x/userguide/localdate-patterns (auch in 2020) Es sieht so aus, als ob momentjs dies hat, weil sie ihr eigenes Lokalisierungsmodell erstellt haben: momentjs.com/docs/#/i18n
Drew Delano
nodatime.org/3.0.x/userguide/limitations Darüber hinaus stammen alle unsere Textlokalisierungsressourcen (Tages- und Monatsnamen) aus dem .NET Framework selbst. Dies weist einige erhebliche Einschränkungen auf und macht Noda Time mehr auf CultureInfo angewiesen als ideal. CLDR enthält weitere Informationen, die Funktionen wie Ordnungszahl ("1.", "2.", "3.") und eine breitere Palette unterstützter Kalender- / Kulturkombinationen (z. B. englische Namen für die hebräischen Kalendermonate) berücksichtigen sollten.
Drew Delano

Antworten:

64

Als Referenz verwende / verweise ich immer auf SteveX String Formatierung und es scheint kein "th" in einer der verfügbaren Variablen zu geben, aber Sie könnten leicht einen String mit erstellen

string.Format("{0:dddd dd}{1} {0:MMMM yyyy}", DateTime.Now, (?));

Sie müssten dann ein "st" für 1, ein "nd" für 2, ein "rd" für 3 und ein "th" für alle anderen angeben und könnten mit einer "?:" - Anweisung versehen sein.

var now = DateTime.Now;
(now.Day % 10 == 1 && now.Day != 11) ? "st"
: (now.Day % 10 == 2 && now.Day != 12) ? "nd"
: (now.Day % 10 == 3 && now.Day != 13) ? "rd"
: "th"
Bryan Bailliache
quelle
22
Dies müsste weiter ausgebaut werden, um die anderen Fälle abzudecken, sonst erhalten Sie beispielsweise "21".
Kasaku
1
Die offizielle Dokumentation zu den Formatierungsoptionen für Zeichenfolgen von Microsoft finden Sie hier .
Bobson
9
DateTime.NowWird derselbe Ausdruck mehrmals abgerufen, können die Werte unterschiedlich sein, wenn der Code gegen Mitternacht ausgeführt wird.
AlexD
243

Eine weitere Option mit Schalter:

string GetDaySuffix(int day)
{
    switch (day)
    {
        case 1:
        case 21:
        case 31:
            return "st";
        case 2:
        case 22:
            return "nd";
        case 3:
        case 23:
            return "rd";
        default:
            return "th";
    }
}
Lazlow
quelle
10
+1 Einfach, leicht zu lesen und vor allem für alle Fälle geeignet.
Lynn Crumbling
24
@Lazlow Falls Sie sich über die plötzliche Aktivität wundern: Ihre Antwort wurde von The Daily WTF als Beispiel "Wie man es richtig macht" verlinkt .
tobias_k
@tobias_k danke - ich habe mich gefragt, wie sich mein winziger Ruf so schnell verdoppelt hat!
Lazlow
1
Für diejenigen, die die vollständige Datumsformatierung wünschen: return date.ToString ("TT MMMM JJJJ"). Einfügen (2, GetDaySuffix (Datum.Tag)); // zB 12. Januar 2020
user3162879
39

Verwenden einiger Erweiterungsmethoden:

namespace System
{
    public static class IntegerExtensions
    {
        public static string ToOccurrenceSuffix(this int integer)
        {
            switch (integer % 100)
            {
                case 11:
                case 12:
                case 13:
                    return "th";
            }
            switch (integer % 10)
            {
                case 1:
                    return "st";
                case 2:
                    return "nd";
                case 3:
                    return "rd";
                default:
                    return "th";
            }
        }
    }   

    public static class DateTimeExtensions
    {
        public static string ToString(this DateTime dateTime, string format, bool useExtendedSpecifiers)
        {
            return useExtendedSpecifiers 
                ? dateTime.ToString(format)
                    .Replace("nn", dateTime.Day.ToOccurrenceSuffix().ToLower())
                    .Replace("NN", dateTime.Day.ToOccurrenceSuffix().ToUpper())
                : dateTime.ToString(format);
        } 
    }
}

Verwendung:

return DateTime.Now.ToString("dddd, dnn MMMM yyyy", useExtendedSpecifiers: true);
// Friday, 7th March 2014

Hinweis: Die Ganzzahl-Erweiterungsmethode kann für eine beliebige Zahl verwendet werden, nicht nur für 1 bis 31. ZB

return 332211.ToOccurrenceSuffix();
// th
Oundless
quelle
1
Danke Kumpel. Sehr hilfreich. Ich habe in meinem Projekt implementiert. :)
Chandan Kumar
6
Ihr Code Art von ... vergisst, den useExtendedSpecifiersBooleschen
Wert
2
Die eleganteste Lösung. Genau dafür sind Erweiterungsmethoden konzipiert. Habe meine ständig wachsende Erweiterungsmethodenbibliothek erweitert, danke!
Radderz
1
ToOrdinal () vielleicht? :)
Mladen B.
13

Eine weitere Option ist die Verwendung des Modulo-Operators :

public string CreateDateSuffix(DateTime date)
{
    // Get day...
    var day = date.Day;

    // Get day modulo...
    var dayModulo = day%10;

    // Convert day to string...
    var suffix = day.ToString(CultureInfo.InvariantCulture);

    // Combine day with correct suffix...
    suffix += (day == 11 || day == 12 || day == 13) ? "th" :
        (dayModulo == 1) ? "st" :
        (dayModulo == 2) ? "nd" :
        (dayModulo == 3) ? "rd" :
        "th";

    // Return result...
    return suffix;
}

Sie würden dann die obige Methode aufrufen, indem Sie ein DateTime- Objekt als Parameter übergeben, zum Beispiel:

// Get date suffix for 'October 8th, 2019':
var suffix = CreateDateSuffix(new DateTime(2019, 10, 8));

Weitere Informationen zum DateTime- Konstruktor finden Sie auf der Microsoft Docs-Seite .

Anthony Walsh
quelle
2
@ Greg Das ist seltsam, da var suffix = CreateDateSuffix(new DateTime(2013, 10, 8));in meinem Fall '8th' zurückgegeben wird?
Anthony Walsh
1
Wenn es 'th' an die Zeichenfolge 'acht' anhängen würde, wäre es falsch, aber in diesem Fall ist es korrekt, da Sie die Ziffer 8 verwendet haben.
Gcochard
Die obige Methode verwendet ein DateTime- Objekt und ich kann nicht sehen, wie es mit etwas anderem als numerischen Werten instanziiert werden kann - in diesem Fall ' 8 ', das den Tag des Monats darstellt.
Anthony Walsh
In diesem Fall ist es richtig. Wenn Sie, ich weiß nicht, den numerischen Wert durch die Textdarstellung der Zahl ersetzen würden, wäre dies falsch. Ich nehme an, es liegt an jedem, der das Ersetzen durchführt, dies zu wissen und '8t' durch 'acht' zu ersetzen, oder genauer gesagt, '8' durch 'acht' zu ersetzen.
Gcochard
7

Hier ist die erweiterte Version einschließlich 11., 12. und 13 .:

DateTime dt = DateTime.Now;
string d2d = dt.ToString("dd").Substring(1);
string daySuffix =
    (dt.Day == 11 || dt.Day == 12 || dt.Day == 13) ? "th"
    : (d2d == "1") ? "st"
    : (d2d == "2") ? "nd"
    : (d2d == "3") ? "rd"
    : "th";
Piotr Lewandowski
quelle
und was ist mit "11.", "12." und "13."?
sjngm
Ich muss das verpasst haben. Ich habe das oben behoben.
Piotr Lewandowski
Zu ("dd")string.PadLeft()
Ihrer Information,
@PiotrLewandowski - Sie kommen nicht zufällig aus Manchester? Weil ich einen von dort kenne. Zu ausgeflippt +1 übrigens
Piotr Kula
7

Ausgehend von der Antwort von @ Lazlow auf eine vollständige Lösung ist das Folgende eine vollständig wiederverwendbare Erweiterungsmethode mit Beispielverwendung.

internal static string HumanisedDate(this DateTime date)
{
    string ordinal;

    switch (date.Day)
    {
        case 1:
        case 21:
        case 31:
            ordinal = "st";
            break;
        case 2:
        case 22:
            ordinal = "nd";
            break;
        case 3:
        case 23:
            ordinal = "rd";
            break;
        default:
            ordinal = "th";
            break;
    }

    return string.Format("{0:dddd dd}{1} {0:MMMM yyyy}", date, ordinal);
} 

Um dies zu verwenden, würden Sie es einfach für ein DateTimeObjekt aufrufen .

var myDate = DateTime.Now();
var myDateString = myDate.HumanisedFormat()

Welches wird Ihnen geben:

Freitag, 17. Juni 2016

Mark Cooper
quelle
5

AKTUALISIEREN

NuGet-Paket:
https://www.nuget.org/packages/DateTimeToStringWithSuffix

Beispiel:
https://dotnetfiddle.net/zXQX7y

Unterstützt:
.NET Core 1.0 und höher
.NET Framework 4.5 und höher


Hier ist eine Erweiterungsmethode (weil jeder Erweiterungsmethoden liebt) mit Lazlows Antwort als Grundlage (ausgewählt Lazlows, da es leicht zu lesen ist).

Funktioniert genau wie die reguläre ToString()Methode, DateTimemit der Ausnahme, dass das Suffix automatisch hinzugefügt wird , wenn das Format ein doder enthält dd.

/// <summary>
/// Return a DateTime string with suffix e.g. "st", "nd", "rd", "th"
/// So a format "dd-MMM-yyyy" could return "16th-Jan-2014"
/// </summary>
public static string ToStringWithSuffix(this DateTime dateTime, string format, string suffixPlaceHolder = "$") {
    if(format.LastIndexOf("d", StringComparison.Ordinal) == -1 || format.Count(x => x == 'd') > 2) {
        return dateTime.ToString(format);
    }

    string suffix;
    switch(dateTime.Day) {
        case 1:
        case 21:
        case 31:
            suffix = "st";
            break;
        case 2:
        case 22:
            suffix = "nd";
            break;
        case 3:
        case 23:
            suffix = "rd";
            break;
        default:
            suffix = "th";
            break;
    }

    var formatWithSuffix = format.Insert(format.LastIndexOf("d", StringComparison.InvariantCultureIgnoreCase) + 1, suffixPlaceHolder);
    var date = dateTime.ToString(formatWithSuffix);

    return date.Replace(suffixPlaceHolder, suffix);
}
GFoley83
quelle
1
Überrascht, dass dies nicht mehr Stimmen hat, bevorzuge ich die Tatsache, dass es sich um eine Erweiterung handelt. Macht es viel einfacher zu bedienen und wohl besser lesbar.
0Neji
2

Ich glaube, dass dies eine gute Lösung ist, die Zahlen wie die 111. abdeckt:

private string daySuffix(int day)
{
    if (day > 0)
    {
        if (day % 10 == 1 && day % 100 != 11)
            return "st";
        else if (day % 10 == 2 && day % 100 != 12)
            return "nd";
        else if (day % 10 == 3 && day % 100 != 13)
            return "rd";
        else
            return "th";
    }
    else
        return string.Empty;
}
Duncan
quelle
Obwohl dies eine allgemeinere Methode ist, für jede Anzahl, nicht nur für Monatstage (glaube ich).
Duncan
1

Für diejenigen, die gerne externe Abhängigkeiten verwenden (in diesem Fall das fantastische Humanizr .net ), ist es so einfach wie

dateVar.Day.Ordinalize(); \\ 1st, 4th etc depending on the value of dateVar

Gumzle
quelle
0

Ich habe es so gemacht, es umgeht einige der Probleme, die in den anderen Beispielen angegeben sind.

    public static string TwoLetterSuffix(this DateTime @this)
    {
        var dayMod10 = @this.Day % 10;

        if (dayMod10 > 3 || dayMod10 == 0 || (@this.Day >= 10 && @this.Day <= 19))
        {
            return "th";
        }
        else if(dayMod10 == 1)
        {
            return "st";
        }
        else if (dayMod10 == 2)
        {
            return "nd";
        }
        else
        {
            return "rd";
        }
    }
Rashleighp
quelle
0

Eine billige und fröhliche VB-Lösung:

litDate.Text = DatePart("dd", Now) & GetDateSuffix(DatePart("dd", Now))

Function GetDateSuffix(ByVal dateIn As Integer) As String

    '// returns formatted date suffix

    Dim dateSuffix As String = ""
    Select Case dateIn
        Case 1, 21, 31
            dateSuffix = "st"
        Case 2, 22
            dateSuffix = "nd"
        Case 3, 23
            dateSuffix = "rd"
        Case Else
            dateSuffix = "th"
    End Select

    Return dateSuffix

End Function
Tony
quelle
0

Für was es hier wert ist, ist meine endgültige Lösung mit den folgenden Antworten

     DateTime dt = DateTime.Now;
        string d2d = dt.ToString("dd").Substring(1); 

        string suffix =
       (dt.Day == 11 || dt.Day == 12 || dt.Day == 13) ? "th"
       : (d2d == "1") ? "st"
       : (d2d == "2") ? "nd"
       : (d2d == "3") ? "rd"
       : "th";


        Date.Text = DateTime.Today.ToString("dddd d") + suffix + " " + DateTime.Today.ToString("MMMM") + DateTime.Today.ToString(" yyyy"); 
Corbin Spicer
quelle
0

public static String SuffixDate (DateTime date) {string ordinal;

     switch (date.Day)
     {
        case 1:
        case 21:
        case 31:
           ordinal = "st";
           break;
        case 2:
        case 22:
           ordinal = "nd";
           break;
        case 3:
        case 23:
           ordinal = "rd";
           break;
        default:
           ordinal = "th";
           break;
     }
     if (date.Day < 10)
        return string.Format("{0:d}{2} {1:MMMM yyyy}", date.Day, date, ordinal);
     else
        return string.Format("{0:dd}{1} {0:MMMM yyyy}", date, ordinal);
  }
Robert Peter Bronstein
quelle
1
Diese Version zeigt nur die erste Ziffer eines Tages, dh den 1. März 2017, an dem ich den Tagesnamen nicht wie bei einem langen Datum zuerst wollte und nicht den 01. statt den 1.
Robert Peter Bronstein
0

Datumssuffix abrufen. (Statische Funktion)

public static string GetSuffix(this string day)
{
    string suffix = "th";

    if (int.Parse(day) < 11 || int.Parse(day) > 20)
    {
        day = day.ToCharArray()[day.ToCharArray().Length - 1].ToString();
        switch (day)
        {
            case "1":
                suffix = "st";
                break;
            case "2":
                suffix = "nd";
                break;
            case "3":
                suffix = "rd";
                break;
        }
    }

    return suffix;
}

Referenz: https://www.aspsnippets.com/Articles/Display-st-nd-rd-and-th-suffix-after-day-numbers-in-Formatted-Dates-using-C-and-VBNet.aspx

Manjunath Bilwar
quelle
0

Schauen Sie sich humanizr an: https://github.com/Humanizr/Humanizer#date-time-to-ordinal-words

new DateTime(2015, 1, 1).ToOrdinalWords() => "1st January 2015"
new DateTime(2015, 2, 12).ToOrdinalWords() => "12th February 2015"
new DateTime(2015, 3, 22).ToOrdinalWords() => "22nd March 2015"
// for English US locale
new DateTime(2015, 1, 1).ToOrdinalWords() => "January 1st, 2015"
new DateTime(2015, 2, 12).ToOrdinalWords() => "February 12th, 2015"
new DateTime(2015, 3, 22).ToOrdinalWords() => "March 22nd, 2015"

Gleich nach dem Posten wurde mir klar, dass @Gumzle dasselbe vorschlug, aber ich habe seinen Beitrag verpasst, weil er in Codefragmenten vergraben war. Dies ist also seine Antwort mit genügend Code, damit jemand (wie ich), der schnell durchblättert, ihn sehen kann.

Drew Delano
quelle
-2

Eine weitere Option, bei der das letzte Zeichen verwendet wird:

public static string getDayWithSuffix(int day) {
 string d = day.ToString();
 if (day < 11 || day > 13) {
  if (d.EndsWith("1")) {
   d += "st";
  } else if (d.EndsWith("2")) {
   d += "nd";
  } else if (d.EndsWith("3")) {
   d += "rd";
  } else {
   d += "th";
 } else {
  d += "th";
 }
 return d;
}
Jodda
quelle
Danke AakashM, Ihr Recht, ich habe es bearbeitet, um den Fehler zu korrigieren.
Jodda
Nun gibt es 1th, 2thund 3th.
AakashM
-4

In der MSDN-Dokumentation gibt es keinen Hinweis auf eine Kultur, die diese 17 in die 17. umwandeln könnte. Sie sollten dies also manuell über CodeBehind tun. Oder erstellen Sie eine ... Sie könnten eine Funktion erstellen, die dies tut.

public string CustomToString(this DateTime date)
    {
        string dateAsString = string.empty;
        <here wright your code to convert 17 to 17th>
        return dateAsString;
    }
GxG
quelle