我在应用程序中使用NodaTime,我需要用户从下拉列表中选择他们的时区.我有以下软要求:
1)该列表仅包含对于真实场所现在和将来合理有效的选择.应过滤掉历史,模糊和通用时区.
2)列表应首先按UTC偏移量排序,然后按时区名称排序.这有希望将它们置于对用户有意义的顺序中.
我写了下面的代码,它确实有效,但并不完全是我所追求的.可能需要调整滤波器,我宁愿让偏移代表基本(非dst)偏移,而不是当前偏移.
建议?建议?
var now = Instant.FromDateTimeUtc(DateTime.UtcNow);
var tzdb = DateTimeZoneProviders.Tzdb;
var list = from id in tzdb.Ids
where id.Contains("/") && !id.StartsWith("etc", StringComparison.OrdinalIgnoreCase)
let tz = tzdb[id]
let offset = tz.GetOffsetFromUtc(now)
orderby offset, id
select new
{
Id = id,
DisplayValue = string.Format("({0}) {1}", offset.ToString("+HH:mm", null), id)
};
// ultimately we build a dropdown list, but for demo purposes you can just dump the results
foreach (var item in list)
Console.WriteLine(item.DisplayValue);
Run Code Online (Sandbox Code Playgroud) 我目前正在编写一个相当简单的应用程序来处理企业的开放/关闭时间,并在试图弄清楚如何正确存储信息时遇到严重困难.
我们的大多数关键功能在很大程度上取决于获得绝对完美的时间,所以显然我希望以最好的方式完成工作!
另外,数据将由用户输入,因此如果底层表示稍微复杂一些(例如,使用TimeSpans来考虑在午夜之后开放),则这对于用户来说是不可见的.
我需要首先存储业务的开放时间,按星期几,与它们相关的时区,例如:
- M: 1000 - 2330
- T: 1000 - 0030
- W: 1900 - 0300
- Th: 2000 - 0300
- F: 2000 - 0800
- Sa: 1000 - 0500
- Su: 1000 - 2300
Run Code Online (Sandbox Code Playgroud)
我目前正在考虑存储它的最佳方法是使用这样的类:
public class OpeningHours
{
ZonedDateTime OpeningTime { get; set; }
Period durationOpen { get; set; }
// TODO: add a method to calculate ClosingTime as a ZonedDateTime
}
Run Code Online (Sandbox Code Playgroud)
但是,这里有两个主要的复杂因素:
我不想存储ZonedDateTime的Year,Month或Date部分 - 我只关心DayOfWeek.
当然,我可以只存储每个值作为第一个周一/周二等1970年1月1日,但这似乎哈克和非常简单的错误之后-作为NodaTime的作者,非常正确,说明这里谈论的BCL日期时间的限制时,实现.我也有一种感觉,如果稍后我们尝试用日期做任何算术,这可能最终会产生奇怪的古怪错误.
我考虑过的另一件事是使用一个有小时/天的表,并让人们突出显示一周中的小时数来选择开放时间,但是你仍然遇到同样的问题而只想存储OpeningTime的DayOfWeek部分.
任何建议都会受到赞赏,花了最近6个小时阅读我们人类代表时间的搞笑愚蠢的方式让我有点沮丧!
在我的第一篇文章后:
在ASP.Net MVC 3 Razor网站上使用NodaTime进行DateTime转换.如何?
我正在努力寻找一种简单的方法来使用NodaTime在本地和UTC(两种方式)之间转换日期/时间.
目前的情况是:
到目前为止我所拥有的:
从UTC转换为本地的扩展(这部分工作正常):
public static DateTime UTCtoLocal(this DateTime dateTime)
{
IDateTimeZoneProvider timeZoneProvider = DateTimeZoneProviders.Tzdb;
var utcTimeZone = timeZoneProvider["UTC"];
var dateTimeFromDb = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond);
var zonedDbDateTime = utcTimeZone.AtLeniently(LocalDateTime.FromDateTime(dateTimeFromDb));
var usersTimezoneId = "Europe/London"; //just an example
var usersTimezone = timeZoneProvider[usersTimezoneId];
var usersZonedDateTime = zonedDbDateTime.WithZone(usersTimezone);
return usersZonedDateTime.ToDateTimeUnspecified();
}
Run Code Online (Sandbox Code Playgroud)
从本地转换回UTC的扩展(这部分是问题):
public static DateTime LocaltoUTC(this DateTime dateTime)
{
IDateTimeZoneProvider timeZoneProvider = DateTimeZoneProviders.Tzdb;
var usersTimezoneId = "Europe/London";
var usersTimezone = timeZoneProvider[usersTimezoneId]; …Run Code Online (Sandbox Code Playgroud) 我目前正在努力确保我们的传统后端可以根据用户的当前时区(或更具体地说是偏移量)支持解析日期时间.我们的服务器处于东部标准时间,我们的大部分日期时间都来自那里.但是,对于位于其他时区的用户,在检索这些日期时间时需要转换到其时区(或者,在这种情况下为偏移).此外,来自用户的日期时间必须在服务器上持久化之前转换为东部标准时间.鉴于我们正在开发的前端是基于Web的,我能够在几分钟内检索用户的偏移量,并将该值传递到标题内的服务层.我看了Noda Time并认为它是一个很棒的API.它确实迫使我在更精致的事情中思考时间,但我仍然不能100%确定我已正确使用它.以下是我为上述转换编写的方法.我测试了它们,它们似乎有效.鉴于上述情况,这看起来是否正确使用了库?我是否正确考虑约会时间?
public static DateTime ConvertToUtcFromEasternTimeZone(DateTime easternDateTime)
{
NodaTime.DateTimeZone easternTimeZone = NodaTime.DateTimeZoneProviders.Tzdb.GetZoneOrNull("America/New_York");
ZoneLocalMappingResolver customResolver = Resolvers.CreateMappingResolver(Resolvers.ReturnLater, Resolvers.ReturnStartOfIntervalAfter);
var easternLocalDateTime = LocalDateTime.FromDateTime(easternDateTime);
var easternZonedDateTime = easternTimeZone.ResolveLocal(easternLocalDateTime, customResolver);
return easternZonedDateTime.ToDateTimeUtc();
}
public static DateTime ConvertToEasternTimeZoneFromUtc(DateTime utcDateTime)
{
NodaTime.DateTimeZone easternTimeZone = NodaTime.DateTimeZoneProviders.Tzdb.GetZoneOrNull("America/New_York");
NodaTime.DateTimeZone utcTimeZone = NodaTime.DateTimeZoneProviders.Tzdb.GetZoneOrNull("UTC");
ZoneLocalMappingResolver customResolver = Resolvers.CreateMappingResolver(Resolvers.ReturnLater, Resolvers.ReturnStartOfIntervalAfter);
var utcLocal = LocalDateTime.FromDateTime(utcDateTime);
var utcZonedDateTime = utcTimeZone.ResolveLocal(utcLocal, customResolver);
var easternZonedDateTime = utcZonedDateTime.ToInstant().InZone(easternTimeZone);
return easternZonedDateTime.ToDateTimeUnspecified();
}
public static DateTime ConvertToUtc(DateTime dateTime, int offsetInMinutes)
{
LocalDateTime localDateTime = LocalDateTime.FromDateTime(dateTime);
var convertedDateTime = localDateTime.PlusMinutes(offsetInMinutes).ToDateTimeUnspecified(); …Run Code Online (Sandbox Code Playgroud) 我开始了解NodaTime并且非常喜欢它.但我还不太清楚(还)!
给定诸如'2014-04-08T09:30:18Z'之类的值,将这样的字符串解析为NodaTime Instant需要哪些步骤?
谢谢!
我已经提供了这种格式"ddMMyyHHmmss"的时间.我知道时间是UTC格式.我想使用NodaTime库将其转换为我当地的时区,但我似乎无法弄明白.我当地的时区目标是新西兰.
这是我尝试过的:
var pattern = LocalDateTimePattern.CreateWithInvariantCulture("ddMMyyHHmmss");
var parseResult = pattern.Parse(utcDateTime);
if (!parseResult.Success)
{
throw new InvalidDataException("Invalid time specified " + date + time);
}
var timeZone = DateTimeZoneProviders.Bcl["New Zealand Standard Time"];
var zone = new ZonedDateTime(
localDateTime,
timeZone,
timeZone.GetUtcOffset(SystemClock.Instance.Now));
return new DateTime(zone.ToInstant().Ticks);
Run Code Online (Sandbox Code Playgroud) 要序列化一个字典,NodaTime.Instance使用json.net到JSON 工作正常,但在反序列化它抛出 Newtonsoft.Json.JsonSerializationException.下面的测试显示了问题:
[Test]
public void DeserializeDictionaryThowsException() {
JsonConverter[] converters = { NodaConverters.IntervalConverter, NodaConverters.InstantConverter };
var dictionary = new Dictionary<Instant, int>() {
{Instant.FromUtc(2012, 1, 2, 3, 4, 5), 0}
};
var json = JsonConvert.SerializeObject(dictionary, Formatting.None, converters);
Assert.AreEqual("{\"2012-01-02T03:04:05Z\":0}", json); //ok
var result = JsonConvert.DeserializeObject<Dictionary<Instant, int>>(json, converters); // throws
}
Run Code Online (Sandbox Code Playgroud)
DeserializeObject抛出:
Newtonsoft.Json.JsonSerializationException:无法将字符串'2012-01-02T03:04:05Z'转换为字典键类型'NodaTime.Instant'.创建TypeConverter以将字符串转换为键类型对象.第1行,第24位.----> Newtonsoft.Json.JsonSerializationException:将值"2012-01-02T03:04:05Z"转换为'NodaTime.Instant'时出错.第1行,第24位.----> System.Exception:无法从System.String转换或转换为NodaTime.Instant.
作为旁注,反序列化DateTime字典可以正常工作.我猜因为String有一个DateTime转换器.
[Test]
public void DeserializeDiciotnaryOfDateTime() // OK
{
var expected = new DateTime(2012, 1, 2, 3, 4, 5, DateTimeKind.Utc);
var dictionary = …Run Code Online (Sandbox Code Playgroud) 我有一种情况,我想将其转换DateTime为Instant.我相信DateTime的Kind会Local.
鉴于它DateTime在一个被调用的变量中time,我在库中找到的最接近的是:
Instant.FromDateTimeUtc(time.ToUniversalTime())
Run Code Online (Sandbox Code Playgroud)
这似乎是合理的,但我想确定这是完全可靠的,并且没有数据丢失或损坏的风险.我不确定这是否是进行转换的最佳方式,或者是否有更可靠的方法.
我查看了NodaTime的BCL转换页面,它说了以下关于这种情况:
请注意,没有转换到
DateTime某种类型Local- 这实际上是系统默认时区,您通常应该明确开始.
如何使用Noda Time获取夏令时的开始和结束日期?下面的功能完成了这个任务,但它非常笨拙,并且正在寻求一个更简单的解决方案.
/// <summary>
/// Gets the start and end of daylight savings time in a given time zone
/// </summary>
/// <param name="tz">The time zone in question</param>
/// <returns>A tuple indicating the start and end of DST</returns>
/// <remarks>Assumes this zone has daylight savings time</remarks>
private Tuple<LocalDateTime, LocalDateTime> GetZoneStartAndEnd(DateTimeZone tz)
{
int thisYear = TimeUtils.SystemLocalDateTime.Year; // Get the year of the current LocalDateTime
// Get January 1, midnight, of this year and next year.
var yearStart = new LocalDateTime(thisYear, …Run Code Online (Sandbox Code Playgroud) 在代码运行的系统上设置的时区中,获取ZonedDateTime(表示当前日期的开始和结束)的正确和更简洁的方法是什么?
以下代码是不是太复杂了?
ZonedDateTime nowInZone = SystemClock.Instance.Now.InZone(DateTimeZoneProviders.Bcl.GetSystemDefault());
ZonedDateTime start = new LocalDateTime(nowInZone.Year, nowInZone.Month, nowInZone.Day, 0, 0, 0).InZoneStrictly(DateTimeZoneProviders.Bcl.GetSystemDefault());
ZonedDateTime end = new LocalDateTime(nowInZone.Year, nowInZone.Month, nowInZone.Day, 23, 59, 59).InZoneStrictly(DateTimeZoneProviders.Bcl.GetSystemDefault());
Run Code Online (Sandbox Code Playgroud)
鉴于这些值,我需要测试另一个ZonedDateTime是否在它们之间.