I am trying to generate random Tdatetime values in given range in delphi 5 lets say we have two dates in the follow format
date1=01/01/2018 12:35:32
date2=05/01/2018 21:35:32
i want to generate exaclty "x" dates increased between this range. As an example i would like to generate 7 Dates from range date1->date2
randomdate[0]:=01/01/2018 12:35:32
randomdate[1]:=01/01/2018 14:35:12
randomdate[2]:=01/01/2018 16:42:22
randomdate[3]:=02/01/2018 21:12:01
randomdate[4]:=03/01/2018 11:13:12
randomdate[5]:=04/01/2018 22:20:05
randomdate[6]:=05/01/2018 20:30:05
the problem is that if second random date rich the date2 then all other dates must be the same as date2 but if the time gets 23:59:59 next date will be out of range
like the folow senario
randomdate[0]:=01/01/2018 12:35:32
randomdate[1]:=05/01/2018 23:59:59
.................................
!! all dates from now on will be
06/01/2018 23:59:59
which is out of my range !!
any help will be appreciate it
After Andreas Suggestion here is the finally code who works on D5 so i guess works on all other versions of delphi
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ComCtrls;
type
TForm1 = class(TForm)
RichEdit1: TRichEdit;
Edit1: TEdit;
Edit2: TEdit;
Button1: TButton;
Edit3: TEdit;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
function SecondsBetween(const Time1, Time2: TDateTime): Longint;
const SecsPerMin=60;
const MinsPerHour=60;
const HoursPerDay=24;
begin
result := Round(SecsPerMin * MinsPerHour * HoursPerDay * Abs(Time2 - Time1));
end;
function RandomDateTime( AFrom, ATo: TDateTime): TDateTime;
var
SecsBetween: int64;
begin
SecsBetween := SecondsBetween(AFrom,ATo);
result := AFrom + (Round(SecsBetween * Random) / (60*60*24));
end;
function CreateSortedListOfRandomDatetimes( AFrom, ATo: TDateTime; N: integer): TStringlist;
var
i: Integer;
begin
result := Tstringlist.Create;
try
// result.Capacity := N; // for an unnoticeable increase in performance
for i := 1 to N do result.Add(formatdatetime('dd/mm/yyyy hh:nn:ss',RandomDateTime(AFrom, ATo)));
result.Sort;
except
result.Free;
raise;
end;
end;
//edit1 Holds the 1st date which is 04/09/2018 16:00:00
//edit2 hold the 2nd date
//edit3 holds the N count value
procedure TForm1.Button1Click(Sender: TObject);
var
timestamps: Tstringlist;
i: Integer;
d1:Tdatetime;
d2:Tdatetime;
begin
d1:=StrtoDatetime(edit1.text);
d2:=StrtoDatetime(edit2.text);
timestamps := CreateSortedListOfRandomDatetimes(d1,d2 ,strtoInt(edit3.text));
try
RichEdit1.Lines.BeginUpdate;
try
RichEdit1.Lines.Clear;
for i := 0 to timestamps.Count - 1 do
RichEdit1.Lines.Add(timestamps.strings[i])
finally
RichEdit1.Lines.EndUpdate;
end;
finally
timestamps.Free;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
randomize;
end;
end.
A function to generate a random TDateTime
value between two fixed values can be written like this ( uses DateUtils
):
function RandomDateTime(const AFrom, ATo: TDateTime): TDateTime;
var
SecsBetween: Int64;
begin
SecsBetween := SecondsBetween(AFrom, ATo);
result := IncSecond(AFrom, Round(SecsBetween * Random));
end;
To create a sorted list of these, use your favourite sorting method. In modern Delphi, you could use the built-in generic list:
function CreateSortedListOfRandomDatetimes(const AFrom, ATo: TDateTime; N: integer): TList<TDateTime>;
var
i: Integer;
begin
result := TList<TDateTime>.Create;
try
result.Capacity := N; // for an unnoticeable increase in performance
for i := 1 to N do
result.Add(RandomDateTime(AFrom, ATo));
result.Sort;
except
result.Free;
raise;
end;
end;
Try it out:
procedure TForm1.FormCreate(Sender: TObject);
var
timestamps: TList<TDateTime>;
i: Integer;
begin
timestamps := CreateSortedListOfRandomDatetimes(
EncodeDateTime(2000, 1, 1, 0, 0, 0, 0),
EncodeDateTime(2000, 12, 31, 23, 59, 59, 999),
10
);
try
RichEdit1.Lines.BeginUpdate;
try
RichEdit1.Lines.Clear;
for i := 0 to timestamps.Count - 1 do
RichEdit1.Lines.Add(DateTimeToStr(timestamps[i]))
finally
RichEdit1.Lines.EndUpdate;
end;
finally
timestamps.Free;
end;
end;
(This approach may produce duplicate datetimes. The Q didn't explicitly mention if this is allowed or not. Also, it only works at second precision, not millisecond precision. You may want to change that, or at least remove the millisecond from AFrom
.)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.