You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apollo GraphQL请求中UTC日期序列化异常问题(GMT+3时区)

原因分析
  1. 默认序列化逻辑的误解:Apollo Client默认使用JSON.stringify序列化变量,而JSON.stringify会调用Date对象的toISOString()方法,输出UTC标准的ISO字符串。如果你的日志打印的是Date对象的toString()(显示本地时区时间),会误以为对象是正确的UTC时间,但实际toISOString()输出的是真正的UTC时间,和你预期的不符。
  2. 时间转换逻辑错误:你可能错误地将本地时间直接作为UTC时间创建Date对象,或者转换过程中时区处理颠倒,导致最终Date对象的UTC值和预期不符。
  3. 自定义序列化未生效:如果配置了自定义日期序列化规则,可能因Apollo Client 3.7.14版本的配置方式错误,导致规则被覆盖或未执行。
排查与解决步骤
  • 验证Date对象的真实UTC值:不要直接打印Date对象,改用toISOString()和getTime()确认实际值:

    const localDate = new Date(2023, 8, 13); // GMT+3时区的00:00
    console.log('UTC字符串:', localDate.toISOString()); // 正确应为"2023-09-12T21:00:00.000Z"
    console.log('时间戳:', localDate.getTime());
    

    对比这个输出和你预期的2023-09-13T03:00:00.000Z,确认是转换逻辑错误还是序列化问题。

  • 自定义Apollo变量序列化:在创建Apollo Client实例时,配置自定义序列化规则,手动控制Date对象的输出格式:

    import { ApolloClient, InMemoryCache, HttpLink } from '@apollo/client';
    
    const client = new ApolloClient({
      uri: '/your-graphql-endpoint',
      cache: new InMemoryCache(),
      link: new HttpLink({ uri: '/your-graphql-endpoint' }),
      defaultOptions: {
        mutate: {
          variablesSerializer: (variables) => {
            return JSON.stringify(variables, (key, value) => {
              if (value instanceof Date) {
                // 若需要输出"2023-09-13T03:00:00.000Z",调整Date对象时间后生成UTC字符串
                return new Date(value.getTime() + 3 * 60 * 60 * 1000).toISOString();
              }
              return value;
            });
          },
        },
      },
    });
    
  • 拦截请求检查变量状态:添加Apollo Link拦截请求,查看序列化前的变量状态,确认问题出在转换还是序列化阶段:

    import { ApolloLink } from '@apollo/client';
    
    const debugLink = new ApolloLink((operation, forward) => {
      console.log('突变变量(序列化前):', operation.variables);
      if (operation.variables.yourDateField) {
        console.log('日期的UTC字符串:', operation.variables.yourDateField.toISOString());
      }
      return forward(operation);
    });
    
    // 将debugLink添加到Client的link链中
    const client = new ApolloClient({
      uri: '/your-graphql-endpoint',
      cache: new InMemoryCache(),
      link: debugLink.concat(new HttpLink({ uri: '/your-graphql-endpoint' })),
    });
    
  • 确认后端Schema的日期要求:检查后端GraphQL Schema中对应字段的类型(如是否为DateTime),确认后端期望的是UTC时间字符串还是带时区偏移的字符串,调整前端序列化逻辑匹配后端要求。

内容的提问来源于stack exchange,提问作者Fatah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 09:42:45