diff --git a/src/char/char.c b/src/char/char.c
index 20d457491..a905701ed 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -464,7 +464,7 @@ static int char_mmo_char_tosql(int char_id, struct mmo_charstatus *p)
 		(p->uniqueitem_counter != cp->uniqueitem_counter) || (p->hotkey_rowshift != cp->hotkey_rowshift) || (p->hotkey_rowshift2 != cp->hotkey_rowshift2) ||
 		(p->clan_id != cp->clan_id) || (p->last_login != cp->last_login) ||
 		(p->title_id != cp->title_id) || (p->inventorySize != cp->inventorySize) ||
-		(p->allow_call != cp->allow_call)
+		(p->allow_call != cp->allow_call) || (p->playtime != cp->playtime)
 	) {
 		//Save status
 		unsigned int opt = 0;
@@ -492,7 +492,7 @@ static int char_mmo_char_tosql(int char_id, struct mmo_charstatus *p)
 			"`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d', `rename`='%d',"
 			"`delete_date`='%lu',`robe`='%d',`slotchange`='%d', `char_opt`='%u', `font`='%u', `uniqueitem_counter` ='%u',"
 			"`hotkey_rowshift`='%d',`hotkey_rowshift2`='%d',`clan_id`='%d',`last_login`='%"PRId64"',"
-			"`title_id`='%d', `inventory_size`='%d'"
+			"`title_id`='%d', `inventory_size`='%d', `playtime`='%" PRIu64 "'"
 			" WHERE  `account_id`='%d' AND `char_id` = '%d'",
 			char_db, p->base_level, p->job_level,
 			p->base_exp, p->job_exp, p->zeny,
@@ -505,7 +505,7 @@ static int char_mmo_char_tosql(int char_id, struct mmo_charstatus *p)
 			(unsigned long)p->delete_date,  // FIXME: platform-dependent size
 			p->look.robe,p->slotchange,opt,p->font,p->uniqueitem_counter,
 			p->hotkey_rowshift, p->hotkey_rowshift2, p->clan_id, p->last_login,
-			p->title_id, p->inventorySize,
+			p->title_id, p->inventorySize, p->playtime,
 			p->account_id, p->char_id) )
 		{
 			Sql_ShowDebug(inter->sql_handle);
@@ -1095,7 +1095,7 @@ static int char_mmo_chars_fromsql(struct char_session_data *sd, uint8 *buf, int
 		"`str`,`agi`,`vit`,`int`,`dex`,`luk`,`max_hp`,`hp`,`max_sp`,`sp`,"
 		"`status_point`,`skill_point`,`option`,`karma`,`manner`,`hair`,`hair_color`,"
 		"`clothes_color`,`body`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`rename`,`delete_date`,"
-		"`robe`,`slotchange`,`unban_time`,`sex`,`title_id`,`inventory_size`"
+		"`robe`,`slotchange`,`unban_time`,`sex`,`title_id`,`inventory_size`,`playtime`"
 		" FROM `%s` WHERE `account_id`='%d' AND `char_num` < '%d'", char_db, sd->account_id, MAX_CHARS)
 	 || SQL_ERROR == SQL->StmtExecute(stmt)
 	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 0,  SQLDT_INT,    &p.char_id,          sizeof p.char_id,          NULL, NULL)
@@ -1140,6 +1140,8 @@ static int char_mmo_chars_fromsql(struct char_session_data *sd, uint8 *buf, int
 	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 39, SQLDT_ENUM,   &sex,                sizeof sex,                NULL, NULL)
 	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 40, SQLDT_INT,    &p.title_id,         sizeof p.title_id,         NULL, NULL)
 	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 41, SQLDT_INT,    &p.inventorySize,    sizeof p.inventorySize,    NULL, NULL)
+ 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 42, SQLDT_UINT,	 &p->playtime, 		  sizeof p.playtime, 		 NULL, NULL)
+
 	) {
 		SqlStmt_ShowDebug(stmt);
 		SQL->StmtFree(stmt);
@@ -1216,7 +1218,7 @@ static int char_mmo_char_fromsql(int char_id, struct mmo_charstatus *p, bool loa
 		"`hair_color`,`clothes_color`,`body`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`last_x`,`last_y`,"
 		"`save_map`,`save_x`,`save_y`,`partner_id`,`father`,`mother`,`child`,`fame`,`rename`,`delete_date`,`robe`,`slotchange`,"
 		"`char_opt`,`font`,`uniqueitem_counter`,`sex`,`hotkey_rowshift`,`hotkey_rowshift2`,`clan_id`,`last_login`,"
-		"`title_id`, `inventory_size`"
+		"`title_id`, `inventory_size`,`playtime`"
 		" FROM `%s` WHERE `char_id`=? LIMIT 1", char_db)
 	 || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, sizeof char_id)
 	 || SQL_ERROR == SQL->StmtExecute(stmt)
@@ -1284,6 +1286,8 @@ static int char_mmo_char_fromsql(int char_id, struct mmo_charstatus *p, bool loa
 	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 61, SQLDT_INT64,  &p->last_login,         sizeof p->last_login,         NULL, NULL)
 	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 62, SQLDT_INT,    &p->title_id,           sizeof p->title_id,           NULL, NULL)
 	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 63, SQLDT_INT,    &p->inventorySize,      sizeof p->inventorySize,      NULL, NULL)
+ 	 ||  SQL_ERROR == SqlStmt_BindColumn(stmt, 64, SQLDT_UINT,  &p->playtime, 			 sizeof p->playtime, 		   NULL, NULL)
+
 	) {
 		SqlStmt_ShowDebug(stmt);
 		SQL->StmtFree(stmt);
diff --git a/src/common/mmo.h b/src/common/mmo.h
index 1a2c3b31c..327e2eef5 100644
--- a/src/common/mmo.h
+++ b/src/common/mmo.h
@@ -804,6 +804,10 @@ struct mmo_charstatus {
 	int spear_faith, spear_calls;
 	int sword_faith, sword_calls;
 
+	// Playtime
+	int playtime;
+	int last_tick;
+
 	struct {
 		int weapon;      ///< Weapon view sprite id.
 		int shield;      ///< Shield view sprite id.
diff --git a/src/map/chrif.c b/src/map/chrif.c
index caebf6981..c97b96f83 100644
--- a/src/map/chrif.c
+++ b/src/map/chrif.c
@@ -270,6 +270,8 @@ static bool chrif_save(struct map_session_data *sd, int flag)
 	if (sd->vars_dirty)
 		intif->saveregistry(sd);
 
+	pc_calc_playtime(sd);
+
 	WFIFOHEAD(chrif->fd, sizeof(sd->status) + 13);
 	WFIFOW(chrif->fd,0) = 0x2b01;
 	WFIFOW(chrif->fd,2) = sizeof(sd->status) + 13;
diff --git a/src/map/pc.c b/src/map/pc.c
index f203d03cf..f0023c253 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -9143,6 +9143,28 @@ static void pc_hide(struct map_session_data *sd, bool show_msg)
 	clif->changeoption(&sd->bl);
 }
 
+/**
+ * Calculates the playtime of a character.
+ *
+ * @param sd The character to calculate the playtime.
+ *
+ **/
+void pc_calc_playtime(struct map_session_data* sd)
+{
+	if (!sd->state.autotrade && sd->state.active)
+	{
+		if (sd->status.last_tick == 0) {
+			sd->status.last_tick = sockt->last_tick;
+		}
+		else {
+			sd->status.playtime += DIFF_TICK(sockt->last_tick, sd->status.last_tick);
+			sd->status.last_tick = sockt->last_tick;
+		}
+	}
+
+	return;
+}
+
 /**
  * Unhides a character.
  *
@@ -13035,4 +13057,5 @@ void pc_defaults(void)
 	pc->auto_exp_insurance = pc_auto_exp_insurance;
 
 	pc->crimson_marker_clear = pc_crimson_marker_clear;
+	pc->calc_playtime = pc_calc_playtime;
 }
diff --git a/src/map/pc.h b/src/map/pc.h
index b842717fc..6804428e7 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -1283,6 +1283,7 @@ END_ZEROED_BLOCK; /* End */
 	bool (*auto_exp_insurance) (struct map_session_data *sd);
 
 	void (*crimson_marker_clear) (struct map_session_data *sd);
+	void (*calc_playtime) (struct map_session_data *sd);
 };
 
 #ifdef HERCULES_CORE
