Avatar billede aaboe Nybegynder
23. januar 2002 - 19:55 Der er 45 kommentarer og
3 løsninger

Sekunder siden 1970-01-01 00:00:00

I forbindelse med at skrive noget i en MySql database, skal jeg bruge en funktion i Delphi, der kan konvertere dag dato klokken nu til antal sekunder siden 1970-01-01 00:00:00. Findes der ikke en smart funktion i Delphi til dette formål?

/Torsten
Avatar billede angelod Novice
23. januar 2002 - 19:59 #1
Jeg bruger denne kode som jeg fandt på en eller anden side:

unixtime := (YourDateTime-EncodeDate(1970,1,1)) * SecsPerDay;
Avatar billede angelod Novice
23. januar 2002 - 20:01 #2
SecsPerDay := 86400;

Mener jeg det er (24*60*60).
Avatar billede morten_s Nybegynder
23. januar 2002 - 20:02 #3
Hvis du bruger tabel komponent kan du bruge AsDateTime, den kaster for dig

Hvis du bruger Query er der et eksempel neden under, AlDate er af typen Date, og alTime er af typen time

  DateTimeToString(TestAlDate,'yyyy-mm-dd',Now);
  TestAlTime := Now;
  QueryMakeAl := TmySQLQuery.Create(Self);
  if MyDB.Connected then
  with QueryMakeAl do
  begin
    Database := MyDB;
    Close;
    SQL.Text := 'SELECT MAX(ID) as NextID FROM aldb';
    Open;
    NextId := FieldByName('NextID').AsInteger + 1;
    DisableControls;
    SQL.Clear;
    SQL.Add('INSERT INTO aldb (Id, AppNo, AlType, AlDate, AlTime, AlText) ' +
            ' VALUES ('''+ IntToStr(NextId)+ ''','''+
                      '1'','''+
                      ''+ IntToStr(TestAlType) +''','''+
                      ''+ TestAlDate + ''',''' +
                      ''+ TimeToStr(TestAlTime) + ''',''' +
                      'Test alarm nr:  ' +IntToStr(TestAlNo)+''')');
    MessageMemo.Lines.Add(sql.text);
    ExecSQL;
    EnableControls;
  end;
  Inc(TestAlNo);
  QueryMakeAl.Free;
end;
Avatar billede angelod Novice
23. januar 2002 - 20:04 #4
Hmm.. Så vil jeg da mene at den metode jeg har fundet er lidt nemmere. O_o
Avatar billede morten_s Nybegynder
23. januar 2002 - 20:07 #5
det kan jeg ikke afvise :)
Avatar billede angelod Novice
23. januar 2002 - 20:09 #6
Hæhæ. Jeg sad og arbejdede med at gennemskue den, og var inde på noget af det rigtige.. Til sidst opgav jeg og fandt denne funktion. Lille og simpel. :o)
Avatar billede morten_s Nybegynder
23. januar 2002 - 20:10 #7
Men hvis det er et tabelkomponent kan han jo gemme direkte

MySqlTabel.FieldByName('DatoFelt').AsDateTime := Now
Avatar billede angelod Novice
23. januar 2002 - 20:12 #8
Hmm.. Ja det er jo rigtigt nok. :o)

Min var mere generelt. :o)
Avatar billede aaboe Nybegynder
23. januar 2002 - 20:26 #9
Ok, UnixTime er af typen extended.

Bruger jeg unixtime := (EncodeDate(2002,1,1)-EncodeDate(1970,1,1))

er værdien af unixtime = 0 ?? nogen logisk forklaring, og hvordan konverterer jeg efterfølgende unixtime til en string?
Avatar billede morten_s Nybegynder
23. januar 2002 - 20:30 #10
Men EncodeDate er af typen datetime

procedure TForm1.Button1Click(Sender: TObject);
var
  UnixTime : TDateTime;
begin
  UnixTime := (EncodeDate(2002,1,1)-EncodeDate(1970,1,1));
  ShowMessage(DateTimeToStr(UnixTime));
end;
Avatar billede stoney Nybegynder
23. januar 2002 - 20:33 #11
Hvis du bruger D6 er der en indbugget functione til det secondsbetween

Husk at tilføje dateutils i uses

procedure TForm1.Button1Click(Sender: TObject);
begin
showmessage('Sekunder siden 1970: ' +inttostr(secondsbetween(now, 01-01-1970 )));

end;

Stoney
Avatar billede aaboe Nybegynder
23. januar 2002 - 20:40 #12
Desværre, jeg bruger Delphi 5.

Men nu har jeg så forskellen i variablen UnixTime, men hvordan får jeg så at vide hvor mange sekunder, det er?
Avatar billede angelod Novice
23. januar 2002 - 20:42 #13
Det skrev jeg altså også. Gang tallet du får med antallet af sekunder på et døgn..

unixtime := (EncodeDate(2002,1,1)-EncodeDate(1970,1,1)) * 86400;
Avatar billede morten_s Nybegynder
23. januar 2002 - 20:42 #14
Du ganger det vel bare sammen (antalår*365+antaldage)*24*60*60
Avatar billede stoney Nybegynder
23. januar 2002 - 20:45 #15
morten_s>>  hvad når det er skudår ?

Stoney
Avatar billede angelod Novice
23. januar 2002 - 20:45 #16
DateTime indeholder antallet af dage siden, et eller andet tidspunkt.
Avatar billede morten_s Nybegynder
23. januar 2002 - 20:46 #17
Jep
The integral part of a TDateTime value is the number of days that have passed since 12/30/1899
Avatar billede aaboe Nybegynder
23. januar 2002 - 20:48 #18
Men hvordan viser jeg så resultatet på f.eks. på en messagebox?
Avatar billede angelod Novice
23. januar 2002 - 20:50 #19
Hmm.. Du kan jo konvertere tiden til en int og så bruge IntToStr. :o)
Avatar billede morten_s Nybegynder
23. januar 2002 - 20:52 #20
Jeg forstår stadig ikke hvorfor den skal over i sekunder, når du kan typecaste til din MySql db sådanher

MySqlTabel.FieldByName('DatoFelt').AsDateTime := Now;
Avatar billede stoney Nybegynder
23. januar 2002 - 20:54 #21
morten_s: Jeg mente når du ville gange med 365.

Jeres løsning giver stadig ikke et nøjagtigt resultat.

Hvis du i dag kl. 14 og kl. 16 spørger hvor mange sekunder der er gået
siden i går kl. 18, vil Tdatetime sige 1 dag * 86400 uanset om det er kl 14 eller 16. Håber du forstår hvad jeg mener.

Stoney
Avatar billede morten_s Nybegynder
23. januar 2002 - 20:56 #22
stoney> forstår ikke hvorfor omregningen skal foretages når der findes funktioner til at gemme i db'en uden at regne om ?
Avatar billede angelod Novice
23. januar 2002 - 20:56 #23
TDateTime indeholder et decimaltal der *vil* give det nøjagtige tal når det ganges med 86400.
Avatar billede aaboe Nybegynder
23. januar 2002 - 20:57 #24
angelod: Sådan helt præcist, det med jonglering mellem typer er ikke lige min stæke side :-(

morten_s: fordi at det så vidt jeg ved skal skrives som sekunder i INSERT statementet.
Avatar billede stoney Nybegynder
23. januar 2002 - 20:59 #25
morten_s: Jeg er heller ikke helt med, men mon ikke AABOE skal poste antal sekunder siden 1970 samtidig.

angelod: gider du uddybe dit sidste indlæg, den er jeg kke helt med på.

Stoney
Avatar billede morten_s Nybegynder
23. januar 2002 - 21:01 #26
Jeg skriver det aldrig som sekunder, jeg har normalt opdelt dato og tid i hver sin række. et insert statement laver jeg sådan her

DateTimeToString(TestAlDate,'yyyy-mm-dd',Now);
TestAlTime := Now;
DisableControls;
    SQL.Clear;
    SQL.Add('INSERT INTO aldb (Id, AppNo, AlType, AlDate, AlTime, AlText) ' +
            ' VALUES ('''+ IntToStr(NextId)+ ''','''+
                      '1'','''+
                      ''+ IntToStr(TestAlType) +''','''+
                      ''+ TestAlDate + ''',''' +
                      ''+ TimeToStr(TestAlTime) + ''',''' +
                      'Test alarm nr:  ' +IntToStr(TestAlNo)+''')');
    ExecSQL;
    EnableControls;
Værdierne bliver altså overført til MySql som strenge
Avatar billede angelod Novice
23. januar 2002 - 21:01 #27
unixtime := Int((EncodeDate(2002,1,1)-EncodeDate(1970,1,1)) * 86400);
Avatar billede morten_s Nybegynder
23. januar 2002 - 21:03 #28
for overskuelighedens skyld:

DateTimeToString(TestAlDate,'yyyy-mm-dd',Now);
TestAlTime := Now;
DisableControls;
with myQuery do
begin
    SQL.Clear;
    SQL.Add('INSERT INTO MinTabel (AlDate, AlTime) ' +
            ' VALUES ('''+ TestAlDate + ''',''' +
                      ''+ TimeToStr(TestAlTime) +''')');
    ExecSQL;
    EnableControls;
  end;
Avatar billede morten_s Nybegynder
23. januar 2002 - 21:04 #29
Og jeg er sikker på at du kan gøre det samme med et DateTime felt
alt overføres som strenge til MySql databasen
Avatar billede aaboe Nybegynder
23. januar 2002 - 21:08 #30
angelod: Problemet er bare at UnixTime stadig SKAL være en extended. Hvordan hiver jeg antal sekunder ud fra denne og f.eks. præsenterer det på en showmessage.

Tak for tålmodigheden . . .
Avatar billede morten_s Nybegynder
23. januar 2002 - 21:12 #31
aaboe> Det med sekunderne er en blindgyde, gør som jeg viser dig ovenover
du undgår konverteringsproblemerne, og koden virker hos mig
Avatar billede angelod Novice
23. januar 2002 - 21:12 #32
unixtime := Round((EncodeDate(2002,1,1)-EncodeDate(1970,1,1)) * 86400);

Sådan.. Har testet det, og det virker. :o)
Avatar billede morten_s Nybegynder
23. januar 2002 - 21:15 #33
Hvorfor Round, ryger der ikke et par sekunder i svinget :)
Avatar billede angelod Novice
23. januar 2002 - 21:19 #34
Nix. Ikke et eneste. Har testet.
Avatar billede aaboe Nybegynder
23. januar 2002 - 21:20 #35
angelod: cool, nu har jeg så det i sekunder, hvordan konverterer jeg den til en streng, som jeg kan skrive i databasen.

morten_s: Jeg synes stadig at angelods er simplest, men hvis jeg ikke kan få det til at virke, kan det være jeg giver dit eksempel en chance :-)
Avatar billede angelod Novice
23. januar 2002 - 21:22 #36
IntToStr(unixtime);

:o)
Avatar billede stoney Nybegynder
23. januar 2002 - 21:23 #37
Der er ingen tvivl om at angelod eks. virker, men med en fejlmargen
på mellem 0 og 86399 sekunder. i den mest extreme situation.

:-)

Stoney
Avatar billede morten_s Nybegynder
23. januar 2002 - 21:26 #38
Stoney> Det er da rimelig præcist ramt inden for 23 timer og 59 sek.
Avatar billede angelod Novice
23. januar 2002 - 21:29 #39
Der er ingen fejlmargen da.. Hvis han bruger EncodeDate så får han kun for dagen, ja.. Men han kan altså bruge Now som vil give det nøjagtige resultat..
Avatar billede morten_s Nybegynder
23. januar 2002 - 21:32 #40
EncodeDate giver kun dagen uanset om der bruges Now eller ej, den indeholder ikke tiden, så de sekunder der er gået i det pågældende døgn går tabt
Avatar billede angelod Novice
23. januar 2002 - 21:34 #41
Argh!! Fat det dog!

unixtime := Round((Now-EncodeDate(1970,1,1)) * 86400);

Dette vil give UNIX tiden for lige nu.
Avatar billede morten_s Nybegynder
23. januar 2002 - 21:45 #42
angelod> du er galt på den, round piller dine sekunder af now. Sekunderne står nemelig bag kommaet.

Hvis du ikke vil tro det så prøv nedenstående eksempel, du kan sætte et breakpoint på den sidste showmessage og aflæse de to værdier med og uden round

procedure TForm1.Button1Click(Sender: TObject);
var
  MinTidMedRound : TDateTime;
  MinTidUdenRound : TDateTime;
begin

  MinTidMedRound :=  Round(Now);
  ShowMessage(DateTimeToStr(MinTidMedRound));
  MinTidUdenRound := Now;
  ShowMessage(DateTimeToStr(MinTidUdenRound));

end;
Avatar billede morten_s Nybegynder
23. januar 2002 - 21:52 #43
angelod> Bemærk i øvrigt at round(now) lige runder op så det er den 24 i dag, det øger din fejmargin til 47 timer og 59 sek. :-0
Avatar billede angelod Novice
23. januar 2002 - 21:53 #44
Hey, hov.. Vent nu lige lidt!

Round afrunder det der står inde i parantesen, altså:
  (Now-EncodeDate(1970,1,1)) * 86400
Avatar billede morten_s Nybegynder
23. januar 2002 - 22:01 #45
Hvis der ingen sekunder skal mistes så må rest i nedenstående vel være 0 ?

Prøv selv

Rest := Frac( (Now-EncodeDate(1970,1,1)) * 86400);
Avatar billede angelod Novice
23. januar 2002 - 22:04 #46
Pis.. Der var noget der.. Hmm, havde testet de forkerte tal.. Underligt, må ha lavet en fejl i forhold til den funktion jeg fandt.. Den virkede nemlig.. Hmm.. :/
Avatar billede aaboe Nybegynder
23. januar 2002 - 23:07 #47
Så virker det!

Jeg fik angelods løsning til at virke, og det spiller bare. Dog skulle jeg trække 3600 sekunder fra resultatet, hvilket må skyldes noget med vinter/sommertid.

Jeg havde ingen problemer med at der var noget, der blev rundet forkert af. Tidspunkterne passer helt perfekt.

Tak for alle de gode forslag, og tålmodigheden :-).
Avatar billede angelod Novice
23. januar 2002 - 23:10 #48
Takker :o)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester