Repository navigation
Description
Describe the bug
It seems that the EPW data being read is being shifted one hour back.
To Reproduce
epwfile = 'USA_AZ_Tucson.Intl.AP.722740_TMY3.epw'
tmyfile = '722740TYA.CSV' # TMY file for Tucson
import pvlib
(epwdata, metadata) = pvlib.iotools.epw.read_epw(epwfile, coerce_year=2002) #pvlib>0.6.1
(tmydata, metadata) = pvlib.iotools.tmy.read_tmy3(tmyfile, coerce_year=2002) #pvlib>0.6.1
fig, ax = plt.subplots()
ax.plot(tmydata.index[0:24], tmydata.DNI[0:24], label='TMY data read with pvlib')
ax.plot(epwdata.index[0:24], epwdata.dni[0:24], label='EPW read with pvlib')
ax.set_ylabel('DNI [W/m$^2$]')
ax.legend()
fig.autofmt_xdate()
Expected behavior
The EPW weather files follow IWEC Manual’s conventions, where the data is aggregated hourly as an average from t-1 to t, just like Typical Meteorological Year Data (TMY). From example, from IWEC Manual:
DNI: This is the Direct Normal Radiation in Wh/m2. (Amount of solar radiation in Wh/m2 received directly from the solar disk on a surface perpendicular to the sun’s rays, during the number of minutes preceding the time indicated.)
Screenshots
If applicable, add screenshots to help explain your problem.

Versions:
pvlib.__version__: '0.9.0-alpha.1+4.g750b1fa'pandas.__version__: '0.24.2'- python: 3.7.3
Additional context
Suggested fix:
epwdata_fix = epwdata.copy()
epwdata_fix .index = epwdata_fix .index+pd.Timedelta(hours=1)
fig, ax = plt.subplots()
ax.plot(tmydata.index[0:24], tmydata.DNI[0:24], label='TMY data read with pvlib')
ax.plot(epwdata.index[0:24], epwdata.dni[0:24], label='EPW read with pvlib ')
ax.plot(epwdata_fix.index[0:24], epwdata_fix .dni[0:24], '*', label='EPW read with pvlib (with suggested shift)')
ax.set_ylabel('DNI [W/m$^2$]')
ax.legend()
fig.autofmt_xdate()
However --- this creates one entry for the first day of the next year at the end of the dataframe which can cause trouble; not sure what to suggest for that, for our use of this we're going to go with deleting the last line.
epwdata_fix = epwdata_fix[:-1]


Activity
cdeil commentedon Nov 6, 2026
@RDaxini, I agree with your comment in #2894 that just documenting the current conventions possibly isn't the best resolution.
I think there are roughly three possible levels of change:
Personally, I would recommend option 3 to have a cleaner solution in the future and would simply ask my coding agent to update my code to match the new conventions when I update. But I don't know your user base and downstream dependencies and what others expect in terms or backward compatibility.
Whichever path is chosen, the semantics should remain explicit: radiation totals and illuminance averages describe intervals, whereas temperature, humidity and pressure are observations at the file time. An end-of-hour labeling scheme should also retain every record, including the final timestamp at midnight on 1 January of the following year, rather than silently dropping or wrapping it.
@RDaxini and @AdamRJensen - what do you think?