65.9K
CodeProject 正在变化。 阅读更多。
Home

日期与像素之间的转换

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.93/5 (5投票s)

2013年11月8日

LGPL3

2分钟阅读

viewsIcon

15807

downloadIcon

364

介绍如何编写一个简单的类,将日期转换为像素 X 值,反之亦然。

Steelray Gantt Chart

引言

本文教你如何编写一个简单的类,将日期转换为 X 轴上的值,反之亦然。这是渲染项目管理软件甘特图的最基本计算之一。我们在 Microsoft Project 的查看器中使用这个类(见上图),但它也可以应用于许多其他方面。

背景

理解计算背后的基本数学知识会有所帮助。首先,一些约定。该算法适用于任何单位,但我们将在本文中将我们的单位称为像素。其次,我们选择天作为时间单位,但根据你的需要,其他单位(秒、天等)同样有效。

要将日期转换为 X 轴上的一个点,我们需要知道一些信息

  • D:要转换的日期
  • S:X 轴开始(最左侧点)的日期
  • W:日期的宽度(以像素为单位)

有了这三个信息,可以使用一个简单的公式计算 X

X = (D - S) * W

要将一个点转换为日期,我们只需解上面方程中的 D

D = (X / W) + S

使用代码

该类需要跟踪 SW,即我们上面公式中的起始日期和日宽度。我们还保留一个常量,用于将毫秒转换为天。

private Date start = null;
private double dayWidth = 0;
private double lengthOfDayInMs = 86400000f;

要实例化并初始化类,请提供一个带有 SW 的构造函数

// 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;
}

历史

这是文章/代码的初始版本。

© . All rights reserved.