{"record":{"id":"9c4660400ab66b94","repo":"binarywang/WxJava","slug":"30-30-30","errorCode":null,"errorMessage":"受限于网络传输，起止时间的最大跨度为30天，如超过30天，则以结束时间为基准向前取30天进行查询","messagePattern":"受限于网络传输，起止时间的最大跨度为30天，如超过30天，则以结束时间为基准向前取30天进行查询","errorType":"validation","errorClass":"WxRuntimeException","httpStatus":null,"severity":"warning","filePath":"weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOaServiceImpl.java","lineNumber":272,"sourceCode":"    JsonObject jsonObject = new JsonObject();\n\n    if (offset == null) {\n      offset = 0;\n    }\n\n    if (limit == null || limit <= 0) {\n      limit = 100;\n    }\n\n    jsonObject.addProperty(\"offset\", offset);\n    jsonObject.addProperty(\"limit\", limit);\n\n    if (startTime != null && endTime != null) {\n      long endtimestamp = endTime.getTime() / 1000L;\n      long starttimestamp = startTime.getTime() / 1000L;\n\n      if (endtimestamp - starttimestamp < 0 || endtimestamp - starttimestamp >= MONTH_SECONDS) {\n        throw new WxRuntimeException(\"受限于网络传输，起止时间的最大跨度为30天，如超过30天，则以结束时间为基准向前取30天进行查询\");\n      }\n\n      jsonObject.addProperty(\"start_time\", starttimestamp);\n      jsonObject.addProperty(\"end_time\", endtimestamp);\n    }\n\n    final String url = this.mainService.getWxCpConfigStorage().getApiUrl(GET_DIAL_RECORD);\n    String responseContent = this.mainService.post(url, jsonObject.toString());\n    JsonObject tmpJson = GsonParser.parse(responseContent);\n\n    return WxCpGsonBuilder.create().fromJson(tmpJson.get(\"record\"),\n      new TypeToken<List<WxCpDialRecord>>() {\n      }.getType()\n    );\n  }\n\n  @Override\n  public WxCpOaApprovalTemplateResult getTemplateDetail(@NonNull String templateId) throws WxErrorException {","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/binarywang/WxJava/blob/1c43293a3c2c9d7e91304b6d037fb017f680d0c6/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOaServiceImpl.java#L254-L290","documentation":"Thrown (as unchecked WxRuntimeException) by getDialRecord() when the optional startTime/endTime pair spans 30 or more days (MONTH_SECONDS) or when endTime precedes startTime. WeChat's dial-record API caps the query window at strictly less than 30 days. Note the boundary uses >= (not >), so exactly 30 days is rejected.","triggerScenarios":"Passing both startTime and endTime where the difference is negative or >= 2,678,400 seconds (31 days as defined by MONTH_SECONDS). The check is `endtimestamp - starttimestamp < 0 || endtimestamp - starttimestamp >= MONTH_SECONDS`. Only fires when both startTime and endTime are non-null.","commonSituations":"Querying a month's worth of call records without accounting for the strict < 30-day limit; passing a pre-built date range object; accidentally inverting start and end.","solutions":["Limit each query window to at most 29 days to stay safely under the boundary","Chunk wide ranges into multiple sub-30-day calls","Pass null for both startTime and endTime if you want the default recent window without time filtering"],"exampleFix":"// before\nList<WxCpDialRecord> records = oaService.getDialRecord(userIds, null, monthStart, monthEnd, null, null); // exactly 30+ days\n\n// after — keep window under 30 days\nlong maxWindow = 29L * 24 * 3600 * 1000;\nDate safeEnd = new Date(Math.min(monthEnd.getTime(), monthStart.getTime() + maxWindow));\nList<WxCpDialRecord> records = oaService.getDialRecord(userIds, null, monthStart, safeEnd, null, null);","handlingStrategy":"validation","validationCode":"// Validate date range before calling getDialRecord\nif (startTime != null && endTime != null) {\n  long diff = (endTime.getTime() - startTime.getTime()) / 1000;\n  if (diff < 0) {\n    throw new IllegalArgumentException(\"endTime 必须晚于 startTime\");\n  }\n  if (diff >= 31 * 24 * 3600) {\n    // Chunk: use 29-day windows\n    Date safeEnd = new Date(startTime.getTime() + 29L * 24 * 3600 * 1000);\n    // call with safeEnd, then advance\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use 29-day windows for dial-record queries to stay safely under the 30-day boundary","Note this method uses >= (strictly less than 30 days), unlike getCheckinData which uses >","Pass null for both startTime and endTime if time filtering is not needed"],"tags":["wechat-cp","oa","dial-record","validation","date-range"],"backgroundTag":null,"analyzedSha":"1c43293a3c2c9d7e91304b6d037fb017f680d0c6","analyzedAt":"2026-08-14T02:29:11.060Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}