Index: gw/smsc/smsc_smpp.c
===================================================================
--- gw/smsc/smsc_smpp.c	(revision 4850)
+++ gw/smsc/smsc_smpp.c	(working copy)
@@ -746,11 +746,64 @@
     }
 }
 
+static Octstr *relative_time(time_t now, struct tm *abs, int interval){
+    struct tm tm = gw_gmtime(now + interval);
 
+    if (tm.tm_sec >= abs->tm_sec)
+        tm.tm_sec -= abs->tm_sec;
+    else{
+        tm.tm_sec += 60 - abs->tm_sec;
+        tm.tm_min += 1;
+    }
+    if (tm.tm_min >= abs->tm_min)
+        tm.tm_min -= abs->tm_min;
+    else{
+        tm.tm_min += 60 - abs->tm_min;
+        tm.tm_hour += 1;
+    }
+    if (tm.tm_hour >= abs->tm_hour)
+        tm.tm_hour -= abs->tm_hour;
+    else{
+        tm.tm_hour += 24 - abs->tm_hour;
+        tm.tm_mday += 1;
+    }
+    if (tm.tm_mday >= abs->tm_mday)
+        tm.tm_mday -= abs->tm_mday;
+    else{
+        int days = 30;
+
+        tm.tm_mon += 1;
+        if (tm.tm_mon == 1){                         // February
+            if ((tm.tm_year + 1900)%4)
+               days = 28;
+            else                                     // Leap year
+               days = 29;
+        }
+        else if (!tm.tm_mon%2){
+            if (tm.tm_mon <= 6)
+                days = 31;
+        }
+        else if (tm.tm_mon > 6)
+             days = 31;
+        tm.tm_mday += days - abs->tm_mday;
+    }
+    if (tm.tm_mon >= abs->tm_mon)
+        tm.tm_mon -= abs->tm_mon;
+    else{
+        tm.tm_mon += 12 - abs->tm_mon;
+        tm.tm_year += 1;
+    }
+    tm.tm_year -= abs->tm_year;
+    return(octstr_format("%02d%02d%02d%02d%02d%02d000R", tm.tm_year, tm.tm_mon,
+        tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec));
+}
+
 static SMPP_PDU *msg_to_pdu(SMPP *smpp, Msg *msg)
 {
     SMPP_PDU *pdu;
     int validity;
+    struct tm tm;
+    time_t now = 0;
 
     pdu = smpp_pdu_create(submit_sm,
     	    	    	  counter_increase(smpp->message_id_counter));
@@ -913,23 +966,25 @@
 
     /*
      * check for validity and defered settings
-     * were message value has higher priiority then smsc config group value
-     * Note: we always send in UTC and just define "Time Difference" as 00 and
-     *       direction '+'.
+     * were message value has higher priority than smsc config group value
+     * Note: we send in relative time.
      */
     validity = msg->sms.validity != SMS_PARAM_UNDEFINED ? msg->sms.validity : smpp->validityperiod;
     if (validity != SMS_PARAM_UNDEFINED) {
-        struct tm tm = gw_gmtime(time(NULL) + validity * 60);
-        pdu->u.submit_sm.validity_period = octstr_format("%02d%02d%02d%02d%02d%02d000+",
-                tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday,
-                tm.tm_hour, tm.tm_min, tm.tm_sec);
+        now = time(NULL);
+        tm = gw_gmtime(now);
+        pdu->u.submit_sm.validity_period = relative_time(now, &tm,
+            validity * 60);
+
     }
 
     if (msg->sms.deferred != SMS_PARAM_UNDEFINED) {
-        struct tm tm = gw_gmtime(time(NULL) + msg->sms.deferred * 60);
-        pdu->u.submit_sm.schedule_delivery_time = octstr_format("%02d%02d%02d%02d%02d%02d000+",
-                tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday,
-                tm.tm_hour, tm.tm_min, tm.tm_sec);
+        if (!now){
+            now = time(NULL);
+            tm = gw_gmtime(now);
+        }
+        pdu->u.submit_sm.schedule_delivery_time = relative_time(now, &tm,
+            msg->sms.deferred * 60);
     }
 
     /* ask for the delivery reports if needed */
