TDateTime To ShortDateString In Satellite Forms "VB-clone"
I am trying to find a calculation that will convert the TDateTime value 40653.6830593 into a year, a month, a day, an hour, a minute and a second.
I am sure this is possible, of course, but my brain doesn't 开发者_如何学Chave the power, it seems, to write a formula that will extract those values from that double.
I am using a Satellite Forms, a vb-like language, but don't expect that I would need any specific .NET libraries to do this, right? It should just be a numeric calculation... right?
Thanks for the help! Most sincerely.
Joe
Based on your 'Delphi' tag...
In Delphi
implementation
uses DateUtils;
....
var
MyDate: TDateTime;
...other vars...
begin
MyDate:= double(40653.6830593);
MyYear:= YearOf(MyDate);
MyMonth:= MonthOf(MyDate);
MyDay:= DayOf(MyDate);
MyHour:= HourOf(MyDate);
MyMinute:= ... ah well you get the idea.
BTW: VB or Delphi, which is it?
If you want to roll your own
From the sysutils unit (released under a dual license GPL2/Borland No nonsense)
Which you can find at: http://www.koders.com/delphi/fidF6715D3FD1D4A92BA7F29F96643D8E9D11C1089F.aspx?s=hook
function DecodeDateFully(const DateTime: TDateTime; var Year, Month, Day, DOW: Word): Boolean;
const
D1 = 365;
D4 = D1 * 4 + 1;
D100 = D4 * 25 - 1;
D400 = D100 * 4 + 1;
var
Y, M, D, I: Word;
T: Integer;
DayTable: PDayTable;
begin
T := DateTimeToTimeStamp(DateTime).Date;
if T <= 0 then
begin
Year := 0;
Month := 0;
Day := 0;
DOW := 0;
Result := False;
end else
begin
DOW := T mod 7 + 1;
Dec(T);
Y := 1;
while T >= D400 do
begin
Dec(T, D400);
Inc(Y, 400);
end;
DivMod(T, D100, I, D);
if I = 4 then
begin
Dec(I);
Inc(D, D100);
end;
Inc(Y, I * 100);
DivMod(D, D4, I, D);
Inc(Y, I * 4);
DivMod(D, D1, I, D);
if I = 4 then
begin
Dec(I);
Inc(D, D1);
end;
Inc(Y, I);
Result := IsLeapYear(Y);
DayTable := @MonthDays[Result];
M := 1;
while True do
begin
I := DayTable^[M];
if D < I then Break;
Dec(D, I);
Inc(M);
end;
Year := Y;
Month := M;
Day := D + 1;
end;
end;
function IsLeapYear(Year: Word): Boolean;
begin
Result := (Year mod 4 = 0) and ((Year mod 100 <> 0) or (Year mod 400 = 0));
end;
function TryEncodeDate(Year, Month, Day: Word; out Date: TDateTime): Boolean;
var
I: Integer;
DayTable: PDayTable;
begin
Result := False;
DayTable := @MonthDays[IsLeapYear(Year)];
if (Year >= 1) and (Year <= 9999) and (Month >= 1) and (Month <= 12) and
(Day >= 1) and (Day <= DayTable^[Month]) then
begin
for I := 1 to Month - 1 do Inc(Day, DayTable^[I]);
I := Year - 1;
Date := I * 365 + I div 4 - I div 100 + I div 400 + Day - DateDelta;
Result := True;
end;
end;
Legacy VB or VBA (even Excel) would treat a Date as the number of days since 12/30/1899, and I believe the same is true for Delphi. As such, in legacy VB/VBA, you could write
Dim myDate as Date
myDate = myDate + 40653.68303593
To get April 20, 2011 4:23:36 PM. In VB.NET, it's different, as the DateTime struct defaults to January 1, 0001.
Dim myDate As New DateTime(1899, 12, 30)
myDate = myDate.AddDays(40653.68303593)
Another user has already posted a Delphi answer.
At any rate, the basic premise is that you're adding the number of days, with the decimal portion representing the time. So in this example, 40653 full days have passed since 12/30/1899, and 0.683... partial days.
To extract Hours:
remember 1.0 = 1 day = 24 hours, thus
DayPart:= double(MyDateTime) - Floor(double(MyDateTime));
//there is a function for fraction, but I forgot the name,
//never use that stuff.
//if we want to round 0.9999999999 up from 23:59:59 to 24:00:00, do this:
if (RoundTimeUpByHalfASecond = true) then DayPart:= DayPart + (1/(24*60*60*2));
hours:= floor(DayPart*24);
minutes:= floor(DayPart*24*60) mod 60;
seconds:= minutes:= floor(DayPart*24*60*60) mod 60;
Hope that helps
精彩评论