performing Arithmetic on SYSTEMTIME

13,217

Solution 1

If you're using C# (or VB.NET, or ASP.NET) you can use

DateTime dt = DateTime.Now.AddHours(1);

You can use negative numbers to subtract:

DateTime dt = DateTime.Now.AddHours(-1);

EDITED: I extract an asnwer from this post

They suggest converting SYSTEMTIME to FILETIME, which is a number of ticks since an epoch. You can then add the required number of 'ticks' (i.e. 100ns intervals) to indicate your time, and convert back to SYSTEMTIME.

The ULARGE_INTEGER struct is a union with a QuadPart member, which is a 64bit number, that can be directly added to (on recent hardware).

SYSTEMTIME add( SYSTEMTIME s, double seconds ) {

    FILETIME f;
    SystemTimeToFileTime( &s, &f );

    ULARGE_INTEGER u  ; 
    memcpy( &u  , &f , sizeof( u ) );

    const double c_dSecondsPer100nsInterval = 100. * 1.E-9;
    u.QuadPart += seconds / c_dSecondsPer100nsInterval; 

    memcpy( &f, &u, sizeof( f ) );

    FileTimeToSystemTime( &f, &s );
    return s;
 }

If you want to add an hour use SYSTEMTIME s2 = add(s1, 60*60)

Solution 2

To add signed seconds (forward or backward in time) in C++:

const double clfSecondsPer100ns = 100. * 1.E-9;
void iAddSecondsToSystemTime(SYSTEMTIME* timeIn, SYSTEMTIME* timeOut, double tfSeconds)
{
    union {
        ULARGE_INTEGER li;
        FILETIME       ft;
    };

    // Convert timeIn to filetime
    SystemTimeToFileTime(timeIn, &ft);

    // Add in the seconds
    li.QuadPart += tfSeconds / clfSecondsPer100ns;

    // Convert back to systemtime
    FileTimeToSystemTime(&ft, timeOut);
}

Solution 3

#include <stdio.h>
#include <windows.h>
#define NSEC 60*60

main()
{
SYSTEMTIME st;
FILETIME ft;

// Get local time from system
GetLocalTime(&st);

printf("%02d/%02d/%04d %02d:%02d:%02d\n",
  st.wDay,st.wMonth,st.wYear,st.wHour,st.wMinute,st.wSecond);

// Convert to filetime
SystemTimeToFileTime(&st,&ft);

// Add NSEC seconds
((ULARGE_INTEGER *)&ft)->QuadPart +=(NSEC*10000000LLU);

// Convert back to systemtime
FileTimeToSystemTime(&ft,&st);

printf("%02d/%02d/%04d %02d:%02d:%02d\n",
  st.wDay,st.wMonth,st.wYear,st.wHour,st.wMinute,st.wSecond);
}
Share:
13,217
Peter
Author by

Peter

Software Developer

Updated on June 12, 2022

Comments

  • Peter
    Peter about 2 years

    I have a time value represented in SYSTEMTIME, i want to add/subtract 1 hour from it and get the newly obtained SYSTEMTIME. I want the conversion should take care of the date change on addition/subtraction or month change or e1 year change .

    Can someone help me with this if there is some windows api which does arithmetic on SYSTEMTIME

  • Peter
    Peter over 12 years
    i am using windows SYSTEMTIME structure
  • Marco
    Marco over 12 years
    @Peter: ok, but which programming language are you using?
  • Sandburg
    Sandburg about 6 years
    What is this trick with the union? You make no calculus on ft, but it is you result back... I don't understand.
  • Rick C. Hodgin
    Rick C. Hodgin about 6 years
    The byte/bit patterns of the 64-bit FILETIME is the same as those of the ULARGE_INTEGER. By populating ft, you are also populating the portions of li, which allows you to use li at that point. The location in memory just examines the data there in the two different ways. By using ft you see it as a FILETIME. By using li you see it as a ULARGE_INTEGER.
  • CookiePLMonster
    CookiePLMonster about 6 years
    This (interpreting FILETIME as ULARGE_INTEGER) is exactly what is discouraged by MSDN, though.
  • Rick C. Hodgin
    Rick C. Hodgin about 6 years
    They discourage it because they don't intend to stay on x86 forever. They want you to use functions that can be ported to other architectures without any changes. That's all find and dandy if you have that need (other architecture portability). But if you're strictly x86 (or more generically, little endian), this method works properly.
  • MSalters
    MSalters almost 6 years
    The MSDN warning is related to unaligned access of a FILETIME. However, C++ unions are aligned to the strictest alignment necessary. Hence, this solution prevents the problem MSDN warns about.
  • Nikunj Chaklasiya
    Nikunj Chaklasiya almost 5 years
    I'm using VS2008 and getting "bad suffix error on the line from where you're adding seconds.
  • Piotr
    Piotr about 3 years
    docs.microsoft.com/en-us/windows/win32/api/minwinbase/… Do not cast a pointer to a FILETIME structure to either a ULARGE_INTEGER* or __int64* value because it can cause alignment faults on 64-bit Windows.