Elysia Tools
Navigation
C++
Windows Date and Time - C++ Samples
Comprehensive C++ date and time examples for Windows platform including time acquisition, formatting, and parsing operations
Samples
Entries inside this sample collection
Current Time Acquisition
Get system current time with various precision levels and time zone considerations
Difficulty
4/10
Estimated time
20 min
Tags
cpp, datetime, time acquisition, windows
Prerequisites
C++ chrono library, Windows API basics, Time concepts
#include <iostream>
#include <chrono>
#include <ctime>
#include <iomanip>
#include <sstream>
#include <string>
#include <windows.h>
#include <vector>
#include <algorithm>
// 1. Basic time acquisition using C++ chrono
void BasicTimeAcquisition() {
std::cout << "=== Basic Time Acquisition ===" << std::endl;
// System clock time (high resolution)
auto now = std::chrono::system_clock::now();
std::time_t currentTime = std::chrono::system_clock::to_time_t(now);
std::cout << "System clock time:" << std::endl;
std::cout << " Raw time_t: " << currentTime << std::endl;
std::cout << " Ctime format: " << std::ctime(¤tTime);
// Convert to tm structure for detailed manipulation
std::tm localTime;
localtime_s(&localTime, ¤tTime);
std::cout << " Local time components:" << std::endl;
std::cout << " Year: " << (localTime.tm_year + 1900) << std::endl;
std::cout << " Month: " << (localTime.tm_mon + 1) << std::endl;
std::cout << " Day: " << localTime.tm_mday << std::endl;
std::cout << " Hour: " << localTime.tm_hour << std::endl;
std::cout << " Minute: " << localTime.tm_min << std::endl;
std::cout << " Second: " << localTime.tm_sec << std::endl;
std::cout << " Day of week: " << localTime.tm_wday << " (0=Sunday)" << std::endl;
std::cout << " Day of year: " << localTime.tm_yday << std::endl;
std::cout << " Daylight saving: " << (localTime.tm_isdst > 0 ? "Yes" : "No") << std::endl;
// UTC time
std::tm utcTime;
gmtime_s(&utcTime, ¤tTime);
std::cout << " UTC time components:" << std::endl;
std::cout << " Hour: " << utcTime.tm_hour << std::endl;
std::cout << " Minute: " << utcTime.tm_min << std::endl;
std::cout << " Second: " << utcTime.tm_sec << std::endl;
}
// 2. High-precision time measurement
void HighPrecisionTime() {
std::cout << "\n=== High-Precision Time Measurement ===" << std::endl;
// Steady clock (monotonic, suitable for measuring intervals)
auto steadyStart = std::chrono::steady_clock::now();
// Simulate some work
std::vector<int> numbers;
for (int i = 0; i < 1000000; i++) {
numbers.push_back(i * i);
}
std::sort(numbers.begin(), numbers.end());
auto steadyEnd = std::chrono::steady_clock::now();
auto steadyDuration = std::chrono::duration_cast<std::chrono::microseconds>(steadyEnd - steadyStart);
std::cout << "Work completed in: " << steadyDuration.count() << " microseconds" << std::endl;
// High resolution clock
auto highResStart = std::chrono::high_resolution_clock::now();
// Another work simulation
volatile long long sum = 0;
for (int i = 0; i < 10000000; i++) {
sum += i;
}
auto highResEnd = std::chrono::high_resolution_clock::now();
auto highResDuration = std::chrono::duration_cast<std::chrono::nanoseconds>(highResEnd - highResStart);
std::cout << "Calculation completed in: " << highResDuration.count() << " nanoseconds" << std::endl;
// Time conversions
auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(highResDuration);
auto seconds = std::chrono::duration_cast<std::chrono::seconds>(highResDuration);
std::cout << "Time conversions:" << std::endl;
std::cout << " Nanoseconds: " << highResDuration.count() << std::endl;
std::cout << " Microseconds: " << std::chrono::duration_cast<std::chrono::microseconds>(highResDuration).count() << std::endl;
std::cout << " Milliseconds: " << milliseconds.count() << std::endl;
std::cout << " Seconds: " << seconds.count() << std::endl;
}
// 3. Windows-specific time functions
void WindowsTimeFunctions() {
std::cout << "\n=== Windows-Specific Time Functions ===" << std::endl;
// GetSystemTime (UTC time)
SYSTEMTIME systemTime;
GetSystemTime(&systemTime);
std::cout << "GetSystemTime (UTC):" << std::endl;
std::cout << " Year: " << systemTime.wYear << std::endl;
std::cout << " Month: " << systemTime.wMonth << std::endl;
std::cout << " Day: " << systemTime.wDay << std::endl;
std::cout << " Hour: " << systemTime.wHour << std::endl;
std::cout << " Minute: " << systemTime.wMinute << std::endl;
std::cout << " Second: " << systemTime.wSecond << std::endl;
std::cout << " Milliseconds: " << systemTime.wMilliseconds << std::endl;
std::cout << " Day of week: " << systemTime.wDayOfWeek << " (0=Sunday)" << std::endl;
// GetLocalTime (local time)
SYSTEMTIME localTime;
GetLocalTime(&localTime);
std::cout << "\nGetLocalTime (Local):" << std::endl;
std::cout << " Year: " << localTime.wYear << std::endl;
std::cout << " Month: " << localTime.wMonth << std::endl;
std::cout << " Day: " << localTime.wDay << std::endl;
std::cout << " Hour: " << localTime.wHour << std::endl;
std::cout << " Minute: " << localTime.wMinute << std::endl;
std::cout << " Second: " << localTime.wSecond << std::endl;
std::cout << " Milliseconds: " << localTime.wMilliseconds << std::endl;
// GetTickCount (time since system start)
DWORD tickCount = GetTickCount();
std::cout << "\nSystem uptime (GetTickCount): " << tickCount << " milliseconds ("
<< (tickCount / 1000.0 / 3600.0) << " hours)" << std::endl;
// GetTickCount64 for systems that support it
ULONGLONG tickCount64 = GetTickCount64();
std::cout << "System uptime (GetTickCount64): " << tickCount64 << " milliseconds ("
<< (tickCount64 / 1000.0 / 3600.0) << " hours)" << std::endl;
// File time
FILETIME fileTime;
GetSystemTimeAsFileTime(&fileTime);
ULARGE_INTEGER uli;
uli.LowPart = fileTime.dwLowDateTime;
uli.HighPart = fileTime.dwHighDateTime;
std::cout << "\nFile time (100-nanosecond intervals since January 1, 1601):" << std::endl;
std::cout << " Value: " << uli.QuadPart << std::endl;
// Convert file time to system time
SYSTEMTIME fileSystemTime;
FileTimeToSystemTime(&fileTime, &fileSystemTime);
std::cout << " Converted to system time: "
<< fileSystemTime.wYear << "-" << fileSystemTime.wMonth << "-" << fileSystemTime.wDay << " "
<< fileSystemTime.wHour << ":" << fileSystemTime.wMinute << ":" << fileSystemTime.wSecond
<< "." << fileSystemTime.wMilliseconds << std::endl;
}
// 4. Performance counter functions
void PerformanceCounterTime() {
std::cout << "\n=== Performance Counter Time ===" << std::endl;
LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency);
LARGE_INTEGER startCount, endCount;
QueryPerformanceCounter(&startCount);
// Simulate some work
volatile double result = 0.0;
for (int i = 0; i < 10000000; i++) {
result += sin(i * 0.001);
}
QueryPerformanceCounter(&endCount);
double elapsedSeconds = static_cast<double>(endCount.QuadPart - startCount.QuadPart) / frequency.QuadPart;
double elapsedMicroseconds = elapsedSeconds * 1000000.0;
std::cout << "Performance counter timing:" << std::endl;
std::cout << " Frequency: " << frequency.QuadPart << " counts per second" << std::endl;
std::cout << " Start count: " << startCount.QuadPart << std::endl;
std::cout << " End count: " << endCount.QuadPart << std::endl;
std::cout << " Elapsed time: " << elapsedSeconds << " seconds" << std::endl;
std::cout << " Elapsed time: " << elapsedMicroseconds << " microseconds" << std::endl;
std::cout << " Calculation result: " << result << std::endl;
}
// 5. Time zone information
void TimeZoneInformation() {
std::cout << "\n=== Time Zone Information ===" << std::endl;
TIME_ZONE_INFORMATION timeZoneInfo;
DWORD result = GetTimeZoneInformation(&timeZoneInfo);
std::cout << "Time zone information:" << std::endl;
std::cout << " Bias from UTC: " << timeZoneInfo.Bias << " minutes" << std::endl;
// Convert bias to hours and minutes
int hours = abs(timeZoneInfo.Bias) / 60;
int minutes = abs(timeZoneInfo.Bias) % 60;
char sign = timeZoneInfo.Bias <= 0 ? '+' : '-';
std::cout << " UTC offset: " << sign << std::setw(2) << std::setfill('0') << hours
<< ":" << std::setw(2) << minutes << std::setfill(' ') << std::endl;
// Standard time
std::cout << "\nStandard time:" << std::endl;
std::wcout << L" Name: " << timeZoneInfo.StandardName << std::endl;
std::cout << " Bias: " << timeZoneInfo.StandardBias << " minutes" << std::endl;
std::cout << " Date: " << timeZoneInfo.StandardDate.wMonth << "/"
<< timeZoneInfo.StandardDate.wDay << " at "
<< timeZoneInfo.StandardDate.wHour << ":"
<< timeZoneInfo.StandardDate.wMinute << std::endl;
// Daylight time
std::cout << "\nDaylight saving time:" << std::endl;
std::wcout << L" Name: " << timeZoneInfo.DaylightName << std::endl;
std::cout << " Bias: " << timeZoneInfo.DaylightBias << " minutes" << std::endl;
std::cout << " Date: " << timeZoneInfo.DaylightDate.wMonth << "/"
<< timeZoneInfo.DaylightDate.wDay << " at "
<< timeZoneInfo.DaylightDate.wHour << ":"
<< timeZoneInfo.DaylightDate.wMinute << std::endl;
// Current time zone status
switch (result) {
case TIME_ZONE_ID_STANDARD:
std::cout << "\nCurrent status: Standard time" << std::endl;
break;
case TIME_ZONE_ID_DAYLIGHT:
std::cout << "\nCurrent status: Daylight saving time" << std::endl;
break;
case TIME_ZONE_ID_UNKNOWN:
std::cout << "\nCurrent status: Unknown" << std::endl;
break;
default:
std::cout << "\nCurrent status: Error (" << result << ")" << std::endl;
break;
}
}
// 6. Timer and alarm functions
void TimerAndAlarm() {
std::cout << "\n=== Timer and Alarm Functions ===" << std::endl;
// Create a timer queue
HANDLE hTimerQueue = CreateTimerQueue();
if (hTimerQueue == NULL) {
std::cout << "Failed to create timer queue" << std::endl;
return;
}
// Timer callback function would be defined elsewhere
// For demonstration, we'll show the setup
HANDLE hTimer;
std::cout << "Timer queue created successfully" << std::endl;
// In a real application, you would create a timer like this:
/*
if (CreateTimerQueueTimer(&hTimer, hTimerQueue,
(WAITORTIMERCALLBACK)TimerCallback,
NULL, 1000, 2000, 0)) {
std::cout << "Timer created successfully" << std::endl;
} else {
std::cout << "Failed to create timer" << std::endl;
}
*/
// Sleep for demonstration
std::cout << "Sleeping for 2 seconds..." << std::endl;
Sleep(2000);
std::cout << "Sleep completed" << std::endl;
// Cleanup
if (hTimerQueue) {
DeleteTimerQueueEx(hTimerQueue, NULL);
std::cout << "Timer queue deleted" << std::endl;
}
// Alternative: Use Waitable Timer
HANDLE hWaitableTimer = CreateWaitableTimer(NULL, FALSE, NULL);
if (hWaitableTimer) {
std::cout << "Waitable timer created" << std::endl;
// Set timer to fire after 1 second
LARGE_INTEGER dueTime;
dueTime.QuadPart = -10000000LL; // 1 second in 100-nanosecond intervals (negative = relative)
if (SetWaitableTimer(hWaitableTimer, &dueTime, 0, NULL, NULL, FALSE)) {
std::cout << "Timer set to fire in 1 second" << std::endl;
// Wait for timer
if (WaitForSingleObject(hWaitableTimer, 2000) == WAIT_OBJECT_0) {
std::cout << "Timer fired!" << std::endl;
} else {
std::cout << "Timer wait timeout" << std::endl;
}
}
CloseHandle(hWaitableTimer);
}
}
// 7. Time measurement utility class
class TimeMeasure {
private:
std::chrono::high_resolution_clock::time_point startTime;
std::string operationName;
public:
TimeMeasure(const std::string& name) : operationName(name) {
startTime = std::chrono::high_resolution_clock::now();
std::cout << "Starting measurement: " << operationName << std::endl;
}
~TimeMeasure() {
auto endTime = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(endTime - startTime);
std::cout << "Completed: " << operationName << " - "
<< duration.count() << " microseconds" << std::endl;
}
// Get elapsed time without destroying the object
double getElapsedMicroseconds() const {
auto currentTime = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(currentTime - startTime);
return static_cast<double>(duration.count());
}
double getElapsedMilliseconds() const {
return getElapsedMicroseconds() / 1000.0;
}
double getElapsedSeconds() const {
return getElapsedMicroseconds() / 1000000.0;
}
};
void demonstrateTimeMeasurement() {
std::cout << "\n=== Time Measurement Utility ===" << std::endl;
// Example 1: Automatic measurement with destructor
{
TimeMeasure measure("Vector operations");
std::vector<int> vec;
for (int i = 0; i < 100000; i++) {
vec.push_back(i);
}
std::sort(vec.begin(), vec.end());
std::reverse(vec.begin(), vec.end());
}
// Example 2: Manual timing
TimeMeasure measure("Loop operations");
for (int i = 0; i < 50000000; i++) {
volatile int x = i * i + i;
(void)x; // Suppress unused variable warning
}
std::cout << "Manual check - elapsed: " << measure.getElapsedMilliseconds() << " ms" << std::endl;
}
// 8. Multiple time format comparison
void compareTimeFormats() {
std::cout << "\n=== Multiple Time Format Comparison ===" << std::endl;
auto now = std::chrono::system_clock::now();
std::time_t currentTime = std::chrono::system_clock::to_time_t(now);
// Format 1: ISO 8601
std::tm utcTime;
gmtime_s(&utcTime, ¤tTime);
std::ostringstream isoStream;
isoStream << std::put_time(&utcTime, "%Y-%m-%dT%H:%M:%SZ");
std::string isoFormat = isoStream.str();
std::cout << "ISO 8601 format: " << isoFormat << std::endl;
// Format 2: RFC 2822
std::ostringstream rfcStream;
rfcStream << std::put_time(&utcTime, "%a, %d %b %Y %H:%M:%S GMT");
std::string rfcFormat = rfcStream.str();
std::cout << "RFC 2822 format: " << rfcFormat << std::endl;
// Format 3: Local time with milliseconds
std::tm localTime;
localtime_s(&localTime, ¤tTime);
// Get milliseconds
auto timeMs = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
auto epochMs = timeMs.time_since_epoch().count();
auto epochSec = currentTime;
int milliseconds = static_cast<int>(epochMs % 1000);
std::ostringstream localStream;
localStream << std::put_time(&localTime, "%Y-%m-%d %H:%M:%S")
<< "." << std::setfill('0') << std::setw(3) << milliseconds;
std::string localFormat = localStream.str();
std::cout << "Local format: " << localFormat << std::endl;
// Format 4: Simple readable format
std::ostringstream readableStream;
readableStream << std::put_time(&localTime, "%B %d, %Y at %I:%M:%S %p");
std::string readableFormat = readableStream.str();
std::cout << "Readable format: " << readableFormat << std::endl;
// Format 5: Compact numeric format
std::ostringstream compactStream;
compactStream << std::put_time(&localTime, "%Y%m%d_%H%M%S");
std::string compactFormat = compactStream.str();
std::cout << "Compact format: " << compactFormat << std::endl;
// Windows SYSTEMTIME to string
SYSTEMTIME systemTime;
GetLocalTime(&systemTime);
std::ostringstream windowsStream;
windowsStream << systemTime.wYear << "-"
<< std::setfill('0') << std::setw(2) << systemTime.wMonth << "-"
<< std::setfill('0') << std::setw(2) << systemTime.wDay << " "
<< std::setfill('0') << std::setw(2) << systemTime.wHour << ":"
<< std::setfill('0') << std::setw(2) << systemTime.wMinute << ":"
<< std::setfill('0') << std::setw(2) << systemTime.wSecond << "."
<< std::setfill('0') << std::setw(3) << systemTime.wMilliseconds;
std::string windowsFormat = windowsStream.str();
std::cout << "Windows format: " << windowsFormat << std::endl;
}
// 9. Time calculation and arithmetic
void timeCalculations() {
std::cout << "\n=== Time Calculations and Arithmetic ===" << std::endl;
// Current time
auto now = std::chrono::system_clock::now();
std::time_t currentTime = std::chrono::system_clock::to_time_t(now);
std::cout << "Current time: " << std::ctime(¤tTime);
// Add 24 hours
auto tomorrow = now + std::chrono::hours(24);
std::time_t tomorrowTime = std::chrono::system_clock::to_time_t(tomorrow);
std::cout << "Tomorrow (24 hours later): " << std::ctime(&tomorrowTime);
// Subtract 7 days
auto weekAgo = now - std::chrono::hours(24 * 7);
std::time_t weekAgoTime = std::chrono::system_clock::to_time_t(weekAgo);
std::cout << "A week ago: " << std::ctime(&weekAgoTime);
// Add 1 hour and 30 minutes
auto future = now + std::chrono::hours(1) + std::chrono::minutes(30);
std::time_t futureTime = std::chrono::system_clock::to_time_t(future);
std::cout << "1 hour 30 minutes later: " << std::ctime(&futureTime);
// Calculate difference between times
auto startTime = now - std::chrono::hours(2);
auto endTime = now + std::chrono::hours(3);
auto duration = endTime - startTime;
auto hours = std::chrono::duration_cast<std::chrono::hours>(duration);
auto minutes = std::chrono::duration_cast<std::chrono::minutes>(duration - hours);
std::cout << "Duration between times: " << hours.count() << " hours, "
<< minutes.count() << " minutes" << std::endl;
// Calculate time of day (seconds since midnight)
std::tm localTime;
localtime_s(&localTime, ¤tTime);
int secondsSinceMidnight = localTime.tm_hour * 3600 +
localTime.tm_min * 60 +
localTime.tm_sec;
std::cout << "Seconds since midnight: " << secondsSinceMidnight << std::endl;
std::cout << "Time remaining until midnight: " << (24 * 3600 - secondsSinceMidnight) << " seconds" << std::endl;
// Calculate week number
char weekBuffer[10];
strftime(weekBuffer, sizeof(weekBuffer), "%U", &localTime);
int weekNumber = std::atoi(weekBuffer);
std::cout << "Week number of year: " << weekNumber << std::endl;
// Calculate day of year
std::cout << "Day of year: " << (localTime.tm_yday + 1) << std::endl;
}
int main() {
std::cout << "=== C++ Windows Date and Time - Time Acquisition ===" << std::endl;
std::cout << "Demonstrating comprehensive time acquisition techniques\n" << std::endl;
try {
// Run all time acquisition examples
BasicTimeAcquisition();
HighPrecisionTime();
WindowsTimeFunctions();
PerformanceCounterTime();
TimeZoneInformation();
TimerAndAlarm();
demonstrateTimeMeasurement();
compareTimeFormats();
timeCalculations();
std::cout << "\nAll time acquisition examples completed successfully!" << std::endl;
} catch (const std::exception& e) {
std::cerr << "Unexpected error: " << e.what() << std::endl;
return 1;
}
return 0;
}Time Formatting and Display
Convert time objects to various string formats with localization and custom formatting options
Difficulty
5/10
Estimated time
25 min
Tags
cpp, datetime, formatting, windows
Prerequisites
C++ iomanip, Time patterns, Locale concepts, Windows API
#include <iostream>
#include <chrono>
#include <ctime>
#include <iomanip>
#include <sstream>
#include <string>
#include <vector>
#include <map>
#include <windows.h>
#include <locale>
// 1. Basic time formatting
void BasicTimeFormatting() {
std::cout << "=== Basic Time Formatting ===" << std::endl;
auto now = std::chrono::system_clock::now();
std::time_t currentTime = std::chrono::system_clock::to_time_t(now);
// Local time structure
std::tm localTime;
localtime_s(&localTime, ¤tTime);
std::cout << "Basic formatting using put_time:" << std::endl;
// ISO 8601 format
std::ostringstream isoStream;
isoStream << std::put_time(&localTime, "%Y-%m-%dT%H:%M:%S");
std::cout << "ISO 8601: " << isoStream.str() << std::endl;
// US format
std::ostringstream usStream;
usStream << std::put_time(&localTime, "%m/%d/%Y %I:%M:%S %p");
std::cout << "US format: " << usStream.str() << std::endl;
// European format
std::ostringstream euStream;
euStream << std::put_time(&localTime, "%d.%m.%Y %H:%M:%S");
std::cout << "European format: " << euStream.str() << std::endl;
// Readable format
std::ostringstream readableStream;
readableStream << std::put_time(&localTime, "%A, %B %d, %Y");
std::cout << "Readable: " << readableStream.str() << std::endl;
// Short date
std::ostringstream shortStream;
shortStream << std::put_time(&localTime, "%x");
std::cout << "Short date: " << shortStream.str() << std::endl;
// Long date
std::ostringstream longStream;
longStream << std::put_time(&localTime, "%c");
std::cout << "Long date: " << longStream.str() << std::endl;
// Time only
std::ostringstream timeOnlyStream;
timeOnlyStream << std::put_time(&localTime, "%X");
std::cout << "Time only: " << timeOnlyStream.str() << std::endl;
// Custom format
std::ostringstream customStream;
customStream << std::put_time(&localTime, "Year: %Y, Week: %U, Day: %j");
std::cout << "Custom: " << customStream.str() << std::endl;
}
// 2. Advanced formatting with milliseconds and microseconds
void HighResolutionFormatting() {
std::cout << "\n=== High-Resolution Formatting ===" << std::endl;
auto now = std::chrono::system_clock::now();
auto timeMs = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
auto timeUs = std::chrono::time_point_cast<std::chrono::microseconds>(now);
std::time_t currentTime = std::chrono::system_clock::to_time_t(now);
std::tm localTime;
localtime_s(&localTime, ¤tTime);
// Get milliseconds and microseconds
auto epochMs = timeMs.time_since_epoch().count();
auto epochUs = timeUs.time_since_epoch().count();
auto epochSec = currentTime;
int milliseconds = static_cast<int>(epochMs % 1000);
int microseconds = static_cast<int>(epochUs % 1000000);
std::cout << "High-resolution formatting:" << std::endl;
// With milliseconds
std::ostringstream msStream;
msStream << std::put_time(&localTime, "%Y-%m-%d %H:%M:%S")
<< "." << std::setfill('0') << std::setw(3) << milliseconds;
std::cout << "With milliseconds: " << msStream.str() << std::endl;
// With microseconds
std::ostringstream usStream;
usStream << std::put_time(&localTime, "%Y-%m-%d %H:%M:%S")
<< "." << std::setfill('0') << std::setw(6) << microseconds;
std::cout << "With microseconds: " << usStream.str() << std::endl;
// Fractional seconds
std::ostringstream fractionStream;
fractionStream << std::put_time(&localTime, "%H:%M:%S")
<< "." << std::fixed << std::setprecision(6)
<< (microseconds / 1000000.0);
std::cout << "Fractional seconds: " << fractionStream.str() << std::endl;
}
// 3. Windows API formatting
void WindowsAPIFormatting() {
std::cout << "\n=== Windows API Formatting ===" << std::endl;
SYSTEMTIME systemTime;
GetLocalTime(&systemTime);
std::cout << "Windows SYSTEMTIME formatting:" << std::endl;
// Manual formatting
std::cout << "Manual format: "
<< systemTime.wYear << "-"
<< std::setfill('0') << std::setw(2) << systemTime.wMonth << "-"
<< std::setfill('0') << std::setw(2) << systemTime.wDay << " "
<< std::setfill('0') << std::setw(2) << systemTime.wHour << ":"
<< std::setfill('0') << std::setw(2) << systemTime.wMinute << ":"
<< std::setfill('0') << std::setw(2) << systemTime.wSecond << "."
<< std::setfill('0') << std::setw(3) << systemTime.wMilliseconds << std::endl;
// GetDateFormat and GetTimeFormat
SYSTEMTIME dateOnly = systemTime;
SYSTEMTIME timeOnly = systemTime;
// Format date
TCHAR dateBuffer[100];
int dateResult = GetDateFormat(
LOCALE_USER_DEFAULT,
DATE_LONGDATE,
&dateOnly,
NULL,
dateBuffer,
sizeof(dateBuffer) / sizeof(TCHAR)
);
if (dateResult > 0) {
std::wcout << L"Long date format: " << dateBuffer << std::endl;
}
// Format time
TCHAR timeBuffer[100];
int timeResult = GetTimeFormat(
LOCALE_USER_DEFAULT,
TIME_FORCE24HOURFORMAT,
&timeOnly,
NULL,
timeBuffer,
sizeof(timeBuffer) / sizeof(TCHAR)
);
if (timeResult > 0) {
std::wcout << L"24-hour time format: " << timeBuffer << std::endl;
}
// Short date format
TCHAR shortDateBuffer[100];
GetDateFormat(
LOCALE_USER_DEFAULT,
DATE_SHORTDATE,
&dateOnly,
NULL,
shortDateBuffer,
sizeof(shortDateBuffer) / sizeof(TCHAR)
);
std::wcout << L"Short date format: " << shortDateBuffer << std::endl;
// 12-hour time format
TCHAR time12Buffer[100];
GetTimeFormat(
LOCALE_USER_DEFAULT,
0, // Default time format
&timeOnly,
NULL,
time12Buffer,
sizeof(time12Buffer) / sizeof(TCHAR)
);
std::wcout << L"12-hour time format: " << time12Buffer << std::endl;
}
// 4. Localization and locale-specific formatting
void LocaleFormatting() {
std::cout << "\n=== Localization and Locale Formatting ===" << std::endl;
auto now = std::chrono::system_clock::now();
std::time_t currentTime = std::chrono::system_clock::to_time_t(now);
std::tm localTime;
localtime_s(&localTime, ¤tTime);
// Different locale examples
std::vector<std::pair<std::string, std::string>> locales = {
{"", "Default locale"},
{"en_US.UTF-8", "US English"},
{"en_GB.UTF-8", "British English"},
{"de_DE.UTF-8", "German"},
{"fr_FR.UTF-8", "French"},
{"ja_JP.UTF-8", "Japanese"}
};
for (const auto& [localeName, description] : locales) {
std::cout << "\n" << description << ":" << std::endl;
try {
// Set locale for this iteration
std::ostringstream dateStream, timeStream;
if (localeName.empty()) {
// Use system default
dateStream << std::put_time(&localTime, "%x");
timeStream << std::put_time(&localTime, "%X");
} else {
// Try to set specific locale
try {
std::locale::global(std::locale(localeName));
dateStream << std::put_time(&localTime, "%x");
timeStream << std::put_time(&localTime, "%X");
} catch (const std::exception&) {
std::cout << " Locale not available, using default" << std::endl;
dateStream << std::put_time(&localTime, "%x");
timeStream << std::put_time(&localTime, "%X");
}
}
std::cout << " Date: " << dateStream.str() << std::endl;
std::cout << " Time: " << timeStream.str() << std::endl;
} catch (const std::exception& e) {
std::cout << " Error: " << e.what() << std::endl;
}
}
// Reset to default locale
try {
std::locale::global(std::locale(""));
} catch (...) {
// Ignore locale reset errors
}
}
// 5. Custom formatting functions
class TimeFormatter {
public:
// Format with custom pattern
static std::string formatWithPattern(const std::tm& timeInfo, const std::string& pattern) {
std::ostringstream result;
std::string currentPattern = pattern;
// Simple pattern replacement
std::map<std::string, std::string> replacements = {
{"YYYY", std::to_string(timeInfo.tm_year + 1900)},
{"YY", std::to_string((timeInfo.tm_year + 1900) % 100)},
{"MM", std::to_string(timeInfo.tm_mon + 1)},
{"DD", std::to_string(timeInfo.tm_mday)},
{"hh", std::to_string(timeInfo.tm_hour)},
{"mm", std::to_string(timeInfo.tm_min)},
{"ss", std::to_string(timeInfo.tm_sec)},
{"DAY", getDayName(timeInfo.tm_wday)},
{"MONTH", getMonthName(timeInfo.tm_mon)}
};
// Pad single digits with leading zero
std::map<std::string, std::string> paddedReplacements;
for (const auto& [key, value] : replacements) {
if (value.length() == 1) {
paddedReplacements[key] = "0" + value;
} else {
paddedReplacements[key] = value;
}
}
// Apply replacements
for (const auto& [key, value] : paddedReplacements) {
size_t pos = currentPattern.find(key);
while (pos != std::string::npos) {
currentPattern.replace(pos, key.length(), value);
pos = currentPattern.find(key, pos);
}
}
result << currentPattern;
return result.str();
}
// Format time ago
static std::string formatTimeAgo(std::chrono::system_clock::time_point pastTime) {
auto now = std::chrono::system_clock::now();
auto duration = now - pastTime;
auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
if (seconds < 60) {
return std::to_string(seconds) + " seconds ago";
}
auto minutes = seconds / 60;
if (minutes < 60) {
return std::to_string(minutes) + " minute" + (minutes == 1 ? "" : "s") + " ago";
}
auto hours = minutes / 60;
if (hours < 24) {
return std::to_string(hours) + " hour" + (hours == 1 ? "" : "s") + " ago";
}
auto days = hours / 24;
if (days < 30) {
return std::to_string(days) + " day" + (days == 1 ? "" : "s") + " ago";
}
auto months = days / 30;
if (months < 12) {
return std::to_string(months) + " month" + (months == 1 ? "" : "s") + " ago";
}
auto years = months / 12;
return std::to_string(years) + " year" + (years == 1 ? "" : "s") + " ago";
}
// Format duration
static std::string formatDuration(std::chrono::milliseconds duration) {
auto totalSeconds = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
auto milliseconds = duration.count() % 1000;
auto hours = totalSeconds / 3600;
auto minutes = (totalSeconds % 3600) / 60;
auto seconds = totalSeconds % 60;
std::ostringstream result;
if (hours > 0) {
result << hours << "h " << minutes << "m " << seconds << "." << std::setfill('0')
<< std::setw(3) << milliseconds << "s";
} else if (minutes > 0) {
result << minutes << "m " << seconds << "." << std::setfill('0')
<< std::setw(3) << milliseconds << "s";
} else {
result << seconds << "." << std::setfill('0') << std::setw(3) << milliseconds << "s";
}
return result.str();
}
private:
static std::string getDayName(int dayOfWeek) {
static const std::vector<std::string> dayNames = {
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
};
return (dayOfWeek >= 0 && dayOfWeek < 7) ? dayNames[dayOfWeek] : "Unknown";
}
static std::string getMonthName(int month) {
static const std::vector<std::string> monthNames = {
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
};
return (month >= 0 && month < 12) ? monthNames[month] : "Unknown";
}
};
void demonstrateCustomFormatting() {
std::cout << "\n=== Custom Formatting Functions ===" << std::endl;
auto now = std::chrono::system_clock::now();
std::time_t currentTime = std::chrono::system_clock::to_time_t(now);
std::tm localTime;
localtime_s(&localTime, ¤tTime);
std::cout << "Custom pattern formatting:" << std::endl;
std::cout << " YYYY-MM-DD hh:mm:ss: "
<< TimeFormatter::formatWithPattern(localTime, "YYYY-MM-DD hh:mm:ss") << std::endl;
std::cout << " DD/MM/YYYY: "
<< TimeFormatter::formatWithPattern(localTime, "DD/MM/YYYY") << std::endl;
std::cout << " MONTH DD, YYYY: "
<< TimeFormatter::formatWithPattern(localTime, "MONTH DD, YYYY") << std::endl;
std::cout << " DAY, MONTH DD, hh:mm: "
<< TimeFormatter::formatWithPattern(localTime, "DAY, MONTH DD, hh:mm") << std::endl;
// Time ago examples
auto pastTime = now - std::chrono::minutes(5);
std::cout << "\nTime ago examples:" << std::endl;
std::cout << " 5 minutes ago: " << TimeFormatter::formatTimeAgo(pastTime) << std::endl;
pastTime = now - std::chrono::hours(2);
std::cout << " 2 hours ago: " << TimeFormatter::formatTimeAgo(pastTime) << std::endl;
pastTime = now - std::chrono::hours(24 * 3);
std::cout << " 3 days ago: " << TimeFormatter::formatTimeAgo(pastTime) << std::endl;
pastTime = now - std::chrono::hours(24 * 30 * 2);
std::cout << " 2 months ago: " << TimeFormatter::formatTimeAgo(pastTime) << std::endl;
// Duration formatting
std::cout << "\nDuration formatting:" << std::endl;
auto duration1 = std::chrono::milliseconds(1500);
auto duration2 = std::chrono::milliseconds(125000);
auto duration3 = std::chrono::milliseconds(3661500);
std::cout << " 1500ms: " << TimeFormatter::formatDuration(duration1) << std::endl;
std::cout << " 125000ms: " << TimeFormatter::formatDuration(duration2) << std::endl;
std::cout << " 3661500ms: " << TimeFormatter::formatDuration(duration3) << std::endl;
}
// 6. Log timestamp formatting
void logTimestampFormatting() {
std::cout << "\n=== Log Timestamp Formatting ===" << std::endl;
auto now = std::chrono::system_clock::now();
auto timeMs = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
std::time_t currentTime = std::chrono::system_clock::to_time_t(now);
std::tm localTime;
localtime_s(&localTime, ¤tTime);
auto epochMs = timeMs.time_since_epoch().count();
int milliseconds = static_cast<int>(epochMs % 1000);
// Different log formats
std::vector<std::pair<std::string, std::string>> logFormats = {
{"Standard", "[%Y-%m-%d %H:%M:%S]"},
{"With Milliseconds", "[%Y-%m-%d %H:%M:%S.%e]"},
{"ISO 8601", "[%Y-%m-%dT%H:%M:%S.%eZ]"},
{"Compact", "[%Y%m%d_%H%M%S]"},
{"Detailed", "[%Y-%m-%d %H:%M:%S.%e %Z]"},
{"RFC 3339", "[%Y-%m-%dT%H:%M:%S.%e%z]"}
};
std::cout << "Log timestamp formats:" << std::endl;
for (const auto& [name, pattern] : logFormats) {
std::ostringstream logStream;
// Replace %e with milliseconds for our custom formatting
std::string customPattern = pattern;
size_t pos = customPattern.find("%e");
if (pos != std::string::npos) {
customPattern.replace(pos, 2, std::to_string(milliseconds));
}
logStream << std::put_time(&localTime, customPattern.c_str());
std::cout << " " << name << ": " << logStream.str() << " [LOG MESSAGE]" << std::endl;
}
// Computer-readable format (Unix timestamp with milliseconds)
double unixTimestampMs = static_cast<double>(currentTime) * 1000.0 + milliseconds;
std::cout << "\nUnix timestamp (ms): " << std::fixed << std::setprecision(0)
<< unixTimestampMs << std::endl;
// High-resolution timestamp
auto highRes = std::chrono::high_resolution_clock::now();
auto highResEpoch = highRes.time_since_epoch().count();
std::cout << "High-res timestamp: " << highResEpoch << " nanoseconds since epoch" << std::endl;
}
// 7. Colorized and styled formatting
void styledFormatting() {
std::cout << "\n=== Styled Formatting ===" << std::endl;
auto now = std::chrono::system_clock::now();
std::time_t currentTime = std::chrono::system_clock::to_time_t(now);
std::tm localTime;
localtime_s(&localTime, ¤tTime);
// For demonstration purposes, we'll show styled text with markers
// In a real console application, you could use ANSI color codes
std::cout << "Styled timestamp examples (using markers):" << std::endl;
// Digital clock style
std::ostringstream digitalClock;
digitalClock << "[" << std::setfill('0') << std::setw(2) << localTime.tm_hour
<< ":" << std::setfill('0') << std::setw(2) << localTime.tm_min
<< ":" << std::setfill('0') << std::setw(2) << localTime.tm_sec << "]";
std::cout << " Digital clock: " << digitalClock.str() << std::endl;
// Binary time (for fun)
std::cout << " Binary time: ";
std::cout << "[" << std::bitset<6>(localTime.tm_hour).to_string()
<< ":" << std::bitset<6>(localTime.tm_min).to_string()
<< ":" << std::bitset<6>(localTime.tm_sec).to_string() << "]" << std::endl;
// Calendar style
std::ostringstream calendar;
calendar << std::put_time(&localTime, "%B %d, %Y");
std::cout << " Calendar: " << calendar.str() << std::endl;
// Military time
std::ostringstream military;
military << std::setfill('0') << std::setw(2) << localTime.tm_hour
<< std::setfill('0') << std::setw(2) << localTime.tm_min
<< "HRS";
std::cout << " Military: " << military.str() << std::endl;
// Word clock
std::string timeWords = convertToWords(localTime.tm_hour, localTime.tm_min);
std::cout << " Word clock: " << timeWords << std::endl;
// Progress bar style (representing time of day)
int dayProgress = (localTime.tm_hour * 3600 + localTime.tm_min * 60 + localTime.tm_sec) * 100 / 86400;
std::cout << " Day progress: [";
for (int i = 0; i < 20; i++) {
if (i < dayProgress / 5) {
std::cout << "=";
} else {
std::cout << " ";
}
}
std::cout << "] " << dayProgress << "%" << std::endl;
}
// Helper function to convert time to words
std::string convertToWords(int hour, int minute) {
static const std::vector<std::string> numbers = {
"twelve", "one", "two", "three", "four", "five",
"six", "seven", "eight", "nine", "ten", "eleven"
};
hour = hour % 12;
if (hour == 0) hour = 12;
std::string result = numbers[hour % 12];
if (minute == 0) {
result += " o'clock";
} else if (minute <= 30) {
if (minute == 15) {
result = "a quarter past " + result;
} else if (minute == 30) {
result = "half past " + result;
} else {
result = numbers[minute] + " past " + result;
}
} else {
int nextHour = hour % 12 + 1;
if (nextHour == 13) nextHour = 1;
if (minute == 45) {
result = "a quarter to " + numbers[nextHour % 12];
} else {
result = numbers[60 - minute] + " to " + numbers[nextHour % 12];
}
}
return result;
}
int main() {
std::cout << "=== C++ Windows Date and Time - Time Formatting ===" << std::endl;
std::cout << "Demonstrating comprehensive time formatting and display techniques\n" << std::endl;
try {
// Run all formatting examples
BasicTimeFormatting();
HighResolutionFormatting();
WindowsAPIFormatting();
LocaleFormatting();
demonstrateCustomFormatting();
logTimestampFormatting();
styledFormatting();
std::cout << "\nAll time formatting examples completed successfully!" << std::endl;
} catch (const std::exception& e) {
std::cerr << "Unexpected error: " << e.what() << std::endl;
return 1;
}
return 0;
}Time Parsing and Validation
Parse various time string formats and validate time inputs with error handling
Difficulty
7/10
Estimated time
30 min
Tags
cpp, datetime, parsing, validation, windows
Prerequisites
Advanced C++ regex, Time formats, Error handling patterns, Validation techniques
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <regex>
#include <chrono>
#include <ctime>
#include <iomanip>
#include <map>
#include <stdexcept>
#include <algorithm>
#include <functional>
// Custom exception for time parsing errors
class TimeParseException : public std::runtime_error {
public:
TimeParseException(const std::string& message) : std::runtime_error(message) {}
};
// 1. Basic time parsing functions
class TimeParser {
public:
// Parse ISO 8601 format: YYYY-MM-DDTHH:MM:SS
static std::tm parseISO8601(const std::string& timeString) {
std::tm timeInfo = {};
std::istringstream iss(timeString);
iss >> std::get_time(&timeInfo, "%Y-%m-%dT%H:%M:%S");
if (iss.fail()) {
throw TimeParseException("Failed to parse ISO 8601 format: " + timeString);
}
return timeInfo;
}
// Parse US format: MM/DD/YYYY HH:MM:SS
static std::tm parseUSFormat(const std::string& timeString) {
std::tm timeInfo = {};
std::istringstream iss(timeString);
iss >> std::get_time(&timeInfo, "%m/%d/%Y %H:%M:%S");
if (iss.fail()) {
throw TimeParseException("Failed to parse US format: " + timeString);
}
return timeInfo;
}
// Parse European format: DD.MM.YYYY HH:MM:SS
static std::tm parseEuropeanFormat(const std::string& timeString) {
std::tm timeInfo = {};
std::istringstream iss(timeString);
iss >> std::get_time(&timeInfo, "%d.%m.%Y %H:%M:%S");
if (iss.fail()) {
throw TimeParseException("Failed to parse European format: " + timeString);
}
return timeInfo;
}
// Parse flexible format with multiple patterns
static std::tm parseFlexible(const std::string& timeString) {
std::vector<std::string> patterns = {
"%Y-%m-%d %H:%M:%S",
"%Y-%m-%dT%H:%M:%S",
"%m/%d/%Y %H:%M:%S",
"%d.%m.%Y %H:%M:%S",
"%d-%b-%Y %H:%M:%S",
"%b %d %H:%M:%S %Y",
"%x %X",
"%c"
};
std::tm timeInfo = {};
for (const auto& pattern : patterns) {
std::istringstream iss(timeString);
iss >> std::get_time(&timeInfo, pattern.c_str());
if (!iss.fail()) {
return timeInfo;
}
}
throw TimeParseException("Failed to parse time with any known pattern: " + timeString);
}
// Parse time-only string (HH:MM:SS)
static std::tm parseTimeOnly(const std::string& timeString) {
std::tm timeInfo = {};
// Set date to current date
auto now = std::chrono::system_clock::now();
std::time_t currentTime = std::chrono::system_clock::to_time_t(now);
localtime_s(&timeInfo, ¤tTime);
std::istringstream iss(timeString);
iss >> std::get_time(&timeInfo, "%H:%M:%S");
if (iss.fail()) {
throw TimeParseException("Failed to parse time: " + timeString);
}
return timeInfo;
}
// Parse date-only string (YYYY-MM-DD)
static std::tm parseDateOnly(const std::string& dateString) {
std::tm timeInfo = {};
// Set time to midnight
timeInfo.tm_hour = 0;
timeInfo.tm_min = 0;
timeInfo.tm_sec = 0;
std::istringstream iss(dateString);
iss >> std::get_time(&timeInfo, "%Y-%m-%d");
if (iss.fail()) {
// Try other date formats
iss.clear();
iss.str(dateString);
iss >> std::get_time(&timeInfo, "%m/%d/%Y");
}
if (iss.fail()) {
iss.clear();
iss.str(dateString);
iss >> std::get_time(&timeInfo, "%d.%m.%Y");
}
if (iss.fail()) {
throw TimeParseException("Failed to parse date: " + dateString);
}
return timeInfo;
}
};
void demonstrateBasicParsing() {
std::cout << "=== Basic Time Parsing ===" << std::endl;
std::vector<std::pair<std::string, std::string>> testStrings = {
{"ISO 8601", "2023-12-25T14:30:45"},
{"US Format", "12/25/2023 14:30:45"},
{"European Format", "25.12.2023 14:30:45"},
{"Flexible", "Dec 25 14:30:45 2023"}
};
for (const auto& [name, timeString] : testStrings) {
try {
std::tm timeInfo;
if (name == "ISO 8601") {
timeInfo = TimeParser::parseISO8601(timeString);
} else if (name == "US Format") {
timeInfo = TimeParser::parseUSFormat(timeString);
} else if (name == "European Format") {
timeInfo = TimeParser::parseEuropeanFormat(timeString);
} else {
timeInfo = TimeParser::parseFlexible(timeString);
}
std::cout << name << " (" << timeString << "): ";
std::cout << (timeInfo.tm_year + 1900) << "-"
<< (timeInfo.tm_mon + 1) << "-"
<< timeInfo.tm_mday << " "
<< timeInfo.tm_hour << ":"
<< timeInfo.tm_min << ":"
<< timeInfo.tm_sec << std::endl;
} catch (const TimeParseException& e) {
std::cout << name << ": Error - " << e.what() << std::endl;
}
}
// Time-only and date-only parsing
std::cout << "\nTime-only and date-only parsing:" << std::endl;
try {
std::tm timeOnly = TimeParser::parseTimeOnly("14:30:45");
std::cout << "Time only: " << timeOnly.tm_hour << ":"
<< timeOnly.tm_min << ":" << timeOnly.tm_sec << std::endl;
std::tm dateOnly = TimeParser::parseDateOnly("2023-12-25");
std::cout << "Date only: " << (dateOnly.tm_year + 1900) << "-"
<< (dateOnly.tm_mon + 1) << "-" << dateOnly.tm_mday << std::endl;
} catch (const TimeParseException& e) {
std::cout << "Error: " << e.what() << std::endl;
}
}
// 2. Advanced parsing with regex
class RegexTimeParser {
public:
struct ParsedTime {
int year = 0;
int month = 0;
int day = 0;
int hour = 0;
int minute = 0;
int second = 0;
int millisecond = 0;
std::string timezone;
bool isValid = false;
};
// Parse with flexible regex patterns
static ParsedTime parseWithRegex(const std::string& timeString) {
ParsedTime result;
// Define regex patterns for different time formats
std::vector<std::pair<std::regex, std::function<void(std::smatch&)>>> patterns = {
// ISO 8601 with timezone: 2023-12-25T14:30:45.123+05:30
{
std::regex(R"(^(d{4})-(d{2})-(d{2})T(d{2}):(d{2}):(d{2})(?:.(d{3}))?(?:([+-]d{2}:d{2})|Z)?$)"),
[&result](std::smatch& match) {
result.year = std::stoi(match[1].str());
result.month = std::stoi(match[2].str());
result.day = std::stoi(match[3].str());
result.hour = std::stoi(match[4].str());
result.minute = std::stoi(match[5].str());
result.second = std::stoi(match[6].str());
if (match[7].matched) {
result.millisecond = std::stoi(match[7].str());
}
if (match[8].matched) {
result.timezone = match[8].str();
} else if (match[0].str().back() == 'Z') {
result.timezone = "UTC";
}
result.isValid = true;
}
},
// Natural language: December 25, 2023 at 2:30 PM
{
std::regex(R"(^(w+)s+(d{1,2}),s+(d{4})s+ats+(d{1,2}):(d{2})(?::(d{2}))?s*(AM|PM)?$)"),
[&result](std::smatch& match) {
static std::map<std::string, int> monthMap = {
{"January", 1}, {"February", 2}, {"March", 3}, {"April", 4},
{"May", 5}, {"June", 6}, {"July", 7}, {"August", 8},
{"September", 9}, {"October", 10}, {"November", 11}, {"December", 12},
{"Jan", 1}, {"Feb", 2}, {"Mar", 3}, {"Apr", 4}, {"May", 5}, {"Jun", 6},
{"Jul", 7}, {"Aug", 8}, {"Sep", 9}, {"Oct", 10}, {"Nov", 11}, {"Dec", 12}
};
result.month = monthMap[match[1].str()];
result.day = std::stoi(match[2].str());
result.year = std::stoi(match[3].str());
result.hour = std::stoi(match[4].str());
result.minute = std::stoi(match[5].str());
if (match[6].matched) {
result.second = std::stoi(match[6].str());
}
if (match[7].matched) {
std::string period = match[7].str();
if (period == "PM" && result.hour != 12) {
result.hour += 12;
} else if (period == "AM" && result.hour == 12) {
result.hour = 0;
}
}
result.isValid = true;
}
},
// Relative time: "yesterday at 3 PM", "in 2 hours"
{
std::regex(R"(^(yesterday|today|tomorrow)(?:s+ats+(d{1,2})(?::(d{2}))?s*(AM|PM))?$)"),
[&result](std::smatch& match) {
auto now = std::chrono::system_clock::now();
std::time_t currentTime = std::chrono::system_clock::to_time_t(now);
std::tm localTime;
localtime_s(&localTime, ¤tTime);
result.year = localTime.tm_year + 1900;
result.month = localTime.tm_mon + 1;
result.day = localTime.tm_mday;
result.hour = localTime.tm_hour;
result.minute = localTime.tm_min;
result.second = localTime.tm_sec;
std::string dayModifier = match[1].str();
if (dayModifier == "yesterday") {
result.day -= 1;
} else if (dayModifier == "tomorrow") {
result.day += 1;
}
if (match[2].matched) {
result.hour = std::stoi(match[2].str());
result.minute = match[3].matched ? std::stoi(match[3].str()) : 0;
result.second = 0;
if (match[4].matched) {
std::string period = match[4].str();
if (period == "PM" && result.hour != 12) {
result.hour += 12;
} else if (period == "AM" && result.hour == 12) {
result.hour = 0;
}
}
}
result.isValid = true;
}
}
};
// Try each pattern
for (const auto& [pattern, processor] : patterns) {
std::smatch match;
if (std::regex_search(timeString, match, pattern)) {
processor(match);
if (result.isValid) {
break;
}
}
}
return result;
}
// Convert ParsedTime to std::tm
static std::tm toTm(const ParsedTime& parsedTime) {
std::tm timeInfo = {};
timeInfo.tm_year = parsedTime.year - 1900;
timeInfo.tm_mon = parsedTime.month - 1;
timeInfo.tm_mday = parsedTime.day;
timeInfo.tm_hour = parsedTime.hour;
timeInfo.tm_min = parsedTime.minute;
timeInfo.tm_sec = parsedTime.second;
// Normalize the time structure
std::time_t normalizedTime = std::mktime(&timeInfo);
localtime_s(&timeInfo, &normalizedTime);
return timeInfo;
}
};
void demonstrateRegexParsing() {
std::cout << "\n=== Advanced Regex Parsing ===" << std::endl;
std::vector<std::string> testStrings = {
"2023-12-25T14:30:45.123+05:30",
"December 25, 2023 at 2:30 PM",
"tomorrow at 3 PM",
"yesterday",
"2024-01-01T00:00:00Z"
};
for (const auto& timeString : testStrings) {
auto parsed = RegexTimeParser::parseWithRegex(timeString);
std::cout << "Parsing: '" << timeString << "'" << std::endl;
if (parsed.isValid) {
std::cout << " Result: " << parsed.year << "-"
<< std::setfill('0') << std::setw(2) << parsed.month << "-"
<< std::setfill('0') << std::setw(2) << parsed.day << " "
<< std::setfill('0') << std::setw(2) << parsed.hour << ":"
<< std::setfill('0') << std::setw(2) << parsed.minute << ":"
<< std::setfill('0') << std::setw(2) << parsed.second;
if (parsed.millisecond > 0) {
std::cout << "." << std::setfill('0') << std::setw(3) << parsed.millisecond;
}
if (!parsed.timezone.empty()) {
std::cout << " " << parsed.timezone;
}
std::cout << std::endl;
// Convert to std::tm and verify
try {
std::tm timeInfo = RegexTimeParser::toTm(parsed);
std::ostringstream oss;
oss << std::put_time(&timeInfo, "%Y-%m-%d %H:%M:%S");
std::cout << " Normalized: " << oss.str() << std::endl;
} catch (const std::exception& e) {
std::cout << " Normalization error: " << e.what() << std::endl;
}
} else {
std::cout << " Failed to parse" << std::endl;
}
std::cout << std::endl;
}
}
// 3. Time validation
class TimeValidator {
public:
struct ValidationResult {
bool isValid;
std::vector<std::string> errors;
std::vector<std::string> warnings;
};
// Validate parsed time components
static ValidationResult validateTime(const RegexTimeParser::ParsedTime& parsedTime) {
ValidationResult result;
result.isValid = true;
// Basic range validation
if (parsedTime.year < 1900 || parsedTime.year > 2100) {
result.errors.push_back("Year out of valid range (1900-2100)");
result.isValid = false;
}
if (parsedTime.month < 1 || parsedTime.month > 12) {
result.errors.push_back("Month out of valid range (1-12)");
result.isValid = false;
}
if (parsedTime.day < 1 || parsedTime.day > 31) {
result.errors.push_back("Day out of valid range (1-31)");
result.isValid = false;
}
if (parsedTime.hour < 0 || parsedTime.hour > 23) {
result.errors.push_back("Hour out of valid range (0-23)");
result.isValid = false;
}
if (parsedTime.minute < 0 || parsedTime.minute > 59) {
result.errors.push_back("Minute out of valid range (0-59)");
result.isValid = false;
}
if (parsedTime.second < 0 || parsedTime.second > 59) {
result.errors.push_back("Second out of valid range (0-59)");
result.isValid = false;
}
if (parsedTime.millisecond < 0 || parsedTime.millisecond > 999) {
result.errors.push_back("Millisecond out of valid range (0-999)");
result.isValid = false;
}
// Validate day against month
if (parsedTime.isValid) {
int maxDay = getDaysInMonth(parsedTime.year, parsedTime.month);
if (parsedTime.day > maxDay) {
result.errors.push_back("Day " + std::to_string(parsedTime.day) +
" is invalid for month " + std::to_string(parsedTime.month) +
" (max: " + std::to_string(maxDay) + ")");
result.isValid = false;
}
}
// Check for suspicious but valid dates
if (parsedTime.month == 2 && parsedTime.day == 29) {
bool isLeapYear = (parsedTime.year % 4 == 0 && parsedTime.year % 100 != 0) ||
(parsedTime.year % 400 == 0);
if (!isLeapYear) {
result.errors.push_back("February 29 is invalid in non-leap year");
result.isValid = false;
}
}
// Warnings (doesn't make it invalid)
if (parsedTime.year == 1900) {
result.warnings.push_back("Year 1900 might indicate missing or default date");
}
if (parsedTime.month == 0 || parsedTime.day == 0) {
result.warnings.push_back("Zero month or day might indicate parsing error");
}
if (parsedTime.hour == 0 && parsedTime.minute == 0 && parsedTime.second == 0) {
result.warnings.push_back("Midnight time might be default/empty");
}
return result;
}
// Validate time string format
static ValidationResult validateFormat(const std::string& timeString) {
ValidationResult result;
result.isValid = true;
// Basic format checks
if (timeString.empty()) {
result.errors.push_back("Empty time string");
result.isValid = false;
return result;
}
// Check for invalid characters
std::string validChars = "0123456789-:.T +ZAPMMDaytuehYonlgirjfbvskc";
for (char c : timeString) {
if (validChars.find(c) == std::string::npos && !std::isspace(c)) {
result.warnings.push_back("Potentially invalid character: '" + std::string(1, c) + "'");
}
}
// Check format patterns
bool hasDate = false;
bool hasTime = false;
bool hasSeparator = false;
// Date patterns
if (timeString.find('-') != std::string::npos ||
timeString.find('/') != std::string::npos ||
timeString.find('.') != std::string::npos) {
hasDate = true;
}
// Time patterns
if (timeString.find(':') != std::string::npos) {
hasTime = true;
}
// ISO 8601 separator
if (timeString.find('T') != std::string::npos) {
hasSeparator = true;
}
if (hasDate && hasTime && !hasSeparator && timeString.find(' ') == std::string::npos) {
result.warnings.push_back("Date and time without separator");
}
return result;
}
private:
// Get number of days in month
static int getDaysInMonth(int year, int month) {
static const int daysInMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (month == 2) {
// Check for leap year
bool isLeapYear = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
return isLeapYear ? 29 : 28;
}
if (month >= 1 && month <= 12) {
return daysInMonth[month - 1];
}
return 31; // Default
}
};
void demonstrateValidation() {
std::cout << "\n=== Time Validation ===" << std::endl;
std::vector<std::string> testStrings = {
"2023-02-29T12:00:00", // Invalid: 2023 is not leap year
"2024-02-30T12:00:00", // Invalid: February never has 30 days
"2023-13-01T12:00:00", // Invalid: Month 13
"2023-12-32T12:00:00", // Invalid: Day 32
"2023-12-25T25:00:00", // Invalid: Hour 25
"2023-12-25T12:60:00", // Invalid: Minute 60
"2024-02-29T12:00:00", // Valid: Leap year
"2023-12-25T00:00:00", // Valid but warning: Midnight default
"0000-01-01T00:00:00", // Valid but warning: Year 1900 default
"invalid-time-string" // Invalid format
};
for (const auto& timeString : testStrings) {
std::cout << "\nValidating: '" << timeString << "'" << std::endl;
// First validate format
auto formatResult = TimeValidator::validateFormat(timeString);
if (!formatResult.isValid) {
std::cout << " Format invalid:" << std::endl;
for (const auto& error : formatResult.errors) {
std::cout << " ERROR: " << error << std::endl;
}
continue;
}
if (!formatResult.warnings.empty()) {
std::cout << " Format warnings:" << std::endl;
for (const auto& warning : formatResult.warnings) {
std::cout << " WARNING: " << warning << std::endl;
}
}
// Try to parse and validate components
try {
auto parsed = RegexTimeParser::parseWithRegex(timeString);
if (!parsed.isValid) {
std::cout << " Parsing failed" << std::endl;
continue;
}
auto validationResult = TimeValidator::validateTime(parsed);
if (validationResult.isValid) {
std::cout << " VALID: " << parsed.year << "-"
<< std::setfill('0') << std::setw(2) << parsed.month << "-"
<< std::setfill('0') << std::setw(2) << parsed.day << " "
<< std::setfill('0') << std::setw(2) << parsed.hour << ":"
<< std::setfill('0') << std::setw(2) << parsed.minute << ":"
<< std::setfill('0') << std::setw(2) << parsed.second << std::endl;
} else {
std::cout << " INVALID:" << std::endl;
for (const auto& error : validationResult.errors) {
std::cout << " ERROR: " << error << std::endl;
}
}
if (!validationResult.warnings.empty()) {
std::cout << " Warnings:" << std::endl;
for (const auto& warning : validationResult.warnings) {
std::cout << " WARNING: " << warning << std::endl;
}
}
} catch (const std::exception& e) {
std::cout << " Parsing error: " << e.what() << std::endl;
}
}
}
// 4. Bulk parsing and error handling
void bulkParsingDemo() {
std::cout << "\n=== Bulk Parsing with Error Handling ===" << std::endl;
std::vector<std::string> timeStrings = {
"2023-12-25 14:30:00",
"invalid-format",
"2023-02-29 00:00:00", // Invalid: not leap year
"",
"2023-13-01 12:00:00", // Invalid month
"2024-02-29T12:30:45Z", // Valid
"not-a-time",
"2023-12-25 25:00:00" // Invalid hour
};
std::vector<std::tm> successfulParses;
std::vector<std::pair<std::string, std::string>> failures;
std::cout << "Parsing " << timeStrings.size() << " time strings..." << std::endl;
for (const auto& timeString : timeStrings) {
try {
std::tm timeInfo = TimeParser::parseFlexible(timeString);
successfulParses.push_back(timeInfo);
std::cout << "✓ Successfully parsed: '" << timeString << "'" << std::endl;
} catch (const TimeParseException& e) {
failures.emplace_back(timeString, e.what());
std::cout << "✗ Failed to parse: '" << timeString << "' - " << e.what() << std::endl;
}
}
std::cout << "\nResults:" << std::endl;
std::cout << "Successfully parsed: " << successfulParses.size() << std::endl;
std::cout << "Failed to parse: " << failures.size() << std::endl;
if (!successfulParses.empty()) {
std::cout << "\nSuccessfully parsed times:" << std::endl;
for (const auto& timeInfo : successfulParses) {
std::ostringstream oss;
oss << std::put_time(&timeInfo, "%Y-%m-%d %H:%M:%S");
std::cout << " " << oss.str() << std::endl;
}
}
if (!failures.empty()) {
std::cout << "\nFailed parses:" << std::endl;
for (const auto& [input, error] : failures) {
std::cout << " '" << input << "' → " << error << std::endl;
}
}
}
// 5. Conversion between time representations
void demonstrateTimeConversion() {
std::cout << "\n=== Time Representation Conversion ===" << std::endl;
// Start with a known time string
std::string timeString = "2023-12-25T14:30:45";
try {
// Parse to std::tm
std::tm timeInfo = TimeParser::parseISO8601(timeString);
// Convert to different representations
std::cout << "Original: " << timeString << std::endl;
// To time_t
std::time_t timeT = std::mktime(&timeInfo);
std::cout << "time_t: " << timeT << std::endl;
// To system_clock time_point
auto systemTime = std::chrono::system_clock::from_time_t(timeT);
std::cout << "system_clock: " << systemTime.time_since_epoch().count() << " ticks" << std::endl;
// To FILETIME (Windows)
FILETIME fileTime;
SYSTEMTIME systemTimeWin;
// Convert tm to SYSTEMTIME
systemTimeWin.wYear = timeInfo.tm_year + 1900;
systemTimeWin.wMonth = timeInfo.tm_mon + 1;
systemTimeWin.wDay = timeInfo.tm_mday;
systemTimeWin.wHour = timeInfo.tm_hour;
systemTimeWin.wMinute = timeInfo.tm_min;
systemTimeWin.wSecond = timeInfo.tm_sec;
systemTimeWin.wMilliseconds = 0;
systemTimeWin.wDayOfWeek = timeInfo.tm_wday;
if (SystemTimeToFileTime(&systemTimeWin, &fileTime)) {
ULARGE_INTEGER uli;
uli.LowPart = fileTime.dwLowDateTime;
uli.HighPart = fileTime.dwHighDateTime;
std::cout << "FILETIME: " << uli.QuadPart << " (100-nanosecond intervals)" << std::endl;
}
// Back to string in different formats
std::ostringstream isoStream;
isoStream << std::put_time(&timeInfo, "%Y-%m-%dT%H:%M:%S");
std::cout << "Back to ISO string: " << isoStream.str() << std::endl;
std::ostringstream usStream;
usStream << std::put_time(&timeInfo, "%m/%d/%Y %I:%M:%S %p");
std::cout << "US format: " << usStream.str() << std::endl;
std::ostringstream readableStream;
readableStream << std::put_time(&timeInfo, "%A, %B %d, %Y at %I:%M %p");
std::cout << "Readable: " << readableStream.str() << std::endl;
} catch (const std::exception& e) {
std::cout << "Error: " << e.what() << std::endl;
}
}
int main() {
std::cout << "=== C++ Windows Date and Time - Time Parsing ===" << std::endl;
std::cout << "Demonstrating comprehensive time parsing and validation techniques\n" << std::endl;
try {
// Run all parsing examples
demonstrateBasicParsing();
demonstrateRegexParsing();
demonstrateValidation();
bulkParsingDemo();
demonstrateTimeConversion();
std::cout << "\nAll time parsing examples completed successfully!" << std::endl;
} catch (const std::exception& e) {
std::cerr << "Unexpected error: " << e.what() << std::endl;
return 1;
}
return 0;
}Tools
Tools frequently paired with this sample
Related