अद्यतन
जॉन सुझाव तुम दोनों momentjs और .NET में NodaTime बीसीएल या IANA डेटा का उपयोग करना होगा। अन्यथा आप विसंगतियां प्राप्त करेंगे। मुझे इसके साथ सहमत होना चाहिए।
आप टाइमज़ोनइन्फो का उपयोग कर 100% विश्वसनीय रूप से .NET 4.5 में कनवर्ट नहीं कर सकते हैं। यहां तक कि यदि आप इसे NodaTime
का उपयोग करके सूचित करते हैं, या नीचे दिए गए TimeZoneToMomentConverter
का उपयोग करते हैं।
मूल जवाब
IANA और Windows समय क्षेत्र डेटा अद्यतन समय के साथ और विभिन्न विवरण के स्तर को की है।
तो तुम नेट और moment.js में बिल्कुल वैसा ही रूपांतरण चाहते हैं - आप (सुझाव के रूप में मैट NodaTime के साथ) हर जगह
- उपयोग IANA के लिए या तो है,
- उपयोग विंडोज समय क्षेत्र हर जगह (परिवर्तित TimeZoneInfo moment.js प्रारूप के नियम)।
हम दूसरे तरीके से गए, और कनवर्टर लागू किया।
यह थ्रेड-सुरक्षित कैश को और अधिक कुशल बनाने के लिए जोड़ता है, क्योंकि यह मूल रूप से तिथियों के माध्यम से loops (TimeZoneInfo
नियमों को स्वयं परिवर्तित करने की कोशिश करने के बजाय)। हमारे परीक्षणों में यह वर्तमान विंडोज टाइमज़ोन को 100% सटीकता के साथ परिवर्तित करता है (GitHub पर परीक्षण देखें)। GitHub पर कोड के लिए
PM> Install-Package Pranas.WindowsTimeZoneToMomentJs
और ब्राउज़र स्रोतों और परीक्षण:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Script.Serialization;
namespace Pranas.WindowsTimeZoneToMomentJs
{
/// <summary>
/// Tool to generates JavaScript that adds MomentJs timezone into moment.tz store.
/// As per http://momentjs.com/timezone/docs/
/// </summary>
public static class TimeZoneToMomentConverter
{
private static readonly DateTimeOffset UnixEpoch = new DateTimeOffset(1970, 1, 1, 0, 0, 0, 0, TimeSpan.Zero);
private static readonly JavaScriptSerializer Serializer = new JavaScriptSerializer();
private static readonly ConcurrentDictionary<Tuple<string, int, int, string>, string> Cache = new ConcurrentDictionary<Tuple<string, int, int, string>, string>();
/// <summary>
/// Generates JavaScript that adds MomentJs timezone into moment.tz store.
/// It caches the result by TimeZoneInfo.Id
/// </summary>
/// <param name="tz">TimeZone</param>
/// <param name="yearFrom">Minimum year</param>
/// <param name="yearTo">Maximum year (inclusive)</param>
/// <param name="overrideName">Name of the generated MomentJs Zone; TimeZoneInfo.Id by default</param>
/// <returns>JavaScript</returns>
public static string GenerateAddMomentZoneScript(TimeZoneInfo tz, int yearFrom, int yearTo, string overrideName = null)
{
var key = new Tuple<string, int, int, string>(tz.Id, yearFrom, yearTo, overrideName);
return Cache.GetOrAdd(key, x =>
{
var untils = EnumerateUntils(tz, yearFrom, yearTo).ToArray();
return string.Format(
@"(function(){{
var z = new moment.tz.Zone();
z.name = {0};
z.abbrs = {1};
z.untils = {2};
z.offsets = {3};
moment.tz._zones[z.name.toLowerCase().replace(/\//g, '_')] = z;
}})();",
Serializer.Serialize(overrideName ?? tz.Id),
Serializer.Serialize(untils.Select(u => "-")),
Serializer.Serialize(untils.Select(u => u.Item1)),
Serializer.Serialize(untils.Select(u => u.Item2)));
});
}
private static IEnumerable<Tuple<long, int>> EnumerateUntils(TimeZoneInfo timeZone, int yearFrom, int yearTo)
{
// return until-offset pairs
int maxStep = (int)TimeSpan.FromDays(7).TotalMinutes;
Func<DateTimeOffset, int> offset = t => (int)TimeZoneInfo.ConvertTime(t, timeZone).Offset.TotalMinutes;
var t1 = new DateTimeOffset(yearFrom, 1, 1, 0, 0, 0, TimeSpan.Zero);
while (t1.Year <= yearTo)
{
int step = maxStep;
var t2 = t1.AddMinutes(step);
while (offset(t1) != offset(t2) && step > 1)
{
step = step/2;
t2 = t1.AddMinutes(step);
}
if (step == 1 && offset(t1) != offset(t2))
{
yield return new Tuple<long, int>((long)(t2 - UnixEpoch).TotalMilliseconds, -offset(t1));
}
t1 = t2;
}
yield return new Tuple<long, int>((long)(t1 - UnixEpoch).TotalMilliseconds, -offset(t1));
}
}
}
तुम भी NuGet के माध्यम से इसे प्राप्त कर सकते हैं:
यह उपकरण का कोड है।
पल-टाइमज़ोन आईएएनए मानक समय क्षेत्र का उपयोग करता है। यदि आपको एक विशिष्ट समय क्षेत्र मिलता है जो लिंक किए गए उत्तर में 'WindowsToIana' फ़ंक्शन का उपयोग करके सही ढंग से मानचित्र नहीं करता है, तो कृपया मुझे बताएं कि कौन सा है। सभी 'TimeZoneInfo' आईडी को मैप करने योग्य होना चाहिए। –
मैट, यह पूरी तरह से सच नहीं है। जबकि moment.js आईएएनए प्रारूप का उपयोग करता है, विंडोज टाइमज़ोन आईएएनए टाइमज़ोन में 100% मैप नहीं किया जा सकता है। कई विसंगतियां होंगी। पूरी तरह से समस्या को हल करने के लिए, हम timeZoneInfo नियमों को moment.js जोन डेटा ऑब्जेक्ट में बदल सकते हैं। तो 100% विंडोज-> Moment.js मैपिंग होगा। – Evgenyt
@Evgenyt - यह वांछित ग्रैन्युलरिटी और इतिहास के स्तर पर निर्भर करता है। एक उपयोगकर्ता के दृष्टिकोण उनके वर्तमान समय क्षेत्र का चयन करके और आधुनिक समय के भीतर डेटा के साथ काम करने से, तो [CLDR मैपिंग] (http://unicode.org/repos/cldr/trunk/common/supplemental/windowsZones.xml) कि यूनिकोड रखरखाव उचित रूप से सटीक हैं, और सभी जोन खिड़कियों-> iana दिशा में मैपबल हैं। यदि आप "प्राथमिक" (001) क्षेत्र चुनने के बजाय देश कोड का उपयोग करते हैं तो आप बेहतर सटीकता भी प्राप्त कर सकते हैं। यह केवल iana-> विंडोज़ दिशा में है कि अपरिवर्तनीय जोन हैं। –