@@ -133,6 +133,9 @@ private struct TimeZoneTests {
133133 try testAbbreviation ( " GMT+8:00 " , 28800 , " GMT+0800 " )
134134 try testAbbreviation ( " GMT+0800 " , 28800 , " GMT+0800 " )
135135 try testAbbreviation ( " UTC " , 0 , " GMT " )
136+ try testAbbreviation ( " UTC+9 " , 32400 , " GMT+0900 " )
137+ try testAbbreviation ( " UTC+9:00 " , 32400 , " GMT+0900 " )
138+ try testAbbreviation ( " UTC+0900 " , 32400 , " GMT+0900 " )
136139 }
137140
138141 @Test func secondsFromGMT_RemoteDates( ) {
@@ -296,6 +299,40 @@ private struct TimeZoneICUTests {
296299 try test ( . init( year: 2023 , month: 11 , day: 5 , hour: 3 , minute: 34 , second: 52 ) , expectedRawOffset: - 28800 , expectedDSTOffset: 0 )
297300 }
298301
302+ @Test func names_rawAndDaylightSavingTimeOffset( ) throws {
303+ var gmt_calendar = Calendar ( identifier: . gregorian)
304+ gmt_calendar. timeZone = . gmt
305+
306+ func test( _ identifier: String , _ dateComponent: DateComponents , expectedRawOffset: Int , expectedDSTOffset: TimeInterval , sourceLocation: SourceLocation = #_sourceLocation) throws {
307+ let tz = try #require( _TimeZoneICU ( identifier: identifier) )
308+ let d = try #require( gmt_calendar. date ( from: dateComponent) ) // date in GMT
309+ let ( rawOffset, dstOffset) = tz. rawAndDaylightSavingTimeOffset ( for: d)
310+ #expect( rawOffset == expectedRawOffset, sourceLocation: sourceLocation)
311+ #expect( dstOffset == expectedDSTOffset, sourceLocation: sourceLocation)
312+ }
313+
314+ // PST
315+ // Not in DST
316+ try test ( " PST " , . init( year: 2023 , month: 3 , day: 12 , hour: 1 , minute: 00 , second: 00 ) , expectedRawOffset: - 28800 , expectedDSTOffset: 0 )
317+ // These times do not exist; we treat it as if in the previous time zone, i.e. not in DST
318+ try test ( " PST " , . init( year: 2023 , month: 3 , day: 12 , hour: 2 , minute: 00 , second: 00 ) , expectedRawOffset: - 28800 , expectedDSTOffset: 0 )
319+ // After DST starts
320+ try test ( " PST " , . init( year: 2023 , month: 3 , day: 12 , hour: 3 , minute: 00 , second: 00 ) , expectedRawOffset: - 28800 , expectedDSTOffset: 3600 )
321+ // These times happen twice; we treat it as if in the previous time zone, i.e. still in DST
322+ try test ( " PST " , . init( year: 2023 , month: 11 , day: 5 , hour: 1 , minute: 00 , second: 00 ) , expectedRawOffset: - 28800 , expectedDSTOffset: 3600 )
323+ // Clock should turn right back as this moment, so if we insist on being at this point, then we've moved past the transition point -- hence not DST
324+ try test ( " PST " , . init( year: 2023 , month: 11 , day: 5 , hour: 2 , minute: 00 , second: 00 ) , expectedRawOffset: - 28800 , expectedDSTOffset: 0 )
325+ // Not in DST
326+ try test ( " PST " , . init( year: 2023 , month: 11 , day: 5 , hour: 2 , minute: 34 , second: 52 ) , expectedRawOffset: - 28800 , expectedDSTOffset: 0 )
327+
328+ // JST: not in DST
329+ let dc = DateComponents ( year: 2023 , month: 3 , day: 12 , hour: 1 , minute: 00 , second: 00 )
330+ try test ( " JST " , dc, expectedRawOffset: 32400 , expectedDSTOffset: 0 )
331+ try test ( " UTC+9 " , dc, expectedRawOffset: 32400 , expectedDSTOffset: 0 )
332+ try test ( " UTC+0900 " , dc, expectedRawOffset: 32400 , expectedDSTOffset: 0 )
333+ try test ( " UTC+9:00 " , dc, expectedRawOffset: 32400 , expectedDSTOffset: 0 )
334+ try test ( " GMT+9 " , dc, expectedRawOffset: 32400 , expectedDSTOffset: 0 )
335+ }
299336}
300337// MARK: - FoundationPreview disabled tests
301338
0 commit comments