/*[deutsch]
<p>Subtrahiert den angegebenen Zeitbetrag von dieser maschinellen
Dauer. </p>

@param   duration    other machine time to be subtracted
@return  difference result
@throws  ArithmeticException in case of numerical overflow
@since   2.0
495909
public MachineTime<U> minus(MachineTime<U> duration) {

        if (duration.isEmpty()) {
            return this;
        } else if (this.isEmpty()) {
            return duration.inverse();
        }

        long s = Math.subtractExact(this.seconds, duration.seconds);
        int f = this.nanos - duration.nanos;
        return new MachineTime<>(s, f, this.scale);

    }
1040070
public int compareTo(DurationField otherField) {
        long otherMillis = otherField.getUnitMillis();
        long thisMillis = getUnitMillis();
        // cannot do (thisMillis - otherMillis) as can overflow
        if (thisMillis == otherMillis) {
            return 0;
        }
        if (thisMillis < otherMillis) {
            return -1;
        } else {
            return 1;
        }
    }
446655
private static Duration parseDuration(String duration) throws ParseException {
        Matcher matcher = pattern.matcher(duration);

        long nanoseconds = 0L;

        if (matcher.find() && matcher.groupCount() == 4) {
            int days = Integer.parseInt(matcher.group(1));
            nanoseconds += TimeUnit.NANOSECONDS.convert(days, TimeUnit.DAYS);
            int hours = Integer.parseInt(matcher.group(2));
            nanoseconds += TimeUnit.NANOSECONDS.convert(hours, TimeUnit.HOURS);
            int minutes = Integer.parseInt(matcher.group(3));
            nanoseconds += TimeUnit.NANOSECONDS.convert(minutes, TimeUnit.MINUTES);
            int seconds = Integer.parseInt(matcher.group(4));
            nanoseconds += TimeUnit.NANOSECONDS.convert(seconds, TimeUnit.SECONDS);
            long nanos = Long.parseLong(matcher.group(5));
            nanoseconds += nanos;
        } else {
            throw new ParseException("Cannot parse duration " + duration, 0);
        }

        return Duration.ofNanos(nanoseconds);
    }
935521
private static final double printDurationFractionsOfMinutes(Duration duration, int factor)
   {
      double result = 0;

      if (duration != null)
      {
         result = duration.getDuration();

         switch (duration.getUnits())
         {
            case HOURS:
            case ELAPSED_HOURS:
            {
               result *= 60;
               break;
            }

            case DAYS:
            {
               result *= (60 * 8);
               break;
            }

            case ELAPSED_DAYS:
            {
               result *= (60 * 24);
               break;
            }

            case WEEKS:
            {
               result *= (60 * 8 * 5);
               break;
            }

            case ELAPSED_WEEKS:
            {
               result *= (60 * 24 * 7);
               break;
            }

            case MONTHS:
            {
               result *= (60 * 8 * 5 * 4);
               break;
            }

            case ELAPSED_MONTHS:
            {
               result *= (60 * 24 * 30);
               break;
            }

            case YEARS:
            {
               result *= (60 * 8 * 5 * 52);
               break;
            }

            case ELAPSED_YEARS:
            {
               result *= (60 * 24 * 365);
               break;
            }

            default:
            {
               break;
            }
         }
      }

      result *= factor;

      return (result);
   }
288803
public static Duration toDuration(String time) {
		if (isBlank(time)) {
			return Duration.ZERO;
		}
		return Duration.of(dehumanize(time), ChronoUnit.MILLIS);
	}
277219
@Override
  public double times(double w1, double w2) {
    if (!isMember(w1) || !isMember(w2)) {
      return Double.NEGATIVE_INFINITY;
    }

    return w1 + w2;
  }
1139967
@NonNull
    @Override
    public TransitionSet setDuration(long duration) {
        super.setDuration(duration);
        if (mDuration >= 0 && mTransitions != null) {
            int numTransitions = mTransitions.size();
            for (int i = 0; i < numTransitions; ++i) {
                mTransitions.get(i).setDuration(duration);
            }
        }
        return this;
    }
236102
public Timecode subtract(SampleCount samples)
	{
		final SampleCount mySamples = getSampleCount();
		final SampleCount result = mySamples.subtract(samples);

		return Timecode.getInstance(result, dropFrame);
	}
1074276
private Duration getDuration(Double duration)
   {
      Duration result = null;

      if (duration != null)
      {
         result = Duration.getInstance(NumberHelper.getDouble(duration), TimeUnit.HOURS);
      }

      return result;
   }
620438
@NonNull
    public static String convertDuration(@IntRange(from = 1) long duration) {
        duration /= 1000;
        int hour = (int) (duration / 3600);
        int minute = (int) ((duration - hour * 3600) / 60);
        int second = (int) (duration - hour * 3600 - minute * 60);

        String hourValue = "";
        String minuteValue;
        String secondValue;
        if (hour > 0) {
            if (hour >= 10) {
                hourValue = Integer.toString(hour);
            } else {
                hourValue = "0" + hour;
            }
            hourValue += ":";
        }
        if (minute > 0) {
            if (minute >= 10) {
                minuteValue = Integer.toString(minute);
            } else {
                minuteValue = "0" + minute;
            }
        } else {
            minuteValue = "00";
        }
        minuteValue += ":";
        if (second > 0) {
            if (second >= 10) {
                secondValue = Integer.toString(second);
            } else {
                secondValue = "0" + second;
            }
        } else {
            secondValue = "00";
        }
        return hourValue + minuteValue + secondValue;
    }
819376
public String format(Duration duration) {
    Long durationInMinutes = duration.toMinutes();
    if (durationInMinutes == 0) {
      return "0";
    }
    boolean isNegative = durationInMinutes < 0;
    Long absDuration = Math.abs(durationInMinutes);

    int days = ((Double) ((double) absDuration / HOURS_IN_DAY / 60)).intValue();
    Long remainingDuration = absDuration - (days * HOURS_IN_DAY * 60);
    int hours = ((Double) (remainingDuration.doubleValue() / 60)).intValue();
    remainingDuration = remainingDuration - (hours * 60);
    int minutes = remainingDuration.intValue();

    return format(days, hours, minutes, isNegative);
  }
88784
public static long durationMS(LocalDateTime start,LocalDateTime end)
   {
      if(start == null || end == null)
      {
         return 0;
      }
      
      return Duration.between(start, end).toMillis();
   }
210815
public Date getStartDate(Date finishDate, Duration duration)
   {
      ProjectProperties properties = getParentFile().getProjectProperties();
      // Note: Using a double allows us to handle date values that are accurate up to seconds.
      //       However, it also means we need to truncate the value to 2 decimals to make the
      //       comparisons work as sometimes the double ends up with some extra e.g. .0000000000003
      //       that wreak havoc on the comparisons.
      double remainingMinutes = NumberHelper.round(duration.convertUnits(TimeUnit.MINUTES, properties).getDuration(), 2);
      Calendar cal = Calendar.getInstance();
      cal.setTime(finishDate);
      Calendar startCal = Calendar.getInstance();

      while (remainingMinutes > 0)
      {
         //
         // Get the current date and time and determine how many
         // working hours remain
         //
         Date currentDate = cal.getTime();
         startCal.setTime(currentDate);
         startCal.add(Calendar.DAY_OF_YEAR, -1);
         Date currentDateEnd = DateHelper.getDayEndDate(startCal.getTime());
         double currentDateWorkingMinutes = getWork(currentDateEnd, currentDate, TimeUnit.MINUTES).getDuration();

         //
         // We have more than enough hours left
         //
         if (remainingMinutes > currentDateWorkingMinutes)
         {
            //
            // Deduct this day's hours from our total
            //
            remainingMinutes = NumberHelper.round(remainingMinutes - currentDateWorkingMinutes, 2);

            //
            // Move the calendar backward to the previous working day
            //
            int count = 0;
            Day day;
            do
            {
               if (count > 7)
               {
                  break; // Protect against a calendar with all days non-working
               }
               count++;
               cal.add(Calendar.DAY_OF_YEAR, -1);
               day = Day.getInstance(cal.get(Calendar.DAY_OF_WEEK));
            }
            while (!isWorkingDate(cal.getTime(), day));

            if (count > 7)
            {
               // We have a calendar with no working days.
               return null;
            }

            //
            // Retrieve the finish time for this day
            //
            Date finishTime = getFinishTime(cal.getTime());
            DateHelper.setTime(cal, finishTime);
         }
         else
         {
            //
            // We have less hours to allocate than there are working hours
            // in this day. We need to calculate the time of day at which
            // our work starts.
            //
            ProjectCalendarDateRanges ranges = getRanges(cal.getTime(), cal, null);

            //
            // Now we have the range of working hours for this day,
            // step through it to work out the start point
            //
            Date startTime = null;
            Date currentDateFinishTime = DateHelper.getCanonicalTime(currentDate);
            boolean firstRange = true;
            // Traverse from end to start
            for (int i = ranges.getRangeCount() - 1; i >= 0; i--)
            {
               DateRange range = ranges.getRange(i);
               //
               // Skip this range if its start is after our end time
               //
               Date rangeStart = range.getStart();
               Date rangeEnd = range.getEnd();

               if (rangeStart == null || rangeEnd == null)
               {
                  continue;
               }

               Date canonicalRangeEnd = DateHelper.getCanonicalTime(rangeEnd);
               Date canonicalRangeStart = DateHelper.getCanonicalTime(rangeStart);

               Date rangeStartDay = DateHelper.getDayStartDate(rangeStart);
               Date rangeEndDay = DateHelper.getDayStartDate(rangeEnd);

               if (rangeStartDay.getTime() != rangeEndDay.getTime())
               {                  
                  canonicalRangeEnd = DateHelper.addDays(canonicalRangeEnd, 1);
               }

               if (firstRange && canonicalRangeStart.getTime() > currentDateFinishTime.getTime())
               {
                  continue;
               }

               //
               // Move the end of the range if our current end is
               // before the range end
               //
               if (firstRange && canonicalRangeEnd.getTime() > currentDateFinishTime.getTime())
               {
                  canonicalRangeEnd = currentDateFinishTime;
               }
               firstRange = false;

               double rangeMinutes;

               rangeMinutes = canonicalRangeEnd.getTime() - canonicalRangeStart.getTime();
               rangeMinutes /= (1000 * 60);

               if (remainingMinutes > rangeMinutes)
               {
                  remainingMinutes = NumberHelper.round(remainingMinutes - rangeMinutes, 2);
               }
               else
               {
                  if (Duration.durationValueEquals(remainingMinutes, rangeMinutes))
                  {
                     startTime = canonicalRangeStart;
                  }
                  else
                  {
                     startTime = new Date((long) (canonicalRangeEnd.getTime() - (remainingMinutes * (60 * 1000))));
                  }
                  remainingMinutes = 0;
                  break;
               }
            }

            DateHelper.setTime(cal, startTime);
         }
      }

      return cal.getTime();
   }
852052
public static Duration getDurationByTimeValues(final long hours, final long minutes, final long seconds) {
        return Duration.ofHours(hours).plusMinutes(minutes).plusSeconds(seconds);
    }
1073392
public void undim(int duration) {
        if (mDimView != null && mDimView.isShown() && mDimView.getAlpha() != 0) {
            mDimView.animate().cancel();
            mDimView.animate().alpha(0.0f)
                .setListener(mDimAnimatorListener)
                .setDuration(duration)
                .start();
        }
    }
1011361
public double getDuration() {
    Map<String, Object> meta = getFileMetaData();
    if (meta != null && meta.containsKey(DURATION)) {
      return ((Number) meta.get(DURATION)).doubleValue();
    }
    return 0;
  }
990551
public final TemporalAmount getDuration() {
        if (duration == null) {
            return TemporalAmountAdapter.fromDateRange(getStart(), getEnd()).getDuration();
        }
        return duration.getDuration();
    }