构建 C# 中的 UNIX 时间到日期自定义控件
本文介绍了如何构建一个自定义控件,该控件可以将 UNIX 时间转换为可读的有用日期,以便在 WinForms 应用程序中显示。

引言
本文介绍了如何构建一个自定义控件,该控件可以将 UNIX 时间转换为可读的有用日期,以便在 WinForms 应用程序中显示。该控件可以接受标准的日期或 UNIX 时间值,并可以在任一方向上转换值(从 UNIX 时间到日期,或从日期到 UNIX 时间)。

该控件包含两个属性,可用于控制显示的输出和控件的可用性。“Convert On Click”(单击转换)属性将启用或禁用控件在用户单击控件时在 UNIX 时间和普通日期之间来回转换值的功能;如果您希望允许用户以一种格式编辑值并在另一种格式中查看它,这可能会很有用。另一个属性是“Direction”(方向)。Direction 用于确定控件是显示 UNIX 时间值还是标准日期值。
入门
要开始,请解压包含的项目并在 Visual Studio 2008 环境中打开解决方案。在解决方案资源管理器中,您应该会看到这些文件(图 2)。

从图 2 可以看出,有两个项目。UnixTime
是自定义控件项目,其中包含一个自定义控件(UTConverter.cs)。第二个项目(ControlTest
)是一个用于测试该控件的 WinForms 应用程序。
自定义控件 (UTConverter.cs)
自定义控件是一个继承自标准 TextBox
控件的类。
代码非常简单。如果您愿意在 IDE 中打开代码视图,您会看到代码文件以以下库导入开头
using System;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
导入之后,定义命名空间和类
namespace UnixTime
{
public partial class UTConverter : TextBox
{
接下来定义一个枚举;这个枚举名为 Direction
。该枚举用于定义扩展的 textbox
控件中显示的日期是显示日期还是 UNIX 时间戳值。UNIX 时间戳值可以定义为自 1970 年 1 月 1 日起或之前的秒数。在声明枚举之后,定义了两个 private
成员变量;一个用于跟踪选定的 Direction
选项,另一个布尔值用于确定是否启用了“Convert On Click”。
#region Members
public enum Direction
{
ToUnix,
ToDate
}
private Direction mCurrentDirection;
private bool mConvertOnClick;
#endregion
接下来,定义一个构造函数;在构造函数中,通过将 CurrentDirection
属性设置为 Direction.ToDate
,并将 ConvertOnClick
属性设置为 true
来设置控件的默认值。在此默认条件下,控件通常会将日期显示为日期,并在单击时将日期转换回 UNIX 时间戳值。
#region Constructor
public UTConverter()
{
InitializeComponent();
CurrentDirection = Direction.ToDate;
ConvertOnClick = true;
}
#endregion
构造函数之后,设置一个区域来包含控件的附加属性。第一个属性是 CurrentDirection
;它提供对 mCurrentDirection
成员变量的 public
访问,用于确定控件是将其值显示为日期还是 UNIX 时间戳值。另一个属性 ConvertOnClick
用于在运行时启用或显示在控件中在 UNIX 和普通日期显示之间进行转换的功能。
#region Properties
[CategoryAttribute("UNIX Time"),
Browsable(true),
BindableAttribute(false),
DescriptionAttribute("Convert to or from UNIX time.")]
public Direction CurrentDirection
{
get
{
return mCurrentDirection;
}
set
{
mCurrentDirection = value;
}
}
[CategoryAttribute("UNIX Time"),
Browsable(true),
BindableAttribute(false),
DescriptionAttribute("Enable or disable On Click UNIX Time format
conversion.")]
public bool ConvertOnClick
{
get
{
return mConvertOnClick;
}
set
{
mConvertOnClick = value;
}
}
#endregion
下一个定义的区域标题为 Methods
;本节包含用于为该自定义控件提供 UNIX-日期转换功能的代码。
#region Methods
ConvertToDateTime
函数将 Unix 时间戳转换为短日期 string
;这很容易通过将提供的秒数添加到用于 UNIX 时间戳的基线数据来完成。
/// <summary>
/// Convert Unix time to date
/// </summary>
/// <param name="unixTime"></param>
private void ConvertToDateTime(double unixTime)
{
DateTime convertedDateTime =
new DateTime(1970,1,1,0,0,0).AddSeconds(unixTime);
this.Text = convertedDateTime.ToShortDateString();
}
下一个函数将日期(作为短日期字符串)转换为 UNIX 时间格式
/// <summary>
/// Convert date to Unix time
/// </summary>
/// <param name="dt"></param>
private void ConvertToUnixTime(DateTime dt)
{
this.Text = (dt - new
DateTime(1970,1,1,0,0,0)).TotalSeconds.ToString();
// Note: This operation will truncate the value to its
// minimum for the date time shown; for example, if "500000000"
// is entered into the textbox, this operation will
// alter the value to “499996800" which is the
// minimum value for the date 11/5/1985. If you
// need to maintain the exact Unix time value,
// create a separate variable to store it in and
// set it to the Unix time stamp prior to
// converting from Unix time to a date.
}
控件的验证事件处理程序用于更新日期或 UNIX 时间值的显示,具体取决于控件的 CurrentDirection
属性是否设置为显示日期或 UNIX 时间。
/// <summary>
/// Upon validation, update the control to
/// display the converted Unix time
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void UTConverter_Validated(object sender, EventArgs e)
{
try
{
if (mCurrentDirection == Direction.ToDate)
{
ConvertToDateTime(Convert.ToDouble(this.Text));
}
else
{
ConvertToUnixTime(Convert.ToDateTime(this.Text));
}
}
catch { }
}
键按下事件处理程序被配置为忽略可能输入到控件中的非数字值。该控件接受数字、控件字符和减号键。以这种方式限制键按下将允许用户输入数字并使用退格键,以及输入减号以在处理 UNIX 时间时输入早于 1970 年 1 月 1 日的日期。
/// <summary>
/// Disregard non-numeric values; allow
/// numbers, controls, and the negative
/// sign.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void UTConverter_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsDigit(e.KeyChar) &&
!char.IsControl(e.KeyChar) &&
e.KeyChar != '-')
{
e.Handled = true;
}
}
下一段代码只是在用户退出、进入或刷新 textbox
时重复调用更新显示的值。
/// <summary>
/// Update the displayed value to show a date
/// in lieu of a Unix time value whenever the
/// leave event is fired.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void UTConverter_Leave(object sender, EventArgs e)
{
try
{
if (mCurrentDirection == Direction.ToDate)
{
ConvertToDateTime(Convert.ToDouble(this.Text));
}
else
{
ConvertToUnixTime(Convert.ToDateTime(this.Text));
}
}
catch { }
}
/// <summary>
/// Update the displayed value to show a Unix
/// time in lieu of a date whenever the enter
/// event is fired.
///
/// Disable this event handler if you do
/// not want the time to convert back to
/// Unix time
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void UTConverter_Enter(object sender, EventArgs e)
{
try
{
if (ConvertOnClick)
{
if (mCurrentDirection == Direction.ToDate)
{
ConvertToUnixTime(Convert.ToDateTime(this.Text));
}
else
{
ConvertToDateTime(Convert.ToDouble(this.Text));
}
}
}
catch { }
}
/// <summary>
/// Override the base refresh method
/// to update the display of each value
/// </summary>
public override void Refresh()
{
base.Refresh();
// convert to date whenever control
// is refreshed
try
{
if (mCurrentDirection == Direction.ToDate)
{
ConvertToDateTime(Convert.ToDouble(this.Text));
}
else
{
ConvertToUnixTime(Convert.ToDateTime(this.Text));
}
}
catch { }
}
#endregion
}
}
这就结束了控件的内容。下一节将讨论演示项目。
主窗体(Control Test 项目中的 Form1.cs)
测试窗体包含八个自定义控件实例;每个控件用于显示不同的内容。四个使用短日期 string
加载,四个使用 UNIX 时间戳加载。在这两组中,每个控件都设置了 ConvertOnClick
方法启用和禁用,并将 Direction
选项设置为 ToDate
或 ToUnix
。在窗体上添加了一个工具提示,当用户将鼠标悬停在控件上时,该工具提示会描述所选选项的某些内容。
窗体的代码全部显示在下方。窗体加载事件处理程序中的代码已加注释,以说明每个部分的作用。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace ControlTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
this.Dispose();
}
private void Form1_Load(object sender, EventArgs e)
{
// use negative numbers to express dates
// prior to 1/1/1970
// load with Unix time
utConverter1.Text = "-885772800"; // a date prior to 1/1/1970
utConverter2.Text = "849312000";
utConverter3.Text = "999648000";
utConverter4.Text = "4000000000";
// load with normal dates
utConverter5.Text = "7/19/1960";
utConverter6.Text = "5/16/1933";
utConverter7.Text = "7/4/2008";
utConverter8.Text = "6/18/3100";
// refresh all of the controls
// to update the display
utConverter1.Refresh();
utConverter2.Refresh();
utConverter3.Refresh();
utConverter4.Refresh();
utConverter5.Refresh();
utConverter6.Refresh();
utConverter7.Refresh();
utConverter8.Refresh();
// move selection off custom controls
button1.Select();
}
}
}
摘要
本文旨在介绍一个具有非常特定目的的自定义控件,即在 UNIX 时间戳格式和普通短日期 string
之间转换值。因此,该项目是一个简单的示例,描述了如何创建一个自定义控件来解决问题,并且您可以使用类似的方法来处理其他情况,在这些情况下,自定义控件可能比使用现有控件并附加额外代码来实现类似结果更方便。
历史
- 2008 年 6 月 3 日:初次发布