В переменной типа DateTime лежит дата с временем «19.06.2016 12:13:17», полученное например методом DateTime.Parse из текстовой строки. Хотим мы его выровнять по пятиминутному интервалу, т.е. получить «19.06.2016 12:10:00» или проделать аналогичную операцию с DateStamp. Как это сделать? Делюсь своим способом.
Немного о сути типа DateTime
Значение DateTime измеряется в 100-наносекундных единицах, называемых тактами, и точная дата представляется числом тактов прошедших с 00 часов 00 минут 1 января 0001.
Например, число 628539264000000000 представляет собой 6 октября 1992 года 00:00:00.
Структура DateTime содержит единственное поле, которое и содержит количество прошедших тактов:
private UInt64 dateData;
Получить число тактов можно вызвав свойство DateTime.Ticks
Внимание алготрейдерам! «Ticks» в DateTime.Ticks - это не тиковые сделки, а другое.
Следует так же сказать, что начиная с .NET 2.0, 2 старших бита данного поля указывают тип DateTime: Unspecfied — не задан, Utc — координированное время, Local — местное время, а остальные 62 бита — количество тактов. Мы можем легко запросить эти два бита с помощью свойства Kind.
Перевод тиков DateTime в секунды
Мой способ предполагает работу с секундами, а не с тиками (100 наносекунд), поэтому переведем тики в секунды.
1 тик = 100 наносекунд = 0,1 микросекунд = 0,0001 миллисекунд = 0,0000001 секунд
Чтобы перевести тики в секунды, нужно тики разделить на 10 000 000.
Например:
double sec = date.Ticks / 10000000;
Округление или выравнивание по интервалу
Чтобы выровнять время по пятиминутному интервалу, нужно секунды разделить на 5 * 60, затем отбросить дробную часть, и умножить на 5 * 60.
var newSec = Math.Floor(sec / 5*60) * 5*60;
Почему 5 * 60?
5 – это 5 минут,
60 – это 60 секунд в одной минуте.
Для 10 минутного интервала будет 10 * 60, для 5 секундного – просто 5.
Теперь остается перевести «округленные» секунды в тики, умножив секунды на 10 000 000, и получить новое значение DateTime:
var newDate = new DateTime(newSec * 1000000);
Привожу пример кода для реализации данного алгоритма
static void Main(string[] args) { var date = (new DateTime(2016, 6, 19, 12, 13, 17, 67)); const double divider = 5 * 60 ; // Делитель //переводим такты в секунды //определемя количесво секунд прошедших с 00:00:00 1 января 0001 года нашей эры double sec = date.Ticks / 10000000; //выравниваем секунды по началу интервала var newSec = Math.Floor(sec / divider) * divider; //переводим секунды в такты var newTicks = (long) newSec * 10000000; //получаем новую выровненную дату var newDate = new DateTime(newTicks); Console.WriteLine(date); Console.WriteLine(newDate); Console.ReadKey(); }
Округление в большую сторону
Приведенный код округляет пятиминутки в меньшую сторону, т.е. из «19.06.2016 12:13:17» получится «19.06.2016 12:10:00».
Если надо получить «19.06.2016 12:15:00», то в завершении операций можно воспользоваться методом DateTime.AddMinutes (AddSeconds / AddHours / AddDays) или просто прибавить соответствующее количество секунд к расчету.
Работа с DateStamp
Тут все еще проще. Структура DateStamp хранит не такты, а количество секунд, прошедших с 1 января 1970 года.
Секунды можно получить свойством TimeSpan.TotalSeconds. Переводить такты в секунды уже не требуется. В остальном алгоритм будет очень похож.
Итог: округлять даты типа DateStamp и DateTime в C# или выравнивать их по интервалу совсем не сложно.
Пишите свои комментарии к статье!!!
at 14:20
А подскажите как в шарпе обстоят дела с датами до н.э.? В чем хранить, чем парсиить? Не нашел об это информации в интернетах.