Java停车费计算



看来,我找不到问题的答案,所以我在这里,首先在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/MontrealAfrica/CasablancaPacific/Auckland。切勿使用2-4个字母缩写,例如ESTIST,因为它们不是真实时区,而不是标准化,甚至不是唯一的(!)。

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 。这通常在日期时间处理中使用。DurationPeriod类应用此方法。

但要小心单独匹配分数。您的日期时间对象可能会持有秒和/或分数秒,这会丢弃您的算法。作为一种习惯,如果有比您想要的粒状更小的可能性,请明确截断您的日期时间对象。例如,ZonedDateTime.truncatedTo

速率变化

显然,费率变化使事情变得复杂。其他答案似乎已经涵盖了这一点,所以我不会重复。但是我可以添加一个很大的提示:有关其类IntervalLocalDateRange 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
******

可能需要更多的测试以确保在所有情况下都很好,但应该是您的起点

相关内容

  • 没有找到相关文章

最新更新