* * * *

Privacy Policy

Blog italiano

Clicca qui se vuoi andare al blog italiano su Lazarus e il pascal.

Forum ufficiale

Se non siete riusciti a reperire l'informazione che cercavate nei nostri articoli o sul nostro forum vi consiglio di visitare il
Forum ufficiale di Lazarus in lingua inglese.

Lazarus 1.0

Trascinare un file nel programma
DB concetti fondamentali e ZeosLib
Recuperare codice HTML da pagina web
Mandare mail con Lazarus
Stabilire il sistema operativo
Esempio lista in pascal
File INI
Codice di attivazione
Realizzare programmi multilingua
Lavorare con le directory
Utilizzare Unità esterne
TTreeView
TTreeview e Menu
Generare controlli RUN-TIME
LazReport, PDF ed immagini
Intercettare tasti premuti
Ampliare Lazarus
Lazarus e la crittografia
System Tray con Lazarus
UIB: Unified Interbase
Il file: questo sconosciuto
Conferma di chiusura di un applicazione
Liste e puntatori
Overload di funzioni
Funzioni a parametri variabili
Proprietà
Conversione numerica
TImage su Form e Panel
Indy gestiore server FTP lato Client
PopUpMenu sotto Pulsante (TSpeedButton)
Direttiva $macro
Toolbar
Evidenziare voci TreeView
Visualizzare un file Html esterno
StatusBar - aggirare l'errore variabile duplicata
Da DataSource a Excel
Le permutazioni
Brute force
Indy 10 - Invio email con allegati
La gestione degli errori in Lazarus
Pascal Script
Linux + Zeos + Firebird
Dataset virtuale
Overload di operatori
Lavorare con file in formato JSON con Lazarus
Zeos ... dietro le quinte (prima parte)
Disporre le finestre in un blocco unico (come Delphi)
Aspetto retrò (Cmd Line)
Lazarus 1.0
Come interfacciare periferica twain
Ubuntu - aggiornare free pascal e lazarus
fpcup: installazioni parallele di lazarus e fpc
Free Pascal e Lazarus sul Raspberry Pi
Cifratura: breve guida all'uso dell'algoritmo BlowFish con lazarus e free pascal.
Creare un server multithread
guida all'installazione di fpc trunk da subversion in linux gentoo
Indice
DB concetti fondamentali e connessioni standard
Advanced Record Syntax
DB concetti fondamentali e DBGrid
DB concetti fondamentali e TDBEdit, TDBMemo e TDBText
Advanced Record Syntax: un esempio pratico
Superclasse form base per programmi gestionali (e non)
Superclasse form base per programmi gestionali (e non) #2 - log, exception call stack, application toolbox
Superclasse form base per programmi gestionali (e non) #3 - traduzione delle form
Superclasse form base per programmi gestionali (e non) #4 - wait animation
Un dialog per la connessione al database:TfmSimpleDbConnectionDialog
Installare lazarus su mac osx sierra
immagine docker per lavorare con lazarus e free pascal
TDD o Test-Driven Development
Benvenuto! Effettua l'accesso oppure registrati.
Aprile 16, 2024, 04:04:38 pm

Inserisci il nome utente, la password e la durata della sessione.

52 Visitatori, 0 Utenti

Autore Topic: [RISOLTO] Data ultima modifica di un file su rete Microsoft  (Letto 4362 volte)

bonmario

  • Hero Member
  • *****
  • Post: 1300
  • Karma: +10/-1
[RISOLTO] Data ultima modifica di un file su rete Microsoft
« il: Aprile 02, 2019, 08:15:09 am »
Ciao a tutti,
ieri mi sono imbattuto in un problema "strano". Non credo che sia a causa di Lazarus, perché lo steso programma su rete Novell non aveva questo problema. Purtroppo non conosco i dettagli delle 2 reti.
Provo a spiegarmi ...
Ho un programma che funziona da anni che, tra le altre cose, deve determinare la data/ora di creazione di parecchi files. Per ognuno, se la data/ora di creazione è maggiore di una certa data di riferimento, deve fare certe operazioni.

- Il 25 marzo, alle 12.00, ho creato un file.
- Il mio programma, quando è girato il 26 marzo, vedeva che quel file era stato creato il 25/03/2019 alle 12.00
- nel weekend c'è stato il cambio dell'ora
- Il mio programma, quando è girato ieri, vedeva che quel file era stato creato il 25/03/2019 alle 13.00, quindi un'ora dopo rispetto a quella effettiva

Qualcuno di voi si è mai imbattuto in questa "anomalia"?

Grazie in anticipo, Mario

P.S. Il mio programma determina la data di creazione, usando "FileDateToDateTime(DirInfo.Time);"
Ho provato anche usando la procedura qui sotto, ma il risultato è il medesimo

Codice: [Seleziona]
  function  DataUltimaModifica(const NomeFile:String;TipoRitorno:TipoData):TDateTime;
  var hFile:Integer;
      ftModifica, ftCreazione, ftAccesso:TFileTime;
      sysDateTime:_SYSTEMTIME;
  begin
    Result:=DimFileNonTrov;

    hFile:=0;
    try
      hFile:=CreateFile(PChar(NomeFile),
                        GENERIC_READ ,
                        FILE_SHARE_READ or FILE_SHARE_WRITE, //Faccio in modo di poter reperire la data
                        nil,                                 //anche dai files vincolati
                        OPEN_EXISTING,
                        FILE_FLAG_BACKUP_SEMANTICS,
                        0);
      if (GetLastError = 0) then begin
        GetFileTime(hFile, @ftCreazione, @ftAccesso, @ftModifica);
        if (GetLastError = 0) then begin
          FileTimeToLocalFileTime(ftModifica, ftModifica);
          FileTimeToSystemTime(ftModifica, sysDateTime);
          Result:=SystemTimeToDateTime(sysDateTime);

          Result:=FormattaData(Result, TipoRitorno);
        end;
      end;
    finally
      if (hFile <> 0) then begin
        CloseHandle(hFile);
      end;
    end;
  end;

Grazie in anticipo, Mario
« Ultima modifica: Aprile 05, 2019, 02:27:30 pm da bonmario »

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2870
  • Karma: +20/-4
Re:Data ultima modifica di un file su rete Microsoft
« Risposta #1 il: Aprile 02, 2019, 08:53:36 am »
in NTFS le date sono memorizzate nel formato UTC che è un formato che non tiene conto dei fusi orari

se usi FileTimeToLocalFileTime o FileTimeToSystemTime questi orari ti verranno convertiti tenendo conto del fuso orario del paese dove ti trovi

non mi è mai capitato un problema del genere ma penso che dovresti utilizzare la funzione GetLocalTimeOffset che trovi in
https://www.freepascal.org/docs-html/rtl/sysutils/getlocaltimeoffset.html
in questo modo dovresti ottenere la data UTC con la quale fare i controlli che ti servono

Edit:
c'è anche questa unit che può essere utile
http://wiki.freepascal.org/PascalTZ
« Ultima modifica: Aprile 02, 2019, 08:58:53 am da nomorelogic »
Imagination is more important than knowledge (A.Einstein)

bonmario

  • Hero Member
  • *****
  • Post: 1300
  • Karma: +10/-1
Re:Data ultima modifica di un file su rete Microsoft
« Risposta #2 il: Aprile 03, 2019, 08:08:44 am »
Ciao,
grazie per la risposta, ma credo che il problema sia già a monte.

Ti faccio un esempio su un file preso a campione:
- se faccio la dir dal prompt di DOS mi da: 25/03/2019 13:43
- visto da Esplora risorse mi da: 25/03/2019 12:43
- visto con un altro file manager (Free Commander XE) mi da: 25/03/2019 13:43
- tutti i metodi che ho provato con Lazarus, mi danno: 25/03/2019 11:43

Credo però che "GetLocalTimeOffset" potrebbe tornarmi utile: al momento mi da come risultato -120. Al prossimo cambio dell'ora mi devo ricordare di riverificare il suo valore, e farci sopra qualche ragionamento.

Grazie, Mario

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2870
  • Karma: +20/-4
Re:Data ultima modifica di un file su rete Microsoft
« Risposta #3 il: Aprile 03, 2019, 05:23:51 pm »
se sommi 120 minuti alle 11:43 ottieni 13:43

se sei sicuro che l'ora 13:43 è quella giusta sai che GetLocalTimeOffset funziona bene
Imagination is more important than knowledge (A.Einstein)

bonmario

  • Hero Member
  • *****
  • Post: 1300
  • Karma: +10/-1
Re:Data ultima modifica di un file su rete Microsoft
« Risposta #4 il: Aprile 04, 2019, 08:17:25 am »
Purtroppo non è così ....

Sono riuscito a recuperare i log del programma che ha creato quel file: è stato creato alle 12.43.

Credo che se i test che sto facendo oggi, li avessi fatti prima del cambio dell'ora, mi avrebbe dato 11:43, con un offset di -60 minuti.

Quindi, in merito al mio post precedente, l'unico che da una risposta corretta sembra essere "Esplora Risorse".

Ciao, Mario

bonmario

  • Hero Member
  • *****
  • Post: 1300
  • Karma: +10/-1
Re:Data ultima modifica di un file su rete Microsoft
« Risposta #5 il: Aprile 05, 2019, 02:27:11 pm »
Ciao,
ho trovato la soluzione cercando su San Google "dst delphi", senza le virgolette.
dst sta per "Daylight Savings Time".


Codice: [Seleziona]
function  DataUltimaModifica(const NomeFile:String; TipoRitorno:TipoData):TDateTime;
var DirInfo: TSearchRec;
    UTCTime: TFileTime;
    GMTST: TSystemTime;
    LocalST: TSystemTime;
    ModifyDT: TDateTime;
    TZ: _TIME_ZONE_INFORMATION;
begin
  Result:=DimFileNonTrov;

  try
    if FindFirstUTF8(NomeFile, faAnyFile, DirInfo) = 0 then begin
      UTCTime:=DirInfo.FindData.ftLastWriteTime;
      if FileTimeToSystemTime(UTCTime, GMTST) then begin
         // Get Timezone Information
        if GetTimeZoneInformation(TZ) <> 0 then begin
          if SystemTimeToTzSpecificLocalTime(@TZ, GMTST, LocalST) then begin
            ModifyDT:=SystemTimeToDateTime(LocalST);
            Result:=FormattaData(ModifyDT, TipoRitorno);
          end;
        end;
      end;
    end;
  finally
    FindCloseUTF8(DirInfo);
  end;
end;

Ciao, Mario

xinyiman

  • Administrator
  • Hero Member
  • *****
  • Post: 3249
  • Karma: +12/-0
Re:[RISOLTO] Data ultima modifica di un file su rete Microsoft
« Risposta #6 il: Aprile 05, 2019, 04:55:22 pm »
Ottimo, grazie della condivisione.
Ieri è passato, domani è futuro, oggi è un dono...

bonmario

  • Hero Member
  • *****
  • Post: 1300
  • Karma: +10/-1
Re:[RISOLTO] Data ultima modifica di un file su rete Microsoft
« Risposta #7 il: Aprile 10, 2019, 01:48:16 pm »
Ciao,
alla fine ho messo tutto in una unit, in modo da poterla usare ovunque mi dovesse servire.

Eccola:
Codice: [Seleziona]
unit BonMarGestDataOra;

{$mode objfpc}{$H+}

interface

uses LazFileUtils, LazUTF8, SysUtils, dateutils
  {$IFDEF UNIX}
    , Unix, unixutil
  {$ELSE}
    , windows
  {$ENDIF}
  ;

const CstConvDataErr=-1;

  function  UnixTimeToLocalTime(UnixFileTime: Int64; var WrkDateTime:TDateTime):Boolean;
  {$IFDEF MSWINDOWS}
  function  UTCFileTimeToLocalTime(UTCFileTime: TFileTime; var WrkDateTime:TDateTime):Boolean;
  {$ENDIF}
  function  DataUltimaModifica(const NomeFile:String):TDateTime;
  function  DataDiCreazione(const NomeFile: String): TDateTime;

implementation

var
    {$IFDEF UNIX}
      SegnaPosto:Integer; //Messa solo per non adre errori di compilazione in Linux
    {$ELSE}
      TZ: _TIME_ZONE_INFORMATION;
    {$ENDIF}



{$IFDEF UNIX}
  function  UnixTimeToLocalTime(UnixFileTime: Int64; var WrkDateTime:TDateTime):Boolean;
  var DiffTimeLinux:Longint;
  begin
    //Inizializzazione output
    Result:=False;
    WrkDateTime:=CstConvDataErr;

    //Trasformo la Data/Ora Unix in una data normale
    WrkDateTime:=UnixToDateTime(UnixFileTime);

    //Determino il DST tra la data che devo gestire ed oggi
    GetLocalTimezone(UnixFileTime);
    DiffTimeLinux:=Tzseconds;

    //Rettifico l'orario ed emetto il risultato
    WrkDateTime:=IncSecond(WrkDateTime, DiffTimeLinux);
    Result:=True;
  end;
{$ELSE}
  function  UnixTimeToLocalTime(UnixFileTime: Int64; var WrkDateTime:TDateTime):Boolean;
  var GMTST: TSystemTime;
      LocalST: TSystemTime;
      ModifyDT: TDateTime;
  begin
    //Inizializzazione output
    Result:=False;
    WrkDateTime:=CstConvDataErr;

    //Trasformo la Data/Ora Unix in una data normale
    WrkDateTime:=UnixToDateTime(UnixFileTime);

    //Trasformo la data/ora appena trovata in una di sistema
    DateTimeToSystemTime(WrkDateTime, GMTST);

    //Converto l'orario in base ai dati della TimeZone
    if SystemTimeToTzSpecificLocalTime(@TZ, GMTST, LocalST) then begin
      //Converto la data nel formato corretto
      ModifyDT:=SystemTimeToDateTime(LocalST);

      //Comunico al chiamante che la conversione è andata a buon fine,
      //e ladata/ora corretta
      WrkDateTime:=ModifyDT;
      Result:=True;
    end;
  end;
{$ENDIF}


{$IFDEF MSWINDOWS}
function  UTCFileTimeToLocalTime(UTCFileTime: TFileTime; var WrkDateTime:TDateTime):Boolean;
var GMTST: TSystemTime;
    LocalST: TSystemTime;
    ModifyDT: TDateTime;
begin
  //Inizializzazione output
  Result:=False;
  WrkDateTime:=CstConvDataErr;

  //Converto la data di un file in una data di sistema
  if FileTimeToSystemTime(UTCFileTime, GMTST) then begin
    //Converto l'orario in base ai dati della TimeZone
    if SystemTimeToTzSpecificLocalTime(@TZ, GMTST, LocalST) then begin
      //Converto la data nel formato corretto
      ModifyDT:=SystemTimeToDateTime(LocalST);

      //Comunico al chiamante che la conversione è andata a buon fine,
      //e ladata/ora corretta
      WrkDateTime:=ModifyDT;
      Result:=True;
    end;
  end;
end;
{$ENDIF}




{Restituisco la data & ora di ultima modifica.
 ATTENZIONE: DirInfo.Time restituisce la data di creazione, non modifica !!!}
{$IFDEF MSWINDOWS}
  {
  function  DataUltimaModifica(const NomeFile:String;TipoRitorno:TipoData):TDateTime;
  var hFile:Integer;
      ftModifica, ftCreazione, ftAccesso:TFileTime;
      sysDateTime:_SYSTEMTIME;
  begin
    Result:=CstConvDataErr;

    hFile:=0;
    try
      hFile:=CreateFile(PChar(NomeFile),
                        GENERIC_READ ,
                        FILE_SHARE_READ or FILE_SHARE_WRITE, //Faccio in modo di poter reperire la data
                        nil,                                 //anche dai files vincolati
                        OPEN_EXISTING,
                        FILE_FLAG_BACKUP_SEMANTICS,
                        0);
      if (GetLastError = 0) then begin
        GetFileTime(hFile, @ftCreazione, @ftAccesso, @ftModifica);
        if (GetLastError = 0) then begin
          FileTimeToLocalFileTime(ftModifica, ftModifica);
          FileTimeToSystemTime(ftModifica, sysDateTime);
          Result:=SystemTimeToDateTime(sysDateTime);
        end;
      end;
    finally
      if (hFile <> 0) then begin
        CloseHandle(hFile);
      end;
    end;
  end;
  }
  function  DataUltimaModifica(const NomeFile:String):TDateTime;
  var DirInfo: TSearchRec;
      UTCFileTime: TFileTime;
      WrkDateTime:TDateTime;
  begin
    Result:=CstConvDataErr;

    try
      if FindFirstUTF8(NomeFile, faAnyFile, DirInfo) = 0 then begin
        UTCFileTime:=DirInfo.FindData.ftLastWriteTime;

        if UTCFileTimeToLocalTime(UTCFileTime, WrkDateTime) then begin
          Result:=WrkDateTime;
        end;
      end;
    finally
      FindCloseUTF8(DirInfo);
    end;
  end;



  function  DataDiCreazione(const NomeFile: String): TDateTime;
  var DirInfo:TSearchRec;
      ftCreazione:TFileTime;
      WrkDateTime:TDateTime;
  begin
    Result:=CstConvDataErr;

    try
      if (FindFirstUTF8(NomeFile, faAnyFile, DirInfo) = 0) then begin
        ftCreazione:=DirInfo.FindData.ftCreationTime;

        if UTCFileTimeToLocalTime(ftCreazione, WrkDateTime) then begin
          Result:=WrkDateTime;
        end;

        {
        FileTimeToLocalFileTime(ftCreazione, ftCreazione);
        FileTimeToSystemTime(ftCreazione, sysDateTime);
        Result:=SystemTimeToDateTime(sysDateTime);
        }
      end;
    finally
      LazFileUtils.FindCloseUTF8(DirInfo);
    end;
  end;
{$ELSE}
  function  DataUltimaModifica(const NomeFile:String):TDateTime;
  var DataFile:Longint;
  begin
    DataFile:=FileAgeUTF8(NomeFile);

    //In caso di file non trovato, DataFile vale -1
    if (DataFile = -1) then begin
      Result:=CstConvDataErr;
    end else begin
      UnixTimeToLocalTime(DataFile, Result);
    end;
  end;



  function  DataDiCreazione(const NomeFile: String): TDateTime;
  var DataFile:Longint;
      DirInfo:TSearchRec;
  begin
    {
    //In linux la data di creazione di un file non viene salvata
    //https://www.cyberciti.biz/tips/understanding-unixlinux-filesystem-inodes.html

    => File type (executable, block special etc)
    => Permissions (read, write etc)
    => Owner
    => Group
    => File Size
    => File access, change and modification time (remember UNIX or Linux never stores
       file creation time, this is favorite question asked in UNIX/Linux sys admin job interview)
    => File deletion time
    => Number of links (soft/hard)
    => Extended attribute such as append only or no one can delete file including root
       user (immutability)
    => Access Control List (ACLs)

    All the above information stored in an inode.
    In short the inode identifies the file and its attributes (as above).
    Each inode is identified by a unique inode number within the file system.
    Inode is also know as index number.    }
    Result:=DataUltimaModifica(NomeFile);
  end;
{$ENDIF}






initialization
  //Questa operazione, se usata per ogni file, ad esempio perché sto elaborando un elenco,
  //potrebbe durare parecchio, quindi la lancio una volta sola
  {$IFDEF UNIX}
    ReadTimezoneFile(GetTimezoneFile);
  {$ELSE}
    GetTimeZoneInformation(TZ);
  {$ENDIF}

finalization;

end.

Ciao, Mario
« Ultima modifica: Aprile 11, 2019, 07:58:55 am da bonmario »

xinyiman

  • Administrator
  • Hero Member
  • *****
  • Post: 3249
  • Karma: +12/-0
Re:[RISOLTO] Data ultima modifica di un file su rete Microsoft
« Risposta #8 il: Aprile 10, 2019, 02:11:10 pm »
Ok, solo un consiglio spassionato. Non usare
Codice: [Seleziona]
{$IFDEF LINUX}
    , Unix, unixutil
  {$ELSE}
    , windows
  {$ENDIF}
ma usa
Codice: [Seleziona]
{$IFDEF UNIX}
    , Unix, unixutil
  {$ELSE}
    , windows
  {$ENDIF}

Così dovrebbe funzionare anche su mac. In quanto mac osx ha un kernel freebsd derivato.
Ieri è passato, domani è futuro, oggi è un dono...

bonmario

  • Hero Member
  • *****
  • Post: 1300
  • Karma: +10/-1
Re:[RISOLTO] Data ultima modifica di un file su rete Microsoft
« Risposta #9 il: Aprile 10, 2019, 03:01:22 pm »
Grazie per il consiglio ... devo solo farci l'abitudine: i miei programmi li uso a casa o al lavoro, su PC Windows o Linux, non avendoli mai compilati/usati su Mac, non ho mai avuto il problema.

P.S. Di solito faccio il contrario: if Windows ... else ... in quel caso mi sarebbe andata bene !!!

Ciao, Mario

bonmario

  • Hero Member
  • *****
  • Post: 1300
  • Karma: +10/-1
Re:[RISOLTO] Data ultima modifica di un file su rete Microsoft
« Risposta #10 il: Aprile 11, 2019, 08:01:35 am »
Ok, solo un consiglio spassionato. Non usare ....


Ciao,
ho "sistemato" il codice postato nel messaggio precedente seguendo il tuo consiglio e facendo un paio di piccole correzioni nel codice specifico per Linux/Unix.

Ciao, Mario

 

Recenti

How To

Utenti
  • Utenti in totale: 785
  • Latest: gmax
Stats
  • Post in totale: 18769
  • Topic in totale: 2232
  • Online Today: 80
  • Online Ever: 900
  • (Gennaio 21, 2020, 08:17:49 pm)
Utenti Online
Users: 0
Guests: 52
Total: 52

Disclaimer:

Questo blog non rappresenta una testata giornalistica poiché viene aggiornato senza alcuna periodicità. Non può pertanto considerarsi un prodotto editoriale ai sensi della legge n. 62/2001.