diff --git a/src/api/step_launch.c b/src/api/step_launch.c
index 9e24597e01de0df558ef9a58747a55b3b91c4218..e68f82a39f67e6274325f863ad71b1c24759f8f2 100644
--- a/src/api/step_launch.c
+++ b/src/api/step_launch.c
@@ -1707,7 +1707,7 @@ _exec_prog(slurm_msg_t *msg)
 	}
 	if (checkpoint) {
 		/* OpenMPI specific checkpoint support */
-		info("Checkpoint started at %s", ctime(&now));
+		info("Checkpoint started at %s", slurm_ctime(&now));
 		for (i=0; (exec_msg->argv[i] && (i<2)); i++) {
 			argv[i] = exec_msg->argv[i];
 		}
@@ -1754,10 +1754,10 @@ fini:	if (checkpoint) {
 		now = time(NULL);
 		if (exit_code) {
 			info("Checkpoint completion code %d at %s",
-				exit_code, ctime(&now));
+			     exit_code, slurm_ctime(&now));
 		} else {
 			info("Checkpoint completed successfully at %s",
-				ctime(&now));
+			     slurm_ctime(&now));
 		}
 		if (buf[0])
 			info("Checkpoint location: %s", buf);
diff --git a/src/common/slurm_cred.c b/src/common/slurm_cred.c
index 7ddaa824d1cb6c50bef34f206318500a14d53170..78f17633716c2e484430e4db653f8dd87fb477ad 100644
--- a/src/common/slurm_cred.c
+++ b/src/common/slurm_cred.c
@@ -1384,7 +1384,7 @@ slurm_cred_print(slurm_cred_t *cred)
 	info("Cred: Job_mem_limit     %u",  cred->job_mem_limit );
 	info("Cred: Step_mem_limit    %u",  cred->step_mem_limit );
 	info("Cred: Step hostlist     %s",  cred->step_hostlist );
-	info("Cred: ctime             %s",  ctime(&cred->ctime) );
+	info("Cred: ctime             %s",  slurm_ctime(&cred->ctime) );
 	info("Cred: siglen            %u",  cred->siglen        );
 #ifndef HAVE_BG
 	{
@@ -2324,6 +2324,6 @@ void  print_sbcast_cred(sbcast_cred_t *sbcast_cred)
 {
 	info("Sbcast_cred: Jobid   %u", sbcast_cred->jobid         );
 	info("Sbcast_cred: Nodes   %s", sbcast_cred->nodes         );
-	info("Sbcast_cred: ctime   %s", ctime(&sbcast_cred->ctime) );
-	info("Sbcast_cred: Expire  %s", ctime(&sbcast_cred->expiration) );
+	info("Sbcast_cred: ctime   %s", slurm_ctime(&sbcast_cred->ctime) );
+	info("Sbcast_cred: Expire  %s", slurm_ctime(&sbcast_cred->expiration) );
 }
diff --git a/src/common/slurm_protocol_defs.c b/src/common/slurm_protocol_defs.c
index 5f05e02b3d1ac4a2d1c8b3a48c048e8d8cdcf9ad..81b04f299e135be3cb7a8a2758ea9b16d20d793d 100644
--- a/src/common/slurm_protocol_defs.c
+++ b/src/common/slurm_protocol_defs.c
@@ -2893,3 +2893,26 @@ extern bool valid_spank_job_env(char **spank_job_env,
 	}
 	return true;
 }
+
+/* Return ctime like string without the newline.
+ * Not thread safe */
+extern char *slurm_ctime(const time_t *timep)
+{
+	static char time_str[25];
+
+	strftime(time_str, sizeof(time_str), "%a %b %d %T %Y",
+		 localtime(timep));
+
+	return time_str;
+}
+
+/* Return ctime like string without the newline, thread safe. */
+extern char *slurm_ctime_r(const time_t *timep, char *time_str)
+{
+	struct tm newtime;
+	localtime_r(timep, &newtime);
+
+	strftime(time_str, 25, "%a %b %d %T %Y", &newtime);
+
+	return time_str;
+}
diff --git a/src/common/slurm_protocol_defs.h b/src/common/slurm_protocol_defs.h
index ba21ecc0a0bd199ed923d8de07d16d3725d70d17..bf5f59a22be9c802cfadd3229fd26ebc309d6de5 100644
--- a/src/common/slurm_protocol_defs.h
+++ b/src/common/slurm_protocol_defs.h
@@ -1236,6 +1236,13 @@ extern char *trigger_type(uint32_t trig_type);
 /* user needs to xfree after */
 extern char *reservation_flags_string(uint16_t flags);
 
+/* Return ctime like string without the newline.
+ * Not thread safe */
+extern char *slurm_ctime(const time_t *timep);
+
+/* Return ctime like string without the newline, thread safe. */
+extern char *slurm_ctime_r(const time_t *timep, char *time_str);
+
 #define safe_read(fd, buf, size) do {					\
 		int remaining = size;					\
 		char *ptr = (char *) buf;				\
diff --git a/src/plugins/accounting_storage/mysql/as_mysql_job.c b/src/plugins/accounting_storage/mysql/as_mysql_job.c
index dea5a6e4bcf01ec87a87cb1e27c8a4fb28352e89..26d40ed9bae8d9c1156b0f2819d7063920e584b6 100644
--- a/src/plugins/accounting_storage/mysql/as_mysql_job.c
+++ b/src/plugins/accounting_storage/mysql/as_mysql_job.c
@@ -323,19 +323,19 @@ extern int as_mysql_job_start(mysql_conn_t *mysql_conn,
 			debug("Need to reroll usage from %sJob %u "
 			      "from %s started then and we are just "
 			      "now hearing about it.",
-			      ctime(&check_time),
+			      slurm_ctime(&check_time),
 			      job_ptr->job_id, mysql_conn->cluster_name);
 		else if (begin_time)
 			debug("Need to reroll usage from %sJob %u "
 			      "from %s became eligible then and we are just "
 			      "now hearing about it.",
-			      ctime(&check_time),
+			      slurm_ctime(&check_time),
 			      job_ptr->job_id, mysql_conn->cluster_name);
 		else
 			debug("Need to reroll usage from %sJob %u "
 			      "from %s was submitted then and we are just "
 			      "now hearing about it.",
-			      ctime(&check_time),
+			      slurm_ctime(&check_time),
 			      job_ptr->job_id, mysql_conn->cluster_name);
 
 		global_last_rollup = check_time;
diff --git a/src/plugins/accounting_storage/mysql/as_mysql_rollup.c b/src/plugins/accounting_storage/mysql/as_mysql_rollup.c
index b05d7286266677594e6d0b03474ddfd29b41d9cd..cb45bf15d658e794b60340d85cdb15f6551be30a 100644
--- a/src/plugins/accounting_storage/mysql/as_mysql_rollup.c
+++ b/src/plugins/accounting_storage/mysql/as_mysql_rollup.c
@@ -263,8 +263,8 @@ static int _process_cluster_usage(mysql_conn_t *mysql_conn,
 	/*      c_usage->d_cpu + c_usage->a_cpu + */
 	/*      c_usage->r_cpu + c_usage->i_cpu, */
 	/*      c_usage->total_time, */
-	/*      ctime(&c_usage->start)); */
-	/* info("to %s", ctime(&c_usage->end)); */
+	/*      slurm_ctime(&c_usage->start)); */
+	/* info("to %s", slurm_ctime(&c_usage->end)); */
 	query = xstrdup_printf("insert into \"%s_%s\" "
 			       "(creation_time, "
 			       "mod_time, time_start, "
@@ -561,8 +561,8 @@ extern int as_mysql_hourly_rollup(mysql_conn_t *mysql_conn,
 		xstrfmtcat(resv_str, ", %s", resv_req_inx[i]);
 	}
 
-/* 	info("begin start %s", ctime(&curr_start)); */
-/* 	info("begin end %s", ctime(&curr_end)); */
+/* 	info("begin start %s", slurm_ctime(&curr_start)); */
+/* 	info("begin end %s", slurm_ctime(&curr_end)); */
 	a_itr = list_iterator_create(assoc_usage_list);
 	c_itr = list_iterator_create(cluster_down_list);
 	w_itr = list_iterator_create(wckey_usage_list);
@@ -580,8 +580,8 @@ extern int as_mysql_hourly_rollup(mysql_conn_t *mysql_conn,
 
 		debug3("%s curr hour is now %ld-%ld",
 		       cluster_name, curr_start, curr_end);
-/* 		info("start %s", ctime(&curr_start)); */
-/* 		info("end %s", ctime(&curr_end)); */
+/* 		info("start %s", slurm_ctime(&curr_start)); */
+/* 		info("end %s", slurm_ctime(&curr_end)); */
 
 		c_usage = _setup_cluster_usage(mysql_conn, cluster_name,
 					       curr_start, curr_end,
@@ -1133,8 +1133,8 @@ end_it:
 	list_destroy(wckey_usage_list);
 	list_destroy(resv_usage_list);
 
-/* 	info("stop start %s", ctime(&curr_start)); */
-/* 	info("stop end %s", ctime(&curr_end)); */
+/* 	info("stop start %s", slurm_ctime(&curr_start)); */
+/* 	info("stop end %s", slurm_ctime(&curr_end)); */
 
 	/* go check to see if we archive and purge */
 
@@ -1173,8 +1173,8 @@ extern int as_mysql_daily_rollup(mysql_conn_t *mysql_conn,
 
 	while (curr_start < end) {
 		debug3("curr day is now %ld-%ld", curr_start, curr_end);
-/* 		info("start %s", ctime(&curr_start)); */
-/* 		info("end %s", ctime(&curr_end)); */
+/* 		info("start %s", slurm_ctime(&curr_start)); */
+/* 		info("end %s", slurm_ctime(&curr_end)); */
 		query = xstrdup_printf(
 			"insert into \"%s_%s\" (creation_time, mod_time, "
 			"id_assoc, "
@@ -1262,8 +1262,8 @@ extern int as_mysql_daily_rollup(mysql_conn_t *mysql_conn,
 		curr_end = mktime(&start_tm);
 	}
 
-/* 	info("stop start %s", ctime(&curr_start)); */
-/* 	info("stop end %s", ctime(&curr_end)); */
+/* 	info("stop start %s", slurm_ctime(&curr_start)); */
+/* 	info("stop end %s", slurm_ctime(&curr_end)); */
 
 	/* go check to see if we archive and purge */
 	rc = _process_purge(mysql_conn, cluster_name, archive_data,
@@ -1298,8 +1298,8 @@ extern int as_mysql_monthly_rollup(mysql_conn_t *mysql_conn,
 
 	while (curr_start < end) {
 		debug3("curr month is now %ld-%ld", curr_start, curr_end);
-/* 		info("start %s", ctime(&curr_start)); */
-/* 		info("end %s", ctime(&curr_end)); */
+/* 		info("start %s", slurm_ctime(&curr_start)); */
+/* 		info("end %s", slurm_ctime(&curr_end)); */
 		query = xstrdup_printf(
 			"insert into \"%s_%s\" (creation_time, "
 			"mod_time, id_assoc, "
diff --git a/src/plugins/accounting_storage/mysql/as_mysql_usage.c b/src/plugins/accounting_storage/mysql/as_mysql_usage.c
index db60e22840401b30bb996d53b83d7140db18ed75..b43f15929f96b77d5b73c7df98c220c486c71b15 100644
--- a/src/plugins/accounting_storage/mysql/as_mysql_usage.c
+++ b/src/plugins/accounting_storage/mysql/as_mysql_usage.c
@@ -240,8 +240,8 @@ static void *_cluster_rollup_usage(void *arg)
 	end_tm.tm_isdst = -1;
 	hour_end = mktime(&end_tm);
 
-/* 	info("hour start %s", ctime(&hour_start)); */
-/* 	info("hour end %s", ctime(&hour_end)); */
+/* 	info("hour start %s", slurm_ctime(&hour_start)); */
+/* 	info("hour end %s", slurm_ctime(&hour_end)); */
 /* 	info("diff is %d", hour_end-hour_start); */
 
 	slurm_mutex_lock(&rollup_lock);
@@ -265,8 +265,8 @@ static void *_cluster_rollup_usage(void *arg)
 	end_tm.tm_isdst = -1;
 	day_end = mktime(&end_tm);
 
-/* 	info("day start %s", ctime(&day_start)); */
-/* 	info("day end %s", ctime(&day_end)); */
+/* 	info("day start %s", slurm_ctime(&day_start)); */
+/* 	info("day end %s", slurm_ctime(&day_end)); */
 /* 	info("diff is %d", day_end-day_start); */
 
 	/* set up the month period */
@@ -290,8 +290,8 @@ static void *_cluster_rollup_usage(void *arg)
 	end_tm.tm_isdst = -1;
 	month_end = mktime(&end_tm);
 
-/* 	info("month start %s", ctime(&month_start)); */
-/* 	info("month end %s", ctime(&month_end)); */
+/* 	info("month start %s", slurm_ctime(&month_start)); */
+/* 	info("month end %s", slurm_ctime(&month_end)); */
 /* 	info("diff is %d", month_end-month_start); */
 
 	if ((hour_end - hour_start) > 0) {
diff --git a/src/plugins/acct_gather_profile/hdf5/acct_gather_profile_hdf5.c b/src/plugins/acct_gather_profile/hdf5/acct_gather_profile_hdf5.c
index c780f2002fbda4da7cd7b2dcf8ce2dafd2b602ef..0994a1eb790fae952760412ac48916def98c8478 100644
--- a/src/plugins/acct_gather_profile/hdf5/acct_gather_profile_hdf5.c
+++ b/src/plugins/acct_gather_profile/hdf5/acct_gather_profile_hdf5.c
@@ -371,7 +371,8 @@ extern int acct_gather_profile_p_node_step_start(stepd_step_rec_t* job)
 	put_string_attribute(gid_node, ATTR_NODENAME, g_job->node_name);
 	put_int_attribute(gid_node, ATTR_NTASKS, g_job->node_tasks);
 	start_time = time(NULL);
-	put_string_attribute(gid_node, ATTR_STARTTIME, ctime(&start_time));
+	put_string_attribute(gid_node, ATTR_STARTTIME,
+			     slurm_ctime(&start_time));
 
 	return rc;
 }
diff --git a/src/plugins/auth/authd/auth_authd.c b/src/plugins/auth/authd/auth_authd.c
index e48a6a63ea1da86746bba9c114e897cb4b3d2f0b..e7bc31eee3f6d458429e9944d3171466d97d957a 100644
--- a/src/plugins/auth/authd/auth_authd.c
+++ b/src/plugins/auth/authd/auth_authd.c
@@ -345,8 +345,8 @@ slurm_auth_print( slurm_auth_credential_t *cred, FILE *fp )
 	verbose( "BEGIN AUTHD CREDENTIAL" );
 	verbose( "   UID: %u", cred->cred.uid );
 	verbose( "   GID: %u", cred->cred.gid );
-	verbose( "   Valid from: %s", ctime( &cred->cred.valid_from ) );
-	verbose( "   Valid to: %s", ctime( &cred->cred.valid_to ) );
+	verbose( "   Valid from: %s", slurm_ctime( &cred->cred.valid_from ) );
+	verbose( "   Valid to: %s", slurm_ctime( &cred->cred.valid_to ) );
 	verbose( "   Signature: 0x%02x%02x%02x%02x ...",
 			 cred->sig.data[ 0 ], cred->sig.data[ 1 ],
 			 cred->sig.data[ 2 ], cred->sig.data[ 3 ] );
diff --git a/src/plugins/auth/munge/auth_munge.c b/src/plugins/auth/munge/auth_munge.c
index c4589301ab6d06a51392660b580630a79d3f73ef..31caf831a4f896e62bd81dc5df4e3143ac5c51d1 100644
--- a/src/plugins/auth/munge/auth_munge.c
+++ b/src/plugins/auth/munge/auth_munge.c
@@ -640,10 +640,10 @@ _print_cred_info(munge_info_t *mi)
 	xassert(mi != NULL);
 
 	if (mi->encoded > 0)
-		info ("ENCODED: %s", ctime_r(&mi->encoded, buf));
+		info ("ENCODED: %s", slurm_ctime_r(&mi->encoded, buf));
 
 	if (mi->decoded > 0)
-		info ("DECODED: %s", ctime_r(&mi->decoded, buf));
+		info ("DECODED: %s", slurm_ctime_r(&mi->decoded, buf));
 }
 
 
diff --git a/src/sacct/options.c b/src/sacct/options.c
index 3af44fdb7d8120690aa4d24a3765f6f447f1d077..e9dad87771ad43737994d87bd01b171318df6c4d 100644
--- a/src/sacct/options.c
+++ b/src/sacct/options.c
@@ -927,20 +927,14 @@ void parse_command_line(int argc, char **argv)
 	}
 
 	if (verbosity > 0) {
-		char *start_char =NULL, *end_char = NULL;
-
-		start_char = xstrdup(ctime(&job_cond->usage_start));
-		/* remove the new line */
-		start_char[strlen(start_char)-1] = '\0';
-		if (job_cond->usage_end) {
-			end_char = xstrdup(ctime(&job_cond->usage_end));
-			/* remove the new line */
-			end_char[strlen(end_char)-1] = '\0';
-		} else
-			end_char = xstrdup("Now");
+		char start_char[25], end_char[25];
+
+		slurm_ctime_r(&job_cond->usage_start, start_char);
+		if (job_cond->usage_end)
+			slurm_ctime_r(&job_cond->usage_end, end_char);
+		else
+			sprintf(end_char, "Now");
 		info("Jobs eligible from %s - %s", start_char, end_char);
-		xfree(start_char);
-		xfree(end_char);
 	}
 
 	debug("Options selected:\n"
diff --git a/src/salloc/salloc.c b/src/salloc/salloc.c
index bf9e13bfb30b3fbc16c6fde948d6c8bab1cdb2b9..9d128c2f0a25347b683b92d1b640d5cb4deab855 100644
--- a/src/salloc/salloc.c
+++ b/src/salloc/salloc.c
@@ -915,7 +915,7 @@ static void _timeout_handler(srun_timeout_msg_t *msg)
 	if (msg->timeout != last_timeout) {
 		last_timeout = msg->timeout;
 		verbose("Job allocation time limit to be reached at %s",
-			ctime(&msg->timeout));
+			slurm_ctime(&msg->timeout));
 	}
 }
 
diff --git a/src/sbcast/sbcast.c b/src/sbcast/sbcast.c
index 027a2a58d51af3cdb0169825eb65ba095e2f78fd..74fa6e73d48e8f2ca8c7ecb2d8368b1f84730402 100644
--- a/src/sbcast/sbcast.c
+++ b/src/sbcast/sbcast.c
@@ -104,9 +104,9 @@ int main(int argc, char *argv[])
 	verbose("modes    = %o", (unsigned int) f_stat.st_mode);
 	verbose("uid      = %d", (int) f_stat.st_uid);
 	verbose("gid      = %d", (int) f_stat.st_gid);
-	verbose("atime    = %s", ctime(&f_stat.st_atime));
-	verbose("mtime    = %s", ctime(&f_stat.st_mtime));
-	verbose("ctime    = %s", ctime(&f_stat.st_ctime));
+	verbose("atime    = %s", slurm_ctime(&f_stat.st_atime));
+	verbose("mtime    = %s", slurm_ctime(&f_stat.st_mtime));
+	verbose("ctime    = %s", slurm_ctime(&f_stat.st_ctime));
 	verbose("size     = %ld", (long) f_stat.st_size);
 	verbose("-----------------------------");
 
diff --git a/src/scontrol/info_job.c b/src/scontrol/info_job.c
index 7aded4865611a8d1345977a7a157f109882f3659..7eaac2201e4f0f16e11c23b24f3869de223e509d 100644
--- a/src/scontrol/info_job.c
+++ b/src/scontrol/info_job.c
@@ -154,7 +154,7 @@ scontrol_pid_info(pid_t job_pid)
 			slurm_perror ("slurm_get_end_time error");
 		return;
 	}
-	printf("Slurm job id %u ends at %s\n", job_id, ctime(&end_time));
+	printf("Slurm job id %u ends at %s\n", job_id, slurm_ctime(&end_time));
 
 	rem_time = slurm_get_rem_time(job_id);
 	printf("slurm_get_rem_time is %ld\n", rem_time);
diff --git a/src/smap/opts.c b/src/smap/opts.c
index 5e0c37eaa68f40c193d5578619c3c0cd9ab56a3f..4b1bfb6713d2f0768503a79efd495fbf71232d04 100644
--- a/src/smap/opts.c
+++ b/src/smap/opts.c
@@ -191,7 +191,7 @@ extern void print_date(void)
 	} else {
 		mvwprintw(text_win, main_ycord,
 			  main_xcord, "%s",
-			  ctime(&now_time));
+			  slurm_ctime(&now_time));
 		main_ycord++;
 	}
 }
diff --git a/src/srun/libsrun/allocate.c b/src/srun/libsrun/allocate.c
index 4a353d24824c8e477ed5dc8b985849acdd88bf1b..82cff17d2b13dcafaa54ea34a54e3308f25d58f4 100644
--- a/src/srun/libsrun/allocate.c
+++ b/src/srun/libsrun/allocate.c
@@ -156,7 +156,7 @@ static void _timeout_handler(srun_timeout_msg_t *msg)
 	if (msg->timeout != last_timeout) {
 		last_timeout = msg->timeout;
 		verbose("job time limit to be reached at %s",
-			ctime(&msg->timeout));
+			slurm_ctime(&msg->timeout));
 	}
 }