News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Convert TimeDateStamp to string

Started by gwapo, February 03, 2006, 05:50:14 AM

Previous topic - Next topic

gwapo

Hi,

I'm trying to write a function that will convert TimeDateStamp (dword) to its equivalent date and time string, the documented method for doing this is to add the converted to ticks TimeDateStamp (TimeDateStamp * 10000000) to 019DB1DED53E8000h (January 1, 1970), but the result is a 64-bit data in which I don't know how to handle in MASM.

Converting to string would be easy, but I'd like to know how to handle 64-bit datatypes (addition/subtraction) in MASM without using 64-bit registers and without data-loss?

Any help would be greatly appreciated.

Thanks,

-chris

Petroizki

When you multiply with 10000000 and add the 19DB1DEE53E8000h to the C type of DWORD time, you get the specific 64bit value, which is the same as FILETIME. You can then use for example, the Windows API FileTimeToSystemTime; to convert the 64bit value to SYSTEMTIME, which then after conversion, holds the time format in much more printable version (WORD values). :wink

msmith

See the recent thread Re: LARGE_INTEGER Divide where Raymond helped me through a similar problem a couple weeks ago.

gwapo

Thanks for the great discussions about LONG_INTEGER, I learned a lot  :U
Also, thanks for telling me that there's an API that do what I want to do, it saved me a lot of coding  :bg

-chris

MichaelW

#4
After sending more than an hour searching I was unable to determine if the correct 100-nanosecond interval adjustment value is 019DB1DED53E8000h or 19DB1DEE53E8000h, so I decided to code a program to derive the value. Unless I'm screwing up again :( , the correct value is 19DB1DED53E8000h.

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc

    ;------------------------------------------------
    ; For the Gregorian Calendar, leap years are all
    ; century years evenly divisible by 400, and all
    ; other years evenly divisible by 4.
    ;------------------------------------------------

    isleapyear MACRO year
        mov   ecx, 100
        mov   eax, year
        xor   edx, edx
        div   ecx
        .IF (edx)             ;; if not century year
          mov   eax, year     ;; reload year
        .ENDIF
        and   eax, 3
        mov   eax, 1
        jz    @F              ;; if evenly divisible by 4
        xor   eax, eax
      @@:
        EXITM <eax>
    ENDM

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
    .code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    ;-------------------------------------------------------------
    ; The C time function returns the number of seconds elapsed
    ; since midnight, January 1, 1970 (as type time_t).
    ;
    ; A system file time is a 64-bit unsigned value representing
    ; the date and time as the number of 100-nanosecond intervals
    ; that have elapsed since midnight, January 1, 1601.
    ;-------------------------------------------------------------
   
    xor   edi, edi          ; days
    mov   ebx, 1601
    .REPEAT
      .IF (isleapyear(ebx))
        add   edi, 366
      .ELSE
        add   edi, 365
      .ENDIF
      add   ebx, 1
    .UNTIL (ebx == 1970)
    mov   eax, 24*60        ; minutes per day
    mul   edi               ; product will fit in eax
    mov   edi, 60*10000000  ; 100-nanosecond intervals per minute
    mul   edi               ; product in edx:eax

    nops 4
    invoke crt_printf, chr$("%I64Xh%c"), edx::eax, 10

    inkey "Press any key to exit..."
    exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start


19DB1DED53E8000h
Press any key to exit...

eschew obfuscation

P1

Did you take into the Julian to Gregorian Calendar skip ?

Scratch that thought:
For example, even though the Gregorian Calendar was implemented on October 15, 1582 (Gregorian) we can still say that the date of the day one year before was October 15, 1581 (Gregorian), even though people alive on that day would have said that the date was October 5, 1581 (the Julian date at that time).

Regards,  P1  :8)

P1

Use the FPU with the 64bit data types.  Check out Ray's tutorials:
http://website.masmforum.com/tutorials/fptute/index.html
Makes using the integers easier, with advanced math functions.

Regards,  P1  :8)

MichaelW

I finally found a definition for the value in question in the time.c source that was included with the Windows Server 2003 PSDK:
Quote
/*
* Number of 100 nanosecond units from 1/1/1601 to 1/1/1970
*/
#define EPOCH_BIAS  116444736000000000i64

And if I change the printf statement in the source above to:

invoke crt_printf, chr$("%I64d%c"), edx::eax, 10

I get:

116444736000000000
Press any key to exit...


And the name is IMO very well chosen:

http://en.wikipedia.org/wiki/Epoch



eschew obfuscation

MichaelW

#8
To complete this:

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc

    EPOCH_BIAS EQU 116444736000000000.0
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
        crttime   dd 0
        filetime  dq 0
        systime1  SYSTEMTIME <>
        systime2  SYSTEMTIME <>
    .code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    invoke GetSystemTime, ADDR systime1

    invoke crt_time, NULL
    mov   crttime, eax

    fld8  10000000.0
    fimul crttime
    fld10 EPOCH_BIAS ; REAL10 because EPOCH_BIAS has 57 significant bits
    fadd
    fistp filetime

    invoke FileTimeToSystemTime, ADDR filetime, ADDR systime2

    movzx eax, systime1.wYear
    print ustr$(eax),9
    movzx eax, systime2.wYear
    print ustr$(eax),13,10

    movzx eax, systime1.wMonth
    print ustr$(eax),9
    movzx eax, systime2.wMonth
    print ustr$(eax),13,10

    movzx eax, systime1.wDayOfWeek
    print ustr$(eax),9
    movzx eax, systime2.wDayOfWeek
    print ustr$(eax),13,10

    movzx eax, systime1.wDay
    print ustr$(eax),9
    movzx eax, systime2.wDay
    print ustr$(eax),13,10

    movzx eax, systime1.wHour
    print ustr$(eax),9
    movzx eax, systime2.wHour
    print ustr$(eax),13,10

    movzx eax, systime1.wMinute
    print ustr$(eax),9
    movzx eax, systime2.wMinute
    print ustr$(eax),13,10

    movzx eax, systime1.wSecond
    print ustr$(eax),9
    movzx eax, systime2.wSecond
    print ustr$(eax),13,10

  ;-----------------------------------------------------
  ; The crt time function returns the number of seconds
  ; elapsed since midnight (00:00:00), January 1, 1970,
  ; coordinated universal time (UTC), so the elapsed
  ; milliseconds will always be zero.
  ;-----------------------------------------------------

    movzx eax, systime1.wMilliseconds
    print ustr$(eax),9
    movzx eax, systime2.wMilliseconds
    print ustr$(eax),13,10

    inkey "Press any key to exit..."
    exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start

Typical result:

2006    2006
2       2
6       6
4       4
23      23
36      36
31      31
795     0
eschew obfuscation