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

如何让React天气App根据搜索城市切换对应时区时间?

解决React天气App中根据城市切换时区时间的问题

我正在使用OpenWeatherAPI开发一款React天气App,目前已成功显示当前时间,但不清楚如何实现根据搜索的城市切换对应时区的时间,附上当前实现代码,尝试过不少方案但均未成功,或是未能理解解决方案。

function App() {
  const [query, setQuery] = useState('');
  const [weather, setWeather] = useState({});

  const search = evt => {
    if (evt.key === "Enter") {
      fetch(`${api.base}weather?q=${query}&units=metric&APPID=${api.key}`)
        .then(res => res.json())
        .then(result => {
          setWeather(result);
          setQuery('');
          console.log(result);
        });
    }
  }

  const dateBuilder = (d) => {
    let months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
    let days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];

    let day = days[d.getDay()];
    let date = d.getDate();
    let month = months[d.getMonth()];
    let year = d.getFullYear();

    return `${day} ${date} ${month} ${year}`
  }

  
   const time = (date) => {
     let hours = date.getHours();
     let minutes = date.getMinutes();

     return `${hours} : ${minutes} `
   }

  

  return (
    <div className={(typeof weather.weather != "undefined") ? 
        ((weather.weather[0].main === "Clear") ? 'app warm' :
         (weather.weather[0].main === "Thunderstorm") ? 'app thunderstorm' :  
         (weather.weather[0].main === "Snow") ? 'app snow' :
         (weather.weather[0].main === "Clouds") ? 'app clouds' :
         (weather.weather[0].main === "Rain") ? 'app rain' :
         (weather.weather[0].main === "Drizzle") ? 'app drizzle' : 'app') : 'app'}>
      <main>
        <div className="search-box">
          <input 
            type="text"
            className="search-bar"
            placeholder="Search City..."
            onChange={e => setQuery(e.target.value)}
            value={query}
            onKeyPress={search}
          />
        </div>
        {(typeof weather.main != "undefined") ? (
        <div>
          <div className="location-box">
            <div className="location">{weather.name}, {weather.sys.country}</div>
            <div className="date">{dateBuilder(new Date())}</div>
          </div>
          <div className="weather-box">
            <div className="temp">
              {Math.round(weather.main.temp)}°c
            </div>
            <div className="weather">{weather.weather[0].main}</div>
            <div className="time">{time(new Date())}</div>
          </div>
        </div>
        ) : ('')}
      </main>
    </div>
  );
}

export default App;

解决方案

OpenWeatherAPI的weather接口会返回目标城市的timezone字段,该值是城市时间相对于UTC的偏移秒数(比如北京为28800,即8小时)。我们可以利用这个值计算出目标城市的当地时间,避免本地时区的干扰。

1. 修改时间/日期生成函数

将dateBuilder和time函数修改为接收时区偏移量参数,基于UTC时间计算当地时间:

const dateBuilder = (timezoneOffset) => {
  const now = new Date();
  // 计算当地时间:UTC时间 + 时区偏移秒数
  const localDate = new Date(now.getTime() + timezoneOffset * 1000);
  const months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
  const days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];

  const day = days[localDate.getUTCDay()];
  const date = localDate.getUTCDate();
  const month = months[localDate.getUTCMonth()];
  const year = localDate.getUTCFullYear();

  return `${day} ${date} ${month} ${year}`;
};

const time = (timezoneOffset) => {
  const now = new Date();
  const localDate = new Date(now.getTime() + timezoneOffset * 1000);
  let hours = localDate.getUTCHours();
  let minutes = localDate.getUTCMinutes();
  // 补零处理,优化显示格式
  hours = hours.toString().padStart(2, '0');
  minutes = minutes.toString().padStart(2, '0');
  return `${hours}:${minutes}`;
};

2. 渲染时传入时区偏移量

在JSX渲染部分,调用函数时传入weather.timezone:

<div className="location-box">
  <div className="location">{weather.name}, {weather.sys.country}</div>
  <div className="date">{dateBuilder(weather.timezone)}</div>
</div>
<div className="weather-box">
  <div className="temp">
    {Math.round(weather.main.temp)}°c
  </div>
  <div className="weather">{weather.weather[0].main}</div>
  <div className="time">{time(weather.timezone)}</div>
</div>

3. 完整修改后的代码

function App() {
  const [query, setQuery] = useState('');
  const [weather, setWeather] = useState({});

  const search = evt => {
    if (evt.key === "Enter") {
      fetch(`${api.base}weather?q=${query}&units=metric&APPID=${api.key}`)
        .then(res => res.json())
        .then(result => {
          setWeather(result);
          setQuery('');
          console.log(result);
        });
    }
  }

  const dateBuilder = (timezoneOffset) => {
    const now = new Date();
    const localDate = new Date(now.getTime() + timezoneOffset * 1000);
    const months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
    const days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];

    const day = days[localDate.getUTCDay()];
    const date = localDate.getUTCDate();
    const month = months[localDate.getUTCMonth()];
    const year = localDate.getUTCFullYear();

    return `${day} ${date} ${month} ${year}`;
  };

  const time = (timezoneOffset) => {
    const now = new Date();
    const localDate = new Date(now.getTime() + timezoneOffset * 1000);
    let hours = localDate.getUTCHours();
    let minutes = localDate.getUTCMinutes();
    hours = hours.toString().padStart(2, '0');
    minutes = minutes.toString().padStart(2, '0');
    return `${hours}:${minutes}`;
  };

  return (
    <div className={(typeof weather.weather != "undefined") ? 
        ((weather.weather[0].main === "Clear") ? 'app warm' :
         (weather.weather[0].main === "Thunderstorm") ? 'app thunderstorm' :  
         (weather.weather[0].main === "Snow") ? 'app snow' :
         (weather.weather[0].main === "Clouds") ? 'app clouds' :
         (weather.weather[0].main === "Rain") ? 'app rain' :
         (weather.weather[0].main === "Drizzle") ? 'app drizzle' : 'app') : 'app'}>
      <main>
        <div className="search-box">
          <input 
            type="text"
            className="search-bar"
            placeholder="Search City..."
            onChange={e => setQuery(e.target.value)}
            value={query}
            onKeyPress={search}
          />
        </div>
        {(typeof weather.main != "undefined") ? (
        <div>
          <div className="location-box">
            <div className="location">{weather.name}, {weather.sys.country}</div>
            <div className="date">{dateBuilder(weather.timezone)}</div>
          </div>
          <div className="weather-box">
            <div className="temp">
              {Math.round(weather.main.temp)}°c
            </div>
            <div className="weather">{weather.weather[0].main}</div>
            <div className="time">{time(weather.timezone)}</div>
          </div>
        </div>
        ) : ('')}
      </main>
    </div>
  );
}

export default App;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 15:10:40