docs: public byte[] getData(byte[] dst, int offset)
  	{
  		final int end = Math.min(data.length, dst.length - offset) & ~0x01;
  		for (int i = 0; i < end; ++i)
  			dst[offset + i] = (byte) data[i];
  		return dst;
  	}
  
  	/**
  	 * Sets the first translation item value from input of unit millisecond.
  	 * <p>
  	 * The method is for DPTs dealing with periods of time, in particular
  	 * {@link #DPT_TIMEPERIOD}, {@link #DPT_TIMEPERIOD_10}, {@link #DPT_TIMEPERIOD_100}
  	 * {@link #DPT_TIMEPERIOD_SEC}, {@link #DPT_TIMEPERIOD_MIN} and
  	 * {@link #DPT_TIMEPERIOD_HOURS}. The milliseconds are converted to the unit of the
  	 * set DPT, with the result rounded to the nearest representable value (with 0.5
  	 * rounded up).<br>
  	 * On any other DPT, the input is treated equal to {@link #setValue(int)}.
  	 * 
  	 * @param milliseconds the value in milliseconds, 0 &lt;= <code>milliseconds</code>
  	 * @throws KNXFormatException on milliseconds out of range for DPT
  	 */
  	public final void setTimePeriod(long milliseconds) throws KNXFormatException
  	{
  		data = toDPT(milliseconds);
  	}
  
  	/* (non-Javadoc)
  	 * @see tuwien.auto.calimero.dptxlator.DPTXlator#getSubTypes()
  	 */
  	public final Map getSubTypes()
  	{
  		return types;
  	}
  
  	/**
  	 * @return the subtypes of the 2-byte unsigned translator type
  	 * @see DPTXlator#getSubTypesStatic()
  	 */
  	protected static Map getSubTypesStatic()
  	{
  		return types;
  	}
  
  	private int fromDPT(int index)
  	{
  		final int v = (data[2 * index] << 8) | data[2 * index + 1];
  		if (dpt.equals(DPT_TIMEPERIOD_10))
  			return v * 10;
  		else if (dpt.equals(DPT_TIMEPERIOD_100))
  			return v * 100;
  		return v;
  	}
  
  	private String makeString(int index)
  	{
  		return appendUnit(String.valueOf(fromDPT(index)));
  	}
  
  	protected void toDPT(String value, short[] dst, int index) throws KNXFormatException
  	{
  		try {
  			toDPT(Integer.decode(removeUnit(value)).intValue(), dst, index);
  		}
  		catch (final NumberFormatException e) {
  			throw logThrow(LogLevel.WARN, "wrong value format " + value, null, value);
  		}
  	}
  
  	private short[] toDPT(long ms) throws KNXFormatException
  	{
  		// prevent round up to 0 from negative milliseconds
  		if (ms < 0)
  			throw logThrow(LogLevel.WARN, "negative input value " + Long.toString(ms),
  				null, Long.toString(ms));
  		long v = ms;
  		if (dpt.equals(DPT_TIMEPERIOD_SEC))
  			v = Math.round(ms / 1000.0);
  		else if (dpt.equals(DPT_TIMEPERIOD_MIN))
  			v = Math.round(ms / 1000.0 / 60.0);
  		else if (dpt.equals(DPT_TIMEPERIOD_HOURS))
  			v = Math.round(ms / 1000.0 / 60.0 / 60.0);
  		final short[] buf = new short[2];
  		toDPT((int) v, buf, 0);
  		return buf;
  	}