docs: public byte[] getData(byte[] dst, int offset)
  	{
  		final int end = Math.min(data.length, dst.length - offset) / 3 * 3;
  		for (int i = 0; i < end; ++i)
  			dst[offset + i] = (byte) data[i];
  		return dst;
  	}
  
  	/* (non-Javadoc)
  	 * @see tuwien.auto.calimero.dptxlator.DPTXlator#getSubTypes()
  	 */
  	public Map getSubTypes()
  	{
  		return types;
  	}
  
  	/**
  	 * @return the subtypes of the date translator type
  	 * @see DPTXlator#getSubTypesStatic()
  	 */
  	protected static Map getSubTypesStatic()
  	{
  		return types;
  	}
  
  	private String fromDPT(int index)
  	{
  		if (sdf != null)
  			synchronized (DPTXlatorDate.class) {
  				try {
  					return sdf.format(new Date(fromDPTMillis(index)));
  				}
  				catch (final KNXFormatException e) {}
  				return "invalid date";
  			}
  		final int i = index * 3;
  		// return year-month-day
  		final int d = data[i + DAY];
  		final int m = data[i + MONTH];
  		return Short.toString(absYear(data[i + YEAR])) + '-' + align(m) + m + '-'
  			+ align(d) + d;
  	}
  
  	private long fromDPTMillis(int index) throws KNXFormatException
  	{
  		synchronized (DPTXlatorDate.class) {
  			getCalendar().clear();
  			final int i = index * 3;
  			c.set(Calendar.DAY_OF_MONTH, data[i + DAY]);
  			c.set(Calendar.MONTH, data[i + MONTH] - 1);
  			c.set(Calendar.YEAR, absYear(data[i + YEAR]));
  			try {
  				return c.getTimeInMillis();
  			}
  			catch (final IllegalArgumentException e) {
  				throw new KNXFormatException(e.getMessage());
  			}
  		}
  	}
  
  	protected void toDPT(String value, short[] dst, int index) throws KNXFormatException
  	{
  		if (sdf != null)
  			synchronized (DPTXlatorDate.class) {
  				toDPT(parse(value), dst, index);
  				return;
  			}
  		final StringTokenizer t = new StringTokenizer(value, "- ");
  		final int maxTokens = 3;
  		final int[] tokens = new int[maxTokens];
  		try {
  			int count = 0;
  			for (; count < maxTokens && t.hasMoreTokens(); ++count)
  				tokens[count] = Short.parseShort(t.nextToken());
  			if (count < 3)
  				throw logThrow(LogLevel.WARN, "invalid date " + value, null, value);
  			set(tokens[0], tokens[1], tokens[2], dst, index);
  		}
  		catch (final KNXIllegalArgumentException e) {
  			throw logThrow(LogLevel.WARN, "invalid date " + value, e.getMessage(), value);
  		}
  		catch (final NumberFormatException e) {
  			throw logThrow(LogLevel.WARN, "invalid number in " + value, null, value);
  		}
  	}
  
  	private short[] toDPT(long milliseconds, short[] dst, int index)
  	{
  		synchronized (DPTXlatorDate.class) {
  			getCalendar().clear();
  			c.setTimeInMillis(milliseconds);
  			set(c.get(Calendar.YEAR), c.get(Calendar.MONTH) + 1, c
  				.get(Calendar.DAY_OF_MONTH), dst, index);
  		}
  		return dst;
  	}
  
  	private short[] set(int year, int month, int day, short[] dst, int index)
  	{
  		if (year < 1990 || year > 2089)
  			throw new KNXIllegalArgumentException("year out of range [1990..2089]");
  		if (month < 1 || month > 12)
  			throw new KNXIllegalArgumentException("month out of range [1..12]");
  		if (day < 1 || day > 31)
  			throw new KNXIllegalArgumentException("day out of range [1..31]");
  		final int i = 3 * index;
  		dst[i + DAY] = (short) day;
  		dst[i + MONTH] = (short) month;
  		dst[i + YEAR] = (short) (year % 100);
  		return dst;
  	}
  
  	private short absYear(int relative)
  	{
  		if (relative > 99)
  			throw new KNXIllegalArgumentException("relative year out of range [0..99]");
  		return (short) (relative + (relative < 90 ? 2000 : 1900));
  	}
  
  	private long parse(String value) throws KNXFormatException
  	{
  		try {
  			return sdf.parse(value).getTime();
  		}
  		catch (final ParseException e) {
  			throw logThrow(LogLevel.WARN, "invalid date format", e.getMessage(), value);
  		}
  	}
  
  	private static String align(int number)
  	{
  		return number > 9 ? "" : "0";
  	}
  
  	private static Calendar getCalendar()
  	{
  		// don't need to synchronize, it's harmless if we have 2 instances
  		// and we synchronize on class anyway
  		if (c == null) {
  			final Calendar calendar = Calendar.getInstance();
  			calendar.setLenient(false);
  			c = calendar;
  		}
  		return c;
  	}
  }