|
@@ -134,51 +134,60 @@ class DeviceReportView(View):
|
|
|
device_id = request_dict.get('device_id')
|
|
|
if not device_id:
|
|
|
return response.json(444, "设备ID不能为空")
|
|
|
- tz_offset = float(request_dict.get('tz', 0)) # 允许小数时区如5.5
|
|
|
+
|
|
|
+ tz_offset = float(request_dict.get('tz', 0))
|
|
|
if not (-12 <= tz_offset <= 14):
|
|
|
- raise ValueError
|
|
|
- tz = pytz.FixedOffset(int(tz_offset * 60)) # 转换为分钟偏移
|
|
|
+ raise ValueError("时区偏移超出范围")
|
|
|
+ tz = pytz.FixedOffset(int(tz_offset * 60))
|
|
|
|
|
|
- # 计算日期范围(关键修改:end_time取昨日23:59:59)
|
|
|
+ # 计算日期范围:查询的是客户端时区下的历史数据
|
|
|
query_days = int(request_dict.get('days', 7))
|
|
|
client_now = datetime.now(tz)
|
|
|
- end_time = client_now.replace(
|
|
|
- hour=23, minute=59, second=59
|
|
|
- ) - timedelta(days=1) # 截止到客户端昨日
|
|
|
|
|
|
- start_time = end_time - timedelta(days=query_days - 1)
|
|
|
- start_time = start_time.replace(hour=0, minute=0, second=0)
|
|
|
+ # 关键修改:数据日期范围 = [今天 - query_days, 昨天]
|
|
|
+ # 因为设备上报的是前一天的数据
|
|
|
+ end_date = (client_now - timedelta(days=1)).date() # 昨天
|
|
|
+ start_date = end_date - timedelta(days=query_days - 1) # 起始日期
|
|
|
+
|
|
|
+ # 转换查询范围到UTC时间戳 (包含整个日期范围)
|
|
|
+ start_utc = int(tz.localize(
|
|
|
+ datetime.combine(start_date, datetime.min.time())
|
|
|
+ ).astimezone(pytz.utc).timestamp())
|
|
|
|
|
|
- # 转换时间范围到UTC时间戳
|
|
|
- start_utc_timestamp = int(start_time.astimezone(pytz.utc).timestamp())
|
|
|
- end_utc_timestamp = int(end_time.astimezone(pytz.utc).timestamp())
|
|
|
+ end_utc = int(tz.localize(
|
|
|
+ datetime.combine(end_date + timedelta(days=1), datetime.min.time())
|
|
|
+ ).astimezone(pytz.utc).timestamp())
|
|
|
|
|
|
# 查询数据库
|
|
|
records = DeviceDailyReport.objects.filter(
|
|
|
device_id=device_id,
|
|
|
type=1,
|
|
|
- report_time__gte=start_utc_timestamp,
|
|
|
- report_time__lte=end_utc_timestamp
|
|
|
+ report_time__gte=start_utc,
|
|
|
+ report_time__lt=end_utc # 不包含结束时间戳
|
|
|
).order_by('report_time')
|
|
|
|
|
|
- # 构建日期-电量映射(按客户端时区)
|
|
|
+ # 构建日期-电量映射 (按数据实际归属的日期)
|
|
|
date_battery_map = {}
|
|
|
for record in records:
|
|
|
- local_date = datetime.fromtimestamp(record.report_time, tz).date()
|
|
|
- date_str = local_date.strftime("%Y-%m-%d")
|
|
|
- date_battery_map[date_str] = record.battery_level
|
|
|
+ # 关键修改:上报时间转客户端时区后减去1天 = 数据实际归属日期
|
|
|
+ record_date = datetime.fromtimestamp(record.report_time, tz).date()
|
|
|
+ data_date = record_date - timedelta(days=1) # 数据属于前一天
|
|
|
+
|
|
|
+ # 只记录查询范围内的数据
|
|
|
+ if start_date <= data_date <= end_date:
|
|
|
+ date_battery_map[data_date.isoformat()] = record.battery_level
|
|
|
|
|
|
- # 生成完整日期序列
|
|
|
+ # 生成完整日期序列 (按客户端时区)
|
|
|
report_data = []
|
|
|
for day_offset in range(query_days):
|
|
|
- current_date = (end_time.date() - timedelta(days=query_days - 1 - day_offset))
|
|
|
+ current_date = start_date + timedelta(days=day_offset)
|
|
|
report_data.append({
|
|
|
"index": current_date.day - 1, # 日期下标从0开始
|
|
|
- "battery": date_battery_map.get(current_date.strftime("%Y-%m-%d"), 0),
|
|
|
+ "battery": date_battery_map.get(current_date.isoformat(), 0),
|
|
|
"time": current_date.strftime("%Y-%m-%d")
|
|
|
})
|
|
|
|
|
|
return response.json(0, report_data)
|
|
|
except Exception as e:
|
|
|
- LOGGER.error('查询设备电量上报列表异常error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
|
|
|
+ LOGGER.error(f'查询设备电量上报列表异常: {e}')
|
|
|
return response.json(0, {})
|