【发布时间】:2021-12-13 11:57:50
【问题描述】:
我正在开发一个 .Net Core 3.1 REST Api。
我对接近午夜的日期和时区有疑问。
我以 UTC 格式保存数据库中的所有数据,前端调用 API 以 UTC 格式传递时间。
我目前处于 GTM+2 时区。
我必须将用户执行的“操作”分成不同的日子。
输出示例:
{
days: [
{
day: '2021-10-28',
actions: [
{
id: 123456,
actionType: 1,
startDate: '2021-10-28T12:04:12Z',
endDate: '2021-10-28T13:04:39Z'
},
{
...
}
],
actualHours: 1,
expectedHours: 4
},
{
day: '2021-10-29',
actions: [
{
id: 123467,
actionType: 1,
startDate: '2021-10-29T12:00:45Z',
endDate: '2021-10-29T14:00:40Z'
},
{
...
}
],
actualHours: 2,
expectedHours: 4
}
]
}
当我们的时间接近午夜时会出现问题,因为在数据库中,这一天将被保存为用户输入的前一天。
为一整天添加操作的用户示例。
前端:
- 开始日期:2021-10-28T00:00:00.000
- 结束日期:2021-10-28T23:59:59.999
Json 请求:
{
actionType: 1,
startDate: '2021-10-27T22:00:00.000Z',
endDate: '2021-10-28T21:59:59.999Z'
}
在数据库中,日期将被保存为:
- 开始日期:2021-10-27T22:00:00.000Z
- 结束日期:2021-10-28T21:59:59.999Z
为了采取行动并将它们按天分开,我编写了这段代码 sn-p..
public async Task<IList<DailyActionItem>> GetAsync(string userId, DateTime startDate, DateTime? endDate)
{
// Other code here..
// Get actions by dates
var tActions = await _actionsQuery.GetPeriodAsync(userId, startDate, endDate).ConfigureAwait(false);
// Create a list of days
var days = new List<DailyActionItem>();
// Cycling the range of dates and also adding the missing days
var ed = endDate.HasValue ? endDate.Value.Date : DateTime.UtcNow.Date;
for (var sd = startDate.Date; sd <= ed; sd = sd.AddDays(1))
{
var daily = new DailyActionItem
{
Day = sd.Date,
Actions = new List<ActionItem>()
};
// Other code here..
var actions = tActions
.Where(t => (t.StartDate <= sd.AddDays(1).AddTicks(-1) && t.StartDate >= sd) ||
(t.StartDate <= sd.AddDays(1).AddTicks(-1) && t.EndDate.HasValue && t.EndDate >= sd))
.OrderBy(c => c.StartDate);
// Add actions nella risposta e calcolo i valori attuali
if (actions?.Any() == true)
{
foreach (var action in actions)
{
daily.Actions.Add(new ActionItem
{
Id = action.Id,
ActionType = action.ActionType,
StartDate = action.StartDate,
EndDate = action.EndDate,
Comment = action.Comment
});
}
// Other code here..
}
// Important: calculations made on the day
daily.ActualHours = tActions.Sum(...);
daily.ExpectedHours = contract.ExpectedHours;
// Other code here..
days.Add(daily);
}
return days;
}
调试示例(单日 - 2021 年 10 月 28 日本地 00:00 到本地 23:59):
- 开始日期:2021-10-27T22:00:00.000Z
- 结束日期:2021-10-28T21:59:59.999Z
在 foreach 中:
第一轮 -> sd = 2021-10-27T00:00:00.000Z
最后一轮 -> sd = 2021-10-28T00:00:00.000Z
输出:
{
days: [
{
day: '2021-10-27',
actions: [
{
id: 123987,
actionType: 1,
startDate: '2021-10-27T22:00:00.000Z',
endDate: '2021-10-28T21:59:59.999Z'
}
],
actualHours: 24, // full day, wrong place!
expectedHours: 4
},
{
day: '2021-10-28',
actions: [
{
...
},
{
...
}
]
}
]
}
由于 API 在 UTC 中工作,此代码根据 UTC 值拆分日期。
例如,最后一天输入的“2021-10-28T00:00:00.000 LOCAL”将放置在“2021-10-27 UTC”这一天之下。
我该如何解决这个问题?我错过了什么?
管理这些案例的最佳方法是什么?
理论上结果是正确的。 但是前端读取的数据不正确。
【问题讨论】:
标签: c# asp.net-core datetime .net-core timezone