public long getNanosecondsInstant(TimeZone aTimeZone){
    // these are always positive:
    Integer year = getYear();
    Integer month = getMonth();
    Integer day = getDay();
    //coerce missing times to 0:
    Integer hour = getHour() == null ? 0 : getHour();
    Integer minute = getMinute() == null ? 0 : getMinute();
    Integer second = getSecond() == null ? 0 : getSecond();
    Integer nanos = getNanoseconds() == null ? 0 : getNanoseconds();
    
    int millis = nanos / MILLION; //integer division truncates, doesn't round
    int nanosRemaining = nanos % MILLION; //0..999,999 - always positive
    
    //base calculation in millis
    Calendar calendar = new GregorianCalendar(aTimeZone);
    calendar.set(Calendar.YEAR, year);
    calendar.set(Calendar.MONTH, month-1); // 0-based
    calendar.set(Calendar.DAY_OF_MONTH, day);
    calendar.set(Calendar.HOUR_OF_DAY, hour); // 0..23
    calendar.set(Calendar.MINUTE, minute);
    calendar.set(Calendar.SECOND, second);
    calendar.set(Calendar.MILLISECOND, millis);
    
    long baseResult = calendar.getTimeInMillis() * MILLION; // either sign
    //the adjustment for nanos is always positive, toward the future:
    return baseResult + nanosRemaining;
  }