55 "path/filepath"
66 "strings"
77 "testing"
8+ "time"
89
910 "github.com/stretchr/testify/assert"
1011 "github.com/stretchr/testify/require"
@@ -163,6 +164,32 @@ func TestParseGeminiAppsEquivalentNumericZonesKeepStableIdentity(t *testing.T) {
163164 assert .Equal (t , ids ["prompt" ], padded ["prompt" ])
164165}
165166
167+ func TestRESPEC2HeadGMT8Reproduction (t * testing.T ) {
168+ path := filepath .Join (t .TempDir (), "activity.html" )
169+ fixture := geminiAppsSingleCellHTML (
170+ "" , "My Activity History" , "Prompted" ,
171+ "Jan 2, 2025, 3:04:05 PM GMT+8" , "<p>prompt</p>" ,
172+ )
173+ require .NoError (t , os .WriteFile (path , []byte (fixture ), 0o644 ))
174+
175+ provider , ok := NewProvider (AgentGeminiApps , ProviderConfig {})
176+ require .True (t , ok )
177+ exporter := provider .(GeminiAppsExportParser )
178+ var result ParseResult
179+ _ , err := exporter .ParseGeminiAppsExport (path , func (got ParseResult ) error {
180+ result = got
181+ return nil
182+ })
183+ require .NoError (t , err )
184+ require .Len (t , result .Messages , 1 )
185+
186+ sessionTimestamp := result .Session .StartedAt .UTC ().Format (time .RFC3339 )
187+ messageTimestamp := result .Messages [0 ].Timestamp .UTC ().Format (time .RFC3339 )
188+ t .Logf ("session=%s message=%s messages=%d id=%s" , sessionTimestamp , messageTimestamp , len (result .Messages ), result .Session .ID )
189+ assert .Equal (t , "2025-01-02T07:04:05Z" , sessionTimestamp )
190+ assert .Equal (t , sessionTimestamp , messageTimestamp )
191+ }
192+
166193func TestParseGeminiAppsRejectsNotPromptedActivityLabel (t * testing.T ) {
167194 fixture := strings .ReplaceAll (
168195 sanitizedGeminiAppsHTML ,
@@ -1165,10 +1192,22 @@ func TestParseGeminiAppsTimestampUsesExplicitZones(t *testing.T) {
11651192 }{
11661193 {"edt" , "Jan 2, 2025, 3:04:05 PM EDT" , "2025-01-02T19:04:05Z" },
11671194 {"pst" , "Jan 2, 2025, 3:04:05 PM PST" , "2025-01-02T23:04:05Z" },
1195+ {"utc" , "Jan 2, 2025, 3:04:05 PM UTC" , "2025-01-02T15:04:05Z" },
1196+ {"gmt" , "Jan 2, 2025, 3:04:05 PM GMT" , "2025-01-02T15:04:05Z" },
1197+ {"est" , "Jan 2, 2025, 3:04:05 PM EST" , "2025-01-02T20:04:05Z" },
1198+ {"cst" , "Jan 2, 2025, 3:04:05 PM CST" , "2025-01-02T21:04:05Z" },
1199+ {"cdt" , "Jan 2, 2025, 3:04:05 PM CDT" , "2025-01-02T20:04:05Z" },
1200+ {"mst" , "Jan 2, 2025, 3:04:05 PM MST" , "2025-01-02T22:04:05Z" },
1201+ {"mdt" , "Jan 2, 2025, 3:04:05 PM MDT" , "2025-01-02T21:04:05Z" },
1202+ {"pdt" , "Jan 2, 2025, 3:04:05 PM PDT" , "2025-01-02T22:04:05Z" },
11681203 {"whole-hour" , "Jan 2, 2025, 3:04:05 PM GMT+8" , "2025-01-02T07:04:05Z" },
11691204 {"whole-hour-padded" , "Jan 2, 2025, 3:04:05 PM GMT+08:00" , "2025-01-02T07:04:05Z" },
1205+ {"whole-hour-two-digit" , "Jan 2, 2025, 3:04:05 PM GMT+08" , "2025-01-02T07:04:05Z" },
1206+ {"whole-hour-lowercase" , "Jan 2, 2025, 3:04:05 PM gmt+8" , "2025-01-02T07:04:05Z" },
1207+ {"whole-hour-mixed-case" , "Jan 2, 2025, 3:04:05 PM GmT+8" , "2025-01-02T07:04:05Z" },
11701208 {"whole-hour-negative" , "Jan 2, 2025, 3:04:05 PM GMT-8" , "2025-01-02T23:04:05Z" },
11711209 {"numeric" , "Jan 2, 2025, 3:04:05 PM GMT+05:30" , "2025-01-02T09:34:05Z" },
1210+ {"numeric-max" , "Jan 2, 2025, 3:04:05 PM GMT+23:59" , "2025-01-01T15:05:05Z" },
11721211 {"negative-zero" , "Jan 2, 2025, 3:04:05 PM GMT-00:30" , "2025-01-02T15:34:05Z" },
11731212 }
11741213 for _ , tt := range tests {
@@ -1182,7 +1221,7 @@ func TestParseGeminiAppsTimestampUsesExplicitZones(t *testing.T) {
11821221 }
11831222
11841223 for _ , zone := range []string {
1185- "GMT+8:3" , "GMT+8junk" , "GMT+8:30junk" , "GMT+24" , "GMT+8:60" , "XYZ" ,
1224+ "GMT+8:3" , "GMT+8junk" , "GMT+8:30junk" , "GMT+24" , "GMT+8:60" , "GMT+8," , " XYZ" ,
11861225 } {
11871226 t .Run ("reject-" + zone , func (t * testing.T ) {
11881227 match := geminiAppsTimestampRE .FindStringSubmatch (
@@ -1191,6 +1230,7 @@ func TestParseGeminiAppsTimestampUsesExplicitZones(t *testing.T) {
11911230 require .Len (t , match , 2 )
11921231 _ , err := parseGeminiAppsTimestamp (match [0 ], match [1 ])
11931232 assert .ErrorContains (t , err , "unsupported" )
1233+ assert .ErrorContains (t , err , strings .ToUpper (zone ))
11941234 })
11951235 }
11961236}
0 commit comments