Classic chart: X axis questions

I had a similar problem with a bar chart and posted a possible solution here.
I should be possible to adjust this for the classic chart, if you are a bit experienced in java programming.

EDIT:
I just realized that things changed bit in 7.6. The solution posted above for the StatusChart is not working anymore, since there is no reliable event to trigger the custom script.
Good news is that we now have the ‘configureChart’ extension function for the classic chart, that seems to be made exactly for this situation (IA team: Can we have this for other chart types also?).

Put the following code in the configureChart function:

def configureChart(self, chart):
	import app
	app.chartUtils.setDateTickUnits(chart, "Displaying %1$td.%1$tm.%1$tY %1$tH:%1$tM to %2$td.%2$tm.%2$tY %2$tH:%2$tM")

and create the app.chartUtils script module with the code below. You can adjust the tick units in the getDefaultTickUnits() method. The result will be something like this:
[attachment=0]custom-date-axis.png[/attachment]

# module app.chartUtils
global app
import app

# Constants for axis
DOMAIN_AXIS = 0
RANGE_AXIS = 1

# Replaces all DateAxis in the given chart with a custom axis
# Call this method from the configureChart extension function
# Parameters:
#  chart:	The JFreeChart object
#  label:	A custom axis label. Java's String.format method is used to format this label.
#			Available format args: %1$ - start Date, %2$ end Date
#  axis:	app.chartUtils.DOMAIN_AXIS (default) or app.chartUtils.RANGE_AXIS
#  units:	An org.jfree.chart.axis.TickUnits object (see getDefaultTickUnits())
def setDateTickUnits(chart, label = None, axis = DOMAIN_AXIS, units = None):
	
	if units == None:
		units = app.chartUtils.getDefaultTickUnits()
	
	# Apply the new tick units to the chart
	plot = chart.getPlot()
	
	# Iterate all axis
	from org.jfree.chart.axis import DateAxis
	if axis == app.chartUtils.DOMAIN_AXIS:
		axisCount = plot.getDomainAxisCount()
		for index in range(0, axisCount):
			axis = plot.getDomainAxis(index)
			if isinstance(axis, DateAxis):
				customAxis = app.chartUtils.CustomDateAxis(label)
				customAxis.setStandardTickUnits(units)
				customAxis.setConfigFromAxis(axis)
				plot.setDomainAxis(index,customAxis)

# Create a new org.jfree.chart.axis.TickUnits
def getDefaultTickUnits():
	from org.jfree.chart.axis import TickUnits
	from org.jfree.chart.axis import DateTickUnit
	from java.text import SimpleDateFormat
	units = TickUnits()
	
	# Format definitions
	# Formats are created with default timezone and default locale
	# format.setTimezone might be used to override the timezone
	# Additional space is added to the format to prevent ticks from being
	# displayed without space (happens sometimes when using anchored layout).
	formatMSec = SimpleDateFormat(" HH:mm:ss SS")
	formatSec = SimpleDateFormat(" HH:mm:ss")
	formatMin = SimpleDateFormat(" HH:mm")
	formatHour = SimpleDateFormat(" HH:mm")
	formatDay = SimpleDateFormat(" dd.MM HH:mm")
	formatMonth = SimpleDateFormat(" dd.MM.yyyy")
	formatYear = SimpleDateFormat(" MMM yyyy")
	
	# Add the units
	units.add(DateTickUnit(DateTickUnit.MILLISECOND, 5, formatMSec))
	units.add(DateTickUnit(DateTickUnit.MILLISECOND, 50, DateTickUnit.MILLISECOND, 5, formatMSec))
	units.add(DateTickUnit(DateTickUnit.MILLISECOND, 250, DateTickUnit.MILLISECOND, 50, formatMSec))
	units.add(DateTickUnit(DateTickUnit.MILLISECOND, 500, DateTickUnit.MILLISECOND, 50, formatMSec))
	units.add(DateTickUnit(DateTickUnit.SECOND, 1, DateTickUnit.MILLISECOND, 50, formatSec))
	units.add(DateTickUnit(DateTickUnit.SECOND, 2, DateTickUnit.MILLISECOND, 250, formatSec))
	units.add(DateTickUnit(DateTickUnit.SECOND, 5, DateTickUnit.MILLISECOND, 250, formatSec))
	units.add(DateTickUnit(DateTickUnit.SECOND, 10, DateTickUnit.MILLISECOND, 500, formatSec))
	units.add(DateTickUnit(DateTickUnit.SECOND, 30, DateTickUnit.SECOND, 2, formatSec))
	units.add(DateTickUnit(DateTickUnit.MINUTE, 1, DateTickUnit.SECOND, 5, formatSec))
	units.add(DateTickUnit(DateTickUnit.MINUTE, 2, DateTickUnit.SECOND, 10, formatMin))
	units.add(DateTickUnit(DateTickUnit.MINUTE, 5, DateTickUnit.SECOND, 30, formatMin))
	units.add(DateTickUnit(DateTickUnit.MINUTE, 10, DateTickUnit.MINUTE, 1, formatMin))
	units.add(DateTickUnit(DateTickUnit.MINUTE, 20, DateTickUnit.MINUTE, 5, formatMin))
	units.add(DateTickUnit(DateTickUnit.MINUTE, 30, DateTickUnit.MINUTE, 5, formatMin))
	units.add(DateTickUnit(DateTickUnit.HOUR, 1, DateTickUnit.MINUTE, 5, formatHour))
	units.add(DateTickUnit(DateTickUnit.HOUR, 2, DateTickUnit.MINUTE, 10, formatHour))
	units.add(DateTickUnit(DateTickUnit.HOUR, 4, DateTickUnit.MINUTE, 30, formatHour))
	units.add(DateTickUnit(DateTickUnit.HOUR, 6, DateTickUnit.HOUR, 1, formatDay))
	units.add(DateTickUnit(DateTickUnit.HOUR, 12, DateTickUnit.HOUR, 2, formatDay))
	units.add(DateTickUnit(DateTickUnit.DAY, 1, DateTickUnit.HOUR, 4, formatDay))
	units.add(DateTickUnit(DateTickUnit.DAY, 2, DateTickUnit.HOUR, 4, formatDay))
	units.add(DateTickUnit(DateTickUnit.DAY, 7, DateTickUnit.DAY, 1, formatDay))
	units.add(DateTickUnit(DateTickUnit.DAY, 14, DateTickUnit.DAY, 1, formatDay))
	units.add(DateTickUnit(DateTickUnit.MONTH, 1, DateTickUnit.DAY, 1, formatDay))
	units.add(DateTickUnit(DateTickUnit.MONTH, 2, DateTickUnit.DAY, 7, formatMonth))
	units.add(DateTickUnit(DateTickUnit.MONTH, 3, DateTickUnit.DAY, 14, formatMonth))
	units.add(DateTickUnit(DateTickUnit.MONTH, 6, DateTickUnit.MONTH, 1, formatMonth))
	units.add(DateTickUnit(DateTickUnit.YEAR, 1, DateTickUnit.MONTH, 1, formatYear))
	units.add(DateTickUnit(DateTickUnit.YEAR, 2, DateTickUnit.MONTH, 3, formatYear))
	
	return units
 	
# Override DateAxis#getLabel to return min & max date in custom format
from org.jfree.chart.axis import DateAxis
class CustomDateAxis(DateAxis):
	def __init__(self, label):
		self.customLabel = label
	
	def getLabel(self):
		if self.customLabel == None:
			return super(DateAxis, self)
		else:	
			from java.lang import String
			minDate = super(app.chartUtils.CustomDateAxis, self).getMinimumDate()
			maxDate = super(app.chartUtils.CustomDateAxis, self).getMaximumDate()
			# Modify the format given here, ore add additional logic to change according to the range
			return String.format(self.customLabel, minDate, maxDate)
		
	# Copy the config from another axis
	def setConfigFromAxis(self, other):
		from org.jfree.chart.axis import DateAxis
		super(DateAxis, self).setLabelAngle(other.labelAngle)
		super(DateAxis, self).setLabelFont(other.labelFont)
		super(DateAxis, self).setLabelPaint(other.labelPaint)

		super(DateAxis, self).setTickLabelFont(other.tickLabelFont)
		super(DateAxis, self).setTickLabelPaint(other.tickLabelPaint)
		super(DateAxis, self).setTickLabelsVisible(other.tickLabelsVisible)
		super(DateAxis, self).setVerticalTickLabels(other.verticalTickLabels)
		
		super(DateAxis, self).setTickMarkInsideLength(other.tickMarkInsideLength)
		super(DateAxis, self).setTickMarkOutsideLength(other.tickMarkOutsideLength)
		super(DateAxis, self).setTickMarkPaint(other.tickMarkPaint)
		super(DateAxis, self).setTickMarksVisible(other.tickMarksVisible)
			
		super(DateAxis, self).setNegativeArrowVisible(other.negativeArrowVisible)
		super(DateAxis, self).setPositiveArrowVisible(other.positiveArrowVisible)
		super(DateAxis, self).setLowerMargin(other.lowerMargin)
		super(DateAxis, self).setUpperMargin(other.upperMargin)
2 Likes