精华内容
下载资源
问答
  • 昨天测试的同事测试接口的时候,测试出来一个Date类型校验问题。 要求输入的日期格式是:yyyy-MM-dd HH:mm:ss,Vo中使用的注解如下: @DateTimeFormat(pattern=”yyyy-MM-dd HH:mm:ss”) 测试同事输入下面两种...

    标题太长有木有?主要是为了把问题描述清楚,免得进错文章。

    问题描述

    昨天测试的同事测试接口的时候,测试出来一个Date类型校验问题。

    要求输入的日期格式是:yyyy-MM-dd HH:mm:ss,Vo中使用的注解如下:

    @DateTimeFormat(pattern=”yyyy-MM-dd HH:mm:ss”)

    测试同事输入下面两种参数都是保存成功,当输入为“202105”参数时,保存的数据变为“1970-01-01 08:03:22”,由此发现这个问题。

    常用的三种日期格式化的注解解释如下:

    //入参格式化注解
    @DateTimeFormat(pattern=”yyyy-MM-dd HH:mm:ss”)
    
    //出餐格式化注解
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JSONField(format = "yyyy-MM-dd HH:mm:ss") //建议这种

    由于@RequestBody注解先将json字符串转换成对应的Vo对象,Vo对象中的字段上添加的注解再生效,@DateTimeFormat只是做格式化,无法做格式校验。

    解决方案

    用自定义注解进行json字符串中的日期格式做校验。

    解决思路

    1.从request对象中获取原始json字符串入参。由于自定义注解接口ConstraintValidator的实现获取到的参数值是@RequestBody注解将json字符串参数解析成Vo对象后的Date对象,不是原始json字符串值,所以需要从request中获取json原始参数值;

    2.获取到json入参原始值使用正则表达式对日期进行格式进行校验。

     

    温馨提示

    1.由于自定义注解中是无法直接获取到request对象,所以需要按照各自框架获取request对象的方式进行获取。

    2.获取到的原始json字符串入参可能包含空格、回车、换行符、制表符这些特殊字符,所以需要进行特殊字符处理。

    3.获取Vo对象中添加注解的属性名。

    详细见:getFieldName(ConstraintValidatorContext context)即:【((ConstraintValidatorContextImpl) context).basePath.currentLeafNode.name】

    代码实现

    SearchTaskVo.java

    /**
     * 任务结束时间
     **/
    @ApiModelProperty("任务结束时间")
    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
    @DateFormatValidation(format = "yyyy-MM-dd HH:mm:ss", message = "与要求的日期格式[yyyy-MM-dd HH:mm:ss]不符")
    private Date afcx5206;

    DateFormatValidation.java

    import javax.validation.Constraint;
    import javax.validation.Payload;
    import java.lang.annotation.*;
    
    /**
     * 说明:日期格式校验
     *
     * @Author Wanghx
     * @Date 2021/5/11 10:16
     * @Version 1.0
     **/
    @Target({ElementType.FIELD, ElementType.PARAMETER})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Constraint(validatedBy = {DateFormatValidator.class})
    public @interface DateFormatValidation {
    
        //验证失败错误提示信息,使用注解时没有设置错误信息则默认使用信息
        String message() default "格式错误";
    
        //验证格式的规则,使用注解时没有设置验证格式规则则默认使用下面的格式
        String format() default "yyyy-MM-dd";
    
        //分组验证
        Class<?>[] groups() default {};
    
        Class<? extends Payload>[] payload() default {};
    
    }
    DateFormatValidator.java
    import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl;
    import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintViolationCreationContext;
    import org.hibernate.validator.internal.engine.path.NodeImpl;
    import org.hibernate.validator.internal.engine.path.PathImpl;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.validation.ConstraintValidator;
    import javax.validation.ConstraintValidatorContext;
    import java.io.IOException;
    import java.text.SimpleDateFormat;
    import java.util.*;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    /**
     * 说明:日期格式校验
     *
     * @Author Wanghx
     * @Date 2021/4/30 10:17
     * @Version 1.0
     **/
    public class DateFormatValidator extends BaseRestService implements ConstraintValidator<DateFormatValidation, Date> {
        private DateFormatValidation dateFormatValidation;
    
        @Override
        public void initialize(DateFormatValidation constraintAnnotation) {
            this.dateFormatValidation = constraintAnnotation;
        }
    
    
        @Override
        public boolean isValid(Date value, ConstraintValidatorContext context) {
            //如果 value 为空则不进行格式验证,为空验证可以使用 @NotBlank @NotNull @NotEmpty 等注解来进行控制,职责分离
            if (value == null) {
                return true;
            }
            //获取规定的格式
            String format = dateFormatValidation.format();
    
            //验证日期的格式是否正确
            try {
                //获取原始json参数值
                String originalValue = getOriginalValueByFieldName(getFieldName(context));
                //用长度进行比较
                if (ValidateUtil.isNotEmpty(originalValue) && originalValue.length() != format.length()) {
                    return false;
                }
                //校验字符串日期格式
                if (!verifyFormatDateStr(originalValue, format)) {
                    return false;
                }
    
                //用日期格式化验证
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
                simpleDateFormat.format(value);
            } catch (Exception e) {
                return false;
            }
            return true;
        }
    
    
        /**
         * 校验字符串日期格式
         *
         * @param dateStr
         * @param format
         * @return
         */
        private boolean verifyFormatDateStr(String dateStr, String format) {
            boolean resultFlag = false;
            //允许的日期格式
            List<String> formatList = Arrays.asList(DatePattern.PATTEN_DATETIME, DatePattern.PATTEN_DATETIME_SERIAL, DatePattern.PATTEN_DATE, DatePattern.PATTEN_DATE_yyyyMMdd);
            Map<String, String> allDateFormat = getAllDateFormat();
            if (ValidateUtil.isNotEmpty(dateStr) && ValidateUtil.isNotEmpty(format) && formatList.contains(format)) {
                String regex = allDateFormat.get(format);//根据format拼接的正则表达式
                resultFlag = Pattern.compile(regex).matcher(dateStr).matches();
            }
            return resultFlag;
        }
    
        /**
         * 获取日期格式的正则表达式,根据具体业务需要可新增
         *
         * @return
         */
        private Map<String, String> getAllDateFormat() {
            String yyyy = "((1|2)[0-9]{3})";
            String MM = "(0[1-9]|1[012])";
            String dd = "(0[1-9]|[12][0-9]|3[01])";
            String HH = "((0|1)[0-9]|2[0-3])";
            String mm = "([0-5][0-9])";
            String ss = "([0-5][0-9])";
    
            Map<String, String> resultMap = new HashMap<String, String>();
            resultMap.put(DatePattern.PATTEN_DATETIME, yyyy + "-" + MM + "-" + dd + " " + HH + ":" + mm + ":" + ss);
            resultMap.put(DatePattern.PATTEN_DATETIME_SERIAL, yyyy + MM + dd + HH + mm + ss);
            resultMap.put(DatePattern.PATTEN_DATE, yyyy + "-" + MM + "-" + dd);
            resultMap.put(DatePattern.PATTEN_DATE_yyyyMMdd, yyyy + MM + dd);
            return resultMap;
        }
    
        /**
         * 获取添加注解的字段名称
         *
         * @param context
         * @return
         */
        private String getFieldName(ConstraintValidatorContext context) {
            String fieldName = "";
            if (context != null) {
                List<ConstraintViolationCreationContext> constraintViolationCreationContexts = ((ConstraintValidatorContextImpl) context).getConstraintViolationCreationContexts();
                if (ValidateUtil.isNotEmpty(constraintViolationCreationContexts)) {
                    ConstraintViolationCreationContext constraintViolationCreationContext = constraintViolationCreationContexts.get(0);
                    PathImpl path = constraintViolationCreationContext.getPath();
                    if (path != null) {
                        NodeImpl node = path.makeLeafNodeIterable();
                        if (node != null) {
                            fieldName = node.getName();
                        }
                    }
                }
            }
    
            return fieldName;
        }
    
    
        /**
         * 根据字段名称获取json原始值
         *
         * @param fieldName
         * @return
         */
        private String getOriginalValueByFieldName(String fieldName) throws Exception {
            String resultStr = "";//结果值
            if (!StringUtil.isBlank(fieldName)) {
                //获取request对象,【注:根据各自项目获取request对象即可】
                HttpServletRequest request = getRequest();
                //获取json参数原始值,并封装到Map集合中
                Map<String, Object> reqPostParamsMap = new HashMap<String, Object>();
                if (request != null) {
                    //未清洗的json原始值
                    String reqPostStr = getRequestPostStr(request);
                    //清洗json原始值
                    if (!StringUtil.isBlank(reqPostStr)) {
                        reqPostStr = reqPostStr.substring(reqPostStr.indexOf("{"), reqPostStr.indexOf("}"));
                        //去除字符串中的空格、回车、换行符、制表符这些特殊字符
                        Pattern p = Pattern.compile("\\s*|\t|\r|\n");
                        Matcher m = p.matcher(reqPostStr);
                        reqPostStr = m.replaceAll("");
                        //去除前后{}和"
                        reqPostStr = reqPostStr.substring(2, reqPostStr.length() - 1);
                        //将json字符串参数解析后封装成Map
                        String[] reqPostParamList = reqPostStr.split("\",\"");
                        for (String reqPostParam : reqPostParamList) {
                            String[] keyAndValue = reqPostParam.split("\":\"");
                            if (keyAndValue.length >= 2) {
                                reqPostParamsMap.put(keyAndValue[0], keyAndValue[1]);
                            }
                        }
                    }
                }
                //根据字段名称获取对应的原始值
                Object o = reqPostParamsMap.get(fieldName);
                if (o != null) {
                    resultStr = o.toString();
                }
            }
            return resultStr;
        }
    
    
        /**
         * 获取 post 请求的 byte[] 数组
         *
         * @param request
         * @return
         * @throws IOException
         */
        private static byte[] getRequestPostBytes(HttpServletRequest request)
                throws IOException {
            int contentLength = request.getContentLength();
            if (contentLength < 0) {
                return null;
            }
            byte buffer[] = new byte[contentLength];
            for (int i = 0; i < contentLength; ) {
    
                int readlen = request.getInputStream().read(buffer, i,
                        contentLength - i);
                if (readlen == -1) {
                    break;
                }
                i += readlen;
            }
            return buffer;
        }
    
        /**
         * 获取 post 请求内容
         *
         * @param request
         * @return
         * @throws IOException
         */
        private static String getRequestPostStr(HttpServletRequest request)
                throws IOException {
            byte buffer[] = getRequestPostBytes(request);
            String charEncoding = request.getCharacterEncoding();
            if (charEncoding == null) {
                charEncoding = "UTF-8";
            }
            return new String(buffer, charEncoding);
        }
    
    
    }

    测试验证结果

    至此问题解决~

    文章中有何隐藏问题欢迎留言交流~

    有好的解决方案欢迎留言~

    展开全文
  • 日期格式date类型 One of the most frequent problems a "newbie" developer may encounter is having to deal with different data formats. One for all: “新手”开发人员可能遇到的最常见问题之一是必须处理...

    日期格式date类型

    One of the most frequent problems a "newbie" developer may encounter is having to deal with different data formats. One for all:

    “新手”开发人员可能遇到的最常见问题之一是必须处理不同的数据格式。 一劳永逸:

    THE DATE

    日期

    We, as humans, need to "see" a date and then interpret it (much of the times this is an automatic operation).

    作为人类,我们需要“看到”一个日期,然后对其进行解释(在很多情况下,这是自动操作)。

    What if I show you: "07/05/2013"?

    如果我告诉您:“ 07/05/2013”​​,该怎么办?

    Many of you would certainly recognize it as July 5, 2013.

    你们中的许多人当然会认识到它是2013年7月5日。

    For just as many (like me), the same format would mean May 7, 2013...

    对于许多人(像我一样),相同的格式意味着2013年5月7日...

                                                        WHY??

    为什么??

    The problem arises from the fact that the format in which this date is shown (and recognized) varies according to the origin and culture.

    问题来自这样一个事实,即显示(和识别)日期的格式根据来源和文化而变化。

    Human thinking is really far from my field of study, but for sure different contexts lead to different solutions.

    人类思维确实离我的研究领域很远,但是可以肯定的是,不同的环境会导致不同的解决方案。

    Since (until proven otherwise) machines do not think, we should not expect that machines too have our same problems.

    由于(除非经过证明,否则)机器不会考虑 ,所以我们不应该期望机器也遇到同样的问题。

    We should limit our programs to only "show" a certain type of data (in this case a Date) in the format expected by the user (because the user is human and prefers a format applied to the type). We should have in mind that date formats are solely for our own interpretation.

    我们应该限制程序以用户期望的格式仅“显示”某种类型的数据(在这种情况下为日期)(因为用户是人类,并且喜欢将格式应用于该类型)。 我们应该记住,日期格式仅用于我们自己的解释。

    Machines don't really need "a format", they understand dates (times) as a number stored in a date/time column.

    机器实际上并不需要“格式”,它们将日期(时间)理解为存储在日期/时间列中的数字。

    Since we could consider formatting for "show" only, then this is an exclusive operation of the user interfaces.

    由于我们只考虑格式化“ show”,因此这是用户界面的排他性操作

    Everything else, that does not concern the user, MUST NOT have to deal with the formatting of dates.

    与用户无关的所有其他信息,都不必处理日期格式。

    So we can say that:

    所以我们可以这样说:

               UI ARE FOR HUMANS --> USER INTERFACE MAY FORMAT DATES

    UI适用于人类->用户界面可能会格式化日期

    A well designed application should not give any "issue date" to any programmer, nor should it lead to confusion the end user.

    设计良好的应用程序不应给任何程序员任何“发布日期”,也不应引起最终用户的困惑。

    When we design a new application, we should also think at the chance to use the data types offered by the programming language we are using.

    当我们设计一个新的应用程序时,我们还应该考虑使用我们正在使用的编程语言提供的数据类型的机会。

    For example, if we are in c # or vb.net we can ("should") use "DateTime".

    例如,如果我们使用的是c#或vb.net,则可以(“应该”)使用“ DateTime”。

    Even in SQL we have the type "Date" (and "Time").

    即使在SQL中,我们也具有类型“日期”(和“时间”)。

    This is the best way IMO to avoid any kind of "conversion" problem.

    这是IMO避免任何形式的“转换”问题的最佳方法。

    PROGRAMS ARE FOR MACHINES --> PROGRAMS SHOULD USE THE CORRECT TYPE ("DateTime" and equivalents).

    程序适用于机器->程序应使用正确的类型 (“ DateTime”和等效项)。

    What do you think about it?

    你怎么看待这件事?

    翻译自: https://www.experts-exchange.com/articles/11953/Date-formats-are-for-humans-Machines-just-use-the-type.html

    日期格式date类型

    展开全文
  • 文章目录Date类型格式化为字符串不同日期格式的字符串之间的转换获取N天后的日期 Date类型格式化为字符串 java 日期格式化-- SimpleDateFormat 的使用。字符串转日期,日期转字符串 不同日期格式的字符串之间的转换...



    Date类型格式化为各种格式字符串

    java 日期格式化-- SimpleDateFormat 的使用。字符串转日期,日期转字符串

    不同日期格式的字符串之间的转换

        //日期字符串 各种格式之间转换 , 如: 20200101 转换 2020-01-01  2020年01月01日等
        public static String dateStrFormat(String str,String srcFormat,String destFormat)  {
            DateFormat format = new SimpleDateFormat(srcFormat);
            Date date = null;
            try {
                date = format.parse(str);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            SimpleDateFormat sdf = new SimpleDateFormat(destFormat);
            return sdf.format(date);
        }
    

    获取N天后的日期

        // 返回第二天的日期字符串, 如: 20200101 的第二天为 20200102
        public static String returnNextDateStr(String todayDateStr){
        //可以修改参数,自定义输入日期的格式
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");  
            Calendar calendar = Calendar.getInstance();
            try {
                calendar.setTime(sdf.parse(todayDateStr));
            } catch (ParseException e) {
                e.printStackTrace();
            }
            calendar.add(Calendar.DAY_OF_MONTH, 1);
            return sdf.format(calendar.getTime());
        }
    

    实用工具类库common-util使用

    • common-util 是一个和任何模块都无关的模块,common-util 模块中主要包含一些功能的类或者是通用的工具, 任何模块都可以依赖它,然后使用其内部提供的一些工具类。
      common-util 整合了众多优秀的第三方工具类,例如:DateTimeUtil、StringUtil、ValidateUtil、IpUtil 等。 除此之外 common-util 中还包含一些公用的 filter,如跨站请求伪造的过滤器 RefererFilter,防止 Xss 和 sql 注入的 XssAndSqlFilter。省去我们一个个分别引入的麻烦。
    • common-util 已经发布到公共的 maven 仓库中(点击查看),我们只要在 Spring Boot 项目中添加如下依赖即可使用
        <groupId>com.github.shalousun</groupId>
        <artifactId>common-util</artifactId>
        <version>1.9.2</version> </dependency> 
    

    DateTimeUtil 示例代码

        void returnFormatDate()  {
    //        用官方定义的格式
            System.out.println("yyyyMMdd :"+DateTimeUtil.dateToStr(new Date(),DateTimeUtil.YYYYMMDD));
    //        自定义的格式
            System.out.println("yyyyMMdd :"+DateTimeUtil.dateToStr(new Date(),"yyyyMMdd"));
            System.out.println("yyyy年MM月dd日 :"+DateTimeUtil.dateToStr(new Date(),"yyyy年MM月dd日"));
    
        }
    

    参考链接

    实用工具类库common-util使用详解

    展开全文
  • java实现格式Date类型,输入Date输出Date。遍历日期
  • SELECT to_char(to_date(m.ma_datetime,'yyyy-MM-dd hh24:mi:ss'),'yyyyMMdd') FROM my_task m; m.ma_datetime是varchar2类型的日期格式,先转换date类型(必须添加时分秒,不然报ora-...

    SELECT to_char(to_date(m.ma_datetime,'yyyy-MM-dd hh24:mi:ss'),'yyyyMMdd') FROM  my_task m;

    m.ma_datetime是varchar2类型的日期格式,先转换date类型(必须添加时分秒,不然报ora-01830错误

    然后在随心所欲的转换成varchar类型

    转载于:https://my.oschina.net/meSpace/blog/63287

    展开全文
  • Date原型的格式,可以在控制台打印出来看一下:new Date().toString(); 打印出来是这样的格式:Wed Jun 29 17:26:16 CST 2016 自己设置的转换格式是这样的:yyyy-MM-dd HH:mm:ss 打印出来:2016-06-29 17:26:16...
  • )的话,我们首先需要将它转换为日期格式,具体实现方法可以写一个通用函数,代码如下:     &lt;span style="font-size:18px;"&gt;Ext.ux.formatDate = function(dateString){ v...
  • return{ //String类型 theoryDate: '', //理论考试日期 operDate: '', //理论考试时间 theoryTime: '', //实操考试日期 operTime: '', //实操考试时间 }
  • js的类型封装了对日期时间的各种操作,包括按年月日时分秒取值一类的,Date有两个特殊函数,一个parse一个toString,把字符串换成date类型或反过来转换成字符串,因为parse只识别类似yyyy-MM-dd HH:mm:ss这种标准...
  • 在实际开发过程中经常会需要将Date类型的数据封装成XML或Json格式在网络上进行传输,另外在将Date类型的数据存到Sqlite数据库中后再取出来的时候只能获取String类型的日期了,这是因为SQLite是无类型的。这样不得不...
  • String类型转Date SimpleDateFormat formatter = new SimpleDateFormat( "yyyy-MM-dd ");...Date类型转String String date = formatter.format(new Date());//格式化数据 自定义获取当前时间格式 S
  • 【已解决】Date类型日期返回JSON格式yyyy-MM-dd 日期不需要返回时分秒,可用注解@JsonFormat(pattern = “yyyy-MM-dd”): 返回JSON数据为 试过了@JSONField(format = “yyyy-MM-dd”),但是无效。 @JsonFormat...
  • js格式化后台返回的Date类型日期

    千次阅读 2019-04-18 16:54:31
    java后台返回Date类型的日期,js解析得到的是Object对象,格式化方式如下: //参数是后台返回的Object对象,不是字符串 function dateFormatter(date){ //Object对象转为日期格式 var date=new Date(date); var ...
  • 后台在返回json格式Date类型数据时,直接通过@ResponseBody返回出去的是一个长整型时间戳: 解决方法: @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") 它的作用是,出参时,自动把Date型...
  • Java日期格式转化工具(date格式转为string格式,string转date,string转timestamp类型
  • 后台传JSON格式Date类型数据时,通过@RestController或者@ResponseBody返回到前端的是一个未经过处理的Date类型数据: 解决方案:/ 在Date类型对应实现类属性上加@JsonFormat(pattern=“yyyy-MM-dd HH:mm:ss”...
  • 添加 spring: jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8
  • 在我们开发的过程中,有时候会遇到日期类型(Date)和字符串类型...将日期类型格式化成字符串的形式 public static String dataFormat(Date date) { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,633
精华内容 2,253
关键字:

date类型日期格式