日期与像素之间的转换






4.93/5 (5投票s)
介绍如何编写一个简单的类,将日期转换为像素 X 值,反之亦然。
引言
本文教你如何编写一个简单的类,将日期转换为 X 轴上的值,反之亦然。这是渲染项目管理软件甘特图的最基本计算之一。我们在 Microsoft Project 的查看器中使用这个类(见上图),但它也可以应用于许多其他方面。
背景
理解计算背后的基本数学知识会有所帮助。首先,一些约定。该算法适用于任何单位,但我们将在本文中将我们的单位称为像素。其次,我们选择天作为时间单位,但根据你的需要,其他单位(秒、天等)同样有效。
要将日期转换为 X 轴上的一个点,我们需要知道一些信息
D
:要转换的日期S
:X 轴开始(最左侧点)的日期W
:日期的宽度(以像素为单位)
有了这三个信息,可以使用一个简单的公式计算 X
值
X = (D - S) * W
要将一个点转换为日期,我们只需解上面方程中的 D
D = (X / W) + S
使用代码
该类需要跟踪 S
和 W
,即我们上面公式中的起始日期和日宽度。我们还保留一个常量,用于将毫秒转换为天。
private Date start = null;
private double dayWidth = 0;
private double lengthOfDayInMs = 86400000f;
要实例化并初始化类,请提供一个带有 S
和 W
的构造函数
// Constructor
// start - start date
// width - how wide (in units) a day is.
public PointConverter(Date start, float width) {
this.dayWidth = width;
this.start = start;
}
转换函数使用我们上面的公式(进行一些天与单位之间的转换,以确保单位统一)。
// dateToPoint - convert Date d to an X value
public float dateToPoint(Date d) {
// Compute how many days since the start
long elapsed = d.getTime() - start.getTime();
double daysPast = ((float)(elapsed / lengthOfDayInMs));
// return the X value
return ((float)(daysPast * dayWidth));
}
// pointToDate - convert an X value to a date
public Date pointToDate(float x) {
// The formula is the reverse of dateToPoint
long elapsed = start.getTime() + ((long)((x / dayWidth) * lengthOfDayInMs));
return new Date(elapsed);
}
如果起始日期或比例尺从未改变,则该类可以正常工作,但在甘特图中,这两个值会经常改变。为了适应这种现实,我们提供了一个 update
方法,允许起始日期和日宽度发生变化
// update - pass new values in for start and width
public void update(Date start, float width) {
this.start = start;
dayWidth = width;
}
历史
这是文章/代码的初始版本。