Tengo esta consulta en PHP Laravel:
$sensor_data = DB::table('devices_sensor_data as D') ->select(DB::raw(' D.id, COALESCE(D.DeviceId,dx.DeviceId) AS DeviceId, D.ENERGY_Total, D.Time') ) ->join(DB::raw(' (SELECT MIN(CONVERT_TZ(Time, "'.$dbTz.'", "'.$usrTz.'")) min_time, MAX(CONVERT_TZ(Time, "'.$dbTz.'", "'.$usrTz.'")) max_time, DeviceId FROM devices_sensor_data WHERE DATE(Time) BETWEEN "'.$fromTzTime.'" AND "'.$toTzTime.'" AND DeviceId IN (\''.$arrayDeviceID.'\') GROUP BY DATE(Time), DeviceId ORDER BY DATE(Time) ) AS dx' ), function($join) { $join->on(DB::raw('D.Time = `dx`.`min_time` OR D.Time'), '=', 'dx.max_time'); $join->where('D.DeviceId', '=', DB::raw('dx.DeviceId')); }) ->whereIn('D.DeviceId', array_keys($devicesArr)) ->whereDate('D.Time', '>=', $fromTzTime) ->whereDate('D.Time', '<=', $toTzTime); $sensor_data = $sensor_data ->orderBy('D.DeviceId') ->orderBy('D.Time') ->get(); Quiero seleccionar MIN y MAX en función de una zona horaria basada en un usuario diferente a la predeterminada, en este momento es Asia / Kolkata , por lo que quiero seleccionarlo en función de, por ejemplo. América/Nueva_York .
Me devuelve el MIN y MAX según la zona horaria IST y simplemente lo convierte en el tiempo de Nueva York, pero quiero buscar el MIN y MAX según la zona horaria de Nueva York.
Si desea utilizar zonas horarias con nombre dentro de la función CONVERT_TZ , debe crear, completar y mantener las tablas del sistema de zonas horarias . Una vez que las tablas están configuradas, puede usar la función así:
SELECT CONVERT_TZ('2021-10-01 17:30:00', 'Asia/Kolkata', 'Europe/London'); -- 2021-10-01 13:00:00 -- British territories use BST in summer, where it is 4:30 hours behind IST SELECT CONVERT_TZ('2021-11-01 17:30:00', 'Asia/Kolkata', 'Europe/London'); -- 2021-11-01 12:00:00 -- Outside of summer, these territories use GMT which is 5:30 hours behind ISTSi las tablas de zonas horarias están vacías, esta función devolverá un valor nulo. Se admiten muy pocas abreviaturas de zonas horarias (por ejemplo, UTC y GMT), por lo que debe utilizar nombres de ciudades.
Para su ejemplo particular, simplemente calcule el MIN/MAX y luego convierta:
SELECT CONVERT_TZ(MIN(...), 'Asia/Kolkata', 'Europe/London') Dado que la pregunta también está etiquetada con php , me gustaría agregar que es posible realizar la conversión en PHP usando la clase DateTime . El soporte de zona horaria está integrado en PHP. Entonces, si tiene una cadena de fecha en un formato conocido y sabe en qué zona horaria se encuentra, puede convertir así:
$date = DateTime::createFromFormat('Ymd H:i:s', '2021-10-01 17:30:00', new DateTimeZone('Asia/Kolkata')); $date->setTimezone(new DateTimeZone('Europe/London')); echo $date->format('Ymd H:i:s'); // 2021-10-01 13:00:00 $date = DateTime::createFromFormat('Ymd H:i:s', '2021-11-01 17:30:00', new DateTimeZone('Asia/Kolkata')); $date->setTimezone(new DateTimeZone('Europe/London')); echo $date->format('Ymd H:i:s'); // 2021-11-01 12:00:00De hecho, necesita usar CONVERT_TZ. Permítanme crear una base de datos de muestra junto con los datos:
create table MyTimes( id int auto_increment primary key, moment timestamp ); insert into MyTimes(moment) values ('2021-01-02 00:00:00'), ('2021-01-01 00:00:00'), ('2021-01-04 00:00:00'), ('2021-01-03 00:00:00'); y ahora select el mínimo y el máximo usando la transición de zona horaria:
select min(convert_tz(moment, '+05:30', '+01:00')) minimum, max(convert_tz(moment, '+05:30', '+01:00')) maximum from MyTimes;Violín: http://sqlfiddle.com/#!9/cfca54f/4
Ahora, veamos qué está pasando en este ejemplo:
momentconvert_tzmoment de paso como primer parámetroSolución de largo alcance...
Elija con cuidado entre DATETIME y TIMESTAMP . Ambos pueden contener fecha y hora.
Piense en DATETIME como la imagen de un reloj. Cuando alguien en una zona horaria diferente lee una columna de este tipo, ve lo que usted vio. No se realiza ningún ajuste para la zona horaria.
Tenga en cuenta que DATETIME tiene contratiempos dos veces al año si su zona horaria utiliza el horario de verano.
Piense en TIMESTAMP como si se convirtiera a UTC a medida que se almacena y luego se vuelve a convertir a la zona horaria del cliente cuando se lee. O piense en ello como un punto en el tiempo en el universo. Esto funciona mejor para anunciar, por ejemplo, la hora de una reunión de Zoom.
Para que funcione según lo previsto (con TIMESTAMP ), cada máquina cliente debe estar configurada en la zona horaria "local".
(Hay algunos otros casos de tiempos que necesitan ajustes; MySQL solo tiene los dos anteriores).