Autor Beitrag
Flamefire
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 30

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: Di 13.07.10 18:54 
Ich veröffentliche hier eine Unit zur alternativen TDateTime Behandlung. Sie funktioniert auf der Basis von Int64 und ist bis auf 1s genau.
Verwendet wird sie wie TDateTime mit Ausnahme des Prefixes "My"

Die unit ist vor einer Weile in einem anderen Projekt entstanden und wird von mir nicht weiter gewartet.
Sie funktioniert aber ohne bekannte Fehler.

Erklärung: In dem Int64 Wert werden die Sekunden seit Beginn der Zeitzählung gespeichert.

Unit als DL (pas, 6.13 KB)

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
{

  ***** BEGIN LICENSE BLOCK *****
  Version: MPL 1.1/GPL 2.0/LGPL 2.1

  The contents of this file are subject to the Mozilla Public License Version
  1.1 (the "License"); you may not use this file except in compliance with
  the License. You may obtain a copy of the License at
  http://www.mozilla.org/MPL/

  Software distributed under the License is distributed on an "AS IS" basis,
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  for the specific language governing rights and limitations under the
  License.

  The Original Code is MyDateUtils;

  The Initial Developer of the Original Code is Flamefire.
  Portions created by the Initial Developer are Copyright (C) 2010
  the Initial Developer. All Rights Reserved.

  Contributor(s):


  Alternatively, the contents of this file may be used under the terms of
  either the GNU General Public License Version 2 or later (the "GPL"), or
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  in which case the provisions of the GPL or the LGPL are applicable instead
  of those above. If you wish to allow use of your version of this file only
  under the terms of either the GPL or the LGPL, and not to allow others to
  use your version of this file under the terms of the MPL, indicate your
  decision by deleting the provisions above and replace them with the notice
  and other provisions required by the GPL or the LGPL. If you do not delete
  the provisions above, a recipient may use your version of this file under
  the terms of any one of the MPL, the GPL or the LGPL.

  ***** END LICENSE BLOCK *****
}


unit MyDateUtils;

interface

uses Windows,SysUtils,DateUtils;

type
  TMyDate=Int64;

const SecsPerHour=SecsPerMin*60;

function MyDateTimeToStr(DateTime:TMyDate;second:boolean=false):String;
function MyDateToStr(DateTime:TMyDate):String;
function MyTimeToStr(DateTime:TMyDate;second:boolean=false):String;
function MyDate():TMyDate;
function MyTime():TMyDate;
function Jetzt():TMyDate;
procedure AddSeconds(var DateTime:TMyDate;ss:Integer=1);
procedure AddMinute(var DateTime:TMyDate;mm:Integer=1);
procedure AddHour(var DateTime:TMyDate;hh:Integer=1);
procedure AddDay(var DateTime:TMyDate;dd:Integer=1);
procedure AddMonth(var DateTime:TMyDate;m:Integer=1);
procedure AddYear(var DateTime:TMyDate;y:Integer=1);
function MyEncodeDateTime(const AYear, AMonth, ADay, AHour, AMinute, ASecond:Word): TMyDate;
function MyMonthsBetween(const ANow, AThen: TMyDate): Integer;
function MyDaysBetween(const ANow, AThen: TMyDate): Integer;
function MyHoursBetween(const ANow, AThen: TMyDate): Integer;
function MyMinutesBetween(const ANow, AThen: TMyDate): Integer;
function MySecondsBetween(const ANow, AThen: TMyDate): Integer;
function myDayOf(const AValue: TMyDate): Word;
function myMonthOf(const AValue: TMyDate): Word;
function MyIsValidTime(const AHour, AMinute, ASecond: Word): Boolean;
function MyIsValidDate(const AYear, AMonth, ADay: Word): Boolean;

implementation

function MyDateTimeToStr(DateTime:TMyDate;second:boolean=false):String;
begin
  Result:=MyDateToStr(DateTime)+' '+MyTimeToStr(DateTime,second);
end;

function MyDateToStr(DateTime:TMyDate):String;
begin
  Result:=FormatDateTime('dd"."mm"."',DateTime div SecsPerDay);
end;

function MyTimeToStr(DateTime:TMyDate;second:boolean=false):String;
var h,m,s:Integer;
begin
  s:=DateTime mod SecsPerDay;
  m:=s div 60;
  s:=s mod 60;
  h:=m div 60;
  m:=m mod 60;
  Result:=Result+Format('%.2d:%.2d',[h,m]);
  If(second) then Result:=Result+Format(':%.2d',[s]);
end;

function MyTime:TMyDate;
var SystemTime: TSystemTime;
begin
  GetLocalTime(SystemTime);
  with SystemTime do
    Result:=(wHour*60+wMinute)*SecsPerMin+wSecond;
end;

function MyDate:TMyDate;
begin
  Result:=Trunc(Date)*SecsPerDay;
end;

function Jetzt():TMyDate;
begin
  Result:=MyDate+MyTime;
end;

procedure AddSeconds(var DateTime:TMyDate;ss:Integer=1);
begin
  Inc(DateTime,ss);
end;

procedure AddMinute(var DateTime:TMyDate;mm:Integer=1);
begin
  Inc(DateTime,mm*SecsPerMin);
end;

procedure AddHour(var DateTime:TMyDate;hh:Integer=1);
begin
  Inc(DateTime,hh*SecsPerHour);
end;

procedure AddDay(var DateTime:TMyDate;dd:Integer=1);
begin
  Inc(DateTime,dd*SecsPerDay);
end;

procedure AddMonth(var DateTime:TMyDate;m:Integer=1);
var tmp:TMyDate;
begin
  tmp:=DateTime mod SecsPerDay;
  DateTime:=Trunc(IncMonth(DateTime div SecsPerDay,m))*SecsPerDay+tmp;
end;

procedure AddYear(var DateTime:TMyDate;y:Integer=1);
var tmp:TMyDate;
begin
  tmp:=DateTime mod SecsPerDay;
  DateTime:=Trunc(IncYear(DateTime div SecsPerDay,y))*SecsPerDay+tmp;
end;

function MyEncodeDateTime(const AYear, AMonth, ADay, AHour, AMinute, ASecond:Word): TMyDate;
var Date:TDateTime;
begin
  Result:=0;
  If(not TryEncodeDate(AYear,AMonth,ADay,Date)) then
    InvalidDateTimeError(AYear, AMonth, ADay, AHour, AMinute, ASecond, 0)
  else
    Result:=Trunc(Date)*SecsPerDay+AHour*SecsPerHour+AMinute*SecsPerMin+ASecond;
end;

function MyMonthsBetween(const ANow, AThen: TMyDate): Integer;
begin
  Result:=MonthsBetween(ANow div SecsPerDay,AThen div SecsPerDay);
end;

function MyDaysBetween(const ANow, AThen: TMyDate): Integer;
begin
  Result:=DaysBetween(ANow div SecsPerDay,AThen div SecsPerDay);
end;

function MyHoursBetween(const ANow, AThen: TMyDate): Integer;
begin
  Result:=MySecondsBetween(ANow,AThen) div SecsPerHour;
end;

function MyMinutesBetween(const ANow, AThen: TMyDate): Integer;
begin
  Result:=MySecondsBetween(ANow,AThen) div SecsPerMin;
end;

function MySecondsBetween(const ANow, AThen: TMyDate): Integer;
begin
  Result:=AThen-ANow;
end;

function myDayOf(const AValue: TMyDate): Word;
begin
  Result:=DayOf(AValue div SecsPerDay);
end;

function myMonthOf(const AValue: TMyDate): Word;
begin
  Result:=MonthOf(AValue div SecsPerDay);
end;

function MyIsValidTime(const AHour, AMinute, ASecond: Word): Boolean;
begin
  Result:=IsValidTime(AHour,AMinute,ASecond,0);
end;

function MyIsValidDate(const AYear, AMonth, ADay: Word): Boolean;
begin
  Result:=IsValidDate(AYear,AMonth,ADay);
end;

end.
Einloggen, um Attachments anzusehen!


Zuletzt bearbeitet von Flamefire am Sa 17.07.10 00:41, insgesamt 1-mal bearbeitet
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Mi 14.07.10 16:31 
Was ist denn an TMyDate besser als TDateTime; was gibt es für Gründe die hier zu nehmen?

Ein paar Tipps:
- Ich würde einen anderen Namen als "My" geben.
- Deklariere TMyDate als "type Int64" statt "Int64".
- Eine Konvertierungsfunktion von/nach TDateTime wäre sicher nützlich.
- Was ist "uses Chat"?
- Deutsche Funktionsnamen sind unüblich.
- Funktioniert deine Unit auch bei negativen Zahlen korrekt (ich glaube nicht)?
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Moderator
Beiträge: 3655
Erhaltene Danke: 594

Win XP x86, Win 8.1 x64
Lazarus Snapshot; Delphi 7,2007,XE; PHP (PHPEdit,PhpStorm); JS; Java(Eclipse)
BeitragVerfasst: Mi 14.07.10 16:34 
Und was sie (IMHO) völlig disqualifiziert:
user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
Erklärung: In dem Int64 Wert werden die Sekunden seit Beginn der Zeitzählung gespeichert.

Warum sowas, und nicht wenigstens Unix-kompatible Mikrosekunden?

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Mi 14.07.10 16:41 
Ein paar Unit-Tests würden sicher nicht schaden:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
var
  MyDate: TMyDate;
begin
  MyDate := MyEncodeDateTime(180011000);
  AddHour(MyDate, 8);
  ShowMessage(MyDateTimeToStr(MyDate)); // output: 02.01. -16:00, expected: 01.01.1800 08:00
end;
matze
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 4613
Erhaltene Danke: 24

XP home, prof
Delphi 2009 Prof,
BeitragVerfasst: Fr 16.07.10 21:43 
Und wo liegt der Vorteil zu TDateTime?

_________________
In the beginning was the word.
And the word was content-type: text/plain.
Flamefire Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 30

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: Sa 17.07.10 00:38 
user profile icondelfiphan hat folgendes geschrieben Zum zitierten Posting springen:
Was ist denn an TMyDate besser als TDateTime; was gibt es für Gründe die hier zu nehmen?

Das hier ist nur ein Ansatz eine andere Variante der Zeitspeicherung zu nehmen. Bei vielen Operationen (Minuten/Sekunden/Stunden verändern) ist es deutlich genauer. (Man rechne mal 1/(60*60*24), was einer Sekunde in TDateTime entspricht) Außerdem habe ich Bugs in einer DLL bei Verwendung der TDateTime Werte festgestellt. Daraus ist diese Unit entstanden.
Es ist z.T. eine Art Wrapper zu TDateTime (es werden einige Standartfkt aufgerufen)

user profile icondelfiphan hat folgendes geschrieben Zum zitierten Posting springen:
Ein paar Tipps:
- Ich würde einen anderen Namen als "My" geben.

Ist halt so entstanden...

user profile icondelfiphan hat folgendes geschrieben Zum zitierten Posting springen:
- Deklariere TMyDate als "type Int64" statt "Int64".

Hö???

user profile icondelfiphan hat folgendes geschrieben Zum zitierten Posting springen:
- Eine Konvertierungsfunktion von/nach TDateTime wäre sicher nützlich.

Hm stimmt...Im Prinzip einfach ein Round(theDateTime*SecsPerHour*24)

user profile icondelfiphan hat folgendes geschrieben Zum zitierten Posting springen:
- Was ist "uses Chat"?

Sinnfreies Artefakt ;-)

user profile icondelfiphan hat folgendes geschrieben Zum zitierten Posting springen:
- Deutsche Funktionsnamen sind unüblich.

War halt nur schnell zusammengeschrieben, da ich was brauchte, was läuft

user profile icondelfiphan hat folgendes geschrieben Zum zitierten Posting springen:
- Funktioniert deine Unit auch bei negativen Zahlen korrekt (ich glaube nicht)?

Dürfte nicht. Es gelten die gleichen Beschränkungen des Wertebereiches wie bei TDateTime

@Martok: AFAIK bietet mind. PHP bei time() die Sekunden. Es dürfte theoretisch (ist schon ne Weile her) 1:1 kompatibel sein.

@Fehler: Wie gesagt: Wertebereich ist auf den von TDateTime beschränkt. Irgendwas um 19xx aufwärts.