环境:

  • window10
  • vs2022
  • .net 6
  • mysql 8.0.25
  • DBeaver

参考:
《MSDN:浮点数值类型(C# 引用)》
《mysql:11.2 Date and Time Data Types》

在mysql中表示日期时间的类型有 datetimeyeardatetimetimstamp五种,列表如下:

五中列类型的一些特点

1. datetime和date的取值范围

mysql文档中声明了date和datetime的取值范围是 '1000-01-01' to '9999-12-31''1000-01-01 00:00:00' to '9999-12-31 23:59:59',但也声明存储更早的时间或许可以,但不保证一定正确,如下:

需要注意的是,timestamp和year却是严格按照mysql指定的范围检查的,比如:我们不能将’1001’插入到year中,也不能将’0001-01-01 00:00:00’插入到timestamp中。

2. datetime、time和timestamp支持毫秒

可以使用datetime(f)、time(f)、timestamp(f)定义列,f取值范围是0-6,默认是0。
比如:当我们定义列类型datetime(6)时可以保存'2022-02-11 01:02:03.123456',查询的结果显示:2022-02-11 01:02:03.123456
注意:虽然我们将'2022-02-11 01:02:03.123456'插入到datetime(0)不会报错,但mysql会丢弃掉毫秒部分。

3. 关于时区(datetime和timestamp的不同点之一)

mysql中不存储时区信息,但我们可以给mysql实例设一个整体的时区,也可以跟随服务器时区(默认就是跟随服务器时区)。
如:select @@time_zone输出:SYSTEM,表示跟随系统时区。

另外,我们可以在插入数据时指定时区信息,如:
insert into test(t_datetime) values('2022-02-11 08:30:01+08:00')

注意:
mysql 8.0.19及以上才允许insert时加时区;
还有,时间和时区之间不能有空格,要紧跟 ‘+’ 号,如:2022-02-11 00:30:01+00:00是正确的,而 2022-02-11 00:30:01 +00:00则会报错。
c#解析带时区数据的时候支持’+'号前有空格和无空格的两种形式。

当我们将指定时区的数据(如:北京时区'2022-02-11 08:30:01')插入到mysql的datetime
时,如果mysql使用的时区也是北京时区那么直接存进去,如果是其他时区,比如:+09:00,那么mysql将它转换时区再存进去(转成:'2022-02-11 09:30:01'
这样下次查询的时候将会得到'2022-02-11 09:30:01'

另外,mysql存取timestamp和datetime的规则是不一样的:

  • datetime
    mysql存数据到datetime时候,最多将指定了时区的数据转换到mysql使用的时区后再存储进去,取得时候就原封不动取出来。
  • timestamp
    mysql存数据的时候,将数据先转换成UTC时间,当取出的时候再转换成mysql使用的时区。

举个例子:

先将机器时区调成 +09:00

然后,将mysql服务器重启,执行select @@time_zone,是否输出SYSTEM,是的话表示mysql使用本机时区,即:+09:00

然后,执行下面脚本,将数据'2022-02-11 08:30:01+08:00'插入到timestamp:

create table test(t_timestamp  timestamp
)
insert into test(t_timestamp) values('2022-02-11 08:30:01+08:00')
select * from test

输出结果:

解释下上面时区操作的情况:

  • 当我们将'2022-02-11 08:30:01+08:00'插入到mysql的timestamp时,mysql首先将它转成+00:00时区(即:UTC时间)的数据(2022-02-11 00:30:01+00:00),然后将它插入列 t_timestamp;
  • 当我们执行查询时,mysql将读取到的2022-02-11 00:30:01+00:00转换成本机时区(+09:00)显示出来,转换结果为:2022-02-11 09:30:01,这个正是我们看到的输出结果。

然后,再接着实验:我们将机器时区调会北京时间(+08:00),然后重启mysql服务。

然后,我们再执行查询,输出结果:

解释上面输出的情况:

mysql的timestamp本身存储的是UTC时间(2022-02-11 00:30:01+00:00),读取后会将它转成本机时区(此时为:+08:00),转换后的结果是:2022-02-11 08:30:01,就是我们看到的样子。

最后总结:

  • 如果mysql使用的时区不会中途更改的话,timestamp内部使用什么时区存储对我们来说是没有什么感觉的。因为,mysql会在存取时自行转换;
  • 如果mysql使用的时区中途会发生更改,那么timestamp类型的数据是不用考虑旧数据的时区问题的,因为mysql存的是utc时间,取得时候直接转换成切换后的时区,而datetime类型的旧数据可能需要考虑转换时区;

4. 关于datetime和timestamp的自动更新

在mysql中,datetime和timestamp可以在定义时指定它自动更新机制。

不过,这种自动更新机制受参数@@explicit_defaults_for_timestamp影响。

@@explicit_defaults_for_timestamp值为0的时候,timestamp列类型可以自动更新(新增和更新时),否则,timestamp列类型不会自动更新。

所以,为了兼容不同的模式,推荐使用下面的写法保持一致性:

create table test(t_timestamp  timestamp(3) default current_timestamp(3) on update current_timestamp(3),t_datetime   datetime(3) default current_timestamp(3) on update current_timestamp(3),name varchar(50)
)

5. 关于日期时间的零值

mysql中允许插入 “0000-00-00 01:02:03” 这样的日期值,但是这样的值其实是无意义的。
时间部分为0好理解,但日期怎么可能为0呢?对于此c#是直接报错的:

mysql中也允许通过修改配置阻止这种数据插入,涉及到mysql的模式参数:NO_ZERO_DATENO_ZERO_IN_DATE,以及是否是严格模式,可参考:《mysql:5.1.11 Server SQL Modes》

话说回来,不管mysql中是否允许0000-00-00 00:00:00这种数据,我们在用程序查询的时候得能读取出来吧?看下图:

为了不报错,我们需要修改连接字符串,如下:

这里注意:如果我们使用 AllowZeroDateTime=True
而不是ConvertZeroDateTime=True,那么读取数据也不会报错,但会得到一个 MySqlConnector.MySqlDateTime结构体(里面记录的时间是’0000-00-00 00:00:00’),如果后续需要将它转成DateTime的话还是很麻烦,所以建议直接使用ConvertZeroDateTime=True

6. 关于time类型的范围

从上面的介绍中可以看出time的范围并不是00:00:00 - 23:59:59,而是'-838:59:59.000000' to '838:59:59.000000'。这让人难理解,但mysql文档的解释是time还要考虑存储一个时间段!引用《剑雨》中转轮王的一句话吐槽下:

“你要练变戏法就变戏法,练武功就练武功,你总是喜欢它们混为一谈,能活到今天,也算件奇事啊。”

不管怎么说吧,mysql这么设计了,我们在程序中想办法兼容吧,不过好在 MySqlConnector中读取后就是TimeSpan,所以我们在c#中记得用TimeSpan去接收就行了。

7. 在c#中使用时间日期列

上面说了5中日期时间类型的特点,下面就谈谈c#中应该怎样使用:

  • datetime和timestamp
    因为mysql中不存储时区信息,所以我们在c#中直接使用datetime接收就行,不过当mysql中允许存在0000-00-00 00:00:00这种数据时,我们可以选择在连接字符串中添加ConvertZeroDateTime=True将它转为0001-01-01 00:00:00,或者是使用MySqlConnector.MySqlDateTime结构体接收。

  • date
    一般我们使用datetime接收即可,但.net6出来后增加了dateonly结构体,我们的选择又多了,不过为了代码的兼容性,推荐使用datetime。

  • time
    上面着重讲了,因为mysql中time既可以表示时间点又可以表示时间段,所以mysqlconnector直接翻译成了timespan,我们也没有其他的选择,直接使用timespan接收即可。

  • year
    这个最简单的,使用int接收。

c#模型定义示例:

public class Model
{/// <summary>/// mysql列类型: year/// </summary>public int? t_year { get; set; }/// <summary>/// mysql列类型: date/// </summary>public DateTime? t_date { get; set; }/// <summary>/// mysql列类型: datetime ConvertZeroDateTime=True/// </summary>public DateTime? t_datetime { get; set; }/// <summary>/// mysql列类型: timestamp/// </summary>public DateTime? t_timestamp { get; set; }/// <summary>/// mysql列类型: time/// </summary>public TimeSpan? t_time { get; set; }
}

mysql:列类型之时间日期相关推荐

  1. MySQL列类型之——数值类型

    如想进一步了解有关mysql的信息请点击http://dev.mysql.com/doc/refman/5.1/zh/column-types.html MySQL支持多种列类型:数值类型.日期/时间 ...

  2. 以下不属于mysql列类型的是什么意思_下列 ________ 类型不是 MySQL 中常用的的数据类型。_学小易找答案...

    [简答题]工作区跳线的制作 请依据EIA568国际标准,制作一根直通线(即两端都是EIA568B线芯排布规律) 做好网线后,请拍照上传作业. [单选题]UNIQUE 惟一索引的作用是 ( ) : [简 ...

  3. mysql整理类型_Mysql 时间类型整理

    一.date_sub.SUBDATE.date_add select now(),  date_sub(now(),interval  1 minute),SUBDATE(now(),interval ...

  4. Mysql列类型-数值型

    2019独角兽企业重金招聘Python工程师标准>>> 一.整数型: 1.取值范围: tinyint    smallint    mediumint    int    bigin ...

  5. mysql中取出的时间日期多个.0

    字段名称为 create_time 字段类型为 datetime 存储的内容为 2019-03-26 09:42:05 但是 通过mybatis取出来放到实体类里,数值就变成了 2019-03-26 ...

  6. 面试官问:mysql中时间日期类型和字符串类型的选择

    摘要:MySQL中有多种表示时间日期的数据类型,主要有YEAR.TIME.DATE.DATETIME.TIMESTAMP等 本文分享自华为云社区<一针见血,mysql中时间日期类型和字符串类型的 ...

  7. mysql 常用的列类型_MySQL 常用列类型

    日期和时间类型为DATETIME.DATE.TIMESTAMP.TIME和YEAR. 注意:在MySQL中,日期时间值使用单引号引起来. 相当于Java中Date,Calender. 最常用的整数类型 ...

  8. C语言中两种方式表示时间日期值time_t和struct tm类型的相互转换

    使用gmtime函数或localtime函数将time_t类型的时间日期转换为structtm类型: 使用time函数返回的是一个long值,该值对用户的意义不大,一般不能根据其值确定具体的年.月.日 ...

  9. mysql字段类型原理_mysql数据类型和字段属性原理与用法详解

    本文实例讲述了mysql数据类型和字段属性.分享给大家供大家参考,具体如下: 本文内容: 数据类型 数值类型 整数型 浮点型 定点型 日期时间类型 字符串类型 补充: 显示宽度与zerofll 记录长 ...

最新文章

  1. CVPR 2021 顶会冠军图像分割算法全解密
  2. awk算术运算一例:统计hdfs上某段时间内的文件大小
  3. 安装opencv3.3.0碰到的问题及解决方法
  4. 文本显示变量_Axure9实操教程10-变量
  5. java中的JDBC
  6. JavaScript 设计模式之构造函数模式
  7. Struts2 文件上传,下载,删除
  8. jenkins Auth fail验证失败
  9. 我们应该学习什么 java、C#还是C++(VC)
  10. Vue工程报错解决方案Warn:import Vue from “vue“;
  11. STM32:UART中的硬件流控RTS与CTS
  12. windows中python虚拟环境_Windows下Python虚拟环境的配置
  13. 从想当亿万富翁到职场、创业、爱情、抑郁、学医学武,我的程序人生
  14. 【存储】AIX存储管理基本概念和操作(LVM)
  15. 微弱信号检测_世界上最轻薄的信号放大器:可精准监测生物信号!
  16. MYQQ复活版 20220801
  17. datax(24):远程调试datax
  18. java设备未就绪_java.io.IOException: 设备未就绪。这个怎么解决?
  19. [转载]圣人的35个习惯
  20. Docker的上手(Ubuntu140.4 Mate)

热门文章

  1. 插值多项式的龙格现象的介绍与模拟
  2. TensorFlow-SSD测试代码梳理
  3. 【架构实践】分布式环境脑裂与Lease机制具体是什么?
  4. 为什么MIPS和MFLOPS不能代表性能?
  5. 【视频】海康摄像头、NVR网络协议简介
  6. Java题目汇总(二)
  7. 鼓励参与计算机考试宣传标语,期末考试励志宣传标语
  8. C# CSV文件读写
  9. Failed to execute goal org.apache.maven.plugins:maven-archetype-plugin:3.1.1:generate
  10. InnoDB存储引擎简介