根据工作日/节假日收货要求计算预计发货时间

1.需求: 根据下单时间orderTime(这里默认是系统时间); 客户收货时间要求:工作日=1,节假日2; 计算预计发货时间(这里需要运输时长);

2.思路:  要计算预计发货时间,(仓库的发货截止时间是当天的16:30 ;16:30以后的当做第二天的订单)

    首先计算正常情况到货时间, 例如正常情况下: 某订单是8月16号的单子, 上海-->江苏省南京市  8月16号 16:30 发货, 运输时效为17小时,预计到货时间是8月17号 9:30(周六) ,

    然后,根据预计到货时间开始计算出客户要求的工作日/节假日时间. 如果客户要求节假日送货,说明8月16号16:30 正常发货即可,延迟时间delayDays=0;

    假如客户需要工作日送货(即到货时间是8月19号 9:30 (周一)  ),推迟发货天数delayDays=2,即8月18号 16:30 发货.

3.难点及解决方案:  这里比较困难的地方是如何获取预计的到货时间是工作日/节假日,并且找到符合要求的预计到货时间.

解决方案基本两种,

  第一,维护一个日历表,专门用来查询日期是工作日还是节假日. 优点是比较容易获取数据,查询方便;   缺点:法定节假日和补班难以维护,手头不一定有现成数据.

  第二,请求第三方网站,查询节假日类型, 优点:查询方便,直接HTTP请求获取; 缺点:第三方网站稳定和安全问题,可能导致不能使用,无法查询;

4 我这里选第二种方案 ,当然,请示领导后得到允许使用第三方网站 http://api.goseek.cn ; 如果第三方不稳定的情况下,直接根据正常日期的周末和工作日来判断就可以;

5.下面提供获取延迟发货天数的代码,(仓库发货截止时间是当天的16:30,这里默认的发货时间就是16:30 ,具体的快递发货时间可以自行调节 )

6.请求第三方网站工具类

package utils.time;

import net.sf.json.JSONObject;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;

public class HolidayUtil {
    /*
    获取指定日期的节假日信息
    1、接口地址:http://api.goseek.cn/Tools/holiday?date=数字日期,支持https协议。
    2、返回数据:正常工作日对应结果为 0, 法定节假日对应结果为 1, 节假日调休补班对应的结果为 2,休息日对应结果为 3
    3、节假日数据说明:本接口包含2017年起的中国法定节假日数据,数据来源国务院发布的公告,每年更新1次,确保数据最新
    4、示例: 请求和返回数据格式
    http://api.goseek.cn/Tools/holiday?date=20191005    {"code":10000,"data":1}     国庆节
    http://api.goseek.cn/Tools/holiday?date=20190805       {"code":10000,"data":0}       星期一
    http://api.goseek.cn/Tools/holiday?date=20190817       {"code":10000,"data":3}       星期六
    http://api.goseek.cn/Tools/holiday?date=20190818      {"code":10000,"data":3}        星期日
    http://api.goseek.cn/Tools/holiday?date=20190815     {"code":10000,"data":0}     星期四
    http://api.goseek.cn/Tools/holiday?date=20190913    {"code":10000,"data":1}       中秋节
    http://api.goseek.cn/Tools/holiday?date=20190929    {"code":10000,"data":2}     调休补班
    * */

    public static Integer request(String httpArg) {
        String httpUrl =  "http://api.goseek.cn/Tools/holiday?date=";
        BufferedReader reader = null;
        String result = null;
        StringBuffer sbf = new StringBuffer();
        httpUrl += httpArg;

        // int d = 0;
        Integer d = null;  // 节假日类型,这里默认为null

        try {
            URL url = new URL(httpUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.connect();
            InputStream is = connection.getInputStream();
            reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
            String strRead = null;
            while ((strRead = reader.readLine()) != null) {
                sbf.append(strRead);
                sbf.append("\r\n");
            }
            reader.close();
            result = sbf.toString();
            JSONObject ob = JSONObject.fromObject(result);
            if (ob != null) {
                d = Integer.parseInt(ob.getString("data"));
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return d;
    }

    /*请求例子*/
    public static void main(String[] args) {
        //判断今天是否是工作日 周末 还是节假日
        SimpleDateFormat f = new SimpleDateFormat("yyyyMMdd");
        String httpArg = "20190216";//f.format(new Date());
        System.out.println(httpArg);
        int n = request(httpArg);
        System.out.println(httpArg + " 请求判断工作日节假日例子结果:" + n);
        //工作日对应结果为 0, 休息日对应结果为 1, 节假日对应的结果为 2

    }

}

7. 计算延迟发货天数

package utils.time;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class DelayDaysDemo {

    public static Integer SCHEDULLE_TYPE_WEEK = 1;  //传投递时延要求,:1=工作日,2=节假日,
    public static Integer SCHEDULLE_TYPE_WEEKEND = 2;  //传投递时延要求,:1=工作日,2=节假日,

    public static String TIME_FORM_HOLIDAY = "yyyyMMdd";  //判断日期是否是工作日节假日周末的时间格式

    /**
     * @Param: startDate  ,预计到达日期(*必填)
     * @Param: scheduleType   传投递时延要求,:1=工作日,2=节假日,(*必填)
     * @Description: 获取日期开始的第一个工作日或者休息日, 返回startDate往后推迟的天数
     * @Author: zyf    2019/8/14
     */
    public static Integer getDelayDay(Date startDate, Integer scheduleType) throws Exception {
        //优先发送http请求第三方查询日期的网站,其次比较正常工作日和周六周末
        SimpleDateFormat f = new SimpleDateFormat(TIME_FORM_HOLIDAY);  //被判断日期的格式
        /*从当天日期开始,往后面推30天内的时间,找出符合要求的日期*/
        for (int i = 0; i < 30; i++) {

            String formatDay = f.format(startDate);

            Integer holidayType = null; //默认null,工作日/节假日类型:1=工作日,2=节假日,对应延时要求的类型1,2
            try {
                //调用第三方工具判断今天是否是工作日 周末 还是节假日,返回的数据类型,工作日=0,法定节假日=1,调休补班=2,休息日=3
                Integer responseType = HolidayUtil.request(formatDay);
                //int c=1/0;  //测试第三方异常

                //返回的类型匹配工作日/节假日类型
                if (responseType != null) {
                    switch (responseType) {
                        case 0:
                            holidayType = SCHEDULLE_TYPE_WEEK; //1,  1=工作日,2=节假日
                            break;
                        case 1:
                            holidayType = SCHEDULLE_TYPE_WEEKEND;//2,  1=工作日,2=节假日
                            break;
                        case 2:
                            holidayType = SCHEDULLE_TYPE_WEEK;//1,  1=工作日,2=节假日
                            break;
                        case 3:
                            holidayType = SCHEDULLE_TYPE_WEEKEND;//2,  1=工作日,2=节假日
                            break;
                        default:
                            break;
                    }
                }
            } catch (Exception e) {
                //logger.error(formatDay + " 调用第三方工具判断是否是工作日出现异常!!", e);
                e.printStackTrace();
                System.out.println(formatDay + " 调用第三方工具判断是否是工作日出现异常!!");
                //有异常继续向下进行
            }

            System.out.println(formatDay + " 工作日/节假日类型是:" + holidayType);

            //try 第三方请求的异常,如果异常,走正常的周末周中类型判断
            if (holidayType == null) {
                holidayType = dayTypeForWeek(startDate);
            }

            if (scheduleType == holidayType) {
                return i;       //如果延时要求的类型跟当前遍历到的日期类型符合直接返回否则继续
            } else {
                startDate = getNextMoreDay(startDate, 1);   //类型不符合,天数+1
                continue;
            }

        }

        return null;  //没有找到直接返回null

    }

    /**
     * @param pDate 修要判断的时间
     * @return dayForWeek 判断结果
     * @Exception 判断是否是周末,//1=工作日,2=节假日
     */
    public static Integer dayTypeForWeek(Date pDate) throws Exception {
        Calendar cal = Calendar.getInstance();
        cal.setTime(pDate);
        int week = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (week == 6 || week == 0) { //0代表周日,6代表周六
            return 2;
        }
        return 1;
    }

    /**
     * @Param: sourceDate  原日期
     * @Param: n  后n天
     * @Description: 获取下N天的时间
     * @Author: zyf    2019/8/14
     */
    public static Date getNextMoreDay(Date sourceDate, int n) {
        int oneDayTime = 24 * 60 * 60 * 1000;       //一天代表的毫秒数
        long initMilliSeconds = sourceDate.getTime() + oneDayTime * n;
        return new Date(initMilliSeconds);  //毫秒时间格式化成Date类型
    }

}

8. 原预计发货时间+延迟发货天数n=真正的预计发货时间 .

9.总结

 ①选择合适的解决问题方法.道路千万条~

② 具体问题需要具体分析,这里计算的预计发货时间只是一个大概的时间范围,具体的时间还跟快递的运输时效,快递的到达(送货)时间有关.

比如,由程序计算出的预计到达时间是周五20:00点,这个时间算工作日呢还是节假日? 这里就要根据实际业务继续优化计算方法了~

原文地址:https://www.cnblogs.com/coloz/p/11349662.html

时间: 2024-10-24 15:00:40

根据工作日/节假日收货要求计算预计发货时间的相关文章

微信收货地址共享开发接口讲解

写在前面的话:微信开发者文档写的比较清楚,也不容易出错,可是偏偏收货地址共享那儿写的比较绕,同时也会有很多坑,这里总结一下. ======正文开始====== 微信收货地址共享开发接口基本使用场景是: 用户点击按钮----->弹出微信收货地址选择页面---->用户选择收货地址,点击确定后,用户能够获取用户收货地址信息. 1.增加页面按钮标签: <div id="select-address">选择收货地址</div> 2.引用相关javascript

【小程序】获取微信 自带的 收货地址获取和整理

1.wx.chooseAddress(OBJECT) if(wx.chooseAddress){ wx.chooseAddress({ success: function (res) { console.log(JSON.stringify(res)) }, fail: function(err){ console.log(JSON.stringify(err)) } }) }else{ console.log('当前微信版本不支持chooseAddress'); } 2.数据处理,仅供参考 /

PHP电商订单自动确认收货redis队列

一.场景 之前做的电商平台,用户在收到货之后,大部分都不会主动的点击确认收货,导致给商家结款的时候,商家各种投诉,于是就根据需求,要做一个订单在发货之后的x天自动确认收货.所谓的订单自动确认收货,就是在在特定的时间,执行一条update语句,改变订单的状态. 二.思路 最笨重的做法,通过linux后台定时任务,查询符合条件的订单,然后update.最理想情况下,如果每分钟都有需要update的订单,这种方式也还行.奈何平台太小,以及卖家发货时间大部分也是密集的,不会分散在24小时的每分钟.那么,

ECSHOP自动收货解决方案 【附代码】

ecshop系统,本身不带自动确认收货的,网上也找了一下,很多很复杂,且需要在服务器端设置定时任务,如果是虚拟主机,基本上就歇菜了. 某宝有一些卖自动收货的插件,不太了解其机制,不过也比较贵,要1-200一个.没办法,就自己开发吧.以下为解决方案. 解决思路: 跟淘宝的类似,默认设置7天后还没有自动确认收货,那么就会系统强制确认收货.只不过这个强制确认收货,没有在系统里设置常驻内存的程序,也没有设置系统自动任务,为变通的方案.设定为用户在登录成功后,进入用户中心页面,就会扫描自己名下,有没有超过

wex5实战之管理收货地址(一)

今天要与大家分享的是实战项目之管理收货地址,现在各种电商app管理收货地址样式越来越多,效果也越来越好.本次项目步骤有这么几个: 1.list迭代json数据,初始化默认收货地址. 2.list数据增.删.改.查. 首先展示效果图,如下: 图一为管理地址页 图二为新增收货地址页 图三为选择城市地区 下面进行详细代码讲解: 1.初始化list数据 Model.prototype.addressDataCustomRefresh = function(event){ var addressData

设置警告框样式为带有两个文本输入的警告框,用于收集用户收货地址和联系电话。并选择合适的代理方法,当警告框上的两输入框有一个为空时限制“购买”按钮点击。

收集购物信息  iOS项目 倒计时:588 步骤 /.panel-heading 项目需求 设置警告框样式为带有两个文本输入的警告框,用于收集用户收货地址和联系电话.并选择合适的代理方法,当警告框上的两输入框有一个为空时限制“购买”按钮点击. #import "TableViewController.h" @interface TableViewController ()<UIAlertViewDelegate> @property (nonatomic, strong)

wex5实战之管理收货地址(二)

接着上一张管理收货地址,这章主要讲解新增,编辑,选择省市区功能,主要有windowReceiver.windowDialog.tree组件的使用. 1.新增.编辑地址,页面. 在页面中放入windowReceiver.windowDialog组件 windowReceiver:用于接收地址参数,判断是否为新增或编辑. windowDialog:用于打开选择省市区弹窗,返回选择数据. Model.prototype.windowReceiver1Receive = function(event){

微信共享收货地址 edit_address:fail 吐白沫级解决方案

又被微信坑了一整天,看完官方文档怎么测试都不通过,我一直怀疑是新版本微信支付我没有设置“共享收货地址”开关造成的. 后来经过验证,新版本不需要做这件事了. 那么,我没错,是微信的文档没及时更新... 查了几个技术博客得知,这个接口在2016年的年中已经升级了,旧版的那个接口不能使了. 于是那个什么Addrsign就去见鬼了. 真的无力吐槽微信团队的文档水平和工作态度,这一家独大的优越感.. 好了好了,说正事儿: 首先,你得开通微信支付,其次,要在微信公众后台配置个安全域名的URL,设置下微信支付

ios仿收货地址管理

最近公司项目增加了一个需求,然后要有收货地址的管理,有单选框的设置,我昨晚也是写了很晚才写出来的,然偶今天就分享一下吧,同时也是我自己积累的过程,当然了,我今天给的是一个demo的例子,我不可能把自己的项目搬进来.下面就不说废话了,直接上代码. 我现在写的是一个简单的demo,至于后面可能会加上难的吧,然后我也会更新的. #import "ViewController.h" #define rowCount        5 @interface ViewController ()&l