您如何将时间四舍五入到最接近的时间,同时更改 NodaTime 调节器中的日期?
How do you round time to the nearest but also change the date in a NodaTime adjuster?
我必须将各种 LocalDateTime 和 OffsetDateTime 对象四舍五入到最近的时间段(总是分钟)。例如,如果您四舍五入到最接近的 3 分钟,9:58 将四舍五入为 9:57,而 9:59 将四舍五入为 10:00。
这可以通过这样的调节器轻松完成:
public static Func<LocalTime, LocalTime> CreateRounder(TimeSpan d) =>
input =>
{
var delta = input.TickOfDay % d.Ticks;
bool roundUp = delta > d.Ticks / 2;
if (roundUp)
{
var rUpDelta = (d.Ticks - (input.TickOfDay % d.Ticks)) % d.Ticks;
return input.PlusTicks(rUpDelta);
}
return input.PlusTicks(-1 * delta);
};
但是,如果 *DateTime 对象接近午夜,比如 23:59,并且四舍五入到午夜,似乎没有 easy向前更改日期的方法。我考虑过做第二个调整器来向前调整日期,但我不知道我是向下舍入还是向上舍入,或者是否确实需要向前调整。
我是不是漏掉了什么?
编辑:
我正在尝试在 NodaTime 中创建和使用 TimeAdjusters,它们的工作方式与定义的 here.
中的构建类似
如果你像这样创建一个
public static Func<LocalDateTime, LocalDateTime> CreateRounder(TimeSpan d) =>
input =>
{
var delta = input.TickOfDay % d.Ticks;
bool roundUp = delta > d.Ticks / 2;
if (roundUp)
{
var rUpDelta = (d.Ticks - (input.TickOfDay % d.Ticks)) % d.Ticks;
return input.PlusTicks(rUpDelta);
}
return input.PlusTicks(-1 * delta);
};
并像这样使用它:
var ldate1 = new LocalDateTime(2019,5,17,23,59,00);
var rounder = CreateRounder(TimeSpan.FromMinutes(3));
var roundedDate1 = ldate1.With(rounder);
您可以在第 3 行指定错误:
Cannot resolve method 'With(System.Func<NodaTime.LocalDateTime,NodaTime.LocalDateTime>)', candidates are:
NodaTime.OffsetDateTime With(System.Func<NodaTime.LocalDate,NodaTime.LocalDate>) (in struct OffsetDateTime)
NodaTime.OffsetDateTime With(System.Func<NodaTime.LocalTime,NodaTime.LocalTime>) (in struct OffsetDateTime)
我不太确定我是否理解正确,但我会这样处理:
public DateTime RoundTime(DateTime input)
{
DateTime output = new DateTime(input.Year, input.Month, input.Day, input.Hour, 0, 0);
if(input.Minute % 3 == 1)
{
output.AddMinutes(input.Minute - 1);
}
else if (input.Minute % 3 == 2)
{
output.AddMinutes(input.Minute + 1);
}
else
{
output.AddMinutes(input.Minute);
}
return output;
}
看看这是否有帮助
编辑
您可以选择将整个内容更改为 LocalDateTime
而不是 LocalTime
吗?
它看起来像这样:
static void Main(string[] args)
{
List<LocalTime> localTimes = new List<LocalTime>();
localTimes.Add(new LocalTime(23, 57, 25));
localTimes.Add(new LocalTime(23, 58, 25));
localTimes.Add(new LocalTime(23, 59, 25));
localTimes.Add(new LocalTime(11, 57, 25));
localTimes.Add(new LocalTime(12, 58, 25));
localTimes.Add(new LocalTime(15, 59, 25));
IEnumerable<LocalTime> locals = localTimes.Select(CreateRounder(new TimeSpan(0, 3, 0)));
foreach (LocalTime t in locals)
{
Console.WriteLine(t.Hour + ":" + t.Minute + ":" + t.Second);
}
List<LocalDateTime> localDateTimes = new List<LocalDateTime>();
localDateTimes.Add(new LocalDateTime(2019, 5, 20, 23, 58, 25));
localDateTimes.Add(new LocalDateTime(2019, 5, 20, 23, 59, 25));
localDateTimes.Add(new LocalDateTime(2019, 5, 20, 11, 42, 25));
localDateTimes.Add(new LocalDateTime(2019, 5, 20, 5, 58, 25));
IEnumerable<LocalDateTime> ldt = localDateTimes.Select(CreateDateTimeRounder(new TimeSpan(0, 3, 0)));
foreach (LocalDateTime t in ldt)
{
Console.WriteLine(t.Year + "-" + t.Month + "-" + t.Day + " " + t.Hour + ":" + t.Minute + ":" + t.Second);
}
Console.ReadLine();
}
public static Func<LocalTime, LocalTime> CreateRounder(TimeSpan d) =>
input =>
{
var delta = input.TickOfDay % d.Ticks;
bool roundUp = delta > d.Ticks / 2;
if (roundUp)
{
var rUpDelta = (d.Ticks - (input.TickOfDay % d.Ticks)) % d.Ticks;
return input.PlusTicks(rUpDelta);
}
return input.PlusTicks(-1 * delta);
};
public static Func<LocalDateTime, LocalDateTime> CreateDateTimeRounder(TimeSpan d) =>
input =>
{
var delta = input.TickOfDay % d.Ticks;
bool roundUp = delta > d.Ticks / 2;
if (roundUp)
{
var rUpDelta = (d.Ticks - (input.TickOfDay % d.Ticks)) % d.Ticks;
return input.PlusTicks(rUpDelta);
}
return input.PlusTicks(-1 * delta);
};
输出结果如下:
23:57:0
23:57:0
0:0:0
11:57:0
12:57:0
16:0:0
2019-5-20 23:57:0
2019-5-21 0:0:0
2019-5-20 11:42:0
2019-5-20 5:57:0
我必须将各种 LocalDateTime 和 OffsetDateTime 对象四舍五入到最近的时间段(总是分钟)。例如,如果您四舍五入到最接近的 3 分钟,9:58 将四舍五入为 9:57,而 9:59 将四舍五入为 10:00。
这可以通过这样的调节器轻松完成:
public static Func<LocalTime, LocalTime> CreateRounder(TimeSpan d) =>
input =>
{
var delta = input.TickOfDay % d.Ticks;
bool roundUp = delta > d.Ticks / 2;
if (roundUp)
{
var rUpDelta = (d.Ticks - (input.TickOfDay % d.Ticks)) % d.Ticks;
return input.PlusTicks(rUpDelta);
}
return input.PlusTicks(-1 * delta);
};
但是,如果 *DateTime 对象接近午夜,比如 23:59,并且四舍五入到午夜,似乎没有 easy向前更改日期的方法。我考虑过做第二个调整器来向前调整日期,但我不知道我是向下舍入还是向上舍入,或者是否确实需要向前调整。
我是不是漏掉了什么?
编辑: 我正在尝试在 NodaTime 中创建和使用 TimeAdjusters,它们的工作方式与定义的 here.
中的构建类似如果你像这样创建一个
public static Func<LocalDateTime, LocalDateTime> CreateRounder(TimeSpan d) =>
input =>
{
var delta = input.TickOfDay % d.Ticks;
bool roundUp = delta > d.Ticks / 2;
if (roundUp)
{
var rUpDelta = (d.Ticks - (input.TickOfDay % d.Ticks)) % d.Ticks;
return input.PlusTicks(rUpDelta);
}
return input.PlusTicks(-1 * delta);
};
并像这样使用它:
var ldate1 = new LocalDateTime(2019,5,17,23,59,00);
var rounder = CreateRounder(TimeSpan.FromMinutes(3));
var roundedDate1 = ldate1.With(rounder);
您可以在第 3 行指定错误:
Cannot resolve method 'With(System.Func<NodaTime.LocalDateTime,NodaTime.LocalDateTime>)', candidates are:
NodaTime.OffsetDateTime With(System.Func<NodaTime.LocalDate,NodaTime.LocalDate>) (in struct OffsetDateTime)
NodaTime.OffsetDateTime With(System.Func<NodaTime.LocalTime,NodaTime.LocalTime>) (in struct OffsetDateTime)
我不太确定我是否理解正确,但我会这样处理:
public DateTime RoundTime(DateTime input)
{
DateTime output = new DateTime(input.Year, input.Month, input.Day, input.Hour, 0, 0);
if(input.Minute % 3 == 1)
{
output.AddMinutes(input.Minute - 1);
}
else if (input.Minute % 3 == 2)
{
output.AddMinutes(input.Minute + 1);
}
else
{
output.AddMinutes(input.Minute);
}
return output;
}
看看这是否有帮助
编辑
您可以选择将整个内容更改为 LocalDateTime
而不是 LocalTime
吗?
它看起来像这样:
static void Main(string[] args)
{
List<LocalTime> localTimes = new List<LocalTime>();
localTimes.Add(new LocalTime(23, 57, 25));
localTimes.Add(new LocalTime(23, 58, 25));
localTimes.Add(new LocalTime(23, 59, 25));
localTimes.Add(new LocalTime(11, 57, 25));
localTimes.Add(new LocalTime(12, 58, 25));
localTimes.Add(new LocalTime(15, 59, 25));
IEnumerable<LocalTime> locals = localTimes.Select(CreateRounder(new TimeSpan(0, 3, 0)));
foreach (LocalTime t in locals)
{
Console.WriteLine(t.Hour + ":" + t.Minute + ":" + t.Second);
}
List<LocalDateTime> localDateTimes = new List<LocalDateTime>();
localDateTimes.Add(new LocalDateTime(2019, 5, 20, 23, 58, 25));
localDateTimes.Add(new LocalDateTime(2019, 5, 20, 23, 59, 25));
localDateTimes.Add(new LocalDateTime(2019, 5, 20, 11, 42, 25));
localDateTimes.Add(new LocalDateTime(2019, 5, 20, 5, 58, 25));
IEnumerable<LocalDateTime> ldt = localDateTimes.Select(CreateDateTimeRounder(new TimeSpan(0, 3, 0)));
foreach (LocalDateTime t in ldt)
{
Console.WriteLine(t.Year + "-" + t.Month + "-" + t.Day + " " + t.Hour + ":" + t.Minute + ":" + t.Second);
}
Console.ReadLine();
}
public static Func<LocalTime, LocalTime> CreateRounder(TimeSpan d) =>
input =>
{
var delta = input.TickOfDay % d.Ticks;
bool roundUp = delta > d.Ticks / 2;
if (roundUp)
{
var rUpDelta = (d.Ticks - (input.TickOfDay % d.Ticks)) % d.Ticks;
return input.PlusTicks(rUpDelta);
}
return input.PlusTicks(-1 * delta);
};
public static Func<LocalDateTime, LocalDateTime> CreateDateTimeRounder(TimeSpan d) =>
input =>
{
var delta = input.TickOfDay % d.Ticks;
bool roundUp = delta > d.Ticks / 2;
if (roundUp)
{
var rUpDelta = (d.Ticks - (input.TickOfDay % d.Ticks)) % d.Ticks;
return input.PlusTicks(rUpDelta);
}
return input.PlusTicks(-1 * delta);
};
输出结果如下:
23:57:0
23:57:0
0:0:0
11:57:0
12:57:0
16:0:0
2019-5-20 23:57:0
2019-5-21 0:0:0
2019-5-20 11:42:0
2019-5-20 5:57:0