Vraag Tijdzone afkortingen


TimeZoneInfo geeft geen afkorting of een korte naam voor een bepaalde tijdzone. De enige goede manier om dit te doen is om een ​​woordenboek te hebben dat afkortingen voor beide in kaart brengt Timezone.id, StandardName of DaylightName eigenschappen. Alle bronnen die ik heb gebruikt voor een lijst met afkortingen hebben echter verschillende namen voor de tijdzone, d.w.z. niet hetzelfde als in Windows.

Hoe toont u een gebruiker niet een volledige naam, id of een andere naam in .NET? Ik wil de UtcOffset maar Timezone afkorting niet - PST voor Pacific, UTC - voor Universal, EST - voor Eastern Standard en etc. Is er een C # compatibele lijst of database met alle mogelijke tijdzones en hun afkortingen die compatibel zijn met die die TimeZoneInfo.GetSystemTimeZones() geeft jou?


43
2018-03-08 19:47


oorsprong


antwoorden:


Dit is een lastige vereiste, het beste wat je kunt doen is de lijst van je keuze te krijgen en een extensie / helper methode te maken om de afkorting te krijgen voor de gegeven TimeZoneInfo.

Een plaats om te beginnen is om http://www.timeanddate.com/library/abbreviations/timezones/ welke een versie van een lijst heeft die de zones beslaat die ik ken.

Het probleem zou zijn bij het selecteren van een geschikte afkorting waarbij er meer dan een bestaat voor een bepaalde tijdzone. Bijvoorbeeld UTC kan worden weergegeven als UTC of WET (West-Europese tijd) of WEZ (Westeuropäische Zeit) of WT (West-Sahara standaardtijd).

Misschien wilt u het eens zijn met uw belanghebbenden over de naamgevingsconventie die u gaat volgen met de gegeven keuzes.


13
2018-03-08 21:22



GEANTWOORDE ANTWOORD

Mijn oorspronkelijke antwoord is hieronder en is nog steeds geldig. Er is nu echter een eenvoudigere manier om te gebruiken de bibliotheek TimeZoneNames. Na installatie van Nuget, je kunt het volgende doen:

string tzid = theTimeZoneInfo.Id;                // example: "Eastern Standard time"
string lang = CultureInfo.CurrentCulture.Name;   // example: "en-US"
var abbreviations = TZNames.GetAbbreviationsForTimeZone(tzid, lang);

Het resulterende object heeft de eigenschappen die lijken op:

abbreviations.Generic == "ET"
abbreviations.Standard == "EST"
abbreviations.Daylight == "EDT"

U kunt dezelfde bibliotheek ook gebruiken om de volledig gelokaliseerde namen van de tijdzones te krijgen. De bibliotheek gebruikt een ingesloten, op zichzelf staande kopie van de CLDR-gegevens.

ORIGINEEL ANTWOORD

Zoals anderen al zeiden, zijn afkortingen voor tijdzones dubbelzinnig. Maar als u er echt een wilt voor weergave, hebt u een IANA / Olson-tijdzonedatabase nodig.

Je kunt ook van een Windows-tijdzone naar een IANA / Olson-tijdzone en de andere richting gaan. Maar let op: er kunnen meerdere IANA / Olson-zones zijn voor elke Windows-zone. Deze toewijzingen worden gehandhaafd in de CLDR hier.

NodaTime heeft zowel de database als de toewijzingen. U kunt gaan vanaf een .Net DateTime of DateTimeOffset met een TimeZoneInfo, naar een NodaTime Instant en DateTimeZone. Vanaf daar kunt u de afkortingnaam krijgen.

// starting with a .Net TimeZoneInfo
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");

// You need to resolve to a specific instant in time - a noda Instant
// For illustrative purposes, I'll start from a regular .Net UTC DateTime
var dateTime = DateTime.UtcNow;
var instant = Instant.FromDateTimeUtc(dateTime);

// note that if we really wanted to just get the current instant,
// it's better and easier to use the following:
// var instant = SystemClock.Instance.Now;


// Now let's map the Windows time zone to an IANA/Olson time zone,
// using the CLDR mappings embedded in NodaTime.  This will use
// the *primary* mapping from the CLDR - that is, the ones marked
// as "territory 001".

// we need the NodaTime tzdb source.  In NodaTime 1.1.0+:
var tzdbSource = TzdbDateTimeZoneSource.Default;

// in previous NodaTime releases:
// var tzdbSource = new TzdbDateTimeZoneSource("NodaTime.TimeZones.Tzdb");

// map to the appropriate IANA/Olson tzid
var tzid = tzdbSource.MapTimeZoneId(timeZoneInfo);

// get a DateTimeZone from that id
var dateTimeZone = DateTimeZoneProviders.Tzdb[tzid];


// Finally, let's figure out what the abbreviation is
// for the instant and zone we have.

// now get a ZoneInterval for the zone and the instant
var zoneInterval = dateTimeZone.GetZoneInterval(instant);

// finally, you can get the correct time zone abbreviation
var abbreviation = zoneInterval.Name;

// abbreviation will be either PST or PDT depending
// on what instant was provided
Debug.WriteLine(abbreviation);

55
2018-03-08 22:25



Uw vraag geeft niet aan in welke tijdzones uw toepassing moet werken, maar in mijn specifieke geval moet ik me alleen bezighouden met tijdzones in de Verenigde Staten en UTC.

De afkortingen van Amerikaanse tijdzones zijn altijd de eerste tekens van elk woord in de naam van de tijdzone. Bijvoorbeeld, de afkorting van "Mountain Standard Time" is "MST" en de afkorting van "Eastern Daylight Time" is "EDT".

Als u vergelijkbare vereisten hebt, kunt u de tijdzone-afkorting van de lokale tijdzone eenvoudig rechtstreeks afleiden uit de naam van de lokale tijdzone (let op: hier ben ik bezig met het bepalen van de juiste naam op basis van de huidige datum en tijd):

string timeZoneName = TimeZone.CurrentTimeZone.IsDaylightSavingTime(DateTime.Now)
                          ? TimeZone.CurrentTimeZone.DaylightName 
                          : TimeZone.CurrentTimeZone.StandardName;

string timeZoneAbbrev = GetTzAbbreviation(timeZoneName);

De code voor de GetTzInitials() functie is vrij eenvoudig. Een ding dat het vermelden waard is, is dat sommige tijdzones kunnen worden ingesteld op Mexico of Canada, en de namen van de tijdzones voor deze zullen overgaan met de landnaam tussen haakjes, zoals "Pacific Standard Time (Mexico)". Om hiermee om te gaan, worden alle haakjes gegeven gegevens direct doorgegeven. De afkorting die voor het bovenstaande wordt teruggegeven, is "PST (Mexico)", wat voor mij werkt.

string GetTzAbbreviation(string timeZoneName) {
    string output = string.Empty;

    string[] timeZoneWords = timeZoneName.Split(' ');
    foreach (string timeZoneWord in timeZoneWords) {
        if (timeZoneWord[0] != '(') {
            output += timeZoneWord[0];
        } else {
            output += timeZoneWord;
        }
    }
    return output;
}

10
2018-03-29 16:02



Hier is nog een fragment met NodaTime:

NodaTime.ZonedDateTime hereAndNow = NodaTime.SystemClock.Instance.Now.InZone(
    NodaTime.DateTimeZoneProviders.Tzdb.GetSystemDefault());

System.TimeSpan zoneOffset = hereAndNow.ToDateTimeOffset().Offset;

string sTimeDisplay = string.Format("{0:G} {1} (UTC{2}{3:hh\\:mm} {4})", 
    hereAndNow.ToDateTimeOffset(), 
    hereAndNow.Zone.GetZoneInterval(hereAndNow.ToInstant()).Name, 
    zoneOffset < TimeSpan.Zero ? "-" : "+", 
    zoneOffset, 
    hereAndNow.Zone.Id);

Op mijn systeem levert dit op: "4/11/2013 5:03:23 PM CDT (UTC-05: 00 America / Chicago)"

(Dank aan Matt Johnson's antwoord voor de aanwijzing dat de afkorting in TimeZoneInterval leeft)

Het zou gemakkelijker zijn als NodaTime.ZonedDateTime een GetZoneInterval-methode had, maar misschien mis ik iets.


2
2018-04-11 22:20



Ik had een soortgelijk probleem, maar wilde geen bibliotheek van derden gebruiken (zoals de meeste van deze antwoorden suggereren). Als u alleen de tijdzones van .Net wilt ondersteunen en besluit om een ​​opzoektabel te gebruiken, neem dan een kijkje mijn antwoord hier, die leunt op PHP om een ​​lijst met afkortingen te genereren. U kunt het fragment daar en de tabel aanpassen aan uw behoeften.


0
2018-03-22 18:42



Dit is handig voor iedereen die Xamarin voor iOS of Android gebruikt, omdat volgens de documentatie "De weergavenaam is gelokaliseerd op basis van de cultuur die is geïnstalleerd met het Windows-besturingssysteem". Wanneer je dit gebruikt in de Central Time Zone, voor de DateTime "2016-09-01 12:00:00 GMT", geeft deze functie "CDT" terug en dat is precies wat ik nodig had toen ik deze vraag kreeg.

public static string GetTimeZoneAbbreviation(DateTime time)
{
    string timeZoneAbbr;
    if(time.IsDaylightSavingTime() == true)
    {
        timeZoneAbbr = TimeZoneInfo.Local.DaylightName;
    }
    else
    {
        timeZoneAbbr = TimeZoneInfo.Local.StandardName;
    }

    return timeZoneAbbr;
}

0
2017-07-14 14:40