Introduction
This article teaches you how to write a simple class to convert dates to
values on an X-axis and vice versa. This is one of the most fundamental
calculations in rendering a Gantt chart for project management software.
We use this class in our viewer for Microsoft Project (see image above),
but it could be applied in many other ways as well.
Background
It will help to understand the basic math behind the calculations.
First, a couple of conventions. The algorithm will work for any kind of units,
but we'll call our units pixels in this article. Second, we've picked days
as our unit of time measure, but depending on your needs, other units (seconds,
days, etc.) would work just as well.
To convert a date to a point on an X axis, we need to know a few things:
D
: the date to convert S
: the date at the start (leftmost point) of the X axis W
: width (in pixels) of a day
With these three pieces of information, the X
value can be calculated with
a simple formula:
X = (D - S) * W
To convert a point to a date, we simply solve the above equation for D
:
D = (X / W) + S
Using the code
The class will need to keep track of S
and W
, the start date and the day width from our formulas above. We also keep a constant to convert milliseconds to days.
private Date start = null;
private double dayWidth = 0;
private double lengthOfDayInMs = 86400000f;
To instantiate and initialize the class, provide a constructor with S
and
W
:
public PointConverter(Date start, float width) {
this.dayWidth = width;
this.start = start;
}
The conversion functions use our formulas from above (with some conversion to/from days to make sure the units are uniform).
public float dateToPoint(Date d) {
long elapsed = d.getTime() - start.getTime();
double daysPast = ((float)(elapsed / lengthOfDayInMs));
return ((float)(daysPast * dayWidth));
}
public Date pointToDate(float x) {
long elapsed = start.getTime() + ((long)((x / dayWidth) * lengthOfDayInMs));
return new Date(elapsed);
}
This class works fine if the starting date or scale never changed, but in a Gantt chart, those two values change quite frequently. To accomodate that reality, we
provide an update
method to allow the start date and day width to change:
public void update(Date start, float width) {
this.start = start;
dayWidth = width;
}
History
This is the initial version of the article/code.