C-基础知识系列-13-常见类库介绍二日期时间类

49次阅读

共计 4451 个字符,预计需要花费 12 分钟才能阅读完成。

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 的基本内容,有兴趣的小伙伴可以查阅一下微软的官方文档继续深入研究一下。

更多内容烦请关注我的博客《高先生小屋》

正文完
 0