根据每周分时电价表 电流 电压 找到最省钱的充电时间段 以及截至的充电时间

package org;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicLong;

/**
 * [
 * {
 * "weeks": [
 * 1,
 * 2,
 * 3,
 * 4,
 * 5
 * ],
 * "weeksRules": [
 * {
 * "beginHour": 0,
 * "beginMinute": 0,
 * "beginTime": "00:00",
 * "endHour": 23,
 * "endMinute": 59,
 * "endTime": "23:59",
 * "level": 1,
 * "unitPrice": 100.0
 * }
 * ]
 * },
 * {
 * "weeks": [
 * 6,
 * 7
 * ],
 * "weeksRules": [
 * {
 * "beginHour": 0,
 * "beginMinute": 0,
 * "beginTime": "00:00",
 * "endHour": 23,
 * "endMinute": 59,
 * "endTime": "23:59",
 * "level": 3,
 * "unitPrice": 1.0
 * }
 * ]
 * }
 * ]
 */

@Data
class WeeklyTOUPricing implements Serializable {


    @ApiModelProperty(value = "适用星期数")
    private List<Integer> weeks;

    @ApiModelProperty(value = "电价计费规则")
    private List<DailyTOUPricing> weeksRules;

}


@Data
@ApiModel
class DailyTOUPricing implements Serializable {

    @ApiModelProperty(value = "电量单价")
    private BigDecimal unitPrice;

    @ApiModelProperty(value = "开始时间-小时部分")
    private Integer beginHour = 0;

    @ApiModelProperty(value = "开始时间-分钟部分")
    private Integer beginMinute = 0;

    @ApiModelProperty(value = "结束时间-小时部分")
    private Integer endHour = 0;

    @ApiModelProperty(value = "结束时间-分钟部分")
    private Integer endMinute = 0;

    @ApiModelProperty(value = "开始时间(HH:mm)")
    private String beginTime;

    @ApiModelProperty(value = "结束时间(HH:mm)")
    private String endTime;
}

public class WeekRule {

    public static void main(String[] args) {
        String a = "[\n" +
                "    {\n" +
                "       \"weeks\": [\n" +
                "         1,\n" +
                "         2,\n" +
                "         3,\n" +
                "         4,\n" +
                "         5\n" +
                "       ],\n" +
                "       \"weeksRules\": [\n" +
                "         {\n" +
                "           \"beginHour\": 0,\n" +
                "           \"beginMinute\": 0,\n" +
                "           \"beginTime\": \"00:00\",\n" +
                "           \"endHour\": 23,\n" +
                "           \"endMinute\": 59,\n" +
                "           \"endTime\": \"23:59\",\n" +
                "         \n" +
                "           \"unitPrice\": 100.0\n" +
                "         }\n" +
                "       ]\n" +
                "     },\n" +
                "     {\n" +
                "       \"weeks\": [\n" +
                "         6,\n" +
                "         7\n" +
                "       ],\n" +
                "       \"weeksRules\": [\n" +
                "         {\n" +
                "           \"beginHour\": 0,\n" +
                "           \"beginMinute\": 0,\n" +
                "           \"beginTime\": \"00:00\",\n" +
                "           \"endHour\": 21,\n" +
                "           \"endMinute\": 59,\n" +
                "           \"endTime\": \"21:59\",\n" +
                "         \n" +
                "           \"unitPrice\": 1.0\n" +
                "         }\n" +

                "{" +
                "           \"beginHour\": 22,\n" +
                "           \"beginMinute\": 00,\n" +
                "           \"beginTime\": \"22:00\",\n" +
                "           \"endHour\": 23,\n" +
                "           \"endMinute\": 59,\n" +
                "           \"endTime\": \"23:59\",\n" +
                "         \n" +
                "           \"unitPrice\": 11.0\n" +
                "         }\n" +
                "       ]\n" +
                "     }\n" +
                "   ]";
        List<WeeklyTOUPricing> weeklyTOUPricings = JSON.parseArray(a, WeeklyTOUPricing.class);
        ZonedDateTime beginZonedDateTime = ZonedDateTime.now();
        TOUPricingHolder touPricingHolder = futureTOUPricing(
                beginZonedDateTime, beginZonedDateTime.plusDays(2), weeklyTOUPricings);
        System.out.println(JSON.toJSONString(touPricingHolder));

        List<TOUPricing> touPricingList = touPricingHolder.getTouPricingList();
        System.out.println(JSON.toJSONString(touPricingList));
        BigDecimal offPeakPrice = touPricingHolder.getOffPeakPrice();
        AtomicLong sumChargeTime = new AtomicLong(0);
        BigDecimal minChargeTime = estimateChargeTime(BigDecimal.valueOf(50), BigDecimal.valueOf(220), BigDecimal.valueOf(6));
        for (TOUPricing t : touPricingList) {
            if (t.getPrice().equals(offPeakPrice)) {
                long beforeAddValue = sumChargeTime.get();
                long afterAddValue = sumChargeTime.addAndGet(t.getDuration());
                if (BigDecimal.valueOf(afterAddValue).compareTo(minChargeTime) < 0) {
                    System.out.println("deadline , charge time is" + t.getEndDateTime() + afterAddValue);
                } else {
                    if (BigDecimal.valueOf(afterAddValue).compareTo(minChargeTime) == 0) {
                        long val = Duration.between(beginZonedDateTime, t.getEndDateTime()).toMinutes();
                        System.out.println("想要最低价格优惠 所需要等待时间 " + BigDecimal.valueOf(val) + "分钟");
                        System.out.println("想要最低价格优惠 截至时间" + beginZonedDateTime.plusMinutes(val));
                    } else {
                        long val = Duration.between(beginZonedDateTime, t.getStartDateTime()).toMinutes();
                        BigDecimal minGreenTime = BigDecimal.valueOf(val).add(minChargeTime.subtract(BigDecimal.valueOf(beforeAddValue)));
                        System.out.println("想要最低价格优惠 所需要等待时间 " + minGreenTime + "分钟");
                        System.out.println("想要最低价格优惠 截至时间" + beginZonedDateTime.plusMinutes(minGreenTime.longValue()));
                    }
                    break;
                }
            }
        }
    }

    public static BigDecimal estimateChargeTime(BigDecimal chargeLevel, BigDecimal voltage, BigDecimal current) {
        return chargeLevel.multiply(BigDecimal.valueOf(1000)).divide(voltage.multiply(current), 3, RoundingMode.UP)
                .multiply(BigDecimal.valueOf(60)).setScale(0, RoundingMode.UP);
    }

    /**
     * 从开始充电到下次用车时间端的 电价
     * 未来电价走势
     *
     * @param startScheduleTime 用户开始智能调度时间
     * @param nextDriveTime     下一次出行时间
     * @return 到下一次出行时
     */
    protected static TOUPricingHolder futureTOUPricing(ZonedDateTime startScheduleTime, ZonedDateTime nextDriveTime, List<WeeklyTOUPricing> rules) {
        List<TOUPricing> result = new ArrayList<>();
        //  启动充电时当天的价格走势
        for (WeeklyTOUPricing ruleWeeksDTO : rules) {
            List<Integer> weeks = ruleWeeksDTO.getWeeks();
            if (weeks.contains(startScheduleTime.getDayOfWeek().getValue())) {
                buildTOUPricing(startScheduleTime, ruleWeeksDTO, result);
            }
        }
        // 启动充电时次天的价格走势
        int offset = 1;
        while (nextDriveTime.isAfter(startScheduleTime.plusDays(offset).withHour(0).withMinute(0).withSecond(0))) {
            for (WeeklyTOUPricing ruleWeeksDTO : rules) {
                List<Integer> weeks = ruleWeeksDTO.getWeeks();
                if (weeks.contains(startScheduleTime.plusDays(offset).getDayOfWeek().getValue())) {
                    buildTOUPricing(startScheduleTime.plusDays(offset), ruleWeeksDTO, result);
                }
            }
            offset++;
        }
        return TOUPricingHolder.hold(result);
    }

    private static void buildTOUPricing(ZonedDateTime startScheduleTime, WeeklyTOUPricing ruleWeeksDTO, List<TOUPricing> result) {
        List<DailyTOUPricing> weeksRules = ruleWeeksDTO.getWeeksRules();
        for (DailyTOUPricing costRulesDTO : weeksRules) {
            ZonedDateTime startDateTime = startScheduleTime.withHour(costRulesDTO.getBeginHour()).withMinute(costRulesDTO.getBeginMinute());
            // 给前面的那个电价结束值补上
            if (!result.isEmpty()) {
                TOUPricing touPricing = result.get(result.size() - 1);
                touPricing.setEndDateTime(startDateTime);
            }
            TOUPricing touPricing = new TOUPricing();
            touPricing.setStartDateTime(startDateTime);
            touPricing.setPrice(costRulesDTO.getUnitPrice());
            result.add(touPricing);
        }
    }

}


@Data
@ApiModel("未来的时间段电价")
class TOUPricingHolder {

    private BigDecimal offPeakPrice;

    private List<TOUPricing> touPricingList;

    private TOUPricingHolder(List<TOUPricing> touPricingList) {
        this.touPricingList = touPricingList;
        BigDecimal lowestPrice = null;
        for (TOUPricing touPricing : touPricingList) {
            if (Objects.isNull(lowestPrice)) {
                lowestPrice = touPricing.getPrice();
            } else {
                if (lowestPrice.compareTo(touPricing.getPrice()) > 0) {
                    lowestPrice = touPricing.getPrice();
                }
            }
        }
        this.offPeakPrice = lowestPrice;
    }

    public static  TOUPricingHolder hold(List<TOUPricing> touPricingList) {
        return new TOUPricingHolder(touPricingList);
    }

}




@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel("分时电价")
  class TOUPricing {

    @ApiModelProperty("开始时间")
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm '['VV']'")
    @JSONField(format = "yyyy-MM-dd HH:mm E '['VV']'")
    private ZonedDateTime startDateTime;

    @ApiModelProperty("结束时间")
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm '['VV']'")
    @JSONField(format = "yyyy-MM-dd HH:mm E '['VV']'")
    private ZonedDateTime endDateTime;

    @ApiModelProperty("电价")
    private BigDecimal price;

    @ApiModelProperty("持续时间 分钟 ")
    private int duration;

    public Long getDuration() {
        if (Objects.isNull(startDateTime) || Objects.isNull(endDateTime)) {
            return -1L;
        }
        return Duration.between(startDateTime, endDateTime).toMinutes();
    }
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值