Merge branch 'dev' of https://310.jisheyun.com/daizan/JiShe.CollectBus into dev
This commit is contained in:
commit
53fa6f503c
@ -250,7 +250,8 @@ namespace JiShe.CollectBus.Protocol.T37612012.SendData
|
|||||||
Pn = request.Pn,
|
Pn = request.Pn,
|
||||||
Fn = request.Fn
|
Fn = request.Fn
|
||||||
};
|
};
|
||||||
var bytes = Build3761SendData.BuildSendCommandBytes(reqParameter);
|
|
||||||
|
var bytes = Build3761SendData.BuildSendCommandBytes(reqParameter,request.DataUnit);
|
||||||
return new Telemetry3761PacketResponse() { Seq = reqParameter.Seq.PRSEQ, Data = bytes, MSA = reqParameter.MSA, };
|
return new Telemetry3761PacketResponse() { Seq = reqParameter.Seq.PRSEQ, Data = bytes, MSA = reqParameter.MSA, };
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@ -706,6 +706,36 @@ namespace JiShe.CollectBus.Protocol.T37612012
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static int CalculateFn(string dt1, string dt2) => dt2.HexToDec() * 8 + (8 - dt1.HexTo4BinZero().IndexOf("1"));
|
public static int CalculateFn(string dt1, string dt2) => dt2.HexToDec() * 8 + (8 - dt1.HexTo4BinZero().IndexOf("1"));
|
||||||
|
|
||||||
|
#region 下行
|
||||||
|
/// <summary>
|
||||||
|
/// 生成二类项采集项时间数据单元
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="timeMark"></param>
|
||||||
|
/// <param name="validLength"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual List<string> Generate_DataUnit(DataTimeMark timeMark)
|
||||||
|
{
|
||||||
|
List<string> values = new List<string>
|
||||||
|
{
|
||||||
|
SplitDataTime(timeMark.DataTime)//数据时间
|
||||||
|
};
|
||||||
|
if (timeMark.Density > 0)
|
||||||
|
values.Add(timeMark.Density.HexToDecStr().PadLeft(2, '0'));//密度
|
||||||
|
if (timeMark.Point > 0)
|
||||||
|
values.Add(timeMark.Point.HexToDecStr().PadLeft(2, '0'));//数据点数
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private string SplitDataTime(DateTime dataTime)
|
||||||
|
{
|
||||||
|
//2101060815
|
||||||
|
List<string> values = new List<string>() { $"{dataTime}:YY", $"{dataTime}:MM", $"{dataTime}:dd", $"{dataTime}:HH", $"{dataTime}:mm", };
|
||||||
|
|
||||||
|
values.Reverse();
|
||||||
|
return string.Join("", values);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region 上行命令
|
#region 上行命令
|
||||||
|
|||||||
@ -113,6 +113,11 @@ namespace JiShe.CollectBus.Protocol.T6452007
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aFNStr == "0D")//二类数据
|
||||||
|
{
|
||||||
|
dataUnit = Generate_DataUnit(request.DataTimeMark);
|
||||||
|
}
|
||||||
|
|
||||||
string afnMethonCode = $"AFN{aFNStr}_Fn_Send";
|
string afnMethonCode = $"AFN{aFNStr}_Fn_Send";
|
||||||
if (base.T3761AFNHandlers != null && base.T3761AFNHandlers.TryGetValue(afnMethonCode
|
if (base.T3761AFNHandlers != null && base.T3761AFNHandlers.TryGetValue(afnMethonCode
|
||||||
, out var handler))
|
, out var handler))
|
||||||
|
|||||||
29
protocols/JiShe.CollectBus.Protocol/Models/DataTimeMark.cs
Normal file
29
protocols/JiShe.CollectBus.Protocol/Models/DataTimeMark.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace JiShe.CollectBus.Protocol
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 数据时间标记
|
||||||
|
/// </summary>
|
||||||
|
public class DataTimeMark
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 数据时间
|
||||||
|
/// </summary>
|
||||||
|
public DateTime DataTime { get; set;}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据点数
|
||||||
|
/// </summary>
|
||||||
|
public int Point { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 冻结密度(-1、采集项本身无密度位,0、无,1、15分钟,2、30分钟,3、60分钟,245、5分钟,255、1分钟)
|
||||||
|
/// </summary>
|
||||||
|
public int Density { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,6 @@
|
|||||||
namespace JiShe.CollectBus.Protocol.Models
|
using JiShe.CollectBus.Common.BuildSendDatas;
|
||||||
|
|
||||||
|
namespace JiShe.CollectBus.Protocol.Models
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 报文构建参数
|
/// 报文构建参数
|
||||||
@ -21,9 +23,9 @@
|
|||||||
public required string ItemCode { get; set; }
|
public required string ItemCode { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 任务时间戳
|
/// 任务时间
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public long TimeStamp { get; set; }
|
public DataTimeMark DataTimeMark { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 集中器转发协议构建构建参数
|
/// 集中器转发协议构建构建参数
|
||||||
|
|||||||
@ -72,51 +72,77 @@ namespace JiShe.CollectBus.DataChannels
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task ScheduledMeterTaskReadding(ChannelReader<Tuple<string, List<MeterReadingTelemetryPacketInfo>>> _telemetryPacketInfoReader)
|
public async Task ScheduledMeterTaskReadding(ChannelReader<Tuple<string, List<MeterReadingTelemetryPacketInfo>>> _telemetryPacketInfoReader)
|
||||||
{
|
{
|
||||||
var metadata = await _dbProvider.GetMetadata<MeterReadingTelemetryPacketInfo>();
|
try
|
||||||
var batchSize = 10000;
|
|
||||||
var timeout = TimeSpan.FromSeconds(5); // 默认超时时间为5秒
|
|
||||||
|
|
||||||
List<MeterReadingTelemetryPacketInfo> taskInfoList = new List<MeterReadingTelemetryPacketInfo>();
|
|
||||||
var startTime = DateTime.Now;
|
|
||||||
var timer = new Stopwatch();
|
|
||||||
while (true)
|
|
||||||
{
|
{
|
||||||
var canRead = await _telemetryPacketInfoReader.WaitToReadAsync();
|
var metadata = await _dbProvider.GetMetadata<MeterReadingTelemetryPacketInfo>();
|
||||||
if (!canRead)
|
var batchSize = 200_00;
|
||||||
{
|
var timeout = TimeSpan.FromSeconds(5); // 默认超时时间为5秒
|
||||||
continue;
|
var timer = Stopwatch.StartNew();
|
||||||
}
|
long timeoutMilliseconds = 0;
|
||||||
|
|
||||||
while (taskInfoList != null && taskInfoList.Count < batchSize && (DateTime.Now - startTime) < timeout)
|
List<MeterReadingTelemetryPacketInfo> taskInfoList = new List<MeterReadingTelemetryPacketInfo>();
|
||||||
|
while (true)
|
||||||
{
|
{
|
||||||
if (_telemetryPacketInfoReader.TryRead(out var dataItem))
|
var canRead = _telemetryPacketInfoReader.Count;
|
||||||
|
if (canRead <= 0)
|
||||||
{
|
{
|
||||||
taskInfoList.AddRange(dataItem.Item2);
|
if (timeoutMilliseconds > 0)
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//无消息时短暂等待
|
|
||||||
await Task.Delay(5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (taskInfoList != null && taskInfoList.Count > 0)
|
|
||||||
{
|
|
||||||
await _dbProvider.BatchInsertAsync(metadata, taskInfoList);
|
|
||||||
|
|
||||||
await DeviceGroupBalanceControl.ProcessWithThrottleAsync<MeterReadingTelemetryPacketInfo>(
|
|
||||||
items: taskInfoList.ToList(),
|
|
||||||
deviceIdSelector: data => data.DeviceId,
|
|
||||||
processor: (data, groupIndex) =>
|
|
||||||
{
|
{
|
||||||
// _ = KafkaProducerIssuedMessageAction(dateItem.Item1, data, groupIndex);
|
_logger.LogError($"{nameof(ScheduledMeterTaskReadding)} 通道处理数据耗时{timeoutMilliseconds}毫秒");
|
||||||
}
|
}
|
||||||
);
|
timeoutMilliseconds = 0;
|
||||||
|
//无消息时短等待1秒
|
||||||
|
await Task.Delay(100_0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
timer.Restart();
|
||||||
|
|
||||||
taskInfoList.Clear();
|
var startTime = DateTime.Now;
|
||||||
|
string topicName = string.Empty;
|
||||||
|
|
||||||
|
while (taskInfoList != null && taskInfoList.Count < batchSize && (DateTime.Now - startTime) < timeout)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_telemetryPacketInfoReader.TryRead(out var dataItem))
|
||||||
|
{
|
||||||
|
topicName = dataItem.Item1;
|
||||||
|
taskInfoList.AddRange(dataItem.Item2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ee)
|
||||||
|
{
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (taskInfoList != null && taskInfoList.Count > 0)
|
||||||
|
{
|
||||||
|
await _dbProvider.BatchInsertAsync(metadata, taskInfoList);
|
||||||
|
|
||||||
|
await DeviceGroupBalanceControl.ProcessWithThrottleAsync<MeterReadingTelemetryPacketInfo>(
|
||||||
|
items: taskInfoList.ToList(),
|
||||||
|
deviceIdSelector: data => data.DeviceId,
|
||||||
|
processor: (data, groupIndex) =>
|
||||||
|
{
|
||||||
|
//_ = KafkaProducerIssuedMessageAction(dateItem.Item1, data, groupIndex);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
taskInfoList.Clear();
|
||||||
|
}
|
||||||
|
timer.Stop();
|
||||||
|
|
||||||
|
timeoutMilliseconds = timeoutMilliseconds + timer.ElapsedMilliseconds;
|
||||||
|
|
||||||
|
startTime = DateTime.Now;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
|
||||||
startTime = DateTime.Now;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -32,6 +32,7 @@ using static IdentityModel.ClaimComparer;
|
|||||||
using JiShe.CollectBus.DataChannels;
|
using JiShe.CollectBus.DataChannels;
|
||||||
using JiShe.CollectBus.DataMigration.Options;
|
using JiShe.CollectBus.DataMigration.Options;
|
||||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||||
|
using static System.Formats.Asn1.AsnWriter;
|
||||||
|
|
||||||
namespace JiShe.CollectBus.ScheduledMeterReading
|
namespace JiShe.CollectBus.ScheduledMeterReading
|
||||||
{
|
{
|
||||||
@ -169,7 +170,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading
|
|||||||
meterType: MeterTypeEnum.Ammeter,
|
meterType: MeterTypeEnum.Ammeter,
|
||||||
taskCreateAction: async (timeDensity, data, groupIndex, timestamps) =>
|
taskCreateAction: async (timeDensity, data, groupIndex, timestamps) =>
|
||||||
{
|
{
|
||||||
var tempTask = await ConcentratorScheduledAutomaticGetTerminalVersion(timeDensity, data, groupIndex, timestamps);
|
var tempTask = await ConcentratorScheduledAutomaticGetTerminalVersion(timeDensity, data, groupIndex, timestamps);
|
||||||
if (tempTask == null || tempTask.Count <= 0)
|
if (tempTask == null || tempTask.Count <= 0)
|
||||||
{
|
{
|
||||||
_logger.LogWarning($"集中器 {data.Name} 任务数据构建失败:{data.Serialize()}");
|
_logger.LogWarning($"集中器 {data.Name} 任务数据构建失败:{data.Serialize()}");
|
||||||
@ -257,7 +258,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading
|
|||||||
var tempTask = await AmmerterCreatePublishTaskAction(timeDensity, data, groupIndex, timestamps);
|
var tempTask = await AmmerterCreatePublishTaskAction(timeDensity, data, groupIndex, timestamps);
|
||||||
if (tempTask == null || tempTask.Count <= 0)
|
if (tempTask == null || tempTask.Count <= 0)
|
||||||
{
|
{
|
||||||
_logger.LogWarning($"电表 {data.Name} 任务数据构建失败:{data.Serialize()}");
|
//_logger.LogWarning($"电表 {data.Name} 任务数据构建失败:{data.Serialize()}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_ = _dataChannelManage.ScheduledMeterTaskWriter(DataChannelManage.TaskDataChannel.Writer, Tuple.Create(ProtocolConst.AmmeterSubscriberWorkerAutoValveControlIssuedEventName, tempTask));
|
_ = _dataChannelManage.ScheduledMeterTaskWriter(DataChannelManage.TaskDataChannel.Writer, Tuple.Create(ProtocolConst.AmmeterSubscriberWorkerAutoValveControlIssuedEventName, tempTask));
|
||||||
@ -298,7 +299,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading
|
|||||||
}
|
}
|
||||||
|
|
||||||
//电表定时阀控任务处理。
|
//电表定时阀控任务处理。
|
||||||
var autoValveControlTask = await AmmeterScheduledAutoValveControl();
|
var autoValveControlTask = await AmmeterScheduledAutoValveControl();
|
||||||
|
|
||||||
if (autoValveControlTask == null || autoValveControlTask.Count <= 0)
|
if (autoValveControlTask == null || autoValveControlTask.Count <= 0)
|
||||||
{
|
{
|
||||||
@ -332,9 +333,10 @@ namespace JiShe.CollectBus.ScheduledMeterReading
|
|||||||
//此处代码不要删除
|
//此处代码不要删除
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
var timeDensity = "15";
|
var timeDensity = "15";
|
||||||
var redisCacheMeterInfoHashKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoHashKey, SystemType, "JiSheCollectBus2", MeterTypeEnum.Ammeter, timeDensity)}";
|
var serverTagName = "JiSheCollectBus2";
|
||||||
var redisCacheMeterInfoSetIndexKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoSetIndexKey, SystemType, "JiSheCollectBus2", MeterTypeEnum.Ammeter, timeDensity)}";
|
var redisCacheMeterInfoHashKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoHashKey, SystemType, serverTagName, MeterTypeEnum.Ammeter, timeDensity)}";
|
||||||
var redisCacheMeterInfoZSetScoresIndexKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoZSetScoresIndexKey, SystemType, "JiSheCollectBus2", MeterTypeEnum.Ammeter, timeDensity)}";
|
var redisCacheMeterInfoSetIndexKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoSetIndexKey, SystemType, serverTagName, MeterTypeEnum.Ammeter, timeDensity)}";
|
||||||
|
var redisCacheMeterInfoZSetScoresIndexKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoZSetScoresIndexKey, SystemType, serverTagName, MeterTypeEnum.Ammeter, timeDensity)}";
|
||||||
|
|
||||||
List<AmmeterInfo> meterInfos = new List<AmmeterInfo>();
|
List<AmmeterInfo> meterInfos = new List<AmmeterInfo>();
|
||||||
List<string> focusAddressDataLista = new List<string>();
|
List<string> focusAddressDataLista = new List<string>();
|
||||||
@ -734,6 +736,12 @@ namespace JiShe.CollectBus.ScheduledMeterReading
|
|||||||
FocusAddress = ammeterInfo.FocusAddress,
|
FocusAddress = ammeterInfo.FocusAddress,
|
||||||
Pn = ammeterInfo.MeteringCode,
|
Pn = ammeterInfo.MeteringCode,
|
||||||
ItemCode = tempItem,
|
ItemCode = tempItem,
|
||||||
|
DataTimeMark = new Protocol.DataTimeMark()
|
||||||
|
{
|
||||||
|
Density = ammeterInfo.TimeDensity,//todo 转换成协议的值
|
||||||
|
Point = 1,
|
||||||
|
DataTime = timestamps,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
if (builderResponse == null || builderResponse.Data.Length <= 0)
|
if (builderResponse == null || builderResponse.Data.Length <= 0)
|
||||||
{
|
{
|
||||||
@ -1499,8 +1507,8 @@ namespace JiShe.CollectBus.ScheduledMeterReading
|
|||||||
List<T> meterInfos = new List<T>();
|
List<T> meterInfos = new List<T>();
|
||||||
decimal? cursor = null;
|
decimal? cursor = null;
|
||||||
string member = null;
|
string member = null;
|
||||||
bool hasNext;
|
|
||||||
do
|
while (true)
|
||||||
{
|
{
|
||||||
var page = await _redisDataCacheService.GetAllPagedData<T>(
|
var page = await _redisDataCacheService.GetAllPagedData<T>(
|
||||||
redisCacheMeterInfoHashKeyTemp,
|
redisCacheMeterInfoHashKeyTemp,
|
||||||
@ -1510,11 +1518,14 @@ namespace JiShe.CollectBus.ScheduledMeterReading
|
|||||||
lastMember: member);
|
lastMember: member);
|
||||||
|
|
||||||
meterInfos.AddRange(page.Items);
|
meterInfos.AddRange(page.Items);
|
||||||
cursor = page.HasNext ? page.NextScore : null;
|
if (!page.HasNext)
|
||||||
member = page.HasNext ? page.NextMember : null;
|
{
|
||||||
hasNext = page.HasNext;
|
break;
|
||||||
} while (hasNext);
|
}
|
||||||
|
|
||||||
|
cursor = page.NextScore;
|
||||||
|
member = page.NextMember;
|
||||||
|
}
|
||||||
|
|
||||||
//var page = await _redisDataCacheService.GetAllPagedData<T>(
|
//var page = await _redisDataCacheService.GetAllPagedData<T>(
|
||||||
// redisCacheMeterInfoHashKeyTemp,
|
// redisCacheMeterInfoHashKeyTemp,
|
||||||
@ -1530,8 +1541,12 @@ namespace JiShe.CollectBus.ScheduledMeterReading
|
|||||||
_logger.LogError($"{nameof(CreateMeterPublishTask)} {meterType}的{timeDensity}分钟采集待下发任务创建失败,没有获取到缓存信息,-105");
|
_logger.LogError($"{nameof(CreateMeterPublishTask)} {meterType}的{timeDensity}分钟采集待下发任务创建失败,没有获取到缓存信息,-105");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
timer.Stop();
|
||||||
|
|
||||||
_logger.LogError($"{nameof(CreateMeterPublishTask)} 构建采集待下发任务,缓存获取信息共花费{timer.ElapsedMilliseconds}毫秒");
|
_logger.LogError($"{nameof(CreateMeterPublishTask)} 构建采集待下发任务,缓存获取信息共花费{timer.ElapsedMilliseconds}毫秒");
|
||||||
|
|
||||||
|
timer.Restart();
|
||||||
|
|
||||||
await DeviceGroupBalanceControl.ProcessWithThrottleAsync(
|
await DeviceGroupBalanceControl.ProcessWithThrottleAsync(
|
||||||
items: meterInfos,
|
items: meterInfos,
|
||||||
deviceIdSelector: data => data.MeterId.ToString(),
|
deviceIdSelector: data => data.MeterId.ToString(),
|
||||||
|
|||||||
@ -166,7 +166,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading
|
|||||||
INNER JOIN TB_AmmeterInfo(nolock) AS C ON B.AmmeterID=C.ID
|
INNER JOIN TB_AmmeterInfo(nolock) AS C ON B.AmmeterID=C.ID
|
||||||
INNER JOIN TB_FocusInfo(nolock) AS D ON D.ID=C.FocusID
|
INNER JOIN TB_FocusInfo(nolock) AS D ON D.ID=C.FocusID
|
||||||
INNER JOIN TB_GatherInfo(NOLOCK) AS E ON E.ID=D.GatherInfoID
|
INNER JOIN TB_GatherInfo(NOLOCK) AS E ON E.ID=D.GatherInfoID
|
||||||
WHERE A.IsForbid=0 and A.State<>-1 and E.GatherCode LIKE '%V4%' and A.TripTime";
|
WHERE A.IsForbid=0 and A.State<>-1 and E.GatherCode LIKE '%V4%' ";
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(currentTime))
|
if (!string.IsNullOrWhiteSpace(currentTime))
|
||||||
{
|
{
|
||||||
|
|||||||
@ -204,6 +204,7 @@ namespace JiShe.CollectBus.Common.DeviceBalanceControl
|
|||||||
|
|
||||||
int actualThreads = maxConcurrency ?? recommendedThreads;
|
int actualThreads = maxConcurrency ?? recommendedThreads;
|
||||||
|
|
||||||
|
|
||||||
// 创建节流器
|
// 创建节流器
|
||||||
using var throttler = new SemaphoreSlim(initialCount: actualThreads);
|
using var throttler = new SemaphoreSlim(initialCount: actualThreads);
|
||||||
|
|
||||||
|
|||||||
@ -245,7 +245,7 @@ namespace JiShe.CollectBus.Common.Extensions
|
|||||||
/// <param name="dateLong"></param>
|
/// <param name="dateLong"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
/// <exception cref="ArgumentException"></exception>
|
/// <exception cref="ArgumentException"></exception>
|
||||||
public static DateTime ParseIntToDate(long dateLong)
|
public static DateTime ParseIntToDate(this long dateLong)
|
||||||
{
|
{
|
||||||
if (dateLong < 10000101 || dateLong > 99991231)
|
if (dateLong < 10000101 || dateLong > 99991231)
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user