Strasmore Research
Learn Matt ConnorBy Matt Connor · data as of September 26, 2026 · refreshed weekly

US Market Hours in German Time (CET/CEST)

US market hours in German time: the NYSE session in CET and CEST, the Xetra overlap window, and the few weeks each year when the clock gap shrinks.

US stock market hours in German time run from 15:January to 22:January, and those two clock times hold all year. Germany sits six hours ahead of New York for roughly 48 weeks of the year, and both regions move their clocks in spring and autumn, which keeps the German start time steady while the label changes from CET to CEST. The exception is a short mismatch each spring and autumn, when the US open arrives an hour earlier on a German clock than the rest of the year.

US stock market hours in German time (CET and CEST)

Every time on this page starts from a single anchor: the New York exchange clock, Eastern Time. Eastern Time runs at UTC minus 5 in the US winter (EST) and UTC minus 4 in the US summer (EDT). German local time runs at UTC plus 1 in winter (CET) and UTC plus 2 in summer (CEST). The panel below converts the anchor through those offsets and recomputes on every rebuild of this page, so nothing in it can go stale as the switch dates move around the calendar.

QueryUS session milestones in ET, UTC and German local time
milestoneet_clockutc_us_wintergerman_cetutc_us_summergerman_cestet_minutes
Premarket opens04:0009:January10:January08:July10:July240
Regular session opens09:3014:January15:January13:July15:July570
Half-day early close13:0018:January19:January17:July19:July780
Regular session closes16:0021:January22:January20:July22:July960
After-hours ends20:0001:January02:January00:July02:July1200
The exact SQL behind every number
SELECT
    tupleElement(m, 1)                                              AS milestone,
    tupleElement(m, 2)                                              AS et_clock,
    formatDateTime(toTimeZone(et_winter, 'UTC'), '%H:%M')           AS utc_us_winter,
    formatDateTime(toTimeZone(et_winter, 'Europe/Berlin'), '%H:%M') AS german_cet,
    formatDateTime(toTimeZone(et_summer, 'UTC'), '%H:%M')           AS utc_us_summer,
    formatDateTime(toTimeZone(et_summer, 'Europe/Berlin'), '%H:%M') AS german_cest,
    tupleElement(m, 3)                                              AS et_minutes
FROM
(
    SELECT
        m,
        toDateTime(concat(toString(toYear(today())), '-01-15 ', tupleElement(m, 2), ':00'), 'America/New_York') AS et_winter,
        toDateTime(concat(toString(toYear(today())), '-07-15 ', tupleElement(m, 2), ':00'), 'America/New_York') AS et_summer
    FROM
    (
        SELECT arrayJoin([
            ('Premarket opens',        '04:00', 240),
            ('Regular session opens',  '09:30', 570),
            ('Half-day early close',   '13:00', 780),
            ('Regular session closes', '16:00', 960),
            ('After-hours ends',       '20:00', 1200)
        ]) AS m
    )
)
ORDER BY et_minutes
Run this yourself

The regular session, the stretch almost every quote, chart and closing price refers to, opens at 09:30 ET and ends at 16:00 ET. In Germany that is 15:January to 22:January in winter and 15:July to 22:July in summer: the same clock times, sitting on different UTC offsets underneath. Premarket trading opens at 04:00 ET, which is 10:January in Germany, and the after-hours session runs to 20:00 ET, or 02:January the following morning German time. The mechanics of those two thin windows sit in after-hours and premarket trading, and the full session-by-session clock in stock market hours.

When are Xetra and the NYSE open at the same time?

Xetra, the main German electronic order book, runs continuous trading from 09:00 to 17:30 German time on an ordinary day, with auctions at the edges. Its own closures and its extended-hours arrangements sit in Xetra trading hours and holidays. New York opens at 15:January German time, which leaves a two-hour overlap, 15:January to 17:30, when both books quote at once. That is the window where a US company's German listing and its home listing are priced side by side. After 17:30 the US tape keeps running alone for another four and a half hours, up to 22:January.

The weeks each year when US hours move in German time

The two regions do not switch to summer time on the same dates. US clocks change on the second Sunday in March and the first Sunday in November. EU clocks change on the last Sunday in March and the last Sunday in October. Two gaps open up:

  • From the second Sunday in March until the last Sunday in March, the US is already on summer time while Germany is still on winter time.
  • From the last Sunday in October until the first Sunday in November, Germany is back on winter time while the US is still on summer time.

In both windows the distance between the two clocks narrows from six hours to five, and the whole US session lands an hour earlier in Germany: the open at 14:March instead of 15:January, the close at 21:March instead of 22:January. The March gap is two or three weeks wide, depending on where the second and last Sundays fall. The autumn gap is always exactly one week. The panel below takes the 09:30 ET open for every US session of the past year and converts it to German local time, week by week.

QueryThe German clock time of the US open, week by week
58 rows (showing 20)
weekgerman_opengerman_closeberlin_minus_et_hours
2025-08-1815:August22:August6
2025-08-2515:August22:August6
2025-09-0115:September22:September6
2025-09-0815:September22:September6
2025-09-1515:September22:September6
2025-09-2215:September22:September6
2025-09-2915:September22:September6
2025-10-0615:October22:October6
2025-10-1315:October22:October6
2025-10-2015:October22:October6
2025-10-2714:October21:October5
2025-11-0315:November22:November6
2025-11-1015:November22:November6
2025-11-1715:November22:November6
2025-11-2415:November22:November6
2025-12-0115:December22:December6
2025-12-0815:December22:December6
2025-12-1515:December22:December6
2025-12-2215:December22:December6
2025-12-2915:January22:January6
The exact SQL behind every number
SELECT
    toString(week)                                                            AS week,
    any(formatDateTime(toTimeZone(us_open_et, 'Europe/Berlin'), '%H:%M'))     AS german_open,
    any(formatDateTime(toTimeZone(us_close_et, 'Europe/Berlin'), '%H:%M'))    AS german_close,
    any(toHour(toTimeZone(us_open_et, 'Europe/Berlin')) - toHour(us_open_et)) AS berlin_minus_et_hours
FROM
(
    SELECT
        toMonday(date)                                                      AS week,
        toDateTime(concat(toString(date), ' 09:30:00'), 'America/New_York') AS us_open_et,
        toDateTime(concat(toString(date), ' 16:00:00'), 'America/New_York') AS us_close_et
    FROM global_markets.stocks_daily_aggs
    WHERE ticker = 'SPY'
      AND date >= today() - 400
)
GROUP BY week
ORDER BY week
Run this yourself

The line sits flat at six hours across 58 weeks of real trading sessions and drops to five inside the two mismatch windows. Counting the affected sessions rather than the weeks makes the size of it concrete.

QueryUS sessions each year that land an hour earlier in Germany
yearmismatch_sessionsmismatch_open_germanmismatch_close_germanaligned_open_germanaligned_close_german
20211514:March21:March15:January22:January
20221514:March21:March15:January22:January
20231514:March21:March15:January22:January
20241914:March21:March15:January22:January
20252014:March21:March15:January22:January
The exact SQL behind every number
SELECT
    toString(toYear(session_date))     AS year,
    countIf(gap_hours = 5)             AS mismatch_sessions,
    anyIf(german_open, gap_hours = 5)  AS mismatch_open_german,
    anyIf(german_close, gap_hours = 5) AS mismatch_close_german,
    anyIf(german_open, gap_hours = 6)  AS aligned_open_german,
    anyIf(german_close, gap_hours = 6) AS aligned_close_german
FROM
(
    SELECT
        date AS session_date,
        formatDateTime(toTimeZone(toDateTime(concat(toString(date), ' 09:30:00'), 'America/New_York'), 'Europe/Berlin'), '%H:%M') AS german_open,
        formatDateTime(toTimeZone(toDateTime(concat(toString(date), ' 16:00:00'), 'America/New_York'), 'Europe/Berlin'), '%H:%M') AS german_close,
        toHour(toTimeZone(toDateTime(concat(toString(date), ' 09:30:00'), 'America/New_York'), 'Europe/Berlin')) - 9            AS gap_hours
    FROM global_markets.stocks_daily_aggs
    WHERE ticker = 'SPY'
      AND date >= toStartOfYear(today() - INTERVAL 5 YEAR)
      AND date <  toStartOfYear(today())
)
GROUP BY year
ORDER BY year
Run this yourself

Across the last 5 complete calendar years the mismatch covered 15 US trading sessions in 2021 and 20 in 2025. A standing alarm set for 15:January German time misses the first half hour of trading on every one of those days. The switch rules themselves, on both sides of the Atlantic, are laid out in US market hours and daylight saving time, and the same conversion done for other regions in US stock market hours around the world.

US holidays, German holidays, and the 13:00 half days

The two calendars disagree far more often than the clocks do. The exchange calendar below lists what is still ahead, with the half-day close converted to German time.

QueryUpcoming US market closures and half days, in German time
closure_dateclosure_labelweekdayholidayday_statuset_closegerman_closedays_away
2026-11-2626 NovemberThuThanksgivingclosed61
2026-11-2727 NovemberFriThanksgivingearly-close13:November19:November62
2026-12-2424 DecemberThuChristmasearly-close13:December19:December89
2026-12-2525 DecemberFriChristmasclosed90
2027-01-011 JanuaryFriNew Years Dayclosed97
2027-01-1818 JanuaryMonMartin Luther King, Jr. Dayclosed114
2027-02-1515 FebruaryMonWashington's Birthdayclosed142
2027-03-2626 MarchFriGood Fridayclosed181
2027-05-3131 MayMonMemorial Dayclosed247
2027-06-1818 JuneFriJuneteenthclosed265
2027-07-055 JulyMonIndependence Dayclosed282
2027-09-066 SeptemberMonLabor Dayclosed345
The exact SQL behind every number
SELECT
    toString(date)                                             AS closure_date,
    concat(toString(toDayOfMonth(date)), ' ', monthName(date)) AS closure_label,
    formatDateTime(date, '%a')                                 AS weekday,
    any(name)                                                  AS holiday,
    any(status)                                                AS day_status,
    any(if(status = 'early-close',
           formatDateTime(toTimeZone(close, 'America/New_York'), '%H:%M'),
           ''))                                                AS et_close,
    any(if(status = 'early-close',
           formatDateTime(toTimeZone(close, 'Europe/Berlin'), '%H:%M'),
           ''))                                                AS german_close,
    dateDiff('day', today(), date)                             AS days_away
FROM global_markets.stocks_market_holidays
WHERE date >= today()
GROUP BY date
ORDER BY date
Run this yourself

The forward calendar carries 12 dated closures. The next one is Thanksgiving on 26 November, 61 days out from today. Most of the rows are days New York sits dark while Xetra holds a perfectly normal session: Thanksgiving, Independence Day, Memorial Day, Labor Day and the two February and January Monday holidays all belong to the US calendar alone. The traffic runs the other way too. German public holidays such as Tag der Deutschen Einheit on 3 October, Labour Day on 1 May and Whit Monday close Xetra while US markets trade the full session, which means a German investor can have a working US market and no local order book on the same afternoon. Only a few dates close both, among them New Year's Day, Good Friday and Christmas Day.

The day_status column marks the third case. On a half day the US regular session ends at 13:00 ET instead of 16:00 ET, which is 19:January in Germany rather than 22:January. Those fall around Thanksgiving and Christmas Eve, and the closing auction still prints, three hours earlier than usual on a German clock. The recurring pattern behind them is covered in US stock market holidays and early closes.

Why the first and last half hour trade differently

The practical question behind all of this is when in a German evening the US market is actually liquid. The panel splits the recent SPY tape into 30-minute buckets by New York clock time and labels each one with the German equivalent at the offset in force at build time (six hours, as of late September 2026). SPY is the S&P 500 exchange-traded fund and the most heavily traded US listing, which makes its profile a clean read on the shape of the day.

QuerySPY volume and one-minute range by 30-minute bucket
et_timegerman_timeavg_volume_millionsavg_range_pct
09:0015:000.230.019
09:3015:304.060.055
10:0016:002.940.044
10:3016:302.510.039
11:0017:002.660.035
11:3017:302.030.032
12:0018:001.840.028
12:3018:301.610.026
13:0019:001.650.025
13:3019:301.460.022
14:0020:001.880.025
14:3020:302.280.025
15:0021:002.640.026
15:3021:307.70.032
16:0022:005.060.021
16:3022:300.290.01
The exact SQL behind every number
WITH
    (
        SELECT toHour(toTimeZone(toDateTime(concat(toString(max(date)), ' 12:00:00'), 'America/New_York'), 'Europe/Berlin')) - 12
        FROM global_markets.stocks_daily_aggs
        WHERE ticker = 'SPY'
    ) AS german_offset_hours
SELECT
    formatDateTime(toDateTime(bucket_min * 60, 'UTC'), '%H:%i')                                            AS et_time,
    formatDateTime(toDateTime(((bucket_min + german_offset_hours * 60) % 1440) * 60, 'UTC'), '%H:%i')       AS german_time,
    round(sum(volume) / countDistinct(session_date) / 1e6, 2)                                              AS avg_volume_millions,
    round(avg(bar_range_pct), 3)                                                                           AS avg_range_pct
FROM
(
    SELECT
        toDate(et)                                     AS session_date,
        intDiv(toHour(et) * 60 + toMinute(et), 30) * 30 AS bucket_min,
        volume,
        toFloat64(high - low) / toFloat64(close) * 100  AS bar_range_pct
    FROM
    (
        SELECT
            toTimeZone(window_start, 'America/New_York') AS et,
            volume,
            high,
            low,
            close
        FROM global_markets.delayed_stocks_minute_aggs
        WHERE ticker = 'SPY'
          AND window_start >= today() - 60
          AND window_start <  today() - 1
    )
    WHERE (toHour(et) * 60 + toMinute(et)) >= 540
      AND (toHour(et) * 60 + toMinute(et)) <  1020
)
GROUP BY bucket_min
ORDER BY bucket_min
Run this yourself

Read the panel bucket by bucket rather than as one headline. The opening half hour, 15:30 German time, averaged 4.06 million shares per session across this sample of the tape. The 12:00 ET bucket averaged 1.84 million, and the half hour before the close averaged 7.7 million. The 16:00 bucket carries the closing auction print, a single large trade struck at the official closing price, which makes it a different kind of bar from the continuous ones around it. One bucket later, at 22:30 in Germany, the regular session has ended and the figure is 0.29 million.

The panel measures one more thing: how far price travels inside a single minute. The average high-to-low range of a one-minute bar came out at 0.055% in the opening half hour and 0.028% in the 12:00 ET bucket. For a German reader the point of the clock is structural. The opening half hour works through orders that piled up overnight and the imbalance left by the opening auction. The final half hour runs into the closing auction that sets the official price, just before 22:January in Germany. Once 22:30 has passed, the regular session is finished and quoting moves to the thin after-hours book, where a market order can fill a long way from the last price it showed.

FAQ

What time does the US stock market open in German time?

The New York open, 09:30 ET, lands at 15:January on a German clock for most of the year, with the close at 22:January. During the two stretches when the EU and US summer-time dates do not line up, the open moves to 14:March and the close to 21:March.

Do US market hours change when Germany switches to summer time?

On a German clock they stay put, since both regions shift. The label moves from CET to CEST and the UTC offset from plus 1 to plus 2, while the US open stays at 15:July German time. Only the mismatch weeks in March and late October break that.

Is Xetra open when the NYSE opens?

Yes, for about two hours. Xetra's continuous trading runs to 17:30 German time and the US regular session starts at 15:January, so the two books overlap from the US open until the German close.

What time do US half days end in German time?

On an early-close day the US regular session ends at 13:00 ET, which is 19:January in Germany. The calendar panel above flags each one in its day_status column.

Can I trade US stocks late in the German evening?

US after-hours trading runs to 20:00 ET, or 02:January the following morning in Germany, and access depends on what your broker supports. Volume in that window is a small fraction of the regular session.


Every panel on this page ships with the exact SQL beneath it. To convert a specific session, half day or holiday into your own local time, ask the question in plain English on the Strasmore terminal.