Est-ce que quelqu’un a implémenté __getzone () pour IAR Embedded Workbench pour MSP430?

Je dois faire face à des conversions de temps dans mon application. J’aimerais continuer à utiliser autant que possible les fonctions de bibliothèque standard. Actuellement, j’utilise une structure time_t comme base de temps système. Cependant, certains appareils peuvent synchroniser l’heure sur mon appareil, et cette heure peut être en UTC ou non. De plus, mon appareil synchronisera l’heure sur un autre appareil et cette heure sera toujours au format UTC.

Quoi qu’il en soit, je peux demander à l’utilisateur quel est le fuseau horaire correspondant à l’heure qui est synchronisée sur mon appareil et s’il utilise ou non l’heure d’été. Lorsque mon appareil reçoit une synchronisation de l’heure, je peux utiliser mktime pour générer directement mon horodatage (l’heure système de mon appareil doit correspondre à l’heure de la synchronisation aux fins de l’horodatage, sinon je dois effectuer des conversions en permanence), puis à partir de ce moment. utilisez gmtime () pour obtenir l’heure UTC si je sais que la synchronisation de l’heure provient d’une source autre que UTC. Le problème, c’est que par défaut, localtime () et gmtime () vont renvoyer la même valeur, car la bibliothèque va par défaut penser qu’elle se trouve en heure UTC directe et qu’il n’y a pas de décalage DST ou timezone.

Donc, je pense que la solution consiste à implémenter et à écraser la fonction de bibliothèque __getzone.

À partir de la page 106 de EW430_ComstackrReference.pdf

Pour que les fonctions __time32, __time64 et la date fonctionnent, vous devez implémenter les fonctions clock, __time32, __time64 et __getzone. Que vous utilisiez __time32 ou __time64 dépend de l’interface que vous utilisez pour time_t, voir time.h, page 304.

L’implémentation par défaut de __getzone spécifie le fuseau horaire UTC (Coordinated Universal Time).

Q1: Suis-je sur la bonne voie dans mon raisonnement, le meilleur moyen de faire ce que je veux est d’implémenter cette fonction __getzone?

La raison pour laquelle je refuse est parce que la valeur renvoyée par __getzone est une chaîne bizarre avec un formatage comme celui-ci:

: [XXX [: YYY [: NNN [: DST [: DST …]]]]]

Où XXX est le nom de fuseau horaire standard (par exemple, GMT-5 pour EST), YYY est le nom de fuseau horaire d’heure avancée (par exemple, GMT-4 pour EST), NNN est un décalage numérique par rapport à UTC sous la forme HHMM (et peut avoir un symbole – )., puis DST spécifie une chaîne d’options pour les règles d’heure qui a sa propre mise en forme irritante.

Quoi qu’il en soit, cela devrait être assez simple pour moi pour le moment, car je ne m’inquiète que du Canada et des États-Unis, qui appliquent les mêmes règles en matière d’heure d’été.

Q2: Quelqu’un a-t-il un exemple de code pour former cette chaîne afin que je puisse vérifier si j’ai bien compris?

Voici mon implémentation de __getzone (). Alors maintenant, ma base de temps système sera UTC. Lorsque l’utilisateur configure mon système, je lui demande quelle est son heure locale si la source de l’heure ne fournit PAS l’heure UTC. Ensuite, lorsqu’ils fournissent une synchronisation de l’heure sur mon système, l’heure qu’ils fournissent sera convertie en UTC par un appel à MKTIME (qui tiendra compte des règles de l’heure d’été). Ensuite, lorsque l’heure est restituée à l’utilisateur, l’opération est effectuée via un appel à localtime ().

Une autre chose que nous avons apprise lors de l’implémentation est que l’implémentation de MKTIME () par IAR appellera __getzone (), mais les règles DST ne seront pas sockets en compte à moins que vous ne définissiez tm_isdst sur ‘-1’. -1 permet à l’appel à MKTIME () de déterminer s’il faut appliquer l’heure d’été ou non en fonction de la règle.

/*! * \brief Overrides default library function __getzone to support different time * zones and DST rules. * \returns Pointer to a const ssortingng containing the timezone + dst rules * * This function supports all time zones and DST rules for the US and Canada. * * \par IAR Notes * The return value should be a ssortingng on the following form: * \code * :[XXX[:YYY[:NNN[:DST[:DST ...]]]]] * \endcode * \par * Where \b XXX is the standard time-zone name, \b YYY is the daylight * savings time-zone name, \b NNN is the time zone offset, and the DSTs * are the daylight savings time rules. Daylight savings time will add * one hour to the normal time. * \par * The time zone offset \b NNN is specified as a number relative to UTC, * possibly negative (east is positive), on the format HHMM, where HH * is hours and MM is minutes. * \par * The DSTs specifes a set of rules for how daylight savings time is * applied. The rules must be sorted in increasing date order starting * from the earliest date. The first rule for a specific year will * enable DST, the next will disable it, and so on. Each rule is on * the following form: * \code * [(YYYY)]MMDD[HH][-W|+W] * \endcode * * * \b (YYYY) is the first year the daylight savings rule was applied. * It is optional. If not specified it will default to the same * year as the previous rule or zero if no previous rule. * * \b MM is the month number (1-12). * * \b DD is the day of the month (1-31). * * \b HH is the hour number in a 24-hour day (optional, defaults to 0). * * \b +/-W specifies the day of the week the rule takes effect (where * Sunday = 0, Monday = 1, etc). +W means that the rule applies * to the first such day on or after the specified date and -W * ssortingctly before the date. If this is not specified, the rule * will take effect on the exact date, regardless of the day of * the week. * * \par Example * US Eastern Standard time is UTC -5. Eastern Daylight time is UTC -4. * Daylight time goes into affect on the second sunday of March at 2:00AM local * time. Daylight time ends on the first sunday of November at 2:00AM local * time. The law that defines this went into affect in 2007. * Therefore here is how the DST ssortingng is constructed: * | \| | STD Time | \| | DST Time | \| | UTC Offset | \| | DST Rule Year | Month DST Starts | Day DST Starts | Hour DST Starts | Day of Week | \| | Month DST Ends | Day DST Ends | Hour DST Ends | Day of Week | * |----|----------|----|----------|----|------------|----|---------------|------------------|----------------|-----------------|-------------|----|----------------|--------------|---------------|-------------| * | : | XXX | : | YYY | : | NNN | : | (YYYY) | MM | DD* | HH | +/-W** | : | MM | DD | HH | +/-W | * | : | GMT-5 | : | GMT-4 | : | -0500 | : | (2007) | 03 | 08 | 02 | +0 | : | 11 | 01 | 02 | +0 | * - * An 8 for the day means that DST will start around the 8th day of the * month. Or that the +/-W parameter is relative to the 8th day of the month. * - ** A + here means that the DST rule will start \b on or \b after the * previously specified day (the 8th). 0 means that it should happen on a * sunday. Therefore if the 8th is a sunday (and the 8th cannot be the first * sunday of the month) then the rule will take affect on that day - or it * will happen on the very next sunday. * \par * Result: * \code * :GMT-5:GMT-4:-0500:(2007)030802+0:110102+0 * \endcode * * \sa * - time_zones - Supported time zones */ const char8_t * __getzone(void) { const char8_t *current_zone = NULL; static const char8_t dst_time_zones[][50] = { // UTC time ":GMT+0:GMT+0:0000:0", // Newfoundland Standard Time UTC – 3:30 ":GMT-3:GMT-2:-0330:(2007)030802+0:110102+0", // Atlantic Standard Time, UTC – 4 ":GMT-4:GMT-3:-0400:(2007)030802+0:110102+0", // Eastern Standard Time, UTC – 5 ":GMT-5:GMT-4:-0500:(2007)030802+0:110102+0", // Central Standard Time, UTC – 6 ":GMT-6:GMT-5:-0600:(2007)030802+0:110102+0", // Mountain Standard Time, UTC – 7 ":GMT-7:GMT-6:-0700:(2007)030802+0:110102+0", // Pacific Standard Time, UTC – 8 ":GMT-8:GMT-7:-0800:(2007)030802+0:110102+0", // Alaska Standard Time, UTC – 9 ":GMT-9:GMT-8:-0900:(2007)030802+0:110102+0", // Hawaii-Aleutian Standard Time, UTC – 10 ":GMT-10:GMT-9:-1000:(2007)030802+0:110102+0" }; static const char8_t std_time_zones[][20] = { // UTC time ":GMT+0:GMT+0:0000", // Newfoundland Standard Time UTC – 3:30 ":GMT-3:GMT-2:-0330", // Atlantic Standard Time, UTC – 4 ":GMT-4:GMT-3:-0400", // Eastern Standard Time, UTC – 5 ":GMT-5:GMT-4:-0500", // Central Standard Time, UTC – 6 ":GMT-6:GMT-5:-0600", // Mountain Standard Time, UTC – 7 ":GMT-7:GMT-6:-0700", // Pacific Standard Time, UTC – 8 ":GMT-8:GMT-7:-0800", // Alaska Standard Time, UTC – 9 ":GMT-9:GMT-8:-0900", // Hawaii-Aleutian Standard Time, UTC – 10 ":GMT-10:GMT-9:-1000" }; switch(get_config()->time_zone) { case NST: { if(get_config()->b_dst) { current_zone = dst_time_zones[NST]; } else { current_zone = std_time_zones[NST]; } } break; case AST: { if(get_config()->b_dst) { current_zone = dst_time_zones[AST]; } else { current_zone = std_time_zones[AST]; } } break; case EST: { if(get_config()->b_dst) { current_zone = dst_time_zones[EST]; } else { current_zone = std_time_zones[EST]; } } break; case CST: { if(get_config()->b_dst) { current_zone = dst_time_zones[CST]; } else { current_zone = std_time_zones[CST]; } } break; case MST: { if(get_config()->b_dst) { current_zone = dst_time_zones[MST]; } else { current_zone = std_time_zones[MST]; } } break; case PST: { if(get_config()->b_dst) { current_zone = dst_time_zones[PST]; } else { current_zone = std_time_zones[PST]; } } break; case AKST: { if(get_config()->b_dst) { current_zone = dst_time_zones[AKST]; } else { current_zone = std_time_zones[AKST]; } } break; case HAST: { if(get_config()->b_dst) { current_zone = dst_time_zones[HAST]; } else { current_zone = std_time_zones[HAST]; } } break; case UTC: default: current_zone = std_time_zones[UTC]; break; } return current_zone; } 
 char const * __getzone() { return ":GMT+2:GMT+3:0200:(1996)033103-0:103104-0"; // Ukraine; rule: (last Sun (March | October) ) } 

La règle ukrainienne ci-dessus n’est pas tout à fait juste, car elle ne fonctionnera pas avec les dimanches du 31. Si vous lisez les règles dans le getzone.c -W signifie le dimanche ssortingctement avant cette date.

 +/-W specifies the day of the week the rule takes effect (where Sunday = 0, Monday = 1, etc). +W means that the rule applies to the first such day on or after the specified date and -W ssortingctly before the date. If this is not specified, the rule will take effect on the exact date, regardless of the day of the week. 

La règle correcte serait la suivante

 char const * __getzone() { return ":GMT+2:GMT+3:0200:(1996)032503+0:102504+0"; // Ukraine; rule: (last Sun (March | October) ) } 

Pour l’Allemagne, vous pouvez utiliser:

 char const * __getzone() { return ":GMT+1:GMT+2:0100:032502+0:102502+0"; } 

Ou bien l’Ukraine a tort ou la mienne, mais j’ai testé le mien avec un appareil réel et j’ai obtenu les bons résultats. Voici mes tests:

 //Forward time_t ts = 1490489997L;//26.03.2017-01:59:57 3 seconds before dst struct tm* pre = localtime(&ts); time_t after = ts + 5L;//wait 5 seconds -> 26.03.2017-03:00:02 struct tm* post = localtime(&after); //Backward time_t ts = 1509238797L;//29.10.2017-02:59:57 3 seconds before dst struct tm* pre = localtime(&ts); time_t after = ts + 5L;//wait 5 seconds -> 29.10.2017-02:00:02 struct tm* post = localtime(&after); 

Cordialement Michael