DateTime time = DateTime.UtcNow; //предположим что это вермя которое мы хотим сконвертить к time_t
DateTime unixEpochMidnight = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
long time_t = (long)(time - unixEpochMidnight).TotalSeconds;
* This source code was highlighted with Source Code Highlighter.
Однако недавно передо мной стала задача в том, чтобы разобрать строчку с простым представлением даты и времени, что-то типа "2010-12-15 14:30:00", сконвертировать ее в time_t, но сделать все это нужно было в unmanaged коде на C++. В том чтобы распарсить строку нет ничего сложного. Проблема только в том, чтобы из года, месяца, дня, часа, минут, секунд перейти к time_t. Сложность встает благодаря наличию високосных годов, однако она оказалась довольно просто решаемой.
Ниже приведен C# код программы осуществляющей преобразование к time_t. Почему не C++? Потому, что мне было удобней сначало решить задачку на языке который я лучше знаю, а потом портировать решение на С++
using System;
namespace TimeCs
{
class Program
{
const long SecPerDay = 3600 * 24;
const long A1 = 365 * SecPerDay; //=365 * 86400
const long A2 = SecPerDay / 4; //=21600
const long A3 = -SecPerDay / 100; //=864 Обратите внимание на занк "-"
const long A4 = SecPerDay / 400; //=216
const long SecPerYear = A1 + A2 + A3 + A4;
static long SubYearsToSec(int y1, int y2)
{
long dif1 = SecPerYear * y1 / SecPerDay;
long dif2 = SecPerYear * y2 / SecPerDay;
return (dif1 - dif2) * SecPerDay;
}
static bool IsLeapYear(int year)
{
if (year % 400 == 0)
return true;
if (year % 100 == 0)
return false;
return year % 4 == 0;
}
//month 1..12
//day 1..31
static int ToDayInYear(int year, int month, int day)
{
int daysInFeb = IsLeapYear(year) ? 29 : 28;
int[] daysInMonths = new int[] { 31, daysInFeb, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int stopIdx = month - 1; //1..12 -> 0..11
int ax = 0;
for (int i=0; i<stopIdx; ++i)
{
ax += daysInMonths[i];
}
ax += day;
return ax;
}
static long SubMonthsDaysToSec(int y1, int m1, int d1, int y2, int m2, int d2)
{
long dd1 = ToDayInYear(y1, m1, d1);
long dd2 = ToDayInYear(y2, m2, d2);
return (dd1 - dd2) * SecPerDay;
}
static long Sub(DateTime dt1, DateTime dt2)
{
long dYearsSec = SubYearsToSec(dt1.Year, dt2.Year);
long dDaysSec = SubMonthsDaysToSec(dt1.Year, dt1.Month, dt1.Day, dt2.Year, dt2.Month, dt2.Day);
long dTime = ((long)(dt1.Hour - dt2.Hour) * 60L + (long)(dt1.Minute - dt2.Minute)) * 60L + (long)(dt1.Second - dt2.Second);
return dYearsSec + dDaysSec + dTime;
}
static long ToTime_T(DateTime dateTime)
{
DateTime unixEpochTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
return Sub(dateTime, unixEpochTime);
}
static void Main(string[] args)
{
DateTime now = new DateTime(2010, 12, 15, 14, 48, 30, DateTimeKind.Utc);
long time_t = ToTime_T(now);
Console.WriteLine("time_t = {0}", time_t);
TimeSpan span = now - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
long referenceTime = (long)span.TotalSeconds;
Console.WriteLine("reference time_t = {0}", referenceTime);
}
} //class
} //namespace
* This source code was highlighted with Source Code Highlighter.
Замечу, что в программе есть места, которые можно несколько улучшить, в частности функцию ToDayInYear можно было бы написать и без использования цикла, но предпочту предоставить это читателю.
Комментариев нет:
Отправить комментарий