performing Arithmetic on SYSTEMTIME
Asked Answered
N

3

7

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

Nydia answered 29/11, 2011 at 9:12 Comment(2)
What language are you using? And what do you mean by SYSTEMTIME?Guidotti
@Marco sorry i got late ..and yeah thanxx man it worked fine for meNydia
K
13

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)

Kin answered 29/11, 2011 at 9:16 Comment(2)
i am using windows SYSTEMTIME structureNydia
@Peter: ok, but which programming language are you using?Kin
U
7

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);
}
Ulrika answered 28/5, 2013 at 20:18 Comment(6)
What is this trick with the union? You make no calculus on ft, but it is you result back... I don't understand.Ferrer
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.Ulrika
This (interpreting FILETIME as ULARGE_INTEGER) is exactly what is discouraged by MSDN, though.Kirkpatrick
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.Ulrika
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.Calycine
MSaltes, the compiler will automatically align variables unless explicitly told to pack things on a 1- or 2-byte boundary. Local variables like this on the stack are always (at a minimum) DWORD-aligned in 32-bit code, and QWORD-aligned in 64-bit code. In 32-bit code it will be two 32-bit accesses, which will be aligned. In 64-bit code it will be one 64-bit access, which will be aligned.Ulrika
V
5
#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);
}
Volleyball answered 8/12, 2013 at 17:16 Comment(3)
I'm using VS2008 and getting "bad suffix error on the line from where you're adding seconds.Necessitate
learn.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.Dicot
Piortr, in 64-bit windows, in a 64-bit app, the ft local variable will be on the stack, and it will be QWORD-aligned (8-byte aligned). It won't ever be misaligned. In a 32-bit app, it will be DWORD-aligned minimally, and accesses to the data will be in two 32-bit reads / writes, so it also won't be misaligned. The 64-bit pointer cast warning is in general. It has cases like this (and many others) where it's not an issue. You have to know your data.Ulrika

© 2022 - 2024 — McMap. All rights reserved.