internet from adjust datetime arduino dst

datetime - from - Cálculo del horario de verano a partir de la fecha



using time in arduino (7)

Aquí está mi respuesta, y doy la bienvenida a cualquier corrección. Se supone que los años son entre 2000 y 2099 inclusive. Más detalles disponibles a través del enlace de referencia.

int timezone = 0; // Set to correct initial value depending on where you are (or via GPS if you like). // Calculate day of week for Daylight savings time. int day_of_week = (day_of_month + int(2.6 * (((month + 12 - 3) % 12) + 1) - 0.2) - 40 + (month < 3 ? year-1 : year) + int((month < 3 ? year-1 : year)/4) + 5) % 7; // Adjust timezone based on Daylight savings time for northern hemisphere, USA if ((month > 3 && month < 11 ) || (month == 3 && day_of_month >= 8 && day_of_week == 0 && hour >= 2) || // DST starts 2nd Sunday of March; 2am (month == 11 && day_of_month < 8 && day_of_week > 0) || (month == 11 && day_of_month < 8 && day_of_week == 0 && hour < 2)) { // DST ends 1st Sunday of November; 2am timezone++; }

Referencia del cálculo del día de la semana : cómo determinar el día de la semana, dado el mes, el día y el año
La referencia de la prueba DST es a través de este artículo tal como fue respondido por y mi propio razonamiento e interpretación de su respuesta.

Estoy trabajando con un Arduino y un chip de reloj en tiempo real. El chip compensa los años bisiestos y demás, por lo que siempre tendrá la fecha correcta, pero no controla el horario de verano, supongo que debido a complicaciones regionales. El reloj me puede dar el día, mes y año (1 basado) y el día de la semana (domingo = 0 a sábado = 6).

Como necesito comparar con las fechas y horas ingresadas por el usuario, necesito saber la fecha y la hora ajustadas para el horario de verano. Si la fecha actual es en horario de verano, simplemente puedo agregar una hora a la hora del reloj y tengo lo que necesito.

La parte difícil es determinar si estoy en horario de verano o no, porque cambia de un año a otro. Solo me importa que funcione en mi ubicación (Mountain Time). No parece haber bibliotecas de fechas completas para mi plataforma, y ​​siento que eso sería una exageración de todos modos. ¿Existe una fórmula simple para determinar si estoy en horario de verano o no?


Código para Europa Central (probado para todos los días en el rango 2014-3000 año)

public static bool IsDst(int day, int month, int dow) { if (month < 3 || month > 10) return false; if (month > 3 && month < 10) return true; int previousSunday = day - dow; if (month == 3) return previousSunday >= 25; if (month == 10) return previousSunday < 25; return false; // this line never gonna happend }

Función de prueba

static void Main(string[] args) { TimeZoneInfo tzf2 = TimeZoneInfo.FindSystemTimeZoneById("Central Europe Standard Time"); var date = new DateTime(2014, 01, 1, 5, 0,0); bool wasSummer = false; while (date <= new DateTime(3000,1,1)) { var dow = (int) date.DayOfWeek; var isDst = IsDst(date.Day, date.Month, dow); DateTime f2 = TimeZoneInfo.ConvertTime(date, tzf2); var isSummer = f2.IsDaylightSavingTime(); if (isSummer != isDst) { Console.WriteLine("ERROR"); Console.WriteLine(date); } if (isSummer != wasSummer) { Console.WriteLine(date.AddDays(-1).ToShortDateString()); } date = date.AddDays(1); wasSummer = isSummer; } Console.ReadKey();

}


El 14 de marzo y el 7 de noviembre son siempre parte de la semana en que ocurren los ahorros de luz en los Estados Unidos. Pueden ser el domingo o el sábado o el día de la semana intermedia, pero siempre forman parte de esa semana. el código a continuación encontrará el domingo en que esas dos fechas forman parte del año en que se produce la fecha en cuestión. Luego, agrega 2 horas a esta fecha para obtener la hora en que realmente se producen los ahorros de luz diurna. a continuación, compara la fecha en cuestión con las fechas de inicio y finalización del horario de verano y ajusta la hora mediante el desplazamiento gmt. Este proceso puede funcionar para que los otros países comiencen y terminen las fechas. podría configurar una tabla que contenga todos los códigos de país y postales con las fechas de finalización y de inicio del horario de verano y la diferencia de gmt para ambos períodos. Las fechas serían los días 7, 14, 21 y 28, del primero al cuarto domingo del mes. Usted debe ingresar el día máximo para el último domingo del mes, del 30 de septiembre al 31 de octubre.

2do domingo de marzo:

cdate("3/14/" & format(now(),"yyyy"))-format(cdate("3/14/" & format(now(),"yyyy")),"W")+1+2/24

1er domingo de noviembre:

cdate("11/7/" & format(now(),"yyyy"))-format(cdate("11/7/" & format(now(),"yyyy")),"W")+1+2/24

Ex.

If(now() < cdate("3/14/" & format(now(),"yyyy"))-format(cdate("3/14/" & format(now(),"yyyy")),"W")+1+2/24, dateadd("H",-5,now()), if(now() < cdate("11/7/" & format(now(),"yyyy"))-format(cdate("11/7/" & format(now(),"yyyy")),"W")+1+2/24, dateadd("H",-6,now()), dateadd("H",-5,now())))

ejemplo t_SQL

CASE WHEN [date2check] <DATEADD (hh, 2, CAST (''3/14 /'' + CAST (DATEPART (yyyy, [date2check]) AS nvarchar (4)) AS datetime) + 1 - DATEPART (w, CAST ('' 3/14 / ''+ CAST (DATEPART (yyyy, [date2check]) AS nvarchar (4)) AS datetime))) THEN dateadd (hh, - DST_GMT_TM_ZN_DIFF, [date2check]) ELSE CASE WHEN [date2check] <DATEAD CHD] 2, CAST (''11 / 7 / ''+ CAST (DATEPART (yyyy, [date2check]) AS nvarchar (4)) AS datetime) + 1 - DATEPART (w, CAST (''11 / 7 /'' + CAST (DATEPART ( yyyy, [date2check]) AS nvarchar (4)) AS datetime))) THEN dateadd (hh, - STD_GMT_TM_ZN_DIFF, [date2check]) ELSE dateadd (hh, - DST_GMT_TM_ZN_DIFF, [date2check] END


Esto es en realidad engañosamente simple. Hay algunos datos que nos ayudarán:

  1. En la mayoría de los EE. UU., El horario de verano comienza el segundo domingo de marzo y finaliza el primer domingo de noviembre, a las 2:00 AM en ambas ocasiones.
  2. El segundo domingo de marzo siempre será entre el 8 y el 14 inclusive.
  3. El primer domingo de noviembre siempre será entre el 1 y el 7 inclusive.
  4. La numeración del día de la semana es bastante conveniente porque el día - día de la semana le dará el domingo anterior.

Estos hechos conducen al siguiente código (C #, pero trivialmente portátil a su plataforma):

public bool IsDST(int day, int month, int dow) { //January, february, and december are out. if (month < 3 || month > 11) { return false; } //April to October are in if (month > 3 && month < 11) { return true; } int previousSunday = day - dow; //In march, we are DST if our previous sunday was on or after the 8th. if (month == 3) { return previousSunday >= 8; } //In november we must be before the first sunday to be dst. //That means the previous sunday must be before the 1st. return previousSunday <= 0; }

Resulta que ni siquiera necesita saber el año para hacer esto, siempre y cuando pueda confiar en el valor del día de la semana.

Escribí una prueba unitaria rápida y verifiqué que este código concuerda con TimeZone.IsDayLightSavingsTime() para todas las fechas de 1800 a 2200. No tomé en cuenta la regla de las 2 am, pero podría hacer esa verificación si el día de la semana es el domingo. y la fecha es entre 8 y 14 (en marzo) o 1 y 7 (en noviembre).


Estoy intentando con este enfoque y creo que es simple y preciso:

// para el primer domingo de marzo como si DoW = 1 para domingo if (month == 3 && day> = 8 && day <= 14 && DoW = 1) devuelva True

// para el segundo domingo de noviembre como si DoW = 1 para domingo si (mes == 11 && día> = 1 && día <= 7 && DoW = 1) devuelva True


Si bien es fácil calcular si una fecha en particular está en horario de verano para una ubicación en particular según las reglas actuales, tenga en cuenta que el horario de verano es un capricho de los políticos y podría cambiar en cualquier momento. Tengo un reloj fabricado antes de 2007 que se ajusta automáticamente al horario de verano, y ahora tengo que cambiarlo cuatro veces al año: dos veces cuando se produce el cambio real, y dos veces cuando ahora se modifica incorrectamente en las fechas anteriores.

En este caso, es posible que pueda ignorar el horario de verano completamente por el simple recurso de que el usuario ingrese la zona horaria junto con la fecha y la hora. O podría hacerlo como la mayoría de los dispositivos de consumo y dejar que el usuario ajuste la hora a la zona horaria local dos veces al año.

Pero si realmente necesita manejar el horario de verano y realmente quiere hacer las cosas bien, use la base de datos zoneinfo y asegúrese de que pueda actualizarse de alguna manera. Si no puede hacerlo por alguna razón, al menos permita que el usuario anule las reglas. Y si incluso eso es demasiado difícil, al menos le da al usuario la opción de desactivar los ajustes automáticos (a diferencia de mi estúpido despertador).


este código usa mktime para obtener un día de la semana. Se utiliza un día de la semana para calcular el horario de verano. Si no desea usar mktime, puede usar el programa second_sunday. Comience con 3/14/2007, que es miércoles. El día de la semana avanzará 1 día por cada año y 2 días por cada salto después de 2004.

#include <stdio.h> #include <string.h> #include <time.h> #include <sys/timeb.h> int isDst(int month, int dayOfMonth, int hour, int dayOfWeek); int main(int argc, char *argv[]) { int isdst, dayOfWeek; char buf[80]; struct tm tmData; if( argc == 1 ) { printf("/nsyntax: %s mm/dd/yyyy_hh:mm:00", argv[0]); return -1; } // 0123456789A12 // 03/12/2018_12 strcpy(buf, argv[1]); tmData.tm_mon = atoi(&buf[0]) - 1; //month -1 tmData.tm_mday = atoi(&buf[3]); //day of month tmData.tm_year = atoi(&buf[6]) - 1900; // year - 1900 tmData.tm_hour = atoi(&buf[11]); // hour tmData.tm_min = 0; //minutes (not used) tmData.tm_sec = 0; //seconds (not used) //tmData.tm_min = atoi(&buf[14]); //tmData.tm_sec = atoi(&buf[27]); //day light saving time variable. //NOT used in this calculation. //Tells mktime the input date is in day light saving time tmData.tm_isdst = 0; // mktime(&tmData); dayOfWeek = tmData.tm_wday; printf("%02d/%02d/%2d_%02d dayWk=%d ", tmData.tm_mon+1, tmData.tm_mday, tmData.tm_year, tmData.tm_hour, dayOfWeek); isdst = isDst(tmData.tm_mon+1, tmData.tm_mday, tmData.tm_hour, dayOfWeek); printf("isdst=%d/n", isdst); return 0; } int isDst(int month, int dayOfMonth, int hour, int dayOfWeek) { int second_sunday, first_sunday; if( month > 3 && month < 11 ) return 1; //4,5,6,7,8,9,10 if( month < 3 || month == 12 ) return 0; //1, 2 or 12 if( month == 3 ) { //The 2nd Sunday in March is 8,9,10,11,12,13,14 if( dayOfMonth < 8 ) return 0; if( dayOfMonth > 14 ) return 1; //To get here dayOfMonth >= 8 && dayOfMonth <= 14 second_sunday = dayOfMonth - dayOfWeek; if( second_sunday < 8 ) second_sunday += 7; printf("2nd_Sunday=%2d ", second_sunday); if( dayOfMonth > second_sunday ) return 1; if( dayOfMonth < second_sunday ) return 0; //To get here dayOfMonth = second_sunday if( hour >= 2 ) return 1; else return 0; } if( month == 11 ) { //The 1st Sunday in Nov is 1,2,3,4,5,6,7 if( dayOfMonth > 7 ) return 0; //To get here dayOfMonth >= 1 && dayOfMonth <= 7 first_sunday = dayOfMonth - dayOfWeek; if( first_sunday < 1 ) first_sunday += 7; printf("1st_Sunday=%2d ", first_sunday); if( dayOfMonth > first_sunday ) return 0; if( dayOfMonth < first_sunday ) return 1; //To get here dayOfMonth = first_sunday if( hour >= 2 ) return 0; else return 1; } return -1; } /************** Compile via cl.exe isDst.c Begin and End dates for day light saving time 03/11/2007_01:00:00 11/04/2007_01:00:00 03/09/2008_01:00:00 11/02/2008_01:00:00 03/08/2009_01:00:00 11/01/2009_01:00:00 03/14/2010_01:00:00 11/07/2010_01:00:00 03/13/2011_01:00:00 11/06/2011_01:00:00 03/11/2012_01:00:00 11/04/2012_01:00:00 03/10/2013_01:00:00 11/03/2013_01:00:00 03/09/2014_01:00:00 11/02/2014_01:00:00 03/08/2015_01:00:00 11/01/2015_01:00:00 03/13/2016_01:00:00 11/06/2016_01:00:00 03/12/2017_01:00:00 11/05/2017_01:00:00 03/11/2018_01:00:00 11/04/2018_01:00:00 03/10/2019_01:00:00 11/03/2019_01:00:00 03/08/2020_01:00:00 11/01/2020_01:00:00 03/14/2021_01:00:00 11/07/2021_01:00:00 03/13/2022_01:00:00 11/06/2022_01:00:00 03/12/2023_01:00:00 11/05/2023_01:00:00 03/10/2024_01:00:00 11/03/2024_01:00:00 03/09/2025_01:00:00 11/02/2025_01:00:00 03/08/2026_01:00:00 11/01/2026_01:00:00 03/14/2027_01:00:00 11/07/2027_01:00:00 03/12/2028_01:00:00 11/05/2028_01:00:00 03/11/2029_01:00:00 11/04/2029_01:00:00 03/10/2030_01:00:00 11/03/2030_01:00:00 03/09/2031_01:00:00 11/02/2031_01:00:00 03/14/2032_01:00:00 11/07/2032_01:00:00 isDst.exe 03/11/2007_02:00:00 >> dst.txt isDst.exe 03/09/2008_02:00:00 >> dst.txt isDst.exe 03/08/2009_02:00:00 >> dst.txt isDst.exe 03/14/2010_02:00:00 >> dst.txt isDst.exe 03/13/2011_02:00:00 >> dst.txt isDst.exe 03/11/2012_02:00:00 >> dst.txt isDst.exe 03/10/2013_02:00:00 >> dst.txt isDst.exe 03/09/2014_02:00:00 >> dst.txt isDst.exe 03/08/2015_02:00:00 >> dst.txt isDst.exe 03/13/2016_02:00:00 >> dst.txt isDst.exe 03/12/2017_02:00:00 >> dst.txt isDst.exe 03/11/2018_02:00:00 >> dst.txt isDst.exe 03/10/2019_02:00:00 >> dst.txt isDst.exe 03/08/2020_02:00:00 >> dst.txt isDst.exe 03/14/2021_02:00:00 >> dst.txt isDst.exe 03/13/2022_02:00:00 >> dst.txt isDst.exe 03/12/2023_02:00:00 >> dst.txt isDst.exe 03/10/2024_02:00:00 >> dst.txt isDst.exe 03/09/2025_02:00:00 >> dst.txt isDst.exe 03/08/2026_02:00:00 >> dst.txt isDst.exe 03/14/2027_02:00:00 >> dst.txt isDst.exe 03/12/2028_02:00:00 >> dst.txt isDst.exe 03/11/2029_02:00:00 >> dst.txt isDst.exe 03/10/2030_02:00:00 >> dst.txt isDst.exe 03/09/2031_02:00:00 >> dst.txt isDst.exe 03/14/2032_02:00:00 >> dst.txt isDst.exe 11/04/2007_02:00:00 >> dst.txt isDst.exe 11/02/2008_02:00:00 >> dst.txt isDst.exe 11/01/2009_02:00:00 >> dst.txt isDst.exe 11/07/2010_02:00:00 >> dst.txt isDst.exe 11/06/2011_02:00:00 >> dst.txt isDst.exe 11/04/2012_02:00:00 >> dst.txt isDst.exe 11/03/2013_02:00:00 >> dst.txt isDst.exe 11/02/2014_02:00:00 >> dst.txt isDst.exe 11/01/2015_02:00:00 >> dst.txt isDst.exe 11/06/2016_02:00:00 >> dst.txt isDst.exe 11/05/2017_02:00:00 >> dst.txt isDst.exe 11/04/2018_02:00:00 >> dst.txt isDst.exe 11/03/2019_02:00:00 >> dst.txt isDst.exe 11/01/2020_02:00:00 >> dst.txt isDst.exe 11/07/2021_02:00:00 >> dst.txt isDst.exe 11/06/2022_02:00:00 >> dst.txt isDst.exe 11/05/2023_02:00:00 >> dst.txt isDst.exe 11/03/2024_02:00:00 >> dst.txt isDst.exe 11/02/2025_02:00:00 >> dst.txt isDst.exe 11/01/2026_02:00:00 >> dst.txt isDst.exe 11/07/2027_02:00:00 >> dst.txt isDst.exe 11/05/2028_02:00:00 >> dst.txt isDst.exe 11/04/2029_02:00:00 >> dst.txt isDst.exe 11/03/2030_02:00:00 >> dst.txt isDst.exe 11/02/2031_02:00:00 >> dst.txt isDst.exe 11/07/2032_02:00:00 >> dst.txt https://.com/questions/5590429/calculating-daylight-saving-time-from-only-date ***************/ /***** The previous programs used mktime to compute day_of_week. It used day_of_week to compute 2nd_sunday in march and 1st_sunday in Nov. If you don''t want to use mktime, you can use this program to compute 2nd_sunday. The same technique will compute 1st_sunday. On 03/14/2007, the day of the week is Wed, or 3. Every year after 2007, the day of the week advances 1 day. on leap years, the day of the week advances 2 days. Must include the no. of leap years sinc 2004. ******/ #include <stdio.h> #include <string.h> #include <time.h> int secondSunday(year); int main(int argc, char *argv[]) { int year, second_sunday; if( argc == 1 ) { printf("/nsyntax: %s year, with year >= 2007./n", argv[0]); return -1; } year = atoi(argv[1]); if( year < 2007 ) { printf("/nsyntax: %s year, with year >= 2007./n", argv[0]); return -1; } second_sunday = secondSunday(year); printf("second_sunday=%d/n", second_sunday); return 0; } int secondSunday(year) { //On 03/14/2007, the day of the week is Wed, or 3. int no_years, no_leaps, day_of_week, second_sunday; no_years = year - 2007; no_leaps = (year - 2004)/4; day_of_week = 3 + (no_years + no_leaps) % 7; second_sunday = 14 - day_of_week; if( second_sunday < 8 ) second_sunday += 7; //printf("no_years=%d,no_leaps=%d,day_of_week=%d, second_sunday=%d/n", //no_years, no_leaps, day_of_week, second_sunday); return second_sunday; } /************** Compile via cl.exe second_sunday.c second_sunday.exe 2007 second_sunday.exe 2008 second_sunday.exe 2009 second_sunday.exe 2010 second_sunday.exe 2011 second_sunday.exe 2012 second_sunday.exe 2013 second_sunday.exe 2014 second_sunday.exe 2015 second_sunday.exe 2016 second_sunday.exe 2017 second_sunday.exe 2018 second_sunday.exe 2019 second_sunday.exe 2020 second_sunday.exe 2021 second_sunday.exe 2022 second_sunday.exe 2023 second_sunday.exe 2024 second_sunday.exe 2025 second_sunday.exe 2026 second_sunday.exe 2027 second_sunday.exe 2028 second_sunday.exe 2029 second_sunday.exe 2030 second_sunday.exe 2031 second_sunday.exe 2032 ***************/