tz.toLocal(systime) correctly returns a time that is 60 minutes past systime.
This doesn't work, and no errors are generated. The method below, tz.toLocal(systime) = systime, which is wrong.
if (x == true) Timezone tz(dSt,sTd);
I included this along with other prototype functions in the initialization section because an error was generated when compiled and that resolved the error, but I'm not sure if it was the correct solution because it is instantiating an object, and it did not resolve the problem.
Also, the exact code below works when included in setup(), localTime is 60 minutes past sysTime, but called as a function as below, no errors are generated, but locTime = sysTime.
Thanks in advance for the help.
void sTime() {
sysTime = now();
if (preset[36] != 0) { // if DST hour is set, use DST function
locTime = tz.toLocal(sysTime);
setTime(locTime); // DST
}
}
//Try this way first - local and utc will be 14400 seconds apart, which is correct
//Then uncomment the two lines above Timezone() and comment Timezone myTZ(myDST, mySTD) - both numbers will be
//equal, which is not correct.
//Next, back to the first way that worked, and comment utc = now(), and local = myTZ.toLocal(utc). Uncomment sTime().
//The same method but in a function, will not throw errors but it will not work.
#include <Time.h>
#include <Timezone.h>
time_t utc, local;
// prototypes
TimeChangeRule myDST = {"DST", 0, 0, 0, 0, 0};
TimeChangeRule mySTD = {"STD", 0, 0, 0, 0, 0};
Timezone myTZ(myDST, mySTD);
void setup() {
Serial.begin(9600);
setTime(12,0,0,24,7,2015); // set to 12:00PM, 7/24/15
TimeChangeRule myDST = {"EDT", Second, Sun, Mar, 2, -240}; //Daylight time = UTC - 4 hours
TimeChangeRule mySTD = {"EST", First, Sun, Nov, 2, -300}; //Standard time = UTC - 5 hours
//Try this both ways *****************************
//This does not work
//int x=2;
//if (x > 1) Timezone myTZ(myDST, mySTD);
//This does work
Timezone myTZ(myDST, mySTD);
//************************************************
//Then try this **********************************
//This does not work
// sTime();
// This does work
utc = now();
local = myTZ.toLocal(utc);
//************************************************
Serial.println(utc);
Serial.println(local);
}
void loop() {
// put your main code here, to run repeatedly:
}
void sTime() {
utc = now();
local = myTZ.toLocal(utc);
}
The problem is that what you think is a prototype is actually a constructor for a time zone object. Get rid of the “prototype”, since that actually instantiates the object. Take a look at this code and I think you’ll see the problem.
//Try this way first - local and utc will be 14400 seconds apart, which is correct
//Then uncomment the two lines above Timezone() and comment Timezone myTZ(myDST, mySTD) - both numbers will be
//equal, which is not correct.
//Next, back to the first way that worked, and comment utc = now(), and local = myTZ.toLocal(utc). Uncomment sTime().
//The same method but in a function, will not throw errors but it will not work.
#include <Time.h>
#include <Timezone.h>
time_t utc, local;
// prototypes
TimeChangeRule myDST = {"DST", 0, 0, 0, 0, 0};
TimeChangeRule mySTD = {"STD", 0, 0, 0, 0, 0};
//Timezone myTZ(myDST, mySTD);
void setup() {
Serial.begin(9600);
setTime(12, 0, 0, 24, 7, 2015); // set to 12:00PM, 7/24/15
TimeChangeRule myDST = {"EDT", Second, Sun, Mar, 2, -240}; //Daylight time = UTC - 4 hours
TimeChangeRule mySTD = {"EST", First, Sun, Nov, 2, -300}; //Standard time = UTC - 5 hours
//Try this both ways *****************************
//This does not work
int x = 0;
Timezone myTZ(myDST, mySTD); // This instantiates the object
if (x > 1) { // You can change x above to test the other branch
sTime(myTZ);
} else {
utc = now();
local = myTZ.toLocal(utc);
}
Serial.println(utc);
Serial.println(local);
}
void loop() {
// put your main code here, to run repeatedly:
}
void sTime(Timezone myTZ) {
utc = now();
local = myTZ.toLocal(utc);
}
When Serial.println(myTZ.locIsDST(utc)); or any reference to myTZ is put in loop(), a compiler error, "'myTZ' was not defined in this scope", was generated. How can it be made global, without the prototype function?
Regarding post #7, I thought about instantiating another object in loop(), but that seems more like a kluge. If there is no good way of doing this, I'll move the code to a function within the program.
I see. So to make the Timezone object properties and methods available everywhere, which is what I need, it would have to be instantiated before setup() where it will be global. Then I would have to add a method function to allow updating the dst and std data to the already instantiated, global object. Once that is done, it should work. Is that correct?
I believe I found a good solution - I added the function, 'updateRules' to the library. That way the object can be created globally in the initialization section, so library functions are available everywhere.
This goes anywhere rules need to be updated:
TimeChangeRule myDST = {"EDT", 2, 1, 3,2, -240}; //Daylight time = UTC - 4 hours
TimeChangeRule mySTD = {"EST", 1, 1, 11,2, -300}; //Standard time = UTC - 5 hours
myTZ.updateRules(myDST,mySTD);
If there is a better way to do this, let me know. Thanks again for the help.
Let's first consider whether, while the Arduino is running, the conversion rules will change. How often is that likely to happen?
There is a better way. The TimeChangeRule class should have a no-argument constructor. It should also have a begin() method. You would instantiate two (empty) rules, and then call the begin() methods to give them values.
Instead of updateRules(), you'd just call begin() again, for the rule instance(s). if the rule(s) changes.
Right now, it appears that the Timezone1 class copies data from the TimeChangeRule instances, instead of storing the TimeChangeRule instances. The data should be obtained from the TimeChangeRule instances, when the Timezone1 instance's methods are called.
That way, you could change the TimeChangeRule instance, and the Timezone1 instance would KNOW.
The rules will probably never change, unfortunately, but they are accessible in menus so I do want to keep the ability to change them if necessary.
TimeChangeRule is just a struct. It is not defined as a class and it doesn't appear in Timezone.cpp. It appears to only store values set to myDST and mySTD.
So if this will work to initialize myDST and mSTD, so they can be set later:
TimeChangeRule myDST = {};
TimeChangeRule mySTD = {};
And this anywhere:
TimeChangeRule myDST = {"EDT", 2, 1, 3,2, -240}; //Daylight time = UTC - 4 hours
TimeChangeRule mySTD = {"EST", 1, 1, 11,2, -300}; //Standard time = UTC - 5 hours
myTZ.updateRules(myDST,mySTD);
Is that accomplishing what you describe, but in a less elegant way? I'm at the limit of what I understand about objects, now. I will check other libraries that have a begin() method, to see how it's done.
So if this will work to initialize myDST and mSTD, so they can be set later:
TimeChangeRule myDST = {};
TimeChangeRule mySTD = {};
Why? You can declare an instance of a struct without providing initializers.
TimeChangeRule myDST;
TimeChangeRule mySTD
TimeChangeRule myDST = {"EDT", 2, 1, 3,2, -240}; //Daylight time = UTC - 4 hours
TimeChangeRule mySTD = {"EST", 1, 1, 11,2, -300}; //Standard time = UTC - 5 hours
myTZ.updateRules(myDST,mySTD);
That works, but the convention is to call the mandatory function begin(). Your mandatory function, before the class is usable is called updateRules() which implies, to me at least, that it is an optional function, to be used when the rules change (not are set).