News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Datetime - Day of Week - Month of Year - Time Zone

Started by herge, August 29, 2013, 07:17:44 PM

Previous topic - Next topic

herge

 Hi DateTime Fans;

If you have downloaded MASM32 you should have Datetime it's a bunch
of files that manipulate the date and time. Alex Lyon made these files.
\masm32\datetime

Please Console Build we are using inkey which is Console Keyboard
input!

This program DOW.ASM uses this Library Datetime. DOW i e Day of Week.

; DoW.ASM Thursday, August 29, 2013 5:01:42 AM
; Day of Week
INCLUDE \masm32\include\masm32rt.inc
INCLUDE \masm32\include\DateTime.inc
INCLUDELIB \masm32\lib\DateTime.lib
.DATA
stUtc SYSTEMTIME<>; Local Time
dtUtc SYSTEMTIME<>
Ptext       dd    0
Buff        db 120 dup(0)
            db 0
dateformat  db " dddd MMMM dd, yyyy", 0
timeformat db "hh:mm:ss tt",0
pzTitle     db "Your Local Time & Time Zone "
date_buf db 260 dup (?)
      db 20 dup (?)
            db    0
FirstSpace  db    " " ; Add a Space!
StdOutBuf   db    148 dup(0)
            db    0
CrLf        db    13, 10, 0
TDow        db    " Day of Week ",0
TMoy        db    " Month of Year ",0
SB          db    " ",0 ; Single SPace   
ST_DOWName  equ $
    db  "Sunday ",0
    db  "Monday ",0
    db  "Tuesday ",0
    db  "Wednesday ",0
    db  "Thursday ",0
    db  "friday ",0
    db  "Saturday ",0
    db  0
ST_MOYName  equ $
    db  "January ",0
    db  "February ",9
    db  "March ",0
    db  "April ",0
    db  "May ",0
    db  "June ",0
    db  "july ",0
    db  "August ",0
    db  "September ",0
    db  "October ",0
    db  "November ",0
    db  "December ",0
    db  0     
   
.CODE
        align 4
PCrLf   proc
        invoke   StdOut, addr CrLf
        ret
PCrLf   endp
        align 4
PSp     proc    uses esi
        mov esi, offset SB
        call P   
        ret
PSp     endp
    align 4
DayOfWeek PROC pdt:PTR DATETIME

    ; Return in eax
    ; Sunday = 0, Monday = 1, ... Saturday = 6
   
    LOCAL _st:SYSTEMTIME
   
    INVOKE FileTimeToSystemTime, pdt, ADDR _st
    .IF eax == 0
        mov eax, -1
    .ELSE   
        movzx eax, _st.wDayOfWeek
    .ENDIF   
    ret   
DayOfWeek ENDP

    align 4
CX_TH proc
; ESI > Table
; ECX is entry in table we
; want.
; find cx_th entry in table
      test  ecx, ecx
jz cx_th_exit
dec ecx ; is it first entry
jz cx_th_exit; is first then exit
@@:
lodsb
and al,al ; is byte equal zero
jnz @B; search for zero
dec ecx
jnz @B; find cx_th zero
cx_th_exit:
; cx_th zero found exit
ret
CX_TH endp

    align 4
CX_TH_Entry proc uses ecx
call CX_TH
ret
CX_TH_Entry endp

    align 4
P   proc    uses    ecx ; Print to Console ESI
    invoke  StdOut, esi
    ret
P   endp
    align 4
NL  proc    uses esi    ; Print CrLf to Console
    mov     esi, offset CrLf
    call    P
    ret
NL  endp

    align 4
; Copy ESI byte to EDI byte until ESI byte = Zero
;
copy_till_byte_Zero proc
    lodsb   ; esi = source
    stosb   ; edi = destination
    and     al, al
    jz      @f
    jmp     copy_till_byte_Zero
@@:         ; Zero Exit
    ret
copy_till_byte_Zero endp

    align 4
start   proc

    INVOKE GetLocalTime, ADDR stUtc
    INVOKE SystemTimeToFileTime, ADDR stUtc, ADDR dtUtc

    cld    ; Direction Flag Up
    mov    esi, offset StdOutBuf
    INVOKE CurrentTimeZoneName, esi
    inc    eax
    jz     err_tz
@@:     
    lodsb
    and    al, al
    jnz    @B
   
    mov    byte ptr [ esi ], 0

    invoke  GetDateFormat, 0, 0, \
    ADDR stUtc, ADDR dateformat, ADDR date_buf, 240

    mov ecx, offset date_buf
    add ecx, eax; add length returned by GetDateFormat
    mov byte ptr [ ecx-1 ], ' '; replace null with space

    invoke GetTimeFormat, 0, 0, \
    ADDR stUtc, ADDR timeformat, ecx, 20
invMess:

     invoke lstrcat, addr date_buf, addr FirstSpace

     invoke   MessageBox, 0,  addr pzTitle, addr date_buf, MB_OK
     call     PCrLf
     invoke   StdOut, addr date_buf
     call     PCrLf 
     inkey    " $$ You Must Hit Any Key to END process! $$ "
     call     PCrLf
     invoke   DayOfWeek, ADDR dtUtc
     inc      eax
     jz       @F
     mov      ecx, eax
     mov      esi, offset ST_DOWName
     call     CX_TH
     mov      Ptext, esi 
     push     esi
     call     PSp
     call     P
     call     PCrLf
     pop      esi
     mov      edi, offset StdOutBuf
     call     copy_till_byte_Zero
     invoke   MessageBox, 0, addr FirstSpace, addr TDow, MB_OK
     mov      esi, offset ST_MOYName
     mov      ax, stUtc.wMonth
     and      ax, ax
     jz       er_month
     dec      eax
     mov      ecx, eax
     call     CX_TH
     push     esi
     call     PSp
     call     P
     call     PCrLf
     pop      esi
     mov      edi, offset StdOutBuf
     call     copy_till_byte_Zero
     invoke   MessageBox, 0, addr FirstSpace, addr TMoy, MB_OK
     inkey   
     exit
     ret
@@:
     inkey    " ** Day of Week - Range Error < 0 or > 6 ** "
     call     PCrLf
     exit
     ret
er_month:
     inkey    " ** Month of Year - Range Error = 0 ** "
     exit
     ret     
start   endp
     align 8
err_tz:
    print   "Time Zone Not Set",7,13,10; 7 = Bell Noise i e Alarm
    exit
    ret
    align 8
end_here    equ $   
     end start



That's All Rubber Duck and DateTime Fans.
Regards herge
Read "Slow Death by Rubber Duck"
for chemical Laughs.

Tedd

A few suggestions..


If you have a list of strings and want to select a particular one by index, you can store a list of their offsets and then index directly into that instead of searching to find the end of each string.

.data
day_name    dd OFFSET day0,OFFSET day1,OFFSET day2,OFFSET day3,OFFSET day4,OFFSET day5,OFFSET day6
day0        db "Sunday ",0
day1        db "Monday ",0
day2        db "Tuesday ",0
day3        db "Wednesday ",0
day4        db "Thursday ",0
day5        db "Friday ",0
day6        db "Saturday ",0

.code
    ...
    invoke DayOfWeek, ADDR dtUtc
    mov edx,OFFSET day_name
    mov ecx,[edx+4*eax]
    invoke StdOut, ecx
    ...

Month names can be done in the same way.

Although, GetDateFormat can actually provide you with the day and month names anyway, and in the correct language.


Calling a function that only calls another function seems a little indirect, even better when that function only really then calls yet another function.
If for readability, try defining the canned function call as a macro.
Potato2

herge

#2
 Hi Tedd:

Good suggestions. I still have not figured out Datetime completely yet I get the
year 1601 and the time is out to lunch. I think iit's a problem at my end not
understnding some concept.

Regards herge
Read "Slow Death by Rubber Duck"
for chemical Laughs.

jj2007

Quote from: Tedd on August 29, 2013, 11:51:27 PMIf you have a list of strings and want to select a particular one by index, you can store a list of their offsets and then index directly into that instead of searching to find the end of each string.

Good solution for a Million loops, but searching for the end is shorter from 3 items upwards:

Thursday is day 4
Thursday is day 4
Thursday is day 4
Thursday is day 4
Sunday is day 0
Sunday is day 0
Sunday is day 0
Sunday is day 0
28       bytes for data
11       bytes for GetDay0 <<< the offsets solution: with 3 items = 11+12=23
29       bytes for GetDay1 <<< herge
28       bytes for GetDay2 <<< repne scasb
22       bytes for GetDay3 <<< shortest lodsb solution



Tedd

Quote from: jj2007 on August 30, 2013, 10:53:41 PM
Quote from: Tedd on August 29, 2013, 11:51:27 PMIf you have a list of strings and want to select a particular one by index, you can store a list of their offsets and then index directly into that instead of searching to find the end of each string.

Good solution for a Million loops, but searching for the end is shorter from 3 items upwards:
Assuming your intention is to save a small proportion of bytes in a file whose size will be rounded up to at least 512 bytes and at least 4k when loaded, rather than the obvious efficiency gain. Obviously, for a small number of strings, you can argue it makes little noticeable difference whichever method you use, but for larger numbers of strings the additional data overhead will be much less significant, not to mention the exponentially increasing time to find the required string.
Potato2

jj2007

Quote from: Tedd on August 30, 2013, 11:21:27 PM... for larger numbers of strings the additional data overhead will be much less significant

While the extra overhead for GetDay3 is a fixed 11 bytes, the size increase is proportional to the number of strings (plus one DWORD per string), so it becomes more significant for larger numbers of strings.

Quotenot to mention the exponentially increasing time to find the required string.

The time increases linearly, not exponentially. And, as I wrote above, your solution is better for a Million loops - finding Saturday a Million times costs already 0.17 seconds.

herge

#6
 Hi Datetime Fans;

Latest version of Showtima.asm
console BuildPlease.

; REM SHOWTIMA.ASM Saturday, August 31, 2013 10:40:13 AM
; Console Build Please
; January 25, 2011 8:22 AM
; Author: Herge
; Location: Waterloo, Ontario, CANADA
.XCREF ; XCREF = NO cross Reference
;.XLIST ; XLIST = NO listing - Windows.inc is kind of massive man!
    include \masm32\include\masm32rt.inc
INCLUDE \masm32\include\DateTime.inc
INCLUDELIB \masm32\lib\DateTime.lib
.LIST
.CREF
.data
stm  SYSTEMTIME<>
StdOutBuf   db 120 dup (0)
            db 0
dateformat  db " dddd, MMMM, dd, yyyy", 0
timeformat  db "hh':'mm':'ss tt ",0
date_buf db 240 dup (0)
        db 21 dup (0)
wDofW       equ $
            db "Sunday ",0
            db "Monday ",0
            db "Tuesday ",0
            db "Wednesday ",0
            db "Thursday ",0
            db "Friday ",0
            db "Saturday ",0
            db 0
wMonthName  equ $
            db "January ",0
            db "February ",0
            db "March ",0
            db "April ",0
            db "May ",0
            db "Jume ",0
            db "July ",0
            db "August ",0
            db "September ",0
            db "October ",0
            db "November ",0
            db "December ",0
            db 0
DyMonth     db "Zero ", 0
            db "One ", 0
            db "Two ", 0
            db "Three ", 0
            db "Four ", 0
            db "Five ", 0
            db "Six ", 0
            db "Seven ", 0
            db "Eight ", 0
            db "Nine ", 0
            db "Ten ", 0
            db "Eleven ", 0
            db "Twelve ", 0
            db "Thirteen ", 0
            db "Fourteen ", 0
            db "Fifteen ", 0
            db "Sixteen ", 0
            db "Seventeen ", 0
            db "Eighteen ", 0
            db "Nineteen ", 0
            db "Twenty ", 0
            db "Twenty-One ", 0
            db "Twenty-Two ", 0
            db "Twenty-Three ", 0
            db "TWO-FOUR (24) ", 0; Was Twenty-Four
            ; a case of beer (24 bottles)
            db "Twenty-Five ", 0
            db "Twenty-Six ", 0
            db "Twenty-Seven ", 0
            db "Twenty-Eight ", 0
            db "Twenty-Nine ", 0
            db "Thirty ", 0
            db "Thirty-Ome ", 0
            db 0
CrLf        db 13,10,0
Space       db " ",0 
morning     db " AM ",0
afternoon   db " PM ",0
            db 0       
.code

CX_TH proc
; ESI > Table
; ECX is entry in table we
; want.
; find cx_th entry in table
      test  ecx, ecx
jz cx_th_exit
dec ecx ; is it first entry
jz cx_th_exit; is first then exit
@@:
lodsb
and al,al ; is byte equal zero
jnz @B; search for zero
dec ecx
jnz @B; find cx_th zero
cx_th_exit:
; cx_th zero found exit
ret
CX_TH endp

CX_TH_Entry proc uses ecx
call CX_TH
ret
CX_TH_Entry endp

    public  P
P   proc    uses    ecx ; Print to Console ESI
    invoke  StdOut, esi
    ret
P   endp

NL  proc    uses esi    ; Print CrLf to Console
    mov     esi, offset CrLf
    call    P
    ret
NL  endp

Pentry  proc    uses ecx
      call  CX_TH_Entry
      call  P
      ret
Pentry  endp

Pentry3 proc uses ecx esi
    mov     ECX, 3
    CALL    CX_TH_Entry
@@:   
    lodsb
    and al,al
    jz  @F  ; Test End of String
    mov dl, al
    ;call    put
    dec ecx
    jnz @B
@@:
; Premature Exit i e Entry is Not Three
; Bytes Long or we got Three Bytes.   
    ret
Pentry3 endp

PutSpace    proc uses esi     
      mov   esi, offset Space
      call  StdOut
      ret
PutSpace    endp

start   proc   
      invoke   GetLocalTime, addr stm; put Values in stm
      movzx    ecx, stm.wDayOfWeek
      inc      ecx
      mov      esi, offset wDofW
      call     Pentry
      movzx   ecx, word ptr stm.wDay
      inc   ecx
      mov   esi, offset DyMonth
      call  Pentry
      movzx  ecx, word ptr stm.wMonth
      mov   esi, offset wMonthName
      call  Pentry
      movzx eax, word ptr stm.wYear
      print   ustr$(eax), " "
      movzx eax, word ptr stm.wHour
      print ustr$(eax),":"
      movzx   eax, word ptr stm.wMinute
      print ustr$(eax),":"
      movzx   eax, word ptr stm.wSecond
      print ustr$(eax)
      movzx eax, word ptr stm.wHour
      sub   eax, 12
      jz    Pmorn
      jc    Pmorn
      mov   esi, offset afternoon
      call  P
      jmp   PTZ
Pmorn:
      mov   esi, offset morning
      call  P
PTZ:
     cld    ; Direction Flag Up
     mov    esi, offset StdOutBuf
     INVOKE CurrentTimeZoneName, esi
     inc    eax
     jz     err_tz
@@:     
    lodsb
    and    al, al
    jnz    @B
     
    mov    byte ptr [ esi ], 0

    mov   esi, offset StdOutBuf
    call  P; Time Zone Name
    call  NL           
    inkey "Hit The Space Bar to End!"
    invoke      ExitProcess, 0
err_tz:
    print   "Time Zone Not Set",7,13,10; 7 = Bell Noise i e Alarm
    exit
    ret
    align 8
end_here    equ $     
start   endp     
        end start


Note Twenty-four is Two-four i e number
of bottles in Case of beer Or  May Two-Four the Queen's
birthday and cottage opening Holiday here in Ontario,
CANADA. Close them some time in October on
Thanksgiving Day.
Regards herge
Read "Slow Death by Rubber Duck"
for chemical Laughs.