更新:问题由@whosrdaddy解决。请参阅此问题下面的评论。
我正在尝试解决以下特殊情况:在朋友的Lazarus项目中,他尝试查询SQLite中的条目。 asString() - 方法(在显示约会的过程中)在Windows 64 Bit上返回正确的日期。但是,在32位操作系统上,只显示前两位数字('16'而不是'28 .02.2016')。可能是什么原因?
这是初始化表单的源代码:
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.6.4/css/bootstrap-datepicker3.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.6.4/locales/bootstrap-datepicker.fr.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.6.4/js/bootstrap-datepicker.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<div id="datepicker" class="input-group date" data-date-format="dd-mm-yyyy"></div>
<input type="hidden" id="my_hidden_input" class="form-control">
还有两个程序:
// Initialise Form
procedure TForm1.FormCreate(Sender: TObject);
begin
SQLite3Connection1.DatabaseName:='Kalender.sqlite';
SQLTransaction1.Database:=SQLite3Connection1;
SQLQuery1.Transaction:=SQLTransaction1;
// Create Table "tblTermine"
SQLQuery1.SQL.text := 'CREATE TABLE IF NOT EXISTS tblKalender (Datum DATETIME, Termin VARCHAR(10))';
SQLQuery1.ExecSQL;
SQLTransaction1.commit;
end;
The intended output into the TListBox would be something like this.
答案 0 :(得分:0)
您应首先将DateTime转换为Julian日期
function DateTimeToJulianDate(const Datum: TDateTime): Double;
和
SqlQuery1.SQL.text:= 'Insert into tblKalender Values (:Datum, :Termin)';
SqlQuery1.ParamByName('Datum').AsFloat := DateTimeToJulianDate(Datum);
...
SqlQuery1.ExecSQL;
测试并获得使用价值:
function TryJulianDateToDateTime(const AValue: Double; ADateTime: TDateTime):Boolean;
if TryJulianDateToDateTime(SQLQuery1.Fields[0].AsFloat,myDate)
then
ListBox1.Items.add(DateTimeToStr(myDate)+ ': ' + .....
else
ShowMessage('Not a valid Julian date');
<强>更新强>
SQLite能够将日期和时间存储为TEXT,REAL或INTEGER值:
- TEXT as ISO8601 strings(&#34; YYYY-MM-DD HH:MM:SS.SSS&#34;)。
- 真实如朱利安日数,即格林威治中午11月24日中午的天数,公元前4714年根据预示 阳历。
- INTEGER as Unix Time,自1970-01-01 00:00:00 UTC以来的秒数。
双重测试
procedure TForm1.Button3Click(Sender: TObject);
var
Datum : TDate;
myDate : TDateTime;
JulianDouble : Double;
begin
// uses ....,DateUtils
Datum := StrToDate('01.01.2013'); //German Culture settings
Memo1.Lines.Add('01/01/2013 = '+DateTimeToStr(Datum)+ ' TDate as Text');
Memo1.Lines.Add('01/01/2013 = '+FloatToStr(Datum) + ' TDate Double');
JulianDouble := DateTimeToJulianDate(Datum);
Memo1.Lines.Add('01/01/2013 = '+FloatToStr(JulianDouble) + ' Julian Double');
if TryJulianDateToDateTime(JulianDouble,myDate)
then
Memo1.Lines.Add('01/01/2013 = '+DateTimeToStr(myDate)+ ' TDate as Text')
else
ShowMessage('Not a valid Julian date');
end;
输出
01/01/2013 = 01.01.2013 TDate as Text
01/01/2013 = 41275 TDate Double
01/01/2013 = 2456293,5 Julian Double
01/01/2013 = 01.01.2013 TDate as Text
更新-2: 将Delphi TDate Double写入SQLite Date字段是错误的
您的评论告诉我您不知道问题。
当然,您可以直接将Delphi Double值写入数据库字段。并将其读回TDateTime 这很快就会导致问题。
示例:
SQLite的:
这些功能仅适用于0000-01-01 00:00:00和之间的日期 9999-12-31 23:59:59(julidan day numbers 1721059.5到5373484.5)。
对于该范围之外的日期,这些函数的结果是 未定义。强>
41275 2013/01/01 Delphi TDate Double超出上述范围!!
无法再使用SQLite自己的日期函数。
计算当前日期。
选择日期(&#39;现在&#39;);
计算当月的最后一天。
选择日期(&#39;现在&#39;,&#39;月初&#39;,&#39; +1个月&#39;,&#39; -1天&#39;);
计算给定unix时间戳1092941466的日期和时间。
选择日期时间(1092941466,&#39; unixepoch&#39;);
计算给定unix时间戳1092941466的日期和时间,并补偿您当地的时区
选择日期时间(1092941466,&#39; unixepoch&#39;,&#39; localtime&#39;);
计算自签署美国独立宣言以来的天数。
SELECT julianday(&#39; now&#39;) - julianday(&#39; 1776-07-04&#39;);
等等。
使用上述功能更改日期值会为日期 2013/01/01 提供双倍 2456293,5
如果您现在使用未经证实并将其传递给Delphi TDateTime,它将 3387/11/26 )。
这与TDateTimePicker
的最大值相差不远
2958465.5 ,意味着 9999/12/31
DateTimePicker1.DateTime := 2958465.5;
DateTimePicker1 9999/12/31
如果一个人已经知道这是错误的,那就不应该用它来崩溃。
答案 1 :(得分:0)
SQLite使用名为manifest typing的东西,这意味着如果存储(Delphi)类型的TDateTime值,SQLite将存储基础浮点值而不发出警告或消息,并为您提供值,这样您就不会请注意,SQLite不会将此视为日期时间值,除非您尝试从SQL中操作该值。
为了抵消这种情况,我使用这段SQL代码将Delphi TDateTime值转换为实际的SQL日期时间:
datetime('1900-01-01','+'||(myDateField-2)||' day')
(另见here)