我正在编写一个ASP.Net Web Api(2.2)。它适用于报告系统(漂亮的图表和事物)
我想用prev / next按钮提供数据的日/周/月视图。
我的URI路径如下所示:
config.Routes.MapHttpRoute(
name: "Api UriPathExtension Report DateCategory ISO 8601",
routeTemplate: "api/{controller}/{dateCategory}/{iso8601date}.{ext}",
defaults: new
{
ext = RouteParameter.Optional
}
);
我想接受我的iso8601日期并根据dateCategory参数中的值(日/周/月)处理它。
/// <param name="dateCategory">string {Day/Week/Month}</param>
/// <param name="iso8601date">The iso8601 compliant
/// date(2014-10-22),
/// week(2014-W43),
/// or month(2014-10)</param>
DateTime date = DateTime.Parse(iso8601date,null,DateTimeStyles.RoundtripKind);
// 2014-10-22 works fine: 2014-10-22T00:00
// 2014-10 works fine: 2014-10-01T00:00
// 2014-W43 throws error:
An exception of type 'System.FormatException' occurred in mscorlib.dll but was not handled in user code
Additional information: The string was not recognized as a valid DateTime. There is an unknown word starting at index 5.
有没有办法将这个2014-W43解析为我可以在JSON.net序列化中使用的时间。也许与NodaTime?我似乎找不到任何东西。
我可以构建它,但似乎应该有一个解决方案。根据维基百科,它是part of the iso8601 spec。
答案 0 :(得分:3)
虽然它是ISO-8601的一部分,但是没有内置于.NET或Noda Time来解析像"2014-W43"
这样的值,并且有一个很好的理由:
该值代表整个周。解析它的结果数据必须是值的范围。在Noda Time中,Interval
类型表示一系列Instant
值,但没有其他通用范围类型。
更具体地说,整周应该被建模为完全包含范围的时区无知的仅限日期值。使用Noda Time,您将获得一对LocalDate
值。
如果没有Noda Time,您将遇到.NET没有仅限日期数据类型的问题。如果您在午夜时间使用一对DateTime
值,那么您需要在前一天调整结束日期,并使用半开区间逻辑,以便开始日期包含但是结束日期是独家的。
解析本身相当简单,但您无法使用任何现有的解析器。在这里,这应该让你开始。我确定您可以完成您可能需要的任何剩余功能:
public struct LocalDateRange
{
public LocalDate StartDate { get; private set; }
public LocalDate EndDate { get; private set; }
public int LengthInDays
{
get
{
var period = Period.Between(StartDate, EndDate, PeriodUnits.Days);
return (int) period.Days + 1;
}
}
public LocalDateRange(LocalDate startDate, LocalDate endDate)
: this()
{
StartDate = startDate;
EndDate = endDate;
}
public static LocalDateRange ParseFromIsoWeek(string s)
{
var m = Regex.Match(s, @"(\d{4})-W(\d{1,2})");
if (!m.Success)
throw new FormatException();
var year = int.Parse(m.Groups[1].Value);
var weekNumber = int.Parse(m.Groups[2].Value);
// Note: ISO8601 weeks run from Monday through Sunday, per spec
var startDate = LocalDate.FromWeekYearWeekAndDay(
year, weekNumber, IsoDayOfWeek.Monday);
var endDate = LocalDate.FromWeekYearWeekAndDay(
year, weekNumber, IsoDayOfWeek.Sunday);
return new LocalDateRange(startDate, endDate);
}
public override string ToString()
{
return string.Format("[{0} - {1}]", StartDate, EndDate);
}
}
调用它很简单,就像这样:
var week = LocalDateRange.ParseFromIsoWeek("2014-W43");
注意,在这个例子中我没有实现相等或比较功能。