001/* 002 * SonarQube 003 * Copyright (C) 2009-2017 SonarSource SA 004 * mailto:info AT sonarsource DOT com 005 * 006 * This program is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public License 017 * along with this program; if not, write to the Free Software Foundation, 018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 019 */ 020package org.sonar.api.utils.internal; 021 022import java.io.Serializable; 023import javax.annotation.Nullable; 024import org.apache.commons.lang.builder.ToStringBuilder; 025import org.apache.commons.lang.builder.ToStringStyle; 026 027/** 028 * @since 4.2 029 */ 030public class WorkDuration implements Serializable { 031 032 static final int DAY_POSITION_IN_LONG = 10_000; 033 static final int HOUR_POSITION_IN_LONG = 100; 034 static final int MINUTE_POSITION_IN_LONG = 1; 035 036 public enum UNIT { 037 DAYS, HOURS, MINUTES 038 } 039 040 private int hoursInDay; 041 042 private long durationInMinutes; 043 private int days; 044 private int hours; 045 private int minutes; 046 047 private WorkDuration(long durationInMinutes, int days, int hours, int minutes, int hoursInDay) { 048 this.durationInMinutes = durationInMinutes; 049 this.days = days; 050 this.hours = hours; 051 this.minutes = minutes; 052 this.hoursInDay = hoursInDay; 053 } 054 055 public static WorkDuration create(int days, int hours, int minutes, int hoursInDay) { 056 long durationInSeconds = 60L * days * hoursInDay; 057 durationInSeconds += 60L * hours; 058 durationInSeconds += minutes; 059 return new WorkDuration(durationInSeconds, days, hours, minutes, hoursInDay); 060 } 061 062 public static WorkDuration createFromValueAndUnit(int value, UNIT unit, int hoursInDay) { 063 switch (unit) { 064 case DAYS: 065 return create(value, 0, 0, hoursInDay); 066 case HOURS: 067 return create(0, value, 0, hoursInDay); 068 case MINUTES: 069 return create(0, 0, value, hoursInDay); 070 default: 071 throw new IllegalStateException("Cannot create work duration"); 072 } 073 } 074 075 static WorkDuration createFromLong(long duration, int hoursInDay) { 076 int days = 0; 077 int hours = 0; 078 int minutes = 0; 079 080 long time = duration; 081 Long currentTime = time / WorkDuration.DAY_POSITION_IN_LONG; 082 if (currentTime > 0) { 083 days = currentTime.intValue(); 084 time = time - (currentTime * WorkDuration.DAY_POSITION_IN_LONG); 085 } 086 087 currentTime = time / WorkDuration.HOUR_POSITION_IN_LONG; 088 if (currentTime > 0) { 089 hours = currentTime.intValue(); 090 time = time - (currentTime * WorkDuration.HOUR_POSITION_IN_LONG); 091 } 092 093 currentTime = time / WorkDuration.MINUTE_POSITION_IN_LONG; 094 if (currentTime > 0) { 095 minutes = currentTime.intValue(); 096 } 097 return WorkDuration.create(days, hours, minutes, hoursInDay); 098 } 099 100 static WorkDuration createFromMinutes(long duration, int hoursInDay) { 101 int days = (int)(duration / (double)hoursInDay / 60.0); 102 Long currentDurationInMinutes = duration - (60L * days * hoursInDay); 103 int hours = (int)(currentDurationInMinutes / 60.0); 104 currentDurationInMinutes = currentDurationInMinutes - (60L * hours); 105 return new WorkDuration(duration, days, hours, currentDurationInMinutes.intValue(), hoursInDay); 106 } 107 108 /** 109 * Return the duration in number of working days. 110 * For instance, 3 days and 4 hours will return 3.5 days (if hoursIndDay is 8). 111 */ 112 public double toWorkingDays() { 113 return durationInMinutes / 60d / hoursInDay; 114 } 115 116 /** 117 * Return the duration using the following format DDHHMM, where DD is the number of days, HH is the number of months, and MM the number of minutes. 118 * For instance, 3 days and 4 hours will return 030400 (if hoursIndDay is 8). 119 */ 120 public long toLong() { 121 int workingDays = days; 122 int workingHours = hours; 123 if (hours >= hoursInDay) { 124 int nbAdditionalDays = hours / hoursInDay; 125 workingDays += nbAdditionalDays; 126 workingHours = hours - (nbAdditionalDays * hoursInDay); 127 } 128 return 1L * workingDays * DAY_POSITION_IN_LONG + workingHours * HOUR_POSITION_IN_LONG + minutes * MINUTE_POSITION_IN_LONG; 129 } 130 131 public long toMinutes() { 132 return durationInMinutes; 133 } 134 135 public WorkDuration add(@Nullable WorkDuration with) { 136 if (with != null) { 137 return WorkDuration.createFromMinutes(this.toMinutes() + with.toMinutes(), this.hoursInDay); 138 } else { 139 return this; 140 } 141 } 142 143 public WorkDuration subtract(@Nullable WorkDuration with) { 144 if (with != null) { 145 return WorkDuration.createFromMinutes(this.toMinutes() - with.toMinutes(), this.hoursInDay); 146 } else { 147 return this; 148 } 149 } 150 151 public WorkDuration multiply(int factor) { 152 return WorkDuration.createFromMinutes(this.toMinutes() * factor, this.hoursInDay); 153 } 154 155 public int days() { 156 return days; 157 } 158 159 public int hours() { 160 return hours; 161 } 162 163 public int minutes() { 164 return minutes; 165 } 166 167 int hoursInDay() { 168 return hoursInDay; 169 } 170 171 @Override 172 public boolean equals(Object o) { 173 if (this == o) { 174 return true; 175 } 176 if (o == null || getClass() != o.getClass()) { 177 return false; 178 } 179 180 WorkDuration that = (WorkDuration) o; 181 return durationInMinutes == that.durationInMinutes; 182 183 } 184 185 @Override 186 public int hashCode() { 187 return (int) (durationInMinutes ^ (durationInMinutes >>> 32)); 188 } 189 190 @Override 191 public String toString() { 192 return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); 193 } 194}