Delphi 日期相关总结20190702完结篇


本文整理自网络,侵删。

 
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls,DateUtils, ComCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Button2: TButton;
    DateTimePicker1: TDateTimePicker;
    Button3: TButton;
    DateTimePicker2: TDateTimePicker;
    Button4: TButton;
    Button5: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation
uses uDateTimeByc;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  dt1:TDateTime;
begin
  {****
  格式1:2019/07/02 10:10:10
  格式2:2019-07-02 10:10:10

  程序里不统一,在字符串和日期两种类型转换时候会报错
  格式1是win7默认格式,
  格式2是软件里常用格式

  ****}

  //坑:delphi的日期是从1899-12-30 00:00:00开始
  memo1.Lines.Add(FormatDateTime('yyyy-MM-dd hh:mm:ss',0));//1899-12-30 00:00:00
  //sql server里则是 1900-01-01 00:00:00  其他数据库没做测试
  {
  declare @dt datetime
  set @dt=0
  print convert(varchar(30),@dt,120) --输出1900-01-01 00:00:00
  --所以不能在delphi里用sql语句传递数值型的日期,但传递TDateTime给sql server的datetime类型可以正常
  update 表 set 列1=12345 where 条件 这种数值类型,就会有时间偏差
  update 表 set 列1='2019-07-07' where 条件 推荐这种写法  ,数据库里日期格式不区分分隔符,都能识别

  }
  //重点:数据库里不能传递毫秒级的,delphi最好把毫秒去掉全是000,不然很容易出现这种错误:record is not found or changed by another
  //比如adoquery.fieldbyname('DT').asDatetime:=Now;这样带毫秒级别,下次修改记录就会出问题

  //日期类型转换成字符串
  memo1.Lines.Add(FormatDateTime('yyyy-MM-dd hh:mm:ss',Now));//Now取电脑当前时间
  //注:如果电脑短日期格式是YYYY/MM/dd 则,即使这里用-,结果也会是2019/07/02 10:10:10

  //日期分解合并函数:
  //EncodeDateTime()和DecodeDateTime();  用的不多

  //字符串转换成日期:
  //StrToDateTime() //这个函数,当电脑短日期格式和字符串格式不一致会报错:日期格式不对
  // 比如短日期格式:2019\07\02  写成这样 StrToDateTime('2019-07-02')就报错
  //同样,数据库adoquery.fieldbyname('DT').asstring:='2019-07-02'//也会报错

  //推荐函数:
  //不管是-还是/或者英文的日期格式都能识别
  dt1:=VarToDateTime('2019-01-01');
  Memo1.Lines.Add(FormatDateTime('yyyy-MM-dd hh:mm:ss.zzz',dt1));

end;

procedure TForm1.Button2Click(Sender: TObject);
var
  dt1,dt2:TDateTime;
begin
  Memo1.lines.Add(ConvertDT2Str(Now)); //参数默认值方便使用'YYYY-MM-DD hh:mm:ss'
  Memo1.lines.Add(ConvertDT2Str(Now,'YYYY-MM-DD'));

  //时间间隔计算 浮点计算偏差解决办法
  dt1:=VarToDateTime('2019-07-02 10:10:10');
  dt2:=VarToDateTime('2019-07-02 10:11:12');
  CalcTimeSpan2(dt1,dt2);//计算出的是秒,分的话div 60 依次类推
end;

procedure TForm1.Button3Click(Sender: TObject);
var
  dt1:tdatetime;
  s:string;
begin
  {kind属性改成Date还是time

  日期控件最好只用datetime属性,即使有的日期控件有date属性和time属性,
  控件属性直接:=赋值,不会触发相关事件,比如,赋值了datetime为 '2019-01-01 13:00:00'
  那么date属性应该是2019-01-01,time属性是13:00:00 但有些控件bug,不会跟着变,
  所以只用datetime肯定没错


  }
  datetimepicker2.Format:='yyyy-MM-dd hh:mm:ss';//hh小写是12小时制
  datetimepicker2.Format:='yyyy-MM-dd HH:mm:ss';//HH大写是24小时制
  datetimepicker2.DateTime:=VarToDateTime('2019-01-01 13:00:00');


  s:=FormatDateTime('yyyy-MM-dd',datetimepicker1.datetime)+' '//取1的日期
    + FormatDateTime('hh:mm:ss',datetimepicker2.datetime);//取2的时间
  dt1:=vartodatetime(s);//这样能保证肯定不会错
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
  //设置统一的软件时间格式,一般放在工程最前面,比如Main窗体的create下
  SetSysDateFormat;
end;

procedure TForm1.Button5Click(Sender: TObject);
begin
  Memo1.lines.Add(FormatDateTime('yyyy-MM-dd hh:mm:ss',Now));
  Memo1.lines.Add(FormatDateTime('yyyy/MM/dd hh:mm:ss',Now));
  //电脑默认是/时候上面结果不同
  //电脑短日期改成yyyy-MM-dd,则上面结果相同 ,都是 yyyy-MM-dd
  

  Memo1.lines.Add(FormatDateTime('yyyyMMdd',Now));//不带分隔符


  //下面自己写的
  Memo1.lines.Add(ConvertDT2Str(Now,'yyyy-MM-dd hh:mm:ss','-'));
  Memo1.lines.Add(ConvertDT2Str(Now,'yyyy/MM/dd hh:mm:ss','/'));

  Memo1.lines.Add(ConvertDT2Str(Now));//参数默认值

end;

end.



uDateTimeByc.pas
unit uDateTimeByc;

interface
uses DateUtils,SysUtils;

//日期转字符串byc 2019-4-28 12:23:57 
function ConvertDT2Str(ADT:TDateTime;AFormat:string='YYYY-MM-DD hh:mm:ss';
  ADTSeparator:string='-'):string;

//时间戳的方式解决SecondsBetween或SecondSpan之类的double类型计算误差byc
function CalcTimeSpan2(AOld,ANew:TDateTime):int64;

//设置软件格式byc,可以在main窗体的create下加
//(目前只用预编译指令写了d7和else,2007、2009、2010,d6及一下未知)
procedure SetSysDateFormat;

implementation

//2019-4-28 12:23:57
function ConvertDT2Str(ADT:TDateTime;AFormat:string='YYYY-MM-DD hh:mm:ss';
  ADTSeparator:string='-'):string;
var
  sSysSeparator:string;
  rRes:string;
begin
  sSysSeparator:=FormatDateTime('YYYY-MM-DD',0);
  sSysSeparator:=sSysSeparator[5];
  rRes:=FormatDateTime(AFormat,ADT);
  rRes:= StringReplace(rRes,sSysSeparator,ADTSeparator,[rfReplaceAll]);
  Result:= rRes;
end;

function CalcTimeSpan2(AOld,ANew:TDateTime):int64;
var
  dt1,dt2:TDateTime;
  UnixDT1,UnixDT2:int64;
  rTmp:int64;
  rRes:int64;
begin
  rRes:= -1;
  try
    if AOld
    begin
      dt1:=AOld;
      dt2:=ANew;
    end
    else
    begin
      dt1:=ANew;
      dt2:=AOld;
    end;
    UnixDT1:=DateTimeToUnix(dt1);
    UnixDT2:=DateTimeToUnix(dt2);
    rTmp:=UnixDT2-UnixDT1;
    rRes:=rTmp
  except
    rRes:=-1;
  end;
  result:= rRes;
end;

procedure SetSysDateFormat;
begin
  // 设置WINDOWS系统的短日期的格式
  //SetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_SSHORTDATE, 'yyyy-MM-dd');
  //Application.UpdateFormatSettings := False;
  // 设定程序本身所使用的日期时间格式

  //在程序create里设置一下时间格式
  {$IFDEF VER150} //delphi 7
  ShortDateFormat := 'yyyy-mm-dd';
  LongDateFormat := 'yyyy-mm-dd';
  ShortTimeFormat := 'hh:nn:ss';
  LongTimeFormat := 'hh:nn:ss';
  DateSeparator := '-';
  TimeSeparator := ':';
  {$ELSE} //其他版本(xe以上版本
  {d6以下不常见版本适当修改,2007,2009,2010三个版本基本没接触过,未测试用哪种方法)}
  with FormatSettings do
  begin
    ShortDateFormat := 'yyyy-mm-dd';
    LongDateFormat := 'yyyy-mm-dd';
    ShortTimeFormat := 'hh:nn:ss';
    LongTimeFormat := 'hh:nn:ss';
    DateSeparator := '-';
    TimeSeparator := ':';
  end;
  {$ENDIF}
end;
end.


感谢:天苍苍野茫茫(964219545)  分享

补充:
格林时间 linux时间戳

  //d7下,默认当前时区多8小时
DateTimeToUnix(Now)-8*60*60 =时间戳
UnixToDateTime(时间戳+8*60*60)=时间

d10 
DateTimeToUnix(Now,false)
true 代表的是本地时间,false是格林时间
d10的true=d7的默认=本地时间,多8小时


设置软件时间格式
在程序create里设置一下时间格式
  ShortDateFormat := 'yyyy-mm-dd';
  LongDateFormat := 'yyyy-mm-dd';
  ShortTimeFormat := 'hh:nn:ss';
  LongTimeFormat := 'hh:nn:ss';
  DateSeparator := '-';
  TimeSeparator := ':';
xe版本需要添加前缀
with FormatSettings do
begin
  ShortDateFormat := 'yyyy-mm-dd';
  LongDateFormat := 'yyyy-mm-dd';
  ShortTimeFormat := 'hh:nn:ss';
  LongTimeFormat := 'hh:nn:ss';
  DateSeparator := '-';
  TimeSeparator := ':';
end;


错误写法:
procedure SetSysDateFormat;
var
  fs: TFormatSettings;
begin
  // 设置WINDOWS系统的短日期的格式
  SetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_SSHORTDATE, 'yyyy-MM-dd');
  Application.UpdateFormatSettings := False;
  // 设定程序本身所使用的日期时间格式
  fs.LongDateFormat := 'yyyy-MM-dd';
  fs.ShortDateFormat := 'yyyy-MM-dd';
  fs.LongTimeFormat := 'hh:nn:ss';
  fs.ShortTimeFormat := 'hh:nn:ss';
  fs.DateSeparator := '-';
  fs.timeSeparator := ':';
end;

时间间隔_加法


var

  aa,bb,cc:TDateTime;

begin

  bb:=VarToDateTime('2018-01-01 13:13:05');

  aa:=VarToDateTime('2018-01-01 13:13:00');


  cc:= incsecond(aa,5);

  Memo1.Lines.Add(FloatToStr(SecondsBetween(bb,aa))) ;

  Memo1.Lines.Add(formatdatetime('yyyy-MM-dd hh:mm:ss',cc)) ;  //加法计算时间差也可以没误差


end;


这样加法

旧时间+间隔 >= dtNow  也可以,或者用函数里的


如果需要计算时间差,就只能用函数里的时间戳的方法

相关阅读 >>

Delphi 窗口全屏

Delphi tdbgrideh导出excel

Delphi 控制台关闭指定窗口

在xp/2k 下实现 win+ctrl+del 等键的屏蔽的方法

Delphi 从 twebbrowser中获得当前输入处的链接

Delphi字符串拆分(字符数限制)

Delphi获取默认浏览器

Delphi xe(indy10)tidbytes转ansistring的实现

Delphi应用程序的调试(1-10)

Delphi 让"显示桌面"功能对你的窗口无效

更多相关阅读请进入《Delphi》频道 >>



打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...