{"record":{"id":"66013b3fa7633a0c","repo":"xpzouying/xiaohongshu-mcp","slug":"iso8601-v","errorCode":null,"errorMessage":"定时发布时间格式错误，请使用 ISO8601 格式: %v","messagePattern":"定时发布时间格式错误，请使用 ISO8601 格式: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"service.go","lineNumber":220,"sourceCode":"}\n\n// PublishContent 发布内容\nfunc (s *XiaohongshuService) PublishContent(ctx context.Context, req *PublishRequest) (*PublishResponse, error) {\n\t// 验证标题长度（小红书限制：最大20个字）\n\tif xhsutil.CalcTitleLength(req.Title) > 20 {\n\t\treturn nil, fmt.Errorf(\"标题长度超过限制\")\n\t}\n\n\timagePaths, err := s.processImages(req.Images)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar scheduleTime *time.Time\n\tif req.ScheduleAt != \"\" {\n\t\tt, err := time.Parse(time.RFC3339, req.ScheduleAt)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"定时发布时间格式错误，请使用 ISO8601 格式: %v\", err)\n\t\t}\n\n\t\t// 校验定时发布时间范围：1小时至14天\n\t\tnow := time.Now()\n\t\tminTime := now.Add(1 * time.Hour)\n\t\tmaxTime := now.Add(14 * 24 * time.Hour)\n\n\t\tif t.Before(minTime) {\n\t\t\treturn nil, fmt.Errorf(\"定时发布时间必须至少在1小时后，当前设置: %s，最早可选: %s\",\n\t\t\t\tt.Format(\"2006-01-02 15:04\"), minTime.Format(\"2006-01-02 15:04\"))\n\t\t}\n\t\tif t.After(maxTime) {\n\t\t\treturn nil, fmt.Errorf(\"定时发布时间不能超过14天，当前设置: %s，最晚可选: %s\",\n\t\t\t\tt.Format(\"2006-01-02 15:04\"), maxTime.Format(\"2006-01-02 15:04\"))\n\t\t}\n\n\t\tscheduleTime = &t\n\t\tlogrus.Infof(\"设置定时发布时间: %s\", t.Format(\"2006-01-02 15:04\"))","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/xpzouying/xiaohongshu-mcp/blob/332d196854a9eac0d2b8c2c0e3d0cc43139d724c/service.go#L202-L238","documentation":"PublishContent parses req.ScheduleAt with time.Parse(time.RFC3339, ...). If the string is not a valid RFC3339/ISO8601 timestamp, publishing is rejected with this error before any scheduling occurs. The wrapped %v contains the underlying parse error.","triggerScenarios":"Calling PublishContent with ScheduleAt set to any non-RFC3339 string, e.g. '2026-09-06 10:00:00' (space instead of T), '2026/09/06', missing timezone offset, or Unix epoch numbers.","commonSituations":"Frontend sending local datetime strings without 'T' separator or timezone; serializing with a non-ISO format; users typing times manually; JavaScript toISOString vs local formatting mismatches.","solutions":["Send ScheduleAt in RFC3339 format, e.g. '2026-09-06T10:00:00+08:00' or '...Z'","On the caller side, parse/convert the user's input with time.Parse(time.RFC3339) first and show a format hint","Normalize common formats (space-separated, no timezone) to RFC3339 before calling the API"],"exampleFix":"// before\nreq.ScheduleAt = \"2026-09-06 10:00:00\" // parse error\n// after\nreq.ScheduleAt = time.Date(2026, 9, 6, 10, 0, 0, 0, time.Local).Format(time.RFC3339)","handlingStrategy":"validation","validationCode":"if req.ScheduleAt != \"\" {\n    if _, err := time.Parse(time.RFC3339, req.ScheduleAt); err != nil {\n        return fmt.Errorf(\"ScheduleAt must be RFC3339, got %q\", req.ScheduleAt)\n    }\n}","typeGuard":"func isRFC3339(s string) bool {\n    _, err := time.Parse(time.RFC3339, s)\n    return err == nil\n}","tryCatchPattern":"resp, err := svc.PublishContent(ctx, req)\nif err != nil && strings.Contains(err.Error(), \"ISO8601\") {\n    return fmt.Errorf(\"bad schedule format: %w — use e.g. %s\", err, time.Now().Add(2*time.Hour).Format(time.RFC3339))\n}","preventionTips":["Always serialize times with t.Format(time.RFC3339)","Never hand-format datetimes with spaces or missing timezone offsets","Add a client-side isRFC3339 check before invoking the service","Document the expected format in the API schema (format: date-time)"],"tags":["go","validation","time-format","iso8601","scheduling"],"backgroundTag":"invalid-datetime-format","analyzedSha":"332d196854a9eac0d2b8c2c0e3d0cc43139d724c","analyzedAt":"2026-09-05T22:22:55.988Z","contentChangedAt":"2026-09-05T22:22:55.988Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}