2012-01-03 34 views
6

Tôi có cấu hình máy chủ-thiết bị mà tôi cần thay đổi cấu hình ngày trang bị, sử dụng UDP. Máy chủ được viết bằng Java và thiết bị, trong Delphi.Ngày chuyển đổi trong Java thành số nguyên và sau đó đến Delphi Time

Vì vậy, dòng chảy của dữ liệu là thế này:

Java server (Java date) -> UDP (integer date) -> Delphi equipment (Delphi date)

Vấn đề là khi tôi vượt qua ngày như một số nguyên, java tính toán miliseconds từ năm 1970, và Delphi, giây. Tôi vượt qua sau đó ngày như sau: today.getTime()/1000, nhưng thiết bị hiểu điều này như là một năm 2008, khi chúng tôi đang trên 2012.

Tôi có thể thay đổi mã Java, nhưng thiết bị là bên thứ 3 và tôi không có truy cập vào mã nguồn của nó.

Có sự khác biệt giữa phân tích ngày tháng Java và Delphi cho phép sự khác biệt này?

EDIT: Nhờ MДΓΓ БДLL tôi nhận thấy tôi đã nhân với 1.000 thay vì chia cho nó, tôi bây giờ có một ngày tốt hơn, nhưng vẫn sai (được somewhen trong năm 2033, bây giờ nó là vào năm 2008).

+4

Tôi hoàn toàn không hiểu. Bạn cần phải đi từ mili giây từ năm 1970 đến giây (từ năm 1970?) Nhưng bạn đang _multiplying_ bằng 1000? Mili giây => giây có nghĩa là _divide_ trước 1000. –

+3

Tôi không biết bất kỳ loại Ngày nào trong Delphi là giây kể từ năm 1970. Bạn có chắc đây là câu hỏi Delphi không? –

+0

Doh! Tôi đã thực sự nhân thay vì chia ... nhưng nó vẫn không khắc phục được sự cố, xem chỉnh sửa –

Trả lời

4

Dấu thời gian Unix giống với dấu thời gian được sử dụng trong Java. Mặt khác, TDateTime của Delphi dựa trên ngày bắt đầu là 12:01 sáng ngày 12/30/1899 (đó là một điều tương thích COM), do đó, một số chuyển đổi là cần thiết. Những chức năng này sẽ làm điều đó; Tôi cũng đã thêm một đoạn mã thử nghiệm nhanh để hiển thị chuyển đổi hoạt động chính xác theo cả hai cách.

const 
    UnixStartDate = 25569.0; 

function DateTimeToUnixTime(const ADateTime: TDateTime): Cardinal; 
begin 
    Result := Round(ADateTime - UnixStartDate) * 86400; 
end; 

function UnixTimeToDateTime(const UnixDate: Cardinal): TDateTime; 
begin 
    Result := UnixDate/86400 + UnixStartDate; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
var StartDate: TDateTime; 
    UnixDate: Cardinal; 
begin 
    StartDate := Date(); 
    Memo1.Lines.Add('Start Date: ' + DateToStr(StartDate)); 
    UnixDate := DateTimeToUnixTime(StartDate); 
    Memo1.Lines.Add('DateTimeToUnixTime = ' + IntToStr(UnixDate)); 
    Memo1.Lines.Add('UnixTimeToDateTime = ' + DateToStr(UnixTimeToDateTime(UnixDate))); 
end; 
+0

Đối với tất cả các thuộc địa không phải là thuộc địa (? Tôi nghĩ người Anh chịu trách nhiệm cho định dạng đó?), Người không biết gì về '12: 01 AM' là .. nó là '0: 01' NOT' 12: 01';) – Voo

+0

It's '0001' hoặc '0: 01' cho những người sử dụng thời gian 24 giờ; trong 12 giờ (AM/PM) định dạng đó là '12:01 AM' như tôi đã nói. :) –

+0

Vâng tôi chỉ muốn làm cho nó có vẻ thú vị hơn một chút;) Nhưng như một người lớn lên với hệ thống 24hour bản thân mình tôi nghĩ nó bảo đảm một số đề cập đến như bạn sẽ không tin có bao nhiêu người (ít nhất là ở Đức/Áo) sẽ giải thích trực quan '12:01 AM' là '12: 01' - hoặc sẽ bị bẻ khóa tại sao chính xác bất kỳ giá trị nào lớn hơn' 12: 00' được phép trong một hệ thống thời gian 12 giờ để bắt đầu. – Voo

6

đơn vị DateUtils Delphi có UnixToDateTime()DateTimeToUnix() chức năng để chuyển đổi giữa TDateTime và Unix timestamps được trình bày như giây từ kỷ nguyên Unix (ngày 01 tháng 1 1970 00:00:00 GMT):

// 1325606144 = Jan 3 2012 3:55:44 PM GMT 

uses 
    DateUtils; 

var 
    DT: TDateTime; 
    Unix: Int64; 
begin 
    DT := UnixToDateTime(1325606144); 
    // returns Jan 3 2012 3:55:44 PM 

    Unix := DateTimeToUnix(EncodeDate(2012, 1, 3) + EncodeTime(15, 55, 44, 0)); 
    // returns 1325606144 
end; 

Lớp Java của Date, mặt khác, dựa trên mili giây từ kỷ nguyên Unix thay thế. Đó là dễ dàng để đưa vào tài khoản, mặc dù:

uses 
    DateUtils; 

function JavaToDateTime(Value: Int64): TDateTime; 
begin 
    Result := UnixToDateTime(Value div 1000); 
end; 

function DateTimeToJava(const Value: TDateTime): Int64; 
begin 
    Result := DateTimeToUnix(Value) * 1000; 
end; 

Hoặc:

uses 
    SysUtils, DateUtils; 

// UnixDateDelta is defined in SysUtils... 

function JavaToDateTime(Value: Int64): TDateTime; 
begin 
    Result := IncMilliSecond(UnixDateDelta, Value); 
end; 

function DateTimeToJava(const Value: TDateTime): Int64; 
begin 
    Result := MilliSecondsBetween(UnixDateDelta, Value); 
    if Value < UnixDateDelta then 
    Result := -Result; 
end; 

Dù bằng cách nào:

// 1325606144000 = Jan 3 2012 3:55:44 PM GMT 

var 
    DT: TDateTime; 
    Java: Int64; 
begin 
    DT := JavaToDateTime(1325606144000); 
    // returns Jan 3 2012 3:55:44 PM 

    Java := DateTimeToJava(EncodeDate(2012, 1, 3) + EncodeTime(15, 55, 44, 0)); 
    // returns 1325606144000 
end; 
+0

Điều này không hiệu quả đối với tôi. Hàm này trả về giá trị TDateTime từ năm 43.000. – TomC

+0

Sau đó, bạn không sử dụng chính xác. –

+0

Hãy cảm thấy tự do để khai sáng cho tôi về cách sử dụng đúng hơn là để nói rằng tôi đã sử dụng nó không chính xác. Tôi đã thành công khi sử dụng hàm JavaToDelphiDateTime từ gói SuperObject được Delphi-OOP sử dụng. – TomC

3

Theo tôi biết ngày Java dựa trên tính theo giờ UTC do đó bạn cũng có để chuyển đổi giờ địa phương từ/sang UTC. Các chức năng này sử dụng mili giây, điều chỉnh mã theo nhu cầu của bạn.

function TzSpecificLocalTimeToSystemTime(
    lpTimeZoneInformation: PTimeZoneInformation; 
    lpLocalTime, lpUniversalTime: PSystemTime): BOOL; stdcall; external 'kernel32.dll'; 

function SystemTimeToTzSpecificLocalTime(
    lpTimeZoneInformation: PTimeZoneInformation; 
    lpUniversalTime, lpLocalTime: PSystemTime): BOOL; stdcall; external 'kernel32.dll'; 

function JavaToDelphiDateTime(const dt: int64): TDateTime; 
var 
    t: TSystemTime; 
begin 
    DateTimeToSystemTime(25569 + (dt/86400000), t); 
    SystemTimeToTzSpecificLocalTime(nil, @t, @t); 
    Result := SystemTimeToDateTime(t); 
end; 

function DelphiToJavaDateTime(const dt: TDateTime): int64; 
var 
    t: TSystemTime; 
begin 
    DateTimeToSystemTime(dt, t); 
    TzSpecificLocalTimeToSystemTime(nil, @t, @t); 
    Result := Round((SystemTimeToDateTime(t) - 25569) * 86400000) 
end; 
1

Lấy gói superobect JSON từ www.progdigy.com và trích xuất các chức năng JavaToDelphiDateTime và etc. từ các tệp nguồn.

Cập nhật ngày 3 tháng 3 năm 2014:

Progdigy.com không còn phục vụ những tập tin này. Tải tệp từ Google. Tệp 1.2.4 ZIP chính thức trong phần tải xuống http://code.google.com/p/superobject/downloads/list ngày từ năm 2010 nhưng các tệp riêng lẻ trong http://code.google.com/p/superobject/source/browse có các bản cập nhật cho đến tháng 10 năm 2012.

Bạn phải sử dụng các tệp được cập nhật đó vì có lỗi tối nghĩa trong chuyển đổi datetime xảy ra xung quanh việc chuyển sang thời gian tiết kiệm ánh sáng ban ngày trong leapyears.

Các vấn đề liên quan