/*****************************************************************************\
* *
* Filename filetime.c *
* *
* Description: MsvcLibX internal routines for managing file times *
* *
* Notes: *
* *
* History: *
* 2014-02-26 JFL Created this module. *
* 2014-03-24 JFL Renamed "statx.h" as the standard <sys/stat.h>. *
* 2014-07-03 JFL Filetime2String: Output time with �s precision if possib. *
* 2016-09-13 JFL Fixed a warning. *
* *
* Copyright 2016 Hewlett Packard Enterprise Development LP *
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
\*****************************************************************************/
#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */
#include "msvcTime.h" /* Define time_t */
#include "sys/msvcStat.h"
#ifdef _MSDOS
/*
Convert a DOS date/time to a Unix time_t
DOS dates start from January 1, 1980. DOS times have a 2-second resolution.
A Unix time_t is the number of 1-second intervals since January 1, 1970.
time_ts are expressed in the GMT time zone. DOS times in the current local time.
*/
time_t Filetime2Timet(uint16_t date, uint16_t time) {
unsigned int year, month, day, hour, minute, second;
struct tm stm;
/* Decode fields */
year = 1980 + ((date & 0xFE00) >> 9);
month = (date & 0x1E0) >> 5;
day = date & 0x1F;
hour = (time & 0xF800) >> 11;
minute = (time & 0x7E0) >> 5;
second = 2 * (time & 0x1F);
stm.tm_year = (int)year - 1900;
stm.tm_mon = (int)month - 1;
stm.tm_mday = (int)day;
stm.tm_hour = (int)hour;
stm.tm_min = (int)minute;
stm.tm_sec = (int)second;
stm.tm_isdst = -1; /* Let mktime decide if DST is in effect or not */
return mktime(&stm);
}
#if 0
/* Older version of the same, trying to generate the time_t manually.
Did not handle DST well */
time_t Filetime2Timet(uint16_t date, uint16_t time) {
unsigned int year, month, day, hour, minute, second;
unsigned int olympiads; /* 4-year periods */
unsigned long t = 0;
/* Decode fields */
year = 1980 + ((date & 0xFE00) >> 9);
month = (date & 0x1E0) >> 5;
day = date & 0x1F;
hour = (time & 0xF800) >> 11;
minute = (time & 0x7E0) >> 5;
second = 2 * (time & 0x1F);
/* Count days */
year -= 1970; /* Start of Unix time_t epoch */
olympiads = year / 4;
year = year % 4;
t = olympiads * (365 + 365 + 366 + 365);
switch (year) {
case 3: t += 366;
case 2: t += 365;
case 1: t += 365;
}
switch (month) {
case 12: t += 30;
case 11: t += 31;
case 10: t += 30;
case 9: t += 31;
case 8: t += 31;
case 7: t += 30;
case 6: t += 31;
case 5: t += 30;
case 4: t += 31;
case 3: t += (year == 2) ? 29 : 28;
case 2: t += 31;
}
t += day-1;
/* Count seconds */
t *= 24;
t += hour;
t *= 60;
t += minute;
t *= 60;
t += second;
/* Correct for the timezone (As DOS returns local times, but time_t is UTC-based) */
t += timezone;
/* Still need correction for DST */
return (time_t)t;
}
#endif
/* Generate a string with the local file time, in the ISO 8601 date/time format */
char *Filetime2String(uint16_t date, uint16_t time, char *pBuf, size_t nBufSize) {
unsigned int year, month, day, hour, minute, second;
/* Decode fields */
year = 1980 + ((date & 0xFE00) >> 9);
month = (date & 0x1E0) >> 5;
day = date & 0x1F;
hour = (time & 0xF800) >> 11;
minute = (time & 0x7E0) >> 5;
second = 2 * (time & 0x1F);
if (nBufSize >= 20) {
sprintf(pBuf, "%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second);
} else {
return "Buffer too small";
}
return pBuf;
}
#endif /* defined(_MSDOS) */
/*****************************************************************************/
#ifdef _WIN32
#include <windows.h>
/*---------------------------------------------------------------------------*\
* *
| Function: LocalFileTime |
| |
| Description: Convert a file GMT time to the local struct tm to display |
| |
| Parameters: const time_t *t The file GMT time_t |
| |
| Returns: struct tm * |
| |
| Notes: This routine is a replacement for Posix' localtime(), |
| using Windows' specific algorithm for generating local |
| file times. |
| |
| Windows displays file times based on the current |
| difference between the local time and GMT. |
| Linux displays file times as the local time when the |
| the file was created. |
| The two times shown may be different if DST was different |
| then and now. (Ex: Displaying in winter the date/time of |
| a file created the previous summer.) |
| The advantage of Windows' method is that apparent |
| relative times will always be correct, even for files |
| created around the winter/summer time transitions. |
| The advantage of Linux method is that the time displayed |
| for a file never changes. The drawback is that files |
| created 1 hour apart around the Winter/summer time |
| transition may be shown with the exact same time. |
| |
| History: |
| 2014-02-26 JFL Created this routine |
* *
\*---------------------------------------------------------------------------*/
/*
Convert a Windows FILETIME to a Unix time_t.
A FILETIME is the number of 100-nanosecond intervals since January 1, 1601.
A time_t is the number of 1-second intervals since January 1, 1970.
Both Windows and Linux file times are expressed in the GMT time zone.
*/
time_t Filetime2Timet(const FILETIME *pFT) {
ULARGE_INTEGER ull;
ull.LowPart = pFT->dwLowDateTime;
ull.HighPart = pFT->dwHighDateTime;
return ull.QuadPart / 10000000ULL - 11644473600ULL;
}
/* Convert a Unix time_t to a Windows FILETIME */
void Timet2Filetime(time_t t, FILETIME *pFT) {
ULARGE_INTEGER ull;
ull.QuadPart = (t * 10000000ULL) + 116444736000000000ULL;
pFT->dwLowDateTime = ull.LowPart;
pFT->dwHighDateTime = ull.HighPart;
return;
}
/*
Convert a Windows FILETIME to a Unix struct timespec.
A FILETIME is the number of 100-nanosecond intervals since January 1, 1601.
A struct timespec contains a time_t and a number of nanoseconds.
Both Windows and Linux file times are expressed in the GMT time zone.
*/
void Filetime2Timespec(const FILETIME *pFT, struct timespec *pTS) {
ULARGE_INTEGER ull;
ull.LowPart = pFT->dwLowDateTime;
ull.HighPart = pFT->dwHighDateTime;
pTS->tv_sec = (time_t)(ull.QuadPart / 10000000ULL - 11644473600ULL);
pTS->tv_nsec = (int)(ull.QuadPart % 10000000ULL) * 100;
return;
}
/* Convert a Unix time_t to a Windows FILETIME */
void Timespec2Filetime(const struct timespec *pTS, FILETIME *pFT) {
ULARGE_INTEGER ull;
ull.QuadPart = (pTS->tv_sec * 10000000ULL) + 116444736000000000ULL + (pTS->tv_nsec / 100);
pFT->dwLowDateTime = ull.LowPart;
pFT->dwHighDateTime = ull.HighPart;
return;
}
/* Convert a file GMT time to a struct tm with the local time to display */
struct tm *LocalFileTime(const time_t *pt) {
FILETIME ft, lft;
time_t lt;
Timet2Filetime(*pt, &ft);
FileTimeToLocalFileTime(&ft, &lft);
lt = Filetime2Timet(&lft);
return gmtime(<);
}
/* Generate a string with the local file time, in the ISO 8601 date/time format */
/* 2014-07-03 Output time with �s precision if possible */
char *Filetime2String(const FILETIME *pFT, char *pBuf, size_t nBufSize) {
FILETIME lft;
SYSTEMTIME sTime;
FileTimeToLocalFileTime(pFT, &lft);
FileTimeToSystemTime(&lft, &sTime);
if (nBufSize >= 20) {
wsprintf(pBuf, "%04d-%02d-%02d %02d:%02d:%02d", sTime.wYear, sTime.wMonth, sTime.wDay,
sTime.wHour, sTime.wMinute, sTime.wSecond);
if (nBufSize >= 27) {
ULARGE_INTEGER uli;
int iFraction; /* Fraction of a second */
uli.LowPart = lft.dwLowDateTime;
uli.HighPart = lft.dwHighDateTime;
iFraction = (int)(uli.QuadPart % 10000000); /* FILETIME has 100ns resolution */
iFraction /= 10; /* Convert 100ns resolution to 1�s resolution */
wsprintf(pBuf+19, ".%06d", iFraction);
} else if (nBufSize >= 24) {
wsprintf(pBuf+19, ".%03d", sTime.wMilliseconds);
}
} else {
return NULL; /* Buffer too small */
}
return pBuf;
}
#endif /* defined(_WIN32) */
C++ 下时间转换(TD)
最新推荐文章于 2024-04-04 11:49:38 发布