Announcement

Collapse
No announcement yet.

Dir$() format of creationTIME ????

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Dir$() format of creationTIME ????

    Hello how to decode the new times ?

    e.g.

    #COMPILE EXE
    #DIM ALL

    FUNCTION PBMAIN () AS LONG

    DIM filed(1:1000) AS dirdata

    ? DIR$("a:" ,TO filed(1))
    ?USING$("######################################################################",filed(1).creationtime)

    END FUNCTION

    What means the quad number of creationtime and how decode it to

    DD.MM.JJJJ and hh.mm.ss ???


    Regards

    Matthias Kuhn

  • #2
    >What means the quad number of creationtime and how decode it to

    That was never stated in the 9.0.0 help. I wrote in about that (bug report), but the 9.0.1 doc does not appear to have been corrected to include this information.

    I have my own theory as to how you could get the formatted dates/times from the DIRDATA var, but I would prefer you bug [email protected] until they get this clarified in the help file.

    (Well, Ok: My theory is those dates are not really QUAD integers, but rather FILETIME structures, which you can format using the GetDateFormat() and GetTimeFormat() WIndows API functions after converting to SYSTEMTIME structures with FileTimeToSystemTime()).

    MCM
    Last edited by Michael Mattias; 10 Mar 2009, 02:09 PM.
    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      I think I made a good guess...

      Code:
      ' TEST_DIRDATA
      ' Get Formatted date and time info from DIRDATA structure
      ' Author: MIchael Mattias Racine WI  3/10/09
      ' USE: Placed in public domain
      ' Compiler:  PB/WIN 9.0.1 SHOULD WORK WITH PB/CC 5+
      #COMPILE     EXE
      #DIM         ALL
      #REGISTER    NONE
      #DEBUG ERROR ON
      
      #COMPILER  PBCC 5, PBWIN 9   ' requires enhanced DIR$
      
      #INCLUDE  "WIN32API.INC"
      ' PB/WIn users: available in source code forum. Search "STDOUT" in subject.
      #IF NOT %DEF(%PB_CC32)
         #INCLUDE "STDOUT_PBWIN.INC"
      #ENDIF
      
      ' Get formatted date and time from the "quad" returned in PB "DIRDATA" variable
      ' formats here match the DATE$ and TIME$ formats
      
      SUB GetformattedDirDataDateTime ( DTOI AS QUAD, sDate AS STRING, sTime AS STRING)
          
          LOCAL szDate AS ASCIIZ * 48, szTime AS ASCIIZ * 48
          LOCAL szDF   AS ASCIIZ * 48, szTF AS ASCIIZ * 48
          LOCAL ft AS FILETIME, ST AS SYSTEMTIME
          LOCAL lft AS FILETIME
          LOCAL pFT   AS FILETIME PTR
          
          IF DTOI <> 0 THEN
          
              pft                           =  VARPTR(DTOI)     ' DTOI = "Date-Time-Of-Interest"
              FileTimeToLocalFileTime @pFT, lft
              FileTimeToSystemTime      lft, St
                 ' use PB DATE$ format  "mm-dd-yyyy
              szDF  = "MM'-'dd'-'yyyy"
              GetDateFormat    BYVAL %NULL, BYVAL %NULL ,st, szDf, szDate, SIZEOF (szDate)
              ' use PB TIME$ format hh:mm:ss  (24 hour)
              szTF =  "HH':'mm':'ss
              GettimeFormat   BYVAL %NULL, BYVAL %NULL ,st,  szTF, szTime, SIZEOF (szTime)
          ELSE
              szDate  = "N/A"
              szTime  = "N/A"
              
          END IF
      
          sDate = szDate
          sTime = szTime
            
      END SUB
      
      FUNCTION PBMAIN () AS LONG
          
          
       LOCAL fmask AS STRING, DD AS DIRDATA
       LOCAL fDate AS STRING, fTime AS STRING   ' output
       LOCAL omask AS STRING
       LOCAL s AS STRING
       
       fMask = "D:\Software_Development\pbwin90\Work\*.bas"
       oMask =  "&  &  &  &"     ' file name, Time type,  date, time
       
       s =    DIR$(fMask TO DD)
       
       WHILE LEN (S)
           
         CALL GetFormattedDirdataDateTime (DD.CreationTime, fDate, fTime)
         STDOUT USING$ (omask, LSET$(S, 25), "Creation   ", fDate, fTime)
         
         CALL GetFormattedDirdataDateTime (DD.LastAccessTime, fDate, fTime)
         STDOUT USING$ (omask, LSET$(S,25),  "Last Access", fDate, fTime)
         
         CALL GetFormattedDirdataDateTime (DD.LastWriteTime, fDate, fTime)
         STDOUT USING$ (omask, LSET$(S,25),  "Last Write ", fDate, fTime)
         
         s = DIR$ (TO DD)
         
           
       WEND
       DIR$ CLOSE
      #IF %DEF(%PB_CC32)
          STDOUT "End of DEmo"
          WAITKEY$
      #ELSE
           MSGBOX "End of Demo"
      #ENDIF
       
      END FUNCTION
      ' END OF FILE
      Not that "Last Access" may not be available on your system. In this case the "quad" will be zero.

      Last Access IS available on my system, so I don't know if the "N/A" shows correctly when it isn't.


      MCM
      Michael Mattias
      Tal Systems (retired)
      Port Washington WI USA
      [email protected]
      http://www.talsystems.com

      Comment


      • #4
        I got a lot of help when I asked a few months ago. I don't remember whose variations I adopted, but I thank them, and pass along what I've been using:

        First this:
        Code:
        Union ftUnion      'for use with PB's new DIR$(..., TO DirData_var)
           q  As Quad
           FT As FILETIME
        End Union
        Then somewhere in my mainline code:
        Code:
           Local t As ftUnion
           sResult = Dir$(Trim$(BackupFile, Any $Dq), Only %NORMAL, To BackupFileData)
           t.q = BackupFileData.CreationTime  
           BackupCreationTime = ConvertFiledateQuadToString(t.FT) 
           MsgBox BackupCreationTime,,"BackupCreationTime"
        And the converter:
        Code:
        Function ConvertFiledateQuadToString(dt As FILETIME) As String
           'converts the compound date and time info in a FileTime structure (a QUAD) into a string
            Local lpsystime As SYSTEMTIME
            Local szDate    As Asciiz * 64 ' date buffer, %LDT_SIZE = 64 bytes
            Local szTime    As Asciiz * 64 ' time buffer, %LDT_SIZE = 64 bytes
        
            Call FileTimeToLocalFileTime(dt, dt)
            Call FileTimeToSystemTime(dt, lpsystime)
            Call GetDateFormat(%LOCALE_USER_DEFAULT, %NULL, lpsystime, "yyyy'-'MM'-'dd", szDate, SizeOf(szDate))
            Call GetTimeFormat (%LOCALE_USER_DEFAULT, %TIME_FORCE24HOURFORMAT, lpsystime, "HH':'mm':'ss" , szTime, SizeOf(szTime))
            Function = szDate & $Spc & szTime
        End Function
        Last edited by John Montenigro; 10 Mar 2009, 11:48 PM.

        Comment


        • #5
          >Call FileTimeToLocalFileTime(dt, dt)

          Jus' plain ole luck so far?

          FileTimeToLocalFileTime

          The FileTimeToLocalFileTime function converts a file time to a local file time.

          Code:
          BOOL FileTimeToLocalFileTime(
            const FILETIME* lpFileTime,
            LPFILETIME lpLocalFileTime
          );
          Parameters
          lpFileTime
          [in] Pointer to a FILETIME structure containing the UTC-based file time to be converted into a local file time.
          lpLocalFileTime
          [out] Pointer to a FILETIME structure to receive the converted local file time. This parameter cannot be the same as the lpFileTime parameter
          MCM
          Michael Mattias
          Tal Systems (retired)
          Port Washington WI USA
          [email protected]
          http://www.talsystems.com

          Comment


          • #6
            I had seen that, too. I researched it and found that MS' own code used it. I think it was in an example in the online MSDN, but I can't find it at this moment. I'll keep looking as I have time.

            This Function was one that someone here had offered me. I only changed the name a bit. For sure, there are many examples of code in the forums that use that same syntax, so I suppose a lot of us are equally lucky...

            If all that's required is another variable, then the change is easy and I leave it to the reader as an exercise in industry (my own lack thereof at this time!)

            Comment


            • #7
              See also current thread..

              http://www.powerbasic.com/support/pb...ad.php?t=40098

              "Search on this page" (IE7) for "forgiving"
              Michael Mattias
              Tal Systems (retired)
              Port Washington WI USA
              [email protected]
              http://www.talsystems.com

              Comment


              • #8
                Thanks all for reply

                Here comes the shorter ( or the shortest ?) one from powerbasic support:

                Hi Matthias,

                The DirData is the same as the WIN32_FIND_DATA User Defined Type (defined in Win32Api.inc) that is returned from the FindFirstFile and FindNextFile API Calls (which DIR$ is a wrapper of). You use the DirData exactly the same as you would the WIN32_FIND_DATA UDT. Here is small example that finds the first file in the root directory and displays its creation date and time:

                #COMPILE EXE
                #DIM ALL

                #INCLUDE "win32api.inc"

                FUNCTION PBMAIN () AS LONG
                LOCAL f AS STRING
                LOCAL d AS DirData
                LOCAL ft AS filetime
                LOCAL lft as filetime
                LOCAL st AS SystemTime

                f = DIR$("C:\*.*", TO d)
                ft.dwLowDateTime = LO(DWORD, d.CreationTime)
                ft.dwHighDateTime = HI(DWORD, d.CreationTime)

                FileTimeToLocalFileTime(ft, lft)
                FileTimeToSystemTime(lft, st)

                ? "Filename :"+f
                ? "Creation Date: "+FORMAT$(st.wMonth, "##")+"/"+FORMAT$(st.wDay, "##")+"/"+FORMAT$(st.wYear)

                ? "Creation Time: "+FORMAT$(st.wHour, "##")+":"+FORMAT$(st.wMinute, "##")+":"+FORMAT$(st.wSecond)

                END FUNCTION

                Sincerely,
                Jeff Daniels
                PowerBASIC Staff


                This example were good to help file in PBWIN 9.01 dir$().

                Best Regards to all

                Matthias Kuhn
                Last edited by Matthias Kuhn; 12 Mar 2009, 05:42 PM. Reason: caveat from MCM

                Comment


                • #9
                  Hey, support says it's a WIN32_FIND_DATA! It must be true! Maybe now it will get into a FAQ or revised help file or something.

                  FWIW...
                  > FileTimeToLocalFileTime(ft, ft)

                  See caveat above: should not use the same variable for both params when calling this WinAPI function.

                  MCM
                  Michael Mattias
                  Tal Systems (retired)
                  Port Washington WI USA
                  [email protected]
                  http://www.talsystems.com

                  Comment


                  • #10
                    I already said that are the same in this thread:
                    http://www.powerbasic.com/support/pb...IN32_FIND_DATA

                    You can use WIN32_FIND_DATA instead of DirData, i.e.

                    Code:
                    #COMPILE EXE
                    #DIM ALL
                    
                    #INCLUDE "win32api.inc"
                    
                    FUNCTION PBMAIN () AS LONG
                    
                       LOCAL f AS STRING
                       LOCAL d AS WIN32_FIND_DATA
                       LOCAL ft AS filetime
                       LOCAL lft as filetime
                       LOCAL st AS SystemTime
                    
                       f = DIR$("C:\*.*", TO d)
                    
                       FileTimeToLocalFileTime(d.ftCreationTime, lft)
                       FileTimeToSystemTime(lft, st)
                    
                       ? "Filename :"+f
                       ? "Creation Date: "+FORMAT$(st.wMonth, "##")+"/"+FORMAT$(st.wDay, "##")+"/"+FORMAT$(st.wYear)
                    
                       ? "Creation Time: "+FORMAT$(st.wHour, "##")+":"+FORMAT$(st.wMinute, "##")+":"+FORMAT$(st.wSecond)
                    
                    END FUNCTION
                    And if you use DirData, you can also use the following:

                    Code:
                    #COMPILE EXE
                    #DIM ALL
                    
                    #INCLUDE "win32api.inc"
                    
                    FUNCTION PBMAIN () AS LONG
                       LOCAL f AS STRING
                       LOCAL d AS DirData
                       LOCAL lft as filetime
                       LOCAL st AS SystemTime
                    
                       f = DIR$("C:\*.*", TO d)
                    
                       FileTimeToLocalFileTime(BYVAL VARPTR(d.CreationTime), lft)
                       FileTimeToSystemTime(lft, st)
                    
                       ? "Filename :"+f
                       ? "Creation Date: "+FORMAT$(st.wMonth, "##")+"/"+FORMAT$(st.wDay, "##")+"/"+FORMAT$(st.wYear)
                    
                       ? "Creation Time: "+FORMAT$(st.wHour, "##")+":"+FORMAT$(st.wMinute, "##")+":"+FORMAT$(st.wSecond)
                    
                    END FUNCTION
                    It happens that a FILETIME structure and a QUAD (aka LONG_INTEGER, LONGLONG, etc) are the same:

                    Code:
                    TYPE FILETIME
                       dwLowDateTime  AS DWORD   ' DWORD dwLowDateTime
                       dwHighDateTime AS DWORD   ' DWORD dwHighDateTime
                    END TYPE
                    Code:
                    TYPE LARGE_INTEGER
                       LowPart  AS DWORD
                       HighPart AS LONG
                    END TYPE
                    That is, two DWORDs.
                    Forum: http://www.jose.it-berater.org/smfforum/index.php

                    Comment


                    • #11
                      >You can use WIN32_FIND_DATA instead of DirData, i.e.

                      Yes, those who are interested, or have experience with FindFirstFile/WIN32_FIND_DATA know that.

                      But go back to post #1 of this thread....

                      How would Herr Kuhn or any other "newbie" know that? You'd think if an intrinsic function (DIR$) returned 'data of interest' ("DIRDATA") then one would be able to read how to use that data in the 'help' for that intrinsic function.

                      Had I not known about WIN32_FIND_DATA structures, I would have done exactly what Herr Kuhn did: "PB says it's a QUAD integer , so let's display it and see where the CCYY, MM,DD, HH, MM and SS are in that string."

                      I'm sure I could look at that displayed value and say to myself, "Oh, I see: that quad integer represents the number of 100-nanosecond intervals since January 1, 1601 (UTC)."
                      Last edited by Michael Mattias; 13 Mar 2009, 08:51 AM.
                      Michael Mattias
                      Tal Systems (retired)
                      Port Washington WI USA
                      [email protected]
                      http://www.talsystems.com

                      Comment


                      • #12
                        There's another warning that could be a gotcha, from a Note in Win32 Help: "It is not recommended that you add and subtract values from the FILETIME structure..."

                        So here are more code fragments that go with what I posted in message #4 above...

                        and they show how to handle those 100-nanosecond intervals.

                        The code generates an ISO format 1 date/time string (yyyy-mm-dd hh:mm:ss) from a data block that contains no date, but the word "Yesterday" plus a time... It uses the CreationTime of the file the block was found in, then subtracts 1 day's worth of 100-nanosecond intervals... and accounts for the local TimeZone adjustment, too.

                        It may not be elegant, but it works well, and well, I'm pleased with the fact that I was able to get it to work at all!

                        Code:
                           Local nsPerDay, nsPerHour, nsPerMinute, Num100nsIntervalsPerDay As Quad
                           nsPerDay    = 86400000000000
                           nsPerHour   =  3600000000000
                           nsPerMinute =    60000000000
                           Num100nsIntervalsPerDay = nsPerDay/100
                        ...
                           MaskYesterday = "Yesterday, [0-9]+:[0-9]+ (A)|(P)M"
                        ...
                              RegExpr MaskYesterday In RawBlock To TSfound
                              If TSfound Then
                                 Stamp = Mid$(RawBlock, TSfound, %Stamp_LEN)
                                 Stamp = Trim$(Extract$(Stamp, Any "=<"), Any "<> =")    
                                 'now replace "Yesterday" with (file's CreationTime -1day
                                 tmp = Dir$(Trim$(Filespec, Any $Dq), To DirStruct)
                                 If tmp <> PathName$(Namex, Filespec) Then
                                    MsgBox Filespec,,"Problem at YESTERDAY marker"
                                    Exit Function  
                                 End If
                                 t.q = DirStruct.CreationTime  'the day I wrote the file to my drive...
                                 'Rather than adjust a string later, let's adjust the time value here.
                                 ' Note in Win32 Help: 
                                 '     "It is not recommended that you add and subtract values from the FILETIME structure..."
                                 ' So instead, we make our adjustment to the Quad:
                                 t.q = t.q - (Num100nsIntervalsPerDay + (%TZA * (nsPerHour/100))) 'TimeZone Adjust (Eastern = -5)
                                 Stamp = ConvertFiledateQuadToString(t.FT)

                        Comment


                        • #13
                          Code:
                          Local nsPerDay, nsPerHour, nsPerMinute, Num100nsIntervalsPerDay As Quad
                             nsPerDay    = 86400000000000
                             nsPerHour   =  3600000000000
                             nsPerMinute =    60000000000
                             Num100nsIntervalsPerDay = nsPerDay/100
                          Another place where setting up some equates in your standard template file can make your life easier...

                          Code:
                          %ONE_FILETIME_MINUTE =   600000000&& 
                          %ONE_FILETIME_HOUR   =   %ONE_FILETIME_MINUTE * 60&&
                          %ONE_FILETIME_DAY    =   %ONE_FILETIME_HOUR   * 24&&
                          MCM
                          Michael Mattias
                          Tal Systems (retired)
                          Port Washington WI USA
                          [email protected]
                          http://www.talsystems.com

                          Comment

                          Working...
                          X