看来,我找不到问题的答案,所以我在这里,首先在stackoverflow上:)
IF语句树将要提及:
buttonSzamol.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//Változók
int StartHour = 18;
int StartMin = 50;
int StopHour = 20;
int StopMin = 49;
int DayTimeIntervalStart = 6;
int DayTimeIntervalStop = 17;
int NightTimeIntervalLateStart = 18;
int NightTimeIntervalLateStop = 23;
int NightTimeIntervalEarlyStart = 0;
int NightTimeIntervalEarlyStop = 5;
int DayHoursTotal = 0;
int NightHoursTotal = 0;
int DayTimePricePerHour = Integer.parseInt(NappaliOraDij.getText());
int NightTimePricePerHour = Integer.parseInt(EjszakaiOraDij.getText());
int StartDay = Integer.parseInt((DatumStart.getText()).replace(".", ""));
int StopDay = Integer.parseInt((DatumStart.getText()).replace(".", ""));
//1 started hour
if( (StartDay == StopDay) && ( ( (StartHour == StopHour) && (StartMin < StopMin) ) || ( ((StartHour + 1) == StopHour) && (StartMin >= StopMin) ) ) ) {
if((DayTimeIntervalStart <= StartHour) && (StopHour <= DayTimeIntervalStop)) {
DayHoursTotal++;
}
if((NightTimeIntervalLateStart <= StartHour) && (StopHour <= NightTimeIntervalLateStop)) {
NightHoursTotal++;
}
} else/*More hours*/if( (StartDay == StopDay) && ( ( (StartHour < StopHour) && (StartMin <= StopMin) ) || ( (StartHour < StopHour) && (StartMin > StopMin) ) ) ) {
if( (StartHour < StopHour) && (StartMin < StopMin) ) {
if((DayTimeIntervalStart <= StartHour) && (StopHour <= DayTimeIntervalStop)) {
DayHoursTotal = DayHoursTotal + (StopHour - StartHour);
DayHoursTotal++;
}
if((NightTimeIntervalLateStart <= StartHour) && (StopHour <= NightTimeIntervalLateStop)) {
NightHoursTotal = NightHoursTotal + (StopHour - StartHour);
NightHoursTotal++;
}
}else if(( (StartHour < StopHour) && (StartMin >= StopMin) )) {
if((DayTimeIntervalStart <= StartHour) && (StopHour <= DayTimeIntervalStop)) {
DayHoursTotal = DayHoursTotal + (StopHour - StartHour);
if(StartMin != StopMin) {
DayHoursTotal--;
}
}
if((NightTimeIntervalLateStart <= StartHour) && (StopHour <= NightTimeIntervalLateStop)) {
NightHoursTotal = NightHoursTotal + (StopHour - StartHour);
if(StartMin != StopMin) {
NightHoursTotal--;
}
}
}
}
NappaliOrak.setText(Integer.toString(DayHoursTotal));
EjszakaiOrak.setText(Integer.toString(NightHoursTotal));
OrakOsszesen.setText(Integer.toString(DayHoursTotal + NightHoursTotal));
NappaliOsszeg.setText(Integer.toString(DayHoursTotal * DayTimePricePerHour));
EjszakaiOsszeg.setText(Integer.toString(NightHoursTotal * NightTimePricePerHour));
VegOsszeg.setText(Integer.toString((DayHoursTotal * DayTimePricePerHour) + (NightHoursTotal * NightTimePricePerHour)));
}
});
因此,简而言之是。我试图为我的同事创建停车费计算器。主要的想法是,它需要计算客户开始的白天和夜间数小时,并且需要计算这些小时的价格。我将Starthour/min-Stophour/min田地更改为直系统,以使其更容易被理解。我不知道是否有一个模块,但是我开始使用很多if语句来做,我刚刚纠结了。在随附的Pastebin中,有开始时间18:50,并停止时间20:49。如果我们输入此数据,则输出应为2天。现在,如果分钟相同,则不算是一个小时。但是,如果我们将输入更改为20:51,则开始了另一个小时,因此DayHourstotal应该等于3。
预先感谢您的任何帮助。如果您对我的代码或想法有更多疑问,请询问。
似乎您正在尝试计算启动小时,而不仅仅是2 times ,但在不同的 dates 之间。
为此,最好使用java.time
软件包,更具体地说是LocalDateTime
类。
LocalDateTime.of(startYear, startMonth, startDay, startHour, startMinute)
LocalDateTimes
与Java 8 ChronoUnit
类中的between()
方法相结合,完全获得了您的需求。
ChronoUnit.MINUTES.between(Temporal t1, Temporal t2)
ps:您不需要那么多'间隔'变量。
只是 day (dayTimeIntervalStart
)和 night (nightTimeIntervalLateStart
)的开始小时就足够了。
在这两个间隔中可以得出之前和之后的小时率。
扰流板!如果您想自己进一步研究,请移开视线!;)
这是一个可运行的代码样本,显示了> 1天的停车逻辑:
(我省略了用户输入解析/逻辑,因为这取决于您的实现)
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
public class ParkingFee {
private static long hoursDifference(LocalDateTime ldt1, LocalDateTime ldt2) {
long minutesDiff = ChronoUnit.MINUTES.between(ldt1, ldt2);
long hoursDiff = Math.round(Math.ceil(minutesDiff/60.0));
return hoursDiff;
}
public static long hoursDifference(
int startDay, int startMonth, int startYear, int startHour, int startMinute,
int endDay, int endMonth, int endYear, int endHour, int endMinute) {
return hoursDifference(
LocalDateTime.of(startYear, startMonth, startDay, startHour, startMinute),
LocalDateTime.of(endYear, endMonth, endDay, endHour, endMinute));
}
public static int determineDayCycle(int dayTimeIntervalStart, int nightTimeIntervalLateStart) {
return nightTimeIntervalLateStart - dayTimeIntervalStart;
}
public static void main(String[] args) {
// Hourly rates
int dayTimePricePerHour = 5;
int nightTimePricePerHour = 10;
// Rate intervals
int dayTimeIntervalStart = 6;
int nightTimeIntervalLateStart = 18;
// Counted hours per rate
int dayHoursTotal = 0;
int nightHoursTotal = 0;
// Start date and time
int startYear = 2019;
int startMonth = 1;
int startDay = 1;
int startHour = 20;
int startMinute = 50;
// End date and time
int endYear = 2019;
int endMonth = 1;
int endDay = 3;
int endHour = 2;
int endMinute = 49;
// Calculate the hours difference
long hourDiff = hoursDifference(
startDay, startMonth, startYear, startHour, startMinute,
endDay, endMonth, endYear, endHour, endMinute);
System.out.println("Hour difference found: "+ hourDiff);
// Handle parking for full days
if (hourDiff > 24) {
int dayCycle = determineDayCycle(dayTimeIntervalStart, nightTimeIntervalLateStart);
long fullDays = hourDiff / 24;
nightHoursTotal += (24-dayCycle)*fullDays;
dayHoursTotal += dayCycle*fullDays;
hourDiff = hourDiff % 24;
}
// Handle the parking for less than full day
while (hourDiff > 0) {
if (startHour < dayTimeIntervalStart) { // Before the day interval -> night
nightHoursTotal++;
} else if(startHour < nightTimeIntervalLateStart) { // Before the night interval -> day
dayHoursTotal++;
} else { // After the day interval -> night
nightHoursTotal++;
}
startHour++;
if (startHour > 23) // At midnight reset the hour to 0
startHour = 0;
hourDiff--;
}
System.out.println("Day hours: "+ dayHoursTotal);
System.out.println("Night hours: "+ nightHoursTotal);
System.out.println("Total hours: "+ (dayHoursTotal + nightHoursTotal));
System.out.println("Day rate charged at "+ dayTimePricePerHour +": "+ (dayHoursTotal * dayTimePricePerHour));
System.out.println("Night rate charged at "+ nightTimePricePerHour +": "+ (nightHoursTotal * nightTimePricePerHour));
System.out.println("Total rate charged: "+ ((dayHoursTotal * dayTimePricePerHour) + (nightHoursTotal * nightTimePricePerHour)));
}
}
此输出:
找到的小时差异:30
一天时间:12
夜间:18
总小时:30
在5:60
的日期费用 夜间费用为10:180
收费的总费率:240
首先,您需要以不同的方式解析整数。您的方法很危险,例如丢失信息。另外,如果有人试图提出不起作用的值,则需要使代码失败。请参阅此问题:如何将字符串转换为Java中的int?
除此之外,仅使用几分钟和几个小时的工作总是很困难。我建议在毫秒中使用绝对时间,这使得进行计算变得更加容易。请参阅此问题:两个日历对象的小时差
时区
您的代码和其他答案无法解决时区异常。如果您正在跟踪实际时刻,当人们实际停放时,与理论24小时的时间相反,则必须考虑到诸如日光节省时间(DST)之类的异常。世界各地的政客表现出一种对重新定义其管辖区时区域的偏爱。因此,天数可以长25小时,23.5小时,24.25或其他时间。
时区是对特定地区人民使用的偏移量的过去,现在和未来的历史。
LocalDateTime
类是用于此目的的错误类。该课程故意没有时区或从UTC的抵消概念。您可以将其用作代码中的构件,但是必须将其分配给ZoneId
,以通过ZonedDateTime
类确定一个实际时刻。
ZoneId
指定您的时区。
如果未指定时区,JVM隐式应用其当前默认时区。该默认值可能会在运行时的任何时刻发生变化(!),因此您的结果可能会有所不同。最好将您所需的/预期时区明确指定为参数。如果至关重要,请与您的用户确认区域。
以Continent/Region
的格式指定适当的时区名称,例如America/Montreal
,Africa/Casablanca
或Pacific/Auckland
。切勿使用2-4个字母缩写,例如EST
或IST
,因为它们不是真实时区,而不是标准化,甚至不是唯一的(!)。
ZoneId z = ZoneId.of( "America/Montreal" ) ;
如果要使用JVM当前默认时区域,请询问并通过参数。如果省略了,代码会模棱两可阅读,我们不确定您是否打算使用默认值,或者您是否像许多程序员一样不知道该问题。
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
组装日期,时间和&amp;确定力矩
的区域组装您的日期和时间。
LocalDate startDate = LocalDate.of( 2019 , 1 , 23 ) ; // 23rd of January in 2019.
LocalTime startTime = LocalTime.of( 18 , 50 ) ; // 6:50 PM.
ZonedDateTime startMoment = ZonedDateTime.of( startDate , startTime , z ) ;
LocalDate stopDate = LocalDate.of( 2019 , 1 , 23 ) ; // 23rd of January in 2019.
LocalTime stopTime = LocalTime.of( 20 , 50 ) ; // Two hours later, exactly — maybe! Depends on any anomalies at that time in that zone.
ZonedDateTime stopMoment = ZonedDateTime.of( stopDate , stopTime , z ) ;
➥请注意,在此示例中,我们 May 的时间跨度恰好为2小时,但也许不是。可能是3个小时或其他时间长度,具体取决于当时在该区域的那个日期安排的异常。
过去的时间
要计算天数(24小时的时间,与日历无关的时间),小时,分钟和秒,请使用Duration
。(对于一年的时间,使用Period
。)
Duration d = Duration.between( startMoment , stopMoment ) ;
在整个时间内询问整个时间。
long hours = d.toHours() ; // Entire duration as count of whole hours.
半开
在随附的粘贴中,有时间18:50,停止时间20:49。如果我们输入此数据,则输出应为2天。现在,如果分钟相同,则不算是一个小时。但是,如果我们将输入更改为20:51,则开始了另一个小时,因此DayHourstotal应该等于3。
这种方法被称为半开的,当开始是包含性时,结束是 exclusive 。这通常在日期时间处理中使用。Duration
和Period
类应用此方法。
但要小心单独匹配分数。您的日期时间对象可能会持有秒和/或分数秒,这会丢弃您的算法。作为一种习惯,如果有比您想要的粒状更小的可能性,请明确截断您的日期时间对象。例如,ZonedDateTime.truncatedTo
。
速率变化
显然,费率变化使事情变得复杂。其他答案似乎已经涵盖了这一点,所以我不会重复。但是我可以添加一个很大的提示:有关其类Interval
和LocalDateRange
的 threeten-extra ,可能对您有帮助。它们包括重叠,包含,基台等方便的比较方法。
divide et impera
在小块中削减大逻辑使得
更容易import java.time.Duration;
import java.time.LocalDateTime;
import java.time.LocalTime;
class Scratch {
static int StartHour = 18;
static int StartMin = 50;
static int StopHour = 20;
static int StopMin = 48;
static int DayTimeIntervalStart = 6;
static int DayTimeIntervalStop = 17;
static int NightTimeIntervalLateStart = 18;
static int NightTimeIntervalLateStop = 23;
static int NightTimeIntervalEarlyStart = 0;
static int NightTimeIntervalEarlyStop = 5;
static int DayTimePricePerHour = 10;
static int NightTimePricePerHour = 5;
static LocalTime dayStart = LocalTime.of(DayTimeIntervalStart, 0);
static LocalTime dayStop = LocalTime.of(DayTimeIntervalStop, 0);
static LocalTime nightEarlyStart = LocalTime.of(NightTimeIntervalEarlyStart, 0);
static LocalTime nightEarlyStop = LocalTime.of(NightTimeIntervalEarlyStop, 0);
static LocalTime nightLateStart = LocalTime.of(NightTimeIntervalLateStart, 0);
static LocalTime nightLateStop = LocalTime.of(NightTimeIntervalLateStop, 0);
public static void main(String[] args) {
LocalDateTime start = LocalDateTime.of(2019, 1, 1, StartHour, StartMin);
LocalDateTime stop = LocalDateTime.of(2019, 1, 1, StopHour, StopMin);
for(int i = 0; i < 3; i++){
stop = stop.plusMinutes(1L);
System.out.println(process(start, stop));
System.out.println("******");
}
stop = stop.plusDays(1L);
System.out.println(process(start, stop));
System.out.println("******");
}
public static int process(LocalDateTime start, LocalDateTime stop){
System.out.println(String.format("checking between %s and %s", start, stop));
if(stop.toLocalDate().isAfter(start.toLocalDate())){
// start and stop not on the same date
// split the computation, first currentDay then the rest
LocalDateTime endOfDay = LocalDateTime.of(start.toLocalDate(), LocalTime.MAX);
int resultForCurrentDay = process(start, endOfDay);
// not for the rest
LocalDateTime startOfNextDay = LocalDateTime.of(start.toLocalDate().plusDays(1L), LocalTime.MIN);
int resultForRest = process(startOfNextDay, stop);
return resultForCurrentDay + resultForRest;
}else{
// start and stop on the same date
return processIntraDay(start, stop);
}
}
private static int processIntraDay(LocalDateTime start, LocalDateTime stop) {
int result = 0;
LocalTime startTime = start.toLocalTime();
LocalTime stopTime = stop.toLocalTime();
// step 1: check early morning
result += checkBoundaries(startTime, stopTime, nightEarlyStart, nightEarlyStop, NightTimePricePerHour);
// step 2: check day time
result += checkBoundaries(startTime, stopTime, dayStart, dayStop, DayTimePricePerHour);
// step 3: check late night
result += checkBoundaries(startTime, stopTime, nightLateStart, nightLateStop, NightTimePricePerHour);
return result;
}
private static int checkBoundaries(LocalTime startTime, LocalTime stopTime, LocalTime lowerBoundary, LocalTime upperBoundary, int priceRatePerHour) {
// check if the period [start;stop] is crossing the period [lowerBoundary;upperBoundary]
if(stopTime.isAfter(lowerBoundary) && startTime.isBefore(upperBoundary)){
// truncate start time to not be before lowerBoundary
LocalTime actualStart = (startTime.isBefore(lowerBoundary))?lowerBoundary:startTime;
// symetrically, truncate stop to not be after upperBounday
LocalTime actualStop = (stopTime.isAfter(upperBoundary))?upperBoundary:stopTime;
// now that we have the proper start and stop of the period, let's compute the price of it
return compute(actualStart, actualStop, priceRatePerHour);
}else{
return 0;
}
}
private static int compute(LocalTime startTime, LocalTime stopTime, int pricePerHour) {
Duration duration = Duration.between(startTime, stopTime);
int hours = (int) duration.toHours();
long minutes = duration.toMinutes();
if(minutes % 60 > 0L){
// hour started, increasing the number
hours++;
}
int result = hours * pricePerHour;
System.out.println(String.format("%d hours at %d price/h => %d", hours, pricePerHour, result));
return result;
}
}
直接用于计算最终价格。更新到商店的白天和晚上的总数应该是一个挑战
我的景象的结果:
checking between 2019-01-01T18:50 and 2019-01-01T20:49
2 hours at 5 price/h => 10
10
******
checking between 2019-01-01T18:50 and 2019-01-01T20:50
2 hours at 5 price/h => 10
10
******
checking between 2019-01-01T18:50 and 2019-01-01T20:51
3 hours at 5 price/h => 15
15
******
checking between 2019-01-01T18:50 and 2019-01-02T20:51
checking between 2019-01-01T18:50 and 2019-01-01T23:59:59.999999999
5 hours at 5 price/h => 25
checking between 2019-01-02T00:00 and 2019-01-02T20:51
5 hours at 5 price/h => 25
11 hours at 10 price/h => 110
3 hours at 5 price/h => 15
175
******
可能需要更多的测试以确保在所有情况下都很好,但应该是您的起点