Skip to content

Commit b126bf6

Browse files
committed
fix timestamp parsing
1 parent 6a548a3 commit b126bf6

File tree

2 files changed

+138
-31
lines changed

2 files changed

+138
-31
lines changed

packages/common-ui/src/components/HeatMap.vue

Lines changed: 94 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,27 @@ export default defineComponent({
111111
try {
112112
this.isLoading = true;
113113
console.log('Fetching activity records using getter...');
114+
114115
// Ensure the getter is called safely with proper error handling
115-
const result = await this.activityRecordsGetter();
116+
let result = await this.activityRecordsGetter();
116117
118+
// Handle the result - ensure it's an array of activity records
117119
if (Array.isArray(result)) {
118-
this.localActivityRecords = result;
119-
console.log('Received activity records:', this.localActivityRecords.length);
120+
// Filter out records with invalid timestamps before processing
121+
this.localActivityRecords = result.filter(record => {
122+
if (!record || !record.timeStamp) return false;
123+
124+
// Basic validation check for timestamps
125+
try {
126+
const m = moment(record.timeStamp);
127+
return m.isValid() && m.year() > 2000 && m.year() < 2100;
128+
} catch (e) {
129+
return false;
130+
}
131+
});
132+
133+
console.log(`Received ${result.length} records, ${this.localActivityRecords.length} valid after filtering`);
134+
120135
// Process the loaded records
121136
this.processRecords();
122137
this.createWeeksData();
@@ -153,34 +168,70 @@ export default defineComponent({
153168
return;
154169
}
155170
156-
records.forEach((record) => {
157-
if (!record || typeof record !== 'object') {
158-
console.warn('Invalid record:', record);
159-
return;
160-
}
171+
// Sample logging of a few records to understand structure without flooding console
172+
const uniqueDates = new Set<string>();
173+
const dateDistribution: Record<string, number> = {};
174+
let validCount = 0;
175+
let invalidCount = 0;
176+
177+
for (let i = 0; i < records.length; i++) {
178+
const record = records[i];
161179
162-
if (!record.timeStamp) {
163-
console.warn('Record missing timeStamp:', record);
164-
return;
180+
if (!record || typeof record !== 'object' || !record.timeStamp) {
181+
invalidCount++;
182+
continue;
165183
}
166184
167-
// Make sure timeStamp is properly handled
168-
let date;
169185
try {
170-
// Try to parse the timestamp
171-
const m = moment(record.timeStamp);
172-
if (m.isValid()) {
173-
date = m.format('YYYY-MM-DD');
174-
data[date] = (data[date] || 0) + 1;
186+
// Attempt to normalize the timestamp
187+
let normalizedDate: string;
188+
189+
if (typeof record.timeStamp === 'string') {
190+
// For ISO strings, parse directly with moment
191+
normalizedDate = moment(record.timeStamp).format('YYYY-MM-DD');
192+
} else if (typeof record.timeStamp === 'number') {
193+
// For numeric timestamps, use Date constructor then moment
194+
normalizedDate = moment(new Date(record.timeStamp)).format('YYYY-MM-DD');
195+
} else if (typeof record.timeStamp === 'object') {
196+
// For objects (like Moment), try toString() or direct parsing
197+
if (typeof record.timeStamp.format === 'function') {
198+
// It's likely a Moment object
199+
normalizedDate = record.timeStamp.format('YYYY-MM-DD');
200+
} else if (record.timeStamp instanceof Date) {
201+
normalizedDate = moment(record.timeStamp).format('YYYY-MM-DD');
202+
} else {
203+
// Try to parse it as a string representation
204+
normalizedDate = moment(String(record.timeStamp)).format('YYYY-MM-DD');
205+
}
206+
} else {
207+
// Unhandled type
208+
invalidCount++;
209+
continue;
210+
}
211+
212+
// Verify the date is valid before using it
213+
if (moment(normalizedDate, 'YYYY-MM-DD', true).isValid()) {
214+
data[normalizedDate] = (data[normalizedDate] || 0) + 1;
215+
uniqueDates.add(normalizedDate);
216+
217+
// Track distribution by month for debugging
218+
const month = normalizedDate.substring(0, 7); // YYYY-MM
219+
dateDistribution[month] = (dateDistribution[month] || 0) + 1;
220+
221+
validCount++;
175222
} else {
176-
console.warn('Invalid date from record:', record);
223+
invalidCount++;
177224
}
178225
} catch (e) {
179-
console.error('Error processing record date:', e, record);
226+
invalidCount++;
180227
}
181-
});
228+
}
229+
230+
// Log summary statistics
231+
console.log(`Processed ${validCount} valid dates, ${invalidCount} invalid dates`);
232+
console.log(`Found ${uniqueDates.size} unique dates`);
233+
console.log('Date distribution by month:', dateDistribution);
182234
183-
console.log('Processed heatmap data:', Object.keys(data).length, 'unique dates');
184235
this.heatmapData = data;
185236
},
186237
@@ -194,7 +245,17 @@ export default defineComponent({
194245
const day = start.clone().startOf('week');
195246
196247
console.log('Creating weeks data from', start.format('YYYY-MM-DD'), 'to', end.format('YYYY-MM-DD'));
248+
249+
// Ensure we have data to display
250+
if (Object.keys(this.heatmapData).length === 0) {
251+
console.log('No heatmap data available to display');
252+
}
197253
254+
// For debugging, log some sample dates from the heatmap data
255+
const sampleDates = Object.keys(this.heatmapData).slice(0, 5);
256+
console.log('Sample dates in heatmap data:', sampleDates);
257+
258+
// Build the week data structure
198259
while (day.isSameOrBefore(end)) {
199260
const weekData: DayData[] = [];
200261
for (let i = 0; i < 7; i++) {
@@ -215,8 +276,17 @@ export default defineComponent({
215276
}
216277
217278
console.log('Weeks data created, maxInRange:', this.maxInRange);
218-
console.log('First week sample:', this.weeks[0]);
219-
console.log('Last week sample:', this.weeks[this.weeks.length - 1]);
279+
280+
// Calculate summary stats for display
281+
let totalDaysWithActivity = 0;
282+
let totalActivity = 0;
283+
284+
Object.values(this.heatmapData).forEach(count => {
285+
totalDaysWithActivity++;
286+
totalActivity += count;
287+
});
288+
289+
console.log(`Activity summary: ${totalActivity} activities across ${totalDaysWithActivity} days`);
220290
},
221291
222292
getColor(count: number): string {

packages/db/src/impl/pouch/userDB.ts

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -254,16 +254,53 @@ Currently logged-in as ${this._username}.`
254254
return allRecords;
255255
}
256256

257+
// Sample the first few records to understand structure
258+
let sampleCount = 0;
259+
257260
for (let i = 0; i < hist.length; i++) {
258261
try {
259262
if (hist[i] && Array.isArray(hist[i]!.records)) {
260263
hist[i]!.records.forEach((record: CardRecord) => {
261264
try {
262-
// Convert Moment objects to ISO string format for consistency
263-
const timeStamp = record.timeStamp && typeof record.timeStamp.isValid === 'function' && record.timeStamp.isValid()
264-
? record.timeStamp.toISOString()
265-
: new Date().toISOString();
266-
265+
// Skip this record if timeStamp is missing
266+
if (!record.timeStamp) {
267+
return;
268+
}
269+
270+
let timeStamp;
271+
272+
// Handle different timestamp formats
273+
if (typeof record.timeStamp === 'object') {
274+
// It's likely a Moment object
275+
if (typeof record.timeStamp.toDate === 'function') {
276+
// It's definitely a Moment object
277+
timeStamp = record.timeStamp.toISOString();
278+
} else if (record.timeStamp instanceof Date) {
279+
// It's a Date object
280+
timeStamp = record.timeStamp.toISOString();
281+
} else {
282+
// Log a sample of unknown object types, but don't flood console
283+
if (sampleCount < 3) {
284+
console.warn('Unknown timestamp object type:', record.timeStamp);
285+
sampleCount++;
286+
}
287+
return;
288+
}
289+
} else if (typeof record.timeStamp === 'string') {
290+
// It's already a string, but make sure it's a valid date
291+
const date = new Date(record.timeStamp);
292+
if (isNaN(date.getTime())) {
293+
return; // Invalid date string
294+
}
295+
timeStamp = record.timeStamp;
296+
} else if (typeof record.timeStamp === 'number') {
297+
// Assume it's a Unix timestamp (milliseconds since epoch)
298+
timeStamp = new Date(record.timeStamp).toISOString();
299+
} else {
300+
// Unknown type, skip
301+
return;
302+
}
303+
267304
allRecords.push({
268305
timeStamp,
269306
courseID: record.courseID || 'unknown',
@@ -272,12 +309,12 @@ Currently logged-in as ${this._username}.`
272309
type: 'card_view'
273310
});
274311
} catch (err) {
275-
console.error('Error processing record:', err, record);
312+
// Silently skip problematic records to avoid flooding logs
276313
}
277314
});
278315
}
279316
} catch (err) {
280-
console.error('Error processing history item:', err, hist[i]);
317+
console.error('Error processing history item:', err);
281318
}
282319
}
283320

0 commit comments

Comments
 (0)