JSON / Highcharts 中的日期
Date in JSON / Highcharts
我在使用 JSON 对象和 Highcharts 插件的图形中绘制日期时间时遇到问题。
我的代码是有组织的:
我的服务器端尽快向我的客户端发送一个 JSON 对象:
[HttpGet]
public JsonResult DadosAtendimentosParticularesPorDentistas()
{
DateTime DataAtual = DateTime.Now;
DateTime InicioMes = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
var _listaProducao = _session.CreateSQLQuery("SELECT DATA_ATENDIMENTO, VALOR FROM T_LANCAMENTO_PRODUCAO_PARTICULAR " +
"WHERE DATA_ATENDIMENTO BETWEEN :INICIO AND :FIM")
.SetParameter("INICIO", InicioMes.AddMonths(-3))
.SetParameter("FIM", DataAtual)
.List();
return Json(_listaProducao, JsonRequestBehavior.AllowGet);
}
我的客户端收到一个 JSON 对象并进行以下处理:
<script type="text/javascript">
function producaoDentista(data) {
Highcharts.setOptions({
global: {
useUTC: false
}
});
$('#testegrafico').highcharts({
chart: {
type: 'spline'
},
title: {
text: 'Grafico de Faturamento',
x: -20
},
subtitle: {
text: 'Amostragem de Convenio e Particular',
x: -20
},
xAxis: {
type: "datetime",
categories: Date,
tickPixelInterval: 150,
maxZoom: 5,
dateTimeLabelFormats: {
month: '%b %e, %Y',
year: '%Y'
}
//dateTimeLabelFormats: {
// month: '%b %e, %Y',
// year: '%Y'
//}
},
yAxis: {
title: {
text: 'Valor em R$'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}],
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'middle',
borderWidth: 0
},
},
series: [{
name: 'Atendimento Particular',
data: data
//name: 'Atendimento Particular',
//data: data,
//tooltip: {
// pointFormat: 'R$:{point.y:.2f}',
//}
//}, {
// name: 'Atendimento Convênio',
// data: [2.0, 3.1, 10, 40.59, 100, 200, 500, 10, 500,11, 33]
,}]
});
}
$(document).ready(function () {
$.ajax({
url: 'GraficoAtendimento/DadosAtendimentosParticularesPorDentistas',
type: 'GET',
async: true,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
producaoDentista(data)
}
});
});
</script>
我的 JSON 由以下数据组成:
[["/日期(1418223600000)/",80],["/日期(1415631600000)/",10],["/日期(1415804400000)/",40],["/日期( 1420077600000)/",8],["/日期(1420164000000)/",10],["/日期(1420164000000)/",30],["/日期(1420164000000)/",140],["/日期(1420164000000)/",10],["/日期(1420423200000)/",560]]
图表上的日期显示如下:/Date(1418223600000)
如何解决这个问题?
创建适配器
public class JsonAdapter : JsonResult
{
/// <summary>
/// <para></para>
/// </summary>
private const string _dateFormat = "dd/MM/yyyy_HH:mm:ss";
/// <summary>
/// <para></para>
/// </summary>
/// <param name="context"></param>
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
HttpResponseBase response = context.HttpContext.Response;
if (!String.IsNullOrEmpty(ContentType))
{
response.ContentType = ContentType;
}
else
{
response.ContentType = "application/json";
}
if (ContentEncoding != null)
{
response.ContentEncoding = ContentEncoding;
}
if (Data != null)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new JavaScriptConverter[] { new DateTimeJavaScriptConverter() });
response.Write(serializer.Serialize(Data));
}
}
}
public class DateTimeJavaScriptConverter : JavaScriptConverter
{
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
return new JavaScriptSerializer().ConvertToType(dictionary, type);
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
if (!(obj is DateTime)) return null;
DateTime data = (DateTime)obj;
return new DateString(data == DateTime.MinValue || data == DateTime.MaxValue ? string.Empty : data.ToString("dd/MM/yyyy_HH:mm:ss"));
}
public override IEnumerable<Type> SupportedTypes
{
get { return new[] { typeof(DateTime) }; }
}
private class DateString : Uri, IDictionary<string, object>
{
public DateString(string str) : base(str, UriKind.Relative)
{
}
void IDictionary<string, object>.Add(string key, object value)
{
throw new NotImplementedException();
}
bool IDictionary<string, object>.ContainsKey(string key)
{
throw new NotImplementedException();
}
ICollection<string> IDictionary<string, object>.Keys
{
get { throw new NotImplementedException(); }
}
bool IDictionary<string, object>.Remove(string key)
{
throw new NotImplementedException();
}
bool IDictionary<string, object>.TryGetValue(string key, out object value)
{
throw new NotImplementedException();
}
ICollection<object> IDictionary<string, object>.Values
{
get { throw new NotImplementedException(); }
}
object IDictionary<string, object>.this[string key]
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
void ICollection<KeyValuePair<string, object>>.Add(KeyValuePair<string, object> item)
{
throw new NotImplementedException();
}
void ICollection<KeyValuePair<string, object>>.Clear()
{
throw new NotImplementedException();
}
bool ICollection<KeyValuePair<string, object>>.Contains(KeyValuePair<string, object> item)
{
throw new NotImplementedException();
}
void ICollection<KeyValuePair<string, object>>.CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
{
throw new NotImplementedException();
}
int ICollection<KeyValuePair<string, object>>.Count
{
get { throw new NotImplementedException(); }
}
bool ICollection<KeyValuePair<string, object>>.IsReadOnly
{
get { throw new NotImplementedException(); }
}
bool ICollection<KeyValuePair<string, object>>.Remove(KeyValuePair<string, object> item)
{
throw new NotImplementedException();
}
IEnumerator<KeyValuePair<string, object>> IEnumerable<KeyValuePair<string, object>>.GetEnumerator()
{
throw new NotImplementedException();
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
}
}
然后使用:
return JsonAdapter(_listaProducao, JsonRequestBehavior.AllowGet);
您的问题是 JSON 从 .NET 传输日期的格式不容易被 JavaScript 理解,需要将其转换为整数时间戳以便 HighCharts 使用它。
您可以在服务器端或客户端解决这个问题,但要在客户端这样做,您需要在将数据发送到 HighCharts 之前转换数据,或者为 HighCharts 提供格式函数来进行转换。
在绘制图表之前将数据转换为整数
在这里,您通过将 .NET 提供给您的所有日期字符串解析为时间戳整数来处理您的数据,然后再将其交给 HighCharts。这允许 HighCharts 使用时间戳来格式化。
$(document).ready(function () {
function parseJsonDateToTimeStamp(value) {
return parseInt(value.substr(6), 10); // The 6 is for trimming '/Date('
}
$.ajax({
url: 'GraficoAtendimento/DadosAtendimentosParticularesPorDentistas',
type: 'GET',
async: true,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
// Iterate data and convert all date strings to integers using
// the parseJsonDateToTimeStamp function above.
//
// Without knowing the JSON structure I cannot show code to do this, but it
// should be done before calling producaoDentista()
//
producaoDentista(data)
}
});
});
此函数修剪从 .NET 获取的字符串的第一部分,并将时间戳部分转换为整数以传递给 Date() 构造函数。您应该 运行 此函数针对 JSON 中的每个日期值,当您第一次收到它时,但在您将数据交给 HighCharts 进行渲染之前。
调整 HighCharts 配置以即时格式化
在这里,您修改 HighCharts 配置以在 xAxis 上为其提供格式化程序功能,该功能将在 运行 时间转换您的值。这是一个更简洁的解决方案,但您失去了使用 dateTimeLabelFormats
格式化日期的正常能力,必须手动使用 HighCharts.dataFormat()
。
$('#testegrafico').highcharts({
chart: {
type: 'spline'
},
title: {
text: 'Grafico de Faturamento',
x: -20
},
subtitle: {
text: 'Amostragem de Convenio e Particular',
x: -20
},
xAxis: {
type: "datetime",
categories: Date,
tickPixelInterval: 150,
maxZoom: 5,
labels: {
formatter: function() {
// Parse the date string to an integer and format it
return HighCharts.dateFormat('%b, %e, %Y', parseInt(this.value.substr(6), 10));
}
}
},
yAxis: {
title: {
text: 'Valor em R$'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}],
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'middle',
borderWidth: 0
},
},
series: [{
name: 'Atendimento Particular',
data: data
//name: 'Atendimento Particular',
//data: data,
//tooltip: {
// pointFormat: 'R$:{point.y:.2f}',
//}
//}, {
// name: 'Atendimento Convênio',
// data: [2.0, 3.1, 10, 40.59, 100, 200, 500, 10, 500,11, 33]
,}]
});
我在使用 JSON 对象和 Highcharts 插件的图形中绘制日期时间时遇到问题。
我的代码是有组织的:
我的服务器端尽快向我的客户端发送一个 JSON 对象:
[HttpGet]
public JsonResult DadosAtendimentosParticularesPorDentistas()
{
DateTime DataAtual = DateTime.Now;
DateTime InicioMes = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
var _listaProducao = _session.CreateSQLQuery("SELECT DATA_ATENDIMENTO, VALOR FROM T_LANCAMENTO_PRODUCAO_PARTICULAR " +
"WHERE DATA_ATENDIMENTO BETWEEN :INICIO AND :FIM")
.SetParameter("INICIO", InicioMes.AddMonths(-3))
.SetParameter("FIM", DataAtual)
.List();
return Json(_listaProducao, JsonRequestBehavior.AllowGet);
}
我的客户端收到一个 JSON 对象并进行以下处理:
<script type="text/javascript">
function producaoDentista(data) {
Highcharts.setOptions({
global: {
useUTC: false
}
});
$('#testegrafico').highcharts({
chart: {
type: 'spline'
},
title: {
text: 'Grafico de Faturamento',
x: -20
},
subtitle: {
text: 'Amostragem de Convenio e Particular',
x: -20
},
xAxis: {
type: "datetime",
categories: Date,
tickPixelInterval: 150,
maxZoom: 5,
dateTimeLabelFormats: {
month: '%b %e, %Y',
year: '%Y'
}
//dateTimeLabelFormats: {
// month: '%b %e, %Y',
// year: '%Y'
//}
},
yAxis: {
title: {
text: 'Valor em R$'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}],
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'middle',
borderWidth: 0
},
},
series: [{
name: 'Atendimento Particular',
data: data
//name: 'Atendimento Particular',
//data: data,
//tooltip: {
// pointFormat: 'R$:{point.y:.2f}',
//}
//}, {
// name: 'Atendimento Convênio',
// data: [2.0, 3.1, 10, 40.59, 100, 200, 500, 10, 500,11, 33]
,}]
});
}
$(document).ready(function () {
$.ajax({
url: 'GraficoAtendimento/DadosAtendimentosParticularesPorDentistas',
type: 'GET',
async: true,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
producaoDentista(data)
}
});
});
</script>
我的 JSON 由以下数据组成:
[["/日期(1418223600000)/",80],["/日期(1415631600000)/",10],["/日期(1415804400000)/",40],["/日期( 1420077600000)/",8],["/日期(1420164000000)/",10],["/日期(1420164000000)/",30],["/日期(1420164000000)/",140],["/日期(1420164000000)/",10],["/日期(1420423200000)/",560]]
图表上的日期显示如下:/Date(1418223600000)
如何解决这个问题?
创建适配器
public class JsonAdapter : JsonResult
{
/// <summary>
/// <para></para>
/// </summary>
private const string _dateFormat = "dd/MM/yyyy_HH:mm:ss";
/// <summary>
/// <para></para>
/// </summary>
/// <param name="context"></param>
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
HttpResponseBase response = context.HttpContext.Response;
if (!String.IsNullOrEmpty(ContentType))
{
response.ContentType = ContentType;
}
else
{
response.ContentType = "application/json";
}
if (ContentEncoding != null)
{
response.ContentEncoding = ContentEncoding;
}
if (Data != null)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new JavaScriptConverter[] { new DateTimeJavaScriptConverter() });
response.Write(serializer.Serialize(Data));
}
}
}
public class DateTimeJavaScriptConverter : JavaScriptConverter
{
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
return new JavaScriptSerializer().ConvertToType(dictionary, type);
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
if (!(obj is DateTime)) return null;
DateTime data = (DateTime)obj;
return new DateString(data == DateTime.MinValue || data == DateTime.MaxValue ? string.Empty : data.ToString("dd/MM/yyyy_HH:mm:ss"));
}
public override IEnumerable<Type> SupportedTypes
{
get { return new[] { typeof(DateTime) }; }
}
private class DateString : Uri, IDictionary<string, object>
{
public DateString(string str) : base(str, UriKind.Relative)
{
}
void IDictionary<string, object>.Add(string key, object value)
{
throw new NotImplementedException();
}
bool IDictionary<string, object>.ContainsKey(string key)
{
throw new NotImplementedException();
}
ICollection<string> IDictionary<string, object>.Keys
{
get { throw new NotImplementedException(); }
}
bool IDictionary<string, object>.Remove(string key)
{
throw new NotImplementedException();
}
bool IDictionary<string, object>.TryGetValue(string key, out object value)
{
throw new NotImplementedException();
}
ICollection<object> IDictionary<string, object>.Values
{
get { throw new NotImplementedException(); }
}
object IDictionary<string, object>.this[string key]
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
void ICollection<KeyValuePair<string, object>>.Add(KeyValuePair<string, object> item)
{
throw new NotImplementedException();
}
void ICollection<KeyValuePair<string, object>>.Clear()
{
throw new NotImplementedException();
}
bool ICollection<KeyValuePair<string, object>>.Contains(KeyValuePair<string, object> item)
{
throw new NotImplementedException();
}
void ICollection<KeyValuePair<string, object>>.CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
{
throw new NotImplementedException();
}
int ICollection<KeyValuePair<string, object>>.Count
{
get { throw new NotImplementedException(); }
}
bool ICollection<KeyValuePair<string, object>>.IsReadOnly
{
get { throw new NotImplementedException(); }
}
bool ICollection<KeyValuePair<string, object>>.Remove(KeyValuePair<string, object> item)
{
throw new NotImplementedException();
}
IEnumerator<KeyValuePair<string, object>> IEnumerable<KeyValuePair<string, object>>.GetEnumerator()
{
throw new NotImplementedException();
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
}
}
然后使用:
return JsonAdapter(_listaProducao, JsonRequestBehavior.AllowGet);
您的问题是 JSON 从 .NET 传输日期的格式不容易被 JavaScript 理解,需要将其转换为整数时间戳以便 HighCharts 使用它。 您可以在服务器端或客户端解决这个问题,但要在客户端这样做,您需要在将数据发送到 HighCharts 之前转换数据,或者为 HighCharts 提供格式函数来进行转换。
在绘制图表之前将数据转换为整数
在这里,您通过将 .NET 提供给您的所有日期字符串解析为时间戳整数来处理您的数据,然后再将其交给 HighCharts。这允许 HighCharts 使用时间戳来格式化。
$(document).ready(function () {
function parseJsonDateToTimeStamp(value) {
return parseInt(value.substr(6), 10); // The 6 is for trimming '/Date('
}
$.ajax({
url: 'GraficoAtendimento/DadosAtendimentosParticularesPorDentistas',
type: 'GET',
async: true,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
// Iterate data and convert all date strings to integers using
// the parseJsonDateToTimeStamp function above.
//
// Without knowing the JSON structure I cannot show code to do this, but it
// should be done before calling producaoDentista()
//
producaoDentista(data)
}
});
});
此函数修剪从 .NET 获取的字符串的第一部分,并将时间戳部分转换为整数以传递给 Date() 构造函数。您应该 运行 此函数针对 JSON 中的每个日期值,当您第一次收到它时,但在您将数据交给 HighCharts 进行渲染之前。
调整 HighCharts 配置以即时格式化
在这里,您修改 HighCharts 配置以在 xAxis 上为其提供格式化程序功能,该功能将在 运行 时间转换您的值。这是一个更简洁的解决方案,但您失去了使用 dateTimeLabelFormats
格式化日期的正常能力,必须手动使用 HighCharts.dataFormat()
。
$('#testegrafico').highcharts({
chart: {
type: 'spline'
},
title: {
text: 'Grafico de Faturamento',
x: -20
},
subtitle: {
text: 'Amostragem de Convenio e Particular',
x: -20
},
xAxis: {
type: "datetime",
categories: Date,
tickPixelInterval: 150,
maxZoom: 5,
labels: {
formatter: function() {
// Parse the date string to an integer and format it
return HighCharts.dateFormat('%b, %e, %Y', parseInt(this.value.substr(6), 10));
}
}
},
yAxis: {
title: {
text: 'Valor em R$'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}],
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'middle',
borderWidth: 0
},
},
series: [{
name: 'Atendimento Particular',
data: data
//name: 'Atendimento Particular',
//data: data,
//tooltip: {
// pointFormat: 'R$:{point.y:.2f}',
//}
//}, {
// name: 'Atendimento Convênio',
// data: [2.0, 3.1, 10, 40.59, 100, 200, 500, 10, 500,11, 33]
,}]
});