0. 前言

上一篇内容介绍了Console类和Math类,这篇内容着重介绍一下C#中时间日期的处理方式。

上一篇勘误: 上一篇中关于静态类没有构造函数,这一表述有误。正确的说法是C#中静态类不包含常规构造函数,但可以添加一个静态构造函数。

静态构造函数与普通普通构造函数的区别是,静态构造函数没有访问修饰符,即访问修饰符是默认的,且静态构造函数只能是无参的,并添加 static 修饰符;静态构造函数不能手动调用,会在类加载的时候由系统自己加载。

1 DateTime 和 TimeSpan

DateTime表示时间点,TimeSpan表示 时间段。在C#中,这两个都是结构体,结构体与类都能继承并实现接口,但是与类不同的是结构体在内存中存放在栈里。这部分在微软官方文档中关于CLR有过介绍。后续也会针对CLR写一个系列。这里就不做过多的介绍了。

DateTime延伸开来也有很多内容要讲,这里只做一个大体的介绍:

1. 创建一个DateTime

DateTime time = new DateTime(2018,1,20);// 2018年1月20日 0时0分0秒
DateTime time = new DateTime(2019,11,30, 12, 01, 59);// 2019年11月30日,12:01:59
DateTime time = DateTime.Now;// 表示代码运行到这里的系统时间,一般意义上的当前时间
DateTime time = new DateTime(long ticks);// 以时间刻度计算日期,以公历 0001 年 1 月 1 日 00:00:00.000 以来所经历的以 100 纳秒为间隔的间隔数来表示

这些是我们常用的创建日期的方法,还有一些通过日历对象结合日历来创建日期时间,不过这块在不涉及到程序国际化之前不需要做过多的深入。

需要注意的是,DateTime.Now在每次运行结果都不一样,这个属性返回的是系统运行时当前时间,而不是程序编写时的时间。与之对应的还有一个DaTime.Today,这个属性返回结果是当天,也就是Now去掉时分秒的时间。

2. 日期变更

DateTime提供了很多可以变更日期的方法,这些方法可以获取一个计算之后的时间值:

public DateTime AddDays (double value);// 计算天数,正数代表 天数增加,负数代表天数减少
public DateTime AddHours (double value);// 返回一个新的 DateTime,它将指定的小时数加到此实例的值上。
public DateTime AddMilliseconds (double value);//返回一个新的 DateTime,它将指定的毫秒数加到此实例的值上。
public DateTime AddMonths (int months);//返回一个新的 DateTime,它将指定的月数加到此实例的值上
public DateTime AddMonths (int months);// 返回一个新的 DateTime,它将指定的月数加到此实例的值上
public DateTime AddSeconds (double value);/// 返回一个新的 DateTime,它将指定的秒数加到此实例的值上。
public DateTime AddTicks (long value);// 返回一个新的 DateTime,它将指定的刻度数加到此实例的值上,也就是构造函数里的ticks
public DateTime AddYears (int value);//返回一个新的 DateTime,它将指定的年份数加到此实例的值上。

以上是DateTime类对日期计算的支持,其中参数如果是正的表示时间后移,如果是负的则表示时间向前移。

需要注意的一点就是,日期的变更不会在原有的DateTime元素上变更,会返回一个计算之后的日期类型。

3. 日期算术运算

说了这么多DateTime,没有介绍TimeSpan,那么这里就会介绍一下TimeSpan是什么了。TimeSpan表示一个时间间隔,也就是两个DateTime之间的差值。说到这里,大家也应该明白日期的算术运算应该是指什么了。以下来看一组示例:

class Program
{
static void Main(string[] args)
{
DateTime lastYear = new DateTime(2019, 03, 08, 20,49, 36);
DateTime now = DateTime.Now;
TimeSpan span = now - lastYear;
DateTime newTime = lastYear + span;
}
}

这就是C#中关于日期运算的基本内容。那我们来看看 TimeSpan里封装了哪些内容吧。

TimeSpan的属性:

public int Days { get; }//获取当前 TimeSpan 结构所表示的时间间隔的天数部分。
public int Hours { get; }// 获取当前 TimeSpan 结构所表示的时间间隔的小时数部分。
public int Milliseconds { get; }//获取当前 TimeSpan 结构所表示的时间间隔的毫秒数部分。
public int Minutes { get; }//获取当前 TimeSpan 结构所表示的时间间隔的分钟数部分。
public int Seconds { get; }//获取当前 TimeSpan 结构所表示的时间间隔的秒数部分。

以上属性表示一个TimeSpan的代表的时间间隔中的天数、小时、分钟等。

public double TotalDays { get; }//获取以整天数和天的小数部分表示的当前 TimeSpan 结构的值。
public double TotalHours { get; }//获取以整小时数和小时的小数部分表示的当前 TimeSpan 结构的值。
public double TotalMinutes { get; }//获取以整分钟数和分钟的小数部分表示的当前 TimeSpan 结构的值。
public double TotalSeconds { get; }//获取以整秒数和秒的小数部分表示的当前 TimeSpan 结构的值。
public double TotalMilliseconds { get; }//获取以整毫秒数和毫秒的小数部分表示的当前 TimeSpan 结构的值。

上述几组属性表示以XXX为单位,返回的TimeSpan的值,与之相对应的TimeSpan提供了一组FormXXX的方法,可以将double类型的值还原成TimeSpan。

因为TimeSpan表示时间间隔,所以TimeSpan也允许两个TimeSpan进行加法运算,并提供了一个Add(TimeSpan ts)的方法。

这些是TimeSpan最常用的一些属性和方法。不过在使用TimeSpan中需要注意的地方是,TimeSpan计算返回的值可正可负,正值表示时间间隔的头在前尾在后,负值表示头在后尾在前;TimeSpan中没有提供TotalMonths这个方法,这是因为每个月具体有多少天不是固定值,如果想计算两个日期直接相差几个月,则需要自定义对应的计算方法了。

4. DateTime与字符串之间的恩怨情仇

在程序中,用户或者三方输入的日期大多都是字符串格式的,而且系统获取到的时间也大多会转成字符串给其他人展示,所以这里就会涉及到DateTime与字符串之间的相互转换。

我们先试试日期的各种ToString会产生什么样的结果:

class Program
{
static void Main(string[] args)
{
DateTime now = DateTime.Now;
Console.WriteLine("ToString :{0}", now.ToString());
Console.WriteLine("ToLongDateString :{0}", now.ToLongDateString());
Console.WriteLine("ToLongTimeString :{0}", now.ToLongTimeString());
Console.WriteLine("ToShortDateString :{0}",now.ToShortDateString());
Console.WriteLine("ToShortTimeString :{0}",now.ToShortTimeString());
}
}

结果:

这是DateTime的默认输出结果,当然会根据系统的语言和地区等设置变化而产生不同的变化。为了避免这种变化,C#提供了一种日期类型的格式化模板,这里介绍几个常用的格式代表:

格式符 含义
yy 年份。00~99,如果年份大于99,则只保留后两位。如2020年则显示20,2019年则显示19
yyyy 年份,显示四位。0000~9999
M 月份,显示1~12
MM 月份,显示01~12
d 天,1~31(具体看月份允许的最大天数)
dd 与d一致,显示为01~31
h 小时,12小时制显示1~12
hh 与h一致,显示为01~12
H 小时,24小时制,显示0~23
HH 小时,24小时制,显示00~23
m 分钟,显示0~59
mm 分钟,显示00~59
s 秒,显示0~59
ss 秒,显示00~59
f 表示日期和时间值的十分之几秒,显示0~9
ff 表示百分之几秒,显示00~99

最后的f,f的次数越多精度越细,但需要考虑系统的时钟精度。

在实际开发中,最常用的格式是:yyyy-MM-dd HH:mm:ss,显示效果就是:2020-04-25 12:00:00。其中连接符可以根据开发需求更换。

上述是时间转字符串,反过来也有字符串转时间。

使用DateTime.Parse或者Convert.ToDateTime就可以将字符串转换为时间类型。C#并不需要在字符串转日期的时候指定字符串的显示格式,这是因为一个约定优于配置的设计理念。C#通过分析字符串,然后将字符串转换成对应的时间类型。当然,在正确解析到时间的时候,C#会抛出异常。为此,C#提供了DateTime.TryParse方法,该方法不会抛出异常,会返回一个是否正确转换的bool值。

它的声明如下:

public static bool TryParse (string s, out DateTime result);// 使用了result作为实际转换结果

虽然C# 不用提供转换格式就可以读取,但是如果时间字符串的格式比较少见呢,或者说就想指定一个格式字符串,怎么办?别急,C#还提供了一个方法:

public static DateTime ParseExact (string s, string format, IFormatProvider provider);

不过,这个方法需要指定一个区域性的格式信息:provider。这个信息可以通过CultureInfo.CurrentCulture来获取,这个属性表示系统的当前区域信息。

以上是DateTime的基本内容,有兴趣的小伙伴可以查阅一下微软的官方文档继续深入研究一下。

更多内容烦请关注我的博客

C# 基础知识系列- 13 常见类库介绍(二)日期时间类的更多相关文章

  1. C# 基础知识系列- 13 常见类库介绍(一)

    0. 前言 每篇一个前言,介绍一下这一篇的内容.之前的内容都是针对某些知识点进行的介绍,这篇内容介绍一下实际开发中常用的一些类和命名空间.这一篇是个连续剧,大概有个三四集.嗯,就是这样. 1. Sys ...

  2. C# 基础知识系列-13 常见类库(三)

    0. 前言 在<C# 基础知识系列- 13 常见类库(二)>中,我们介绍了一下DateTime和TimeSpan这两个结构体的内容,也就是C#中日期时间的简单操作.本篇将介绍Guid和Nu ...

  3. C# 基础知识系列- 3 集合数组

    简单的介绍一下集合,通俗来讲就是用来保管多个数据的方案.比如说我们是一个公司的仓库管理,公司有一堆货物需要管理,有同类的,有不同类的,总而言之就是很多.很乱.我们对照集合的概念对仓库进行管理的话,那么 ...

  4. 学习javascript基础知识系列第二节 - this用法

    通过一段代码学习javascript基础知识系列 第二节 - this用法 this是面向对象语言中的一个重要概念,在JAVA,C#等大型语言中,this固定指向运行时的当前对象.但是在javascr ...

  5. C# 基础知识系列- 9 字符串的更多用法(一)

    0. 前言 在前面的文章里简单介绍了一下字符串的相关内容,并没有涉及到更多的相关内容,这一篇将尝试讲解一下在实际开发工作中会遇到的字符串的很多操作. 1. 创建一个字符串 这部分介绍一下如何创建一个字 ...

  6. C# 基础知识系列- 10 反射和泛型(二)

    0. 前言 这篇文章延续<C# 基础知识系列- 5 反射和泛型>,继续介绍C#在反射所开发的功能和做的努力.上一篇文章大概介绍了一下泛型和反射的一些基本内容,主要是通过获取对象的类型,然后 ...

  7. C# 基础知识系列- 12 任务和多线程

    0. 前言 照例一份前言,在介绍任务和多线程之前,先介绍一下异步和同步的概念.我们之间介绍的知识点都是在同步执行,所谓的同步就是一行代码一行代码的执行,就像是我们日常乘坐地铁通过安检通道一样,想象我们 ...

  8. C# 基础知识系列- 14 IO篇 文件的操作 (3)

    本篇继续前两篇内容,跟大家介绍一下Path类以及FileSystemInfo这个类的主要方法和属性. 上文提到,在<C# 基础知识系列-IO篇>之文件相关的内容完结之后,会带领大家开发一个 ...

  9. C# 基础知识系列- 14 IO篇 流的使用

    0. 前言 继续之前的C# IO流,在前几篇小短片中我们大概看了下C# 的基础IO也对文件.目录和路径的操作有了一定的了解.这一篇开始,给大家演示一下流的各种操作.以文件流为例,一起来看看如何操作吧. ...

随机推荐

  1. HDU - 2444 二分图最大匹配 之 判断二分图+匈牙利算法

    题意:第一行给出数字n个学生,m条关系,关系表示a与b认识,判断给定数据是否可以构成二分图,如果可以,要两个互相认识的人住一个房间,问最大匹配数(也就是房间需要的最小数量) 思路:要看是否可以构成二分 ...

  2. rabbitmq++:RabbitMQ的消息确认ACK机制介绍

    1):什么是消息确认ACK. 答:如果在处理消息的过程中,消费者的服务器在处理消息的时候出现异常,那么可能这条正在处理的消息就没有完成消息消费,数据就会丢失.为了确保数据不会丢失,RabbitMQ支持 ...

  3. [算法]移除指定元素&strSr()的实现

    移除指定元素 题目 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度. 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原 ...

  4. 关于C#中Partial局部类型关键字的使用

    虽然之前在做Winform开发时候,经常遇到Partial关键字,但是最近在代码中看到使用Partial将同名类文件写在多个源文件中,因此想要记录下Partial的详细使用. Partial type ...

  5. Linux的五种IO模型及同步和异步的区别

    前置知识 缓存 I/O 缓存 I/O 又被称作标准 I/O,大多数文件系统的默认 I/O 操作都是缓存 I/O.在 Linux 的缓存 I/O 机制中,操作系统会将 I/O 的数据缓存在文件系统的页缓 ...

  6. Java 对象容器

    一.ArrayList 容器 1.记事本 package booknote; import java.util.ArrayList; public class NoteBook { private A ...

  7. IdentityServer 部署踩坑记

    IdentityServer 部署踩坑记 Intro 周末终于部署了 IdentityServer 以及 IdentityServerAdmin 项目,踩了几个坑,在此记录分享一下. 部署架构 项目是 ...

  8. Flutter 完美的验证码输入框

    老孟导读:刚开始看到这个功能的时候一定觉得so easy,开始的时候我也是这么觉得的,这还不简单,然而真正写的时候才发现并没有想象的那么简单. 先上图,不上图你们都不想看,我难啊,到Github:ht ...

  9. jq日历一周为单位轮播

    简单效果图: 代码如下: <!doctype html> <html lang="en"> <head> <meta charset=&q ...

  10. echarts整理

    保存一些常用的echarts图表及制作方法