Apollo GraphQL请求中UTC日期序列化异常问题(GMT+3时区)
原因分析
- 默认序列化逻辑的误解:Apollo Client默认使用
JSON.stringify序列化变量,而JSON.stringify会调用Date对象的toISOString()方法,输出UTC标准的ISO字符串。如果你的日志打印的是Date对象的toString()(显示本地时区时间),会误以为对象是正确的UTC时间,但实际toISOString()输出的是真正的UTC时间,和你预期的不符。 - 时间转换逻辑错误:你可能错误地将本地时间直接作为UTC时间创建Date对象,或者转换过程中时区处理颠倒,导致最终Date对象的UTC值和预期不符。
- 自定义序列化未生效:如果配置了自定义日期序列化规则,可能因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
相关产品推荐
相关产品推荐

