The Time library adds timekeeping functionality to Arduino with or without external timekeeping hardware. It allows a sketch to get the time and date as: second, minute, hour, day, month and year. It also provides time as a standard C time_t so elapsed times can be easily calculated and time values shared across different platforms.
Update: Newer versions of Time, TimeAlarms, and DS1307RTC are available, featuring more updates for newer version of the Arduino IDE and compatibility with Arduino Due.The code is derived from the earlier Playground DateTime library but is updatedto provide an API that is more flexible and easier to use.
Additional documentation is included in a readme.txt file
struct tm { int8_t tm_sec; /**< seconds after the minute - [ 0 to 59 ] */ int8_t tm_min; /**< minutes after the hour - [ 0 to 59 ] */ int8_t tm_hour; /**< hours since midnight - [ 0 to 23 ] */ int8_t tm_mday; /**< day of the month - [ 1 to 31 ] */ int8_t tm_wday; /**< days since Sunday - [ 0 to 6 ] */ int8_t tm_mon; /**< months since January - [ 0 to 11 ] */ int16_t tm_year; /**< years since 1900 */ int16_t tm_yday; /**< days since January 1 - [ 0 to 365 ] */ int16_t tm_isdst; /**< Daylight Saving Time flag */ };
The time and date functions can take an optional parameter for the time. This preventserrors if the time rolls over between elements. For example, if a new minute begins between getting the minute and second, the values will be inconsistent. Using the following functions eliminates this problem
time_t t = now() // Store the current time in time variable 't'
hour(t); // Returns the hour for the given time t
minute(t); // Returns the minute for the given time t
second(t); // Returns the second for the given time t
day(t); // The day for the given time t
weekday(t); // Day of the week for the given time t
month(t); // The month for the given time t
year(t); // The year for the given time t
out string descriptions for day and month
monthStr()
monthShortStr()
dayStr()
dayShortStr()
Be aware that a parameter is required for this string functions. The argument is NOT the timestamp, e.g. time_t, but must be something like month(). So monthStr(month()) or dayStr(weekday()) will work.
See also the >TimeSerialDateStrings.ino example sketch in the Time library
setTime(t); // Set the system time to the given time t
setTime( hr, min, sec, day, month, yr); // Another way to set the time
adjustTime( adjustment ); // Adjust system time by adding the adjustment value
// WARNING: this is not compatible with using a sync provider as it
// only adjusts the library system time and not time in the sync provider.
// This offset adjustment will be lost on the next time sync.
// If the time is moved forward, an immediate call to now() can get the time
// from the sync provider rather than the adjusted library system time.
// i.e. do not depend on now() to return an adjusted time when using
// a sync provider even when called immediately after adjustTime()
timeStatus(); // Indicates if time has been set and recently synchronized
// returns one of the following
// enumerations:
*timeNotSet // The time has never been set, the clock started at Jan 1 1970
*timeNeedsSync // The time had been set but a sync attempt did not succeed
*timeSet // The time is set and is synced
// Time and Date values are not valid if
// the status is timeNotSet. Otherwise values can be used but the returned
// time may have drifted if the status is
// timeNeedsSync.
setSyncProvider( getTimeFunction);// Set the external time provider
setSyncInterval( interval ); // Set the number of seconds between re-syncs
There are many convenience macros in >TimeLib.h for time constants and conversion of time units.
Using the Library Copy the download to the Library directory.The Time directory contains the Time library and some example sketches illustrating how the library can be used with various time sources:
->TimeSerial.ino shows Arduino as a clock without external hardware.
It is synchronized by time messages sent over the serial port. A companion Processing sketch will automatically provide these messages if it is running and connected to the Arduino serial port.
->TimeRTC uses a >DS1307 Real Time Clock (or >DS3231 >ChronoDot RTC*) to provide time synchronization. To run this sketch the >DS1307RTC library must be installed. * The >I2C '>DS3231' interface is very straightforward and virtually identical to the register addresses of the popular >DS1337 and >DS1307 >RTCs , which means that existing code for the Arduino, Basic Stamp, Cubloc, and other controllers should work with no modification. For reference purposes see >> https://www.adafruit.com/products/255
- >TimeNTP uses the Arduino Ethernet shield to access time using the internet NTP time service. The NTP protocol uses UDP and the >UdpBytewise library is required, see: https://bitbucket.org/bjoern/arduino_osc/src/tip/libraries/Ethernet/ Note: This is out of date. For Arduino 0022, see the built in Udp NTP example, and also see http://arduino.cc/en/Tutorial/UdpNtpClient .
->T imeGPS gets time from a GPS
This requires the >TinyGPS library from Mikal Hart: http://arduiniana.org/libraries/TinyGPS
The test sketch uses a message on the serial port to set the time. A Processing sketch that sends these messages is included in the download but you can test this sketch by sending T1262347200 using the serial monitor (this sets the time to noon on Jan 1 2010). On a Unix system, you can set the time with the shell command:
-- edit: The above code did not work for me in my Linux terminal, I wrote the below script which worked. ( I was using zsh and >UnoR3)
/*H******************************************************************** * **********************************************************************/ #include <Time.h> // ********************** DEFINES ************************ #define BAUD 9600 #define TIME_MSG_LEN 11 // TIME SYNC TO PC IS HEADER FOLLOWED BY Unix time_t // AS TEN ASCII DIGITS #define TIME_HEADER 'T' // HEADER TAG FOR SERIAL TIME SYNC MESSAGE #define TIME_REQUEST 7 // ASCII BELL CHARACTER REQUESTS A TIME SYNC MESSAGE // T1262347200 == NOON Jan 1 2010 // ********************** PROTOTYPES ************************ void digitalClockDisplay(); void printDigits( int digits ); void digitalClockDisplay(); // ********************** VARIABLES ************************ /*F******************************************************************** * **********************************************************************/ void setup() { Serial.begin( BAUD ); } /*F******************************************************************** * **********************************************************************/ void loop() { if( Serial.available() ) processSyncMessage(); if( timeStatus() == timeNotSet) Serial.println( "waiting for sync message"); else digitalClockDisplay(); delay( 1000); } /*F******************************************************************** * **********************************************************************/ void digitalClockDisplay() { // digital clock display of the time Serial.print( hour() ); printDigits( minute() ); printDigits( second() ); Serial.print( " " ); Serial.print( day() ); Serial.print( " " ); Serial.print( month() ); Serial.print( " " ); Serial.print( year() ); Serial.println(); } /*F******************************************************************** * utility for digital clock display: prints preceding colon and leading 0 **********************************************************************/ void printDigits( int digits ) { Serial.print( ":" ); if( digits < 10) Serial.print( '0' ); Serial.print( digits ); } /*F******************************************************************** * if time sync available from serial port, update time and return true **********************************************************************/ void processSyncMessage() { while( Serial.available() >= TIME_MSG_LEN ) { // TIME MESSAGE CONSISTS OF HEADER & 10 ASCII DIGITS char c = Serial.read(); Serial.print( c ); if( c == TIME_HEADER ) { time_t pctime = 0; for( int i = 0; i < TIME_MSG_LEN - 1; i++) { c = Serial.read(); if( c >= '0' && c <= '9') pctime = (10 * pctime) + (c - '0') ; // convert digits to nmbr } setTime( pctime ); // Sync Arduino clock to time received on serial port } } }
Here is a fragment from the >TimeNTP.ino example sketch showing how the syncProvider functionality simplifies the sketch code. This sketch gets time from an Internet time provider (NTP) using the Arduino Ethernet shield. Note that the loop code does not require any logic to maintain time sync. The Time library will automatically monitor NTP and sync the time as necessary.
/*H******************************************************************** * **********************************************************************/ // ******************** DEFINES **************************** #define BAUD 9600 // ******************** PROTOTYPES **************************** void printDigits( int digits ); void digitalClockDisplay(); // ******************** VARIABLES **************************** /*F******************************************************************** * **********************************************************************/ void setup() { Serial.begin( BAUD ); Ethernet.begin( mac, ip, gateway); Serial.println( "waiting for sync" ); setSyncProvider( getNtpTime ); while( timeStatus() == timeNotSet ) ; // wait until the time is set by the sync provider } /*F******************************************************************** * **********************************************************************/ void loop() { if( now() != prevDisplay) // update display only if time has changed { prevDisplay = now(); digitalClockDisplay(); } } /*F******************************************************************** * digital clock display of the time **********************************************************************/ void digitalClockDisplay() { Serial.print( hour( )); printDigits( minute( )); printDigits( second( )); Serial.print( " "); Serial.print( day( )); Serial.print( " "); Serial.print( month( )); Serial.print( " "); Serial.print( year( )); Serial.println( ); } /*F******************************************************************** * digital clock display: prints preceding colon and leading 0 **********************************************************************/ void printDigits( int digits ) { Serial.print( ":" ); if( digits < 10 ) Serial.print( '0' ); Serial.print( digits ); }
/*H******************************************************* * Time_NTP.pde * Example showing time sync to NTP time source * This sketch uses Ethernet library ********************************************************/ #include <Time.h> #include <Ethernet.h> #include <EthernetUdp.h> #include <SPI.h> //************************* DEFINES ************************************ //************************* PROTOTYPES ************************************ //************************* VARIABLES ************************************ EthernetUDP Udp; byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // NTP Servers: IPAddress timeServer( 132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov // IPAddress timeServer( 132, 163, 4, 102); // time-b.timefreq.bldrdoc.gov // IPAddress timeServer( 132, 163, 4, 103); // time-c.timefreq.bldrdoc.gov time_t prevDisplay = 0; // WHEN DIGITAL CLOCK WAS DISPLAYED const int timeZone = 1; // Central European Time //const int timeZone = -5; // Eastern Standard Time (USA) //const int timeZone = -4; // Eastern Daylight Time (USA) //const int timeZone = -8; // Pacific Standard Time (USA) //const int timeZone = -7; // Pacific Daylight Time (USA) unsigned int localPort = 8888; // local port to listen for UDP packets /*F******************************************************************** * **********************************************************************/ void setup() { Serial.begin( 9600 ); while( !Serial ) ; // Needed for Leonardo only delay( 250 ); Serial.println( "TimeNTP Example"); if( Ethernet.begin( mac ) == 0) { while( 1 ) // no point in carrying on, so do nothing forevermore: { Serial.println( "Failed to configure Ethernet using DHCP"); delay( 10000 ); } } Serial.print( "IP number assigned by DHCP is "); Serial.println( Ethernet.localIP()); Udp.begin( localPort ); Serial.println( "waiting for sync"); setSyncProvider( getNtpTime); } /*F******************************************************************** * **********************************************************************/ void loop() { if( timeStatus() != timeNotSet) { if( now() != prevDisplay) { //update display only if time has changed prevDisplay = now(); digitalClockDisplay(); } } } /*F******************************************************************** * **********************************************************************/ void digitalClockDisplay() { // digital clock display of the time Serial.print( hour()); printDigits( minute()); printDigits( second()); Serial.print( " "); Serial.print( day()); Serial.print( " "); Serial.print( month()); Serial.print( " "); Serial.print( year()); Serial.println(); } /*F******************************************************************** * **********************************************************************/ void printDigits( int digits ) { // utility for digital clock display: prints preceding colon and leading 0 Serial.print( ":" ); if( digits < 10 ) Serial.print( '0' ); Serial.print( digits ); } /*-------- NTP code ----------*/ const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets /*F******************************************************************** * **********************************************************************/ time_t getNtpTime() { while( Udp.parsePacket() > 0) ; // discard any previously received packets Serial.println( "Transmit NTP Request"); sendNTPpacket( timeServer ); uint32_t beginWait = millis(); while( millis() - beginWait < 1500) { int size = Udp.parsePacket(); if( size >= NTP_PACKET_SIZE) { Serial.println( "Receive NTP Response"); Udp.read( packetBuffer, NTP_PACKET_SIZE); // RD PKT unsigned long secsSince1900; // convert four bytes starting at location 40 to a long integer secsSince1900 = (ulong)packetBuffer[40] << 24; secsSince1900 |= (ulong)packetBuffer[41] << 16; secsSince1900 |= (ulong)packetBuffer[42] << 8; secsSince1900 |= (ulong)packetBuffer[43]; return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR; } } Serial.println("No NTP Response :-("); return 0; // return 0 if unable to get the time } /*F******************************************************************** * send an NTP request to the time server at the given address **********************************************************************/ void sendNTPpacket( IPAddress &address) { // set all bytes in the buffer to 0 memset( packetBuffer, 0, NTP_PACKET_SIZE); // Initialize values needed to form NTP request // (see URL above for details on the packets) packetBuffer[0] = 0b11100011; // LI, Version, Mode packetBuffer[1] = 0; // Stratum, or type of clock packetBuffer[2] = 6; // Polling Interval packetBuffer[3] = 0xEC; // Peer Clock Precision // 8 bytes of zero for Root Delay & Root Dispersion packetBuffer[12] = 49; packetBuffer[13] = 0x4E; packetBuffer[14] = 49; packetBuffer[15] = 52; // all NTP fields have been given values, now // you can send a packet requesting a timestamp: Udp.beginPacket( address, 123); //NTP requests are to port 123 Udp.write( packetBuffer, NTP_PACKET_SIZE ); Udp.endPacket(); }
The macro to convert days to time_t was corrected as of July 22 2011