Clark.Pan 发表于 2024-2-2 18:44:19

所有OADate相关的知识都在这里

本帖最后由 Clark.Pan 于 2024-2-2 18:57 编辑

前言:

OADate(OLE Automation Date)是一种日期和时间表示形式,通常在OLE(Object Linking and Embedding)自动化中使用。它是一种浮点数表示法,用于在不同的编程环境中传递日期和时间信息。

在OADate中,日期被表示为从"1899年12月30日 00:00:00"开始的天数,而时间则以小数部分表示。负数表示该日期在"1899年12月30日"之前,而正数表示在之后。
具体而言,OADate的计算方式是将日期和时间转换为一个浮点数,其中整数部分表示日期,小数部分表示时间。例如,OADate为0.0表示"1899年12月30日 00:00:00",而OADate为1.0表示"1899年12月31日 00:00:00"。

在某些编程语言和环境中,使用OADate可以方便地在不同系统和平台之间传递日期和时间信息,因为它是一种标准的自动化日期表示方法。

SpreadJS中OADate的应用:

SpreadJS中使用了OADate,用于日期格式的处理以及序列化。在SpreadJS中,当单元格的 value 是一个日期类型时,toJSON 或者导出 sjs 序列化,数据绑定等功能会将该日期以OADate字符串的形式表现出来,例如:"/OADate(45317)/"。

注意,这里所说的日期类型指的是Date对象,而非日期字符串,例如new Date("2024-01-31") 这个是一个日期类型,"2024-01-31" 这个不是一个日期类型,是一个字符串类型的日期。

因为无法将一个对象直接序列化,所以需要借助OADate这种形式做转换。

OADate转换:
那么具体 OADate 与 日期类型,或者字符串之间该如何转换呢,下文会详细进行介绍。

JavaScript 将日期字符串转 OADate :
function toOADateStr(dateStr){
                              const ticks = new Date(dateStr).valueOf() - new Date().getTimezoneOffset() * 60 * 1000;
                              const oad = ticks / 86400000 + 25569;
                              if (oad < 0) {
                                        const frac = oad - Math.trunc(oad);
                                        if (frac !== 0) {
                                                oad = Math.ceil(oad) - frac - 2;
                                        }
                              }
                              return "/OADate(" + oad + ")/";
                        }
JavaScript 将 OADate 转为日期字符串:
function toDateStr(oADateStr){
                              var oaDateReg = new RegExp('^/OADate\\(([-+]?(\\d+(\\.\\d*)?|\\.\\d+)([-+]?\\d+)?)\\)/\\s*$');
                              if (typeof oADateStr === "string" && oaDateReg.test(oADateStr)) {
                                        var oadate = parseFloat(oADateStr.match(oaDateReg));
                                        var ms = (oadate * 86400000 * 1440 - 25569 * 86400000 * 1440 + new Date((oadate - 25569) * 86400000).getTimezoneOffset() * 86400000 ) / 1440;
                                        return new Date(ms);
                              }else{
                                        return date;
                              }
                        }
考虑到一些客户通过解析和获取,拿到 OADate 字符串后自己分析,亦或是有时候需要修改 ssjson 或者 DataSource 中的 OADate 场景,这里将一些后端语言处理OADate 的方法也列举出来,供大家参考:

Java 将日期字符串转 OADate:
public static Double convertToOADate(String dateStr) throws ParseException {
                SimpleDateFormat myFormat = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss");
                Date date = myFormat.parse(dateStr);
                BigDecimal time = new BigDecimal(date.getTime());
                time = (time.add(new BigDecimal("2209190400000"))).divide(new BigDecimal(86400000),11,RoundingMode.HALF_UP);
                System.out.println("OADate:"+time.doubleValue());
                return time.doubleValue();

      }
Java 将 OADate 转为日期字符串:
public static String convertFromOADateStr(String oADateStr) throws ParseException {
                String pattern = "/OADate\\((\\d+(\\.\\d+)?)\\)/";

                Pattern r = Pattern.compile(pattern);
                Matcher m = r.matcher(oADateStr);
            if (m.find()) {
                  double d = Double.parseDouble(m.group(1));
                  doublemantissa = d - (long) d;
                        double hour = mantissa*24;
                        double min =(hour - (long)hour) * 60;
                        double sec=(min- (long)min) * 60;

                        SimpleDateFormat myFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
                        Date baseDate = myFormat.parse("1899-12-30 00:00:00");
                        Calendar c = Calendar.getInstance();
                        c.setTime(baseDate);
                        c.add(Calendar.DATE,(int)d);
                        c.add(Calendar.HOUR,(int)hour);
                        c.add(Calendar.MINUTE,(int)min);
                        c.add(Calendar.SECOND,(int)sec);
                        return myFormat.format(c.getTime());
            }else {
                  return "Not a OADate";
            }

      }




页: [1]
查看完整版本: 所有OADate相关的知识都在这里