处理时间的 Time 类
我需要一个简单的类来处理CD歌曲时长的时间加减,结果却变成了一个庞大的类
引言
我正在编写一个跟踪CD的程序。我需要一种方法来存储每首歌曲的时长,我尝试使用DateTime
变量来保存这些值。不用说,DateTime
数据类型根本不够用。我搜索了一个可以用来保存这些值的类
,但一无所获。很多人推荐使用TimeSpan
,但对我需要的功能来说,它完全没有用。所以我从小处着手,创建了一个Time
数据类型来保存小时、分钟和秒。然后我意识到在减去值时可能会出现负数,所以我添加了一个Sign
。然后,事情就失控了...
背景
我正在为Visual Basic和Visual C#准备一个培训课程。我需要多个示例程序,所以在过去两个月左右的时间里,我一直在不断地编写它们。嗯,这个主项目是一个CD跟踪程序,随着培训的每个部分完成,它将被扩展和增强。
在第一部分:基础中,我有一个控制台程序,它使用一个Structure
来保存艺术家姓名和专辑标题,并将数据保存到文本文件中。
在第二部分:面向对象编程中,我将程序升级为使用类和XML文件。这就是这段代码的来源。第二部分不仅存储艺术家和专辑,还存储歌曲标题和时长、发行年份,并计算总时长。
在第三部分:GUI编程中,我将把程序转换为GUI界面,并添加专辑封面和歌词。
最后,在第四部分:数据库编程中,我将再次升级,并将整个程序转换为使用数据库。
Using the Code
将Time
类添加到您的项目中,它会暴露以下内容:
属性
Hours
- 一个整数值,保存小时部分Minutes
- 一个整数值,保存分钟部分。范围:0(零)到59(五十九)Seconds
- 一个整数值,保存秒部分。范围:0(零)到59(五十九)Sign
- 一个整数值,保存时间的符号。范围:-1表示负数,0表示零,+1表示正数
构造函数
New()
- 无参构造函数。设置默认值为+00:00:00。New(seconds)
- 带参构造函数。会将秒转换为小时、分钟和秒。New(minutes, seconds)
- 带参构造函数。将创建S00:MM:SS格式的值,其中第一个S是数字的符号。New(hours, minutes, seconds)
- 带参构造函数。将创建SHH:MM:SS格式的值,其中第一个S是数字的符号。New(sign, hours, minutes, seconds)
- 带参构造函数。与前一个构造函数类似,但您可以显式设置符号。New(string)
- 带参构造函数。将解析字符串,使用冒号(:)作为分隔符。如果字符串中的参数缺失,则从右到左填充值。New(string, delimeter)
- 带参构造函数。与前一个构造函数类似,但您可以提供一个显式分隔符来解析字符串。
关系运算符
您可以使用以下关系运算符:
CompareTo(time)
- 实现System.IComparable(Of Time).CompareTo
Compare(time, time)
- 实现System.Collections.Generic.IComparer(Of Time).Compare
Equals1(time)
- 实现System.IEquatable(Of Time).Equals
GetHashCode()
- 因为我们有一个Equals()
方法< (小于) > (大于) <= (小于等于) >= (大于等于) = (等于) <> (不等于)
- 所有有意义的关系运算符都已包含
重载运算符
您可以使用的重载数学运算符有:
- (取反)
- 返回正时间的负值,负时间的正值+ (加) - (减) * (乘) / (除)
- 我当初写这个类的全部原因ToShort ToUShort ToInt16 ToUInt16 ToInteger ToUInteger ToInt32 ToUInt32 ToLong ToUlong ToInt64 ToUint64
- 标准转换方法ToSingle ToDouble ToDecimal
- 这些数字的整数部分转换为小时和分钟,而秒是小数部分(即30秒=0.5)ToTime() and CType()
- 可以将几乎所有其他类型转换为Time类型
杂项方法
您可以使用其他数学运算:
Abs()
- 绝对值Min()
andMax()
- 两个值的最小值和最大值Ceiling()
,Floor()
andRound()
- 这些工作方式与标准四舍五入方法类似,并四舍五入到分钟ToString()
- 输出#0:00:00
或-#0:00:00
关于可能的缩小转换,我使用了一些范围检查,如果超出范围则抛出OverflowException
。我使用标准异常,以便您可以轻松地将代码集成到您的程序中。
Public Shared Function ToShort(ByVal time As Time) As Short
Dim temp As Integer = time.Sign * ((time.Hours * 3600) + (time.Minutes * 60) + time.Seconds)
If temp < -32768 Or temp > 32767 Then
Throw New OverflowException
End If
Return CShort(temp)
End Function
我意识到比较两个Time
值会很繁琐且冗长,所以我在Compare()
方法中,将Time
转换为Integer
,然后将它们作为整数进行比较。
Public Function CompareTo(other As Time) As Integer _
Implements System.IComparable(Of Time).CompareTo
Dim time1, time2 As Integer
time1 = Me.Sign * ((Me.Hours * 3600) + (Me.Minutes * 60) + Me.Seconds)
time2 = other.Sign * ((other.Hours * 3600) + (other.Minutes * 60) + other.Seconds)
Return time1.CompareTo(time2)
End Function
在加/减/乘法方法中,我将它们转换为整数,进行数学运算,然后将它们转换回Time
。
Public Shared Operator +(ByVal time1 As Time, ByVal time2 As Time) As Time
Dim temp As Integer
temp = ToInteger(time1) + ToInteger(time2)
Return ToTime(temp)
End Operator
还有ToTime
方法。
Public Shared Function ToTime(ByVal value As Integer) As Time
Dim hours, minutes, seconds As Integer
hours = value \ 3600
seconds = value Mod 3600
minutes = seconds \ 60
seconds = seconds Mod 60
Return New Time(Math.Sign(value), hours, minutes, seconds)
End Function
但在Division
方法中,我首先将它们转换为Decimal
,然后进行除法运算。
Public Shared Operator /(ByVal time1 As Time, ByVal time2 As Time) As Time
Dim temp As Decimal
temp = ToDecimal(time1) / ToDecimal(time2)
Return ToTime(temp)
End Operator
否则结果会很奇怪。
快速测试
我使用下面的小程序对此进行了测试。在我有限的测试中,它通过了,但广泛的测试可能(而且很可能会)暴露缺陷。如果您发现任何问题,请告诉我!
Module TestTimeClass
Sub Main()
Dim i As Time
Dim j As New Time(275)
Dim k As New Time("4:15")
i = j + k
Console.WriteLine(i.ToString())
i = k - j
Console.WriteLine(i.ToString())
Console.WriteLine(Time.ToDecimal(i))
If k < j Then
Console.WriteLine("k is smaller than j.")
Else
Console.WriteLine("j is smaller than k.")
End If
Console.ReadLine()
End Sub
End Module
关注点
我试图将代码压缩到我能达到的最小程度,而不至于让我自己发疯。这就是为什么这么多地方调用其他地方,主要是因为我不仅讨厌打字,而且我知道如果一个例程的代码有效,那么在另一个例程中重用它就能确保它在那里也能工作。我从小处着手:只想添加和减去时间值。然后,当我添加一点小东西让代码工作得更好一点时,最终我发现我有一个巨大的Time Class
,可以处理您可能需要对Time
值做的几乎所有事情。
我在这里发布它,希望您可以在自己的程序中使用它,同时也看看我如何改进它、扩展它和/或优化它。
非常欢迎任何问题!
历史
- 2013-07-04 - 版本 0.0.0.1 (预预预alpha)
- 2013-07-07 - 添加了
Time
类的C#版本