由读写arrow引发的对时间时区的思考

arrow是apache开发的一种高压缩的数据结构,发现用来存储K线还是很不错的选择。

测试用python读写很方便,关键是足够小,A股1支票1分钟的数据,1个月大约是140多K吧。

结果从数据库取出来存入arrow中,再用C++进行读取,发现总有8小时的时差问题,估计就是东八区的问题。

c++读取arrow数据,时间默认是按格林尼治时间来读取,然后存入进去的没有带时区信息,因此读,比如数据是2024年5月15日9点31分,存入应先将其转成格林时间,即减掉8小时,即2024年5月15日1点31分,然后再消除时区印迹(貌似有时间印记c++读取时会出错),这样C++那边读取的时间才能够和这里写入的时间对得上。

好,总结一下时间转换,df中的时间一般从数据库中读取或是csv中读取默认都没有时间印记,但因为我们是在中国,所有人都认为看到的时间为东八区,因此存入arrow前先做时区调整,将之本地化东八区,然后转成格林时间,再消除时间印记,存入arrow中,这样所有人从arrow中读取的时间都是格林时间,互相就对得上了。

demo示例:

读取csv数据,注意,由于已经解析了时间格式,因此不需要再额外进行时间转换:

df['time'] = pd.to_datetime(df['time'])  # 一般都是要做时间转换的,但这时已经通过parse_dates已经成功解析了时间成为了datetime64[ns]这样的类型
def read_csv(file_name):
    # 定义列名列表
    columns = ["time", "open"]
    data_types = {
        'open': 'float64'
    }
    # 读取 CSV 文件,指定列名
    df_read = pd.read_csv(file_name, names=columns, dtype=data_types, header=None, parse_dates=["time"])
    # 打印读取后的 DataF
<think>好的,我现在需要帮用户解决在WinCC中用VBS实现温度最大值监控的问题。首先,用户的需求是记录温度的最大值,如果在5分钟内这个最大值没有变化,就给出提示;当温度再次变化时,提示要消除。我得先理清楚实现这个功能的步骤和需要考虑的方面。 首先,我需要确定如何持续记录温度值,并跟踪最大值。可能需要使用一个全局变量来存储当前的最大值。然后,每次新的温度值进来时,比较是否超过当前最大值。如果超过,就更新最大值,并记录更新时间。如果没超过,就检查当前时间与最后一次更新时间时间差是否超过5分钟,如果是,则触发提示。 接下来,时间的处理是关键。WinCC的VBS中如何获取当前时间?应该使用Now函数来获取当前的时间戳。然后,需要将时间差转换为分钟,判断是否超过5分钟。这里需要注意的是,时间差的计算可能需要用到DateDiff函数,或者直接相减得到时间间隔的总分钟数。 另外,需要考虑存储上一次最大值的时间。可能需要另一个全局变量来保存这个时间戳。当最大值更新时,同时更新这个时间变量。当温度变化但未超过最大值时,检查时间差。 然后,关于提示的触发和消除。当满足5分钟未更新条件时,触发提示,比如设置一个布尔变量为True。而当温度值发生变化(即新的温度值小于当前最大值,但可能触发了其他变化),此时如果最大值被更新,则重置提示;或者当温度值变化导致最大值变化时,才消除提示。这里可能需要明确用户的需求,温度变化是否指任何温度变化,还是只有超过当前最大值的变化。根据用户描述,应该是当温度值有变化时消除提示,所以即使温度下降,只要温度值有变化,就应该消除之前的提示。不过这里可能需要更仔细的分析。 可能用户的意图是,当温度值发生变化(比如新的读数进来,不管是否超过最大值),如果这个变化导致最大值更新,则更新时间戳;否则,检查是否已经5分钟没有更新最大值,如果是则提示。而当有新的温度值进来时,无论是否超过最大值,只要温度值有变化,就消除之前的提示。不过这里可能存在矛盾,需要明确逻辑。 假设用户的意思是,只要温度值有变化(即每次新的采样值,无论高低),都检查是否超过当前最大值。如果超过,更新最大值和时间戳;否则,检查时间差是否超过5分钟,如果是,则提示。但提示一旦触发,只有当温度值再次变化(即新的采样值进来)并且导致最大值更新时,才会消除提示。或者,可能用户希望当温度值变化(无论是否更新最大值)时都消除提示,只有在连续5分钟没有新的最大值时才触发提示。 需要进一步理清逻辑。根据用户的问题描述:“当它的最大值在一定时间内,比如说5分钟没有变化,进行提示。温度值有变化时消除提示。” 这里的“最大值没有变化”指的是最大值这个变量没有改变,而“温度值有变化”可能指的是新的温度读数进来,无论是否改变了最大值。因此,正确的逻辑应该是: 1. 每次获取新的温度值,比较是否大于当前最大值: a. 如果大于,则更新当前最大值,并记录当前时间,同时清除提示。 b. 如果小于或等于,则检查当前时间与最后一次更新时间时间差是否超过5分钟。如果超过,则触发提示。 2. 当有新的温度值进来(无论是否改变最大值),只要温度值本身有变化,就清除之前的提示。但根据用户描述,“温度值有变化时消除提示”,可能需要更明确:是否只有当最大值被更新时才消除提示,还是任何温度变化都消除提示? 例如,如果温度值当前最大值是100,之后温度在5分钟内一直波动在90-99之间,那么最大值仍然是100,但每次新的温度值进来时,是否应该消除提示?根据用户描述,似乎是的。但这样的话,提示可能永远不会触发,因为只要温度在变化,即使没有超过最大值,也会消除提示。这可能需要用户澄清,但根据问题描述,可能的逻辑是: - 最大值在5分钟内未更新时触发提示。 - 当温度值变化(即新的温度读数进来)导致最大值更新时,清除提示。 - 如果温度值变化但未导致最大值更新,不清除提示,但需要检查是否已经超过5分钟未更新最大值,如果是则触发提示,否则继续等待。 但这样的话,提示可能不会自动清除,除非最大值被更新。但用户说“温度值有变化时消除提示”,这可能意味着只要温度值有变化,不管是否更新最大值,都清除提示。这可能需要进一步确认,但根据字面意思,可能用户希望当温度值变化时(即新的数据进来),如果此时最大值未变化,则开始计时,如果5分钟内最大值仍未变化,则提示。而一旦温度变化导致最大值更新,则重置计时器,并消除提示。 因此,正确的逻辑可能是: - 当新的温度值到达: 1. 如果新值 > 当前最大值: - 更新当前最大值为新值 - 记录当前时间为最后更新时间 - 清除提示(如果有) 2. 否则: - 检查当前时间与最后更新时间时间差是否≥5分钟 - 如果是,触发提示 - 否则,保持状态 3. 无论是否更新最大值,只要有新的温度值进来,都检查时间差,可能触发提示,但一旦最大值被更新,提示就会被清除。 但用户提到“温度值有变化时消除提示”,可能意味着只要温度值变化(即使未更新最大值),就消除之前的提示,然后重新开始计时。例如,温度最大值是100,之后温度变成95,虽然最大值没变,但温度值变化了,这时需要消除提示,并重新开始计时5分钟。这可能与之前的理解不同,需要明确。 这种情况下,逻辑可能需要调整为: - 每次温度值变化(新值进来): 1. 如果新值 > 当前最大值: - 更新最大值,记录时间,清除提示 2. 否则: - 清除之前的提示(如果有) - 检查是否自最后一次更新最大值已经超过5分钟: - 如果是,触发提示 - 否则,不触发 但这样逻辑有问题,因为当温度值变化但未超过最大值时,清除提示,但可能此时已经超过5分钟,导致提示被清除后又立即触发?这可能需要更仔细的处理。 可能用户的需求是:当温度的最大值在5分钟内没有更新(即没有新的最大值出现),则触发提示。而当任何温度变化发生(即新的温度值进来,无论是否超过最大值),如果这个变化导致最大值更新,则清除提示并重置计时器;如果未导致最大值更新,则检查计时器是否超过5分钟,超过则触发提示,否则继续等待。同时,如果温度值变化但未更新最大值,此时可能不需要清除提示,而是只有在最大值更新时才清除提示。 这里可能存在理解偏差,需要根据常见逻辑推测。通常,这种需求是当系统检测到最大值长时间没有刷新时报警,而最大值刷新是指有更高的温度出现。因此,正确的逻辑应该是: - 持续监控温度值,记录历史最大值。 - 当有更高的温度出现时,更新最大值,并记录更新时间。 - 如果从最后一次更新最大值开始,经过5分钟没有新的最大值出现,则触发提示。 - 当提示触发后,一旦有新的最大值出现,则清除提示。 但用户还提到“温度值有变化时消除提示”,这可能意味着即使温度变化但没有超过最大值,也要消除提示。这可能需要不同的处理方式,比如: - 提示一旦触发,只有当温度值发生变化(无论是否超过最大值)时,才消除提示,并重新开始计时。 这种情况下,逻辑会更复杂: - 当提示处于激活状态时,任何新的温度值(无论是否更新最大值)都会清除提示,并重新检查是否满足条件。 但这样可能导致提示频繁触发和清除,需要根据实际需求调整。 综合考虑,可能用户的需求是:当最大值在5分钟内没有更新时触发提示,而任何导致最大值更新的温度变化都会清除提示;同时,如果温度值变化但未更新最大值,则不影响提示状态,即提示一旦触发,会持续存在,直到最大值被更新。 但根据用户的原话:“温度值有变化时消除提示”,这可能意味着只要温度值有新的数据进来,不管是否更新最大值,都清除之前的提示,然后重新判断是否满足5分钟条件。例如,如果提示已经触发,当有新的温度值进来(即使未超过最大值),则清除提示,然后检查是否距离上次最大值更新已经超过5分钟,如果是,则再次触发提示;否则不触发。这种情况下,提示可能在清除后立即再次触发,如果时间差仍然超过5分钟。 这可能不符合实际需求,但需要按用户描述实现。因此,可能的逻辑是: 1. 定义两个全局变量:MaxTemperature(记录最大值)和LastUpdateTime(记录最后一次更新时间)。 2. 每次新的温度值到达时: a. 如果Temperature > MaxTemperature: - 更新MaxTemperature为Temperature - 更新LastUpdateTime为当前时间 - 清除提示(如果有) b. 否则: - 检查当前时间与LastUpdateTime的时间差是否≥5分钟: - 如果是,触发提示 - 否则,无操作 - 同时,无论是否触发提示,只要有温度变化,都清除之前的提示?这需要明确。 但用户说“温度值有变化时消除提示”,所以可能当温度值变化时,无论是否更新最大值,都先清除提示,然后判断是否需要触发新的提示。例如: 每次温度变化: 1. 清除提示 2. 如果新温度 > 当前最大值: - 更新最大值和时间为当前时间 3. 检查当前时间与最大值更新时间是否超过5分钟: - 如果是,触发提示 但这样的话,每次温度变化都会清除提示,但如果未更新最大值且时间超过5分钟,会立即重新触发提示,导致提示闪烁。可能用户希望的是,当温度变化但未更新最大值时,如果已经超过5分钟,则触发提示,否则不触发。而当温度变化导致最大值更新时,清除提示并更新时间。 可能的正确逻辑是: - 当温度值变化: a. 如果新值 > MaxTemperature: - 更新MaxTemperature和LastUpdateTime - 清除提示 b. 否则: - 计算当前时间与LastUpdateTime的时间差 - 如果时间差 ≥5分钟,触发提示 - 否则,无操作 c. 无论a或b,只要温度值变化,都检查时间差,决定是否触发提示 但此时,提示可能在温度变化但未更新最大值时触发,例如,当温度低于最大值但已经5分钟未更新,则触发提示。而当温度再次变化(即使未更新最大值),会再次检查,如果时间差仍然≥5分钟,则保持提示,否则清除。但用户说“温度值有变化时消除提示”,这可能意味着只要温度变化,无论是否满足时间条件,都清除之前的提示,然后重新评估是否应该触发。例如,每次温度变化都清除提示,然后如果此时时间差≥5分钟,则立即触发提示,否则不触发。这可能不符合实际需求,因为如果温度频繁变化但始终未超过最大值,提示会不断被清除和重新触发,导致闪烁。 因此,可能需要更精确的逻辑: - 提示一旦触发,会保持触发状态,直到温度值变化导致最大值更新,此时清除提示。或者,当温度变化时,无论是否更新最大值,都重新评估是否满足触发条件,如果满足则触发,否则不触发。 这可能需要使用一个标记来表示提示是否处于激活状态。例如: 变量: - MaxTemperature - LastUpdateTime - AlertActive (布尔型,表示提示是否激活) 流程: 每次温度变化: 1. 如果Temperature > MaxTemperature: - MaxTemperature = Temperature - LastUpdateTime = Now - AlertActive = False 2. 否则: - 计算时间差 = Now - LastUpdateTime - 如果时间差 >=5分钟: - AlertActive = True - 否则: - AlertActive = False 3. 根据AlertActive的状态,执行提示操作 但这样,当温度变化但未超过最大值时,如果时间差≥5分钟,则AlertActive变为True,否则为False。因此,提示会在满足条件时立即激活,否则不激活。这样,当温度变化时,会重新评估条件,可能导致提示状态变化。 这可能符合用户的需求:当最大值5分钟未更新,进行提示;温度变化时(即每次新的值进来),重新检查条件,更新提示状态。 因此,在WinCC中实现的话,需要: 1. 创建三个内部变量: - MaxTemperature (浮点数) - LastUpdateTime (日期时间) - TemperatureAlert (布尔型,用于触发提示) 2. 在VBS脚本中,编写以下逻辑(例如,在全局脚本中,根据数据变化触发): - 当温度值更新时,执行脚本: a. 获取当前温度值Temp b. 比较Temp与MaxTemperature c. 如果Temp > MaxTemperature: - 更新MaxTemperature为Temp - 更新LastUpdateTime为Now - 设置TemperatureAlert为False d. 否则: - 计算时间差:DateDiff("n", LastUpdateTime, Now) >=5 - 如果时间差>=5,设置TemperatureAlert为True - 否则,设置TemperatureAlert为False e. 根据TemperatureAlert的状态,控制提示(如显示消息、触发报警等) 但需要注意,WinCC中的VBS脚本可能需要通过触发器执行,比如在温度变量的属性中设置“数据更改”触发执行该脚本。 此外,还需要处理初始状态,比如MaxTemperature的初始值可能设为负无穷大,或者第一次读取温度值时的初始化。例如,在第一次运行时,MaxTemperature可能为当前温度,LastUpdateTime为当前时间。 另外,关于时间的处理,在VBS中,可以使用DateDiff函数来计算分钟差,例如: Dim diffMinutes diffMinutes = DateDiff("n", LastUpdateTime, Now) 如果diffMinutes >=5,则触发提示。 同时,需要考虑LastUpdateTime的初始值,可能需要初始化为一个很早的时间,或者在第一次温度值到来时进行初始化。 例如,在脚本中: If IsEmpty(MaxTemperature) Then MaxTemperature = Temp LastUpdateTime = Now End If 这样,当第一次执行时,会初始化MaxTemperature和LastUpdateTime。 另外,关于全局变量的存储,WinCC中可以使用内部变量(Tags),将MaxTemperature、LastUpdateTime和TemperatureAlert定义为内部变量,然后在VBS中通过HMIRuntime.Tags访问它们。 例如: Dim objTagTemp, objTagMax, objTagTime, objTagAlert Set objTagTemp = HMIRuntime.Tags("Temperature") ' 当前温度变量 Set objTagMax = HMIRuntime.Tags("MaxTemperature") Set objTagTime = HMIRuntime.Tags("LastUpdateTime") Set objTagAlert = HMIRuntime.Tags("TemperatureAlert") ' 读取当前温度值 objTagTemp.Read Dim currentTemp currentTemp = objTagTemp.Value ' 读取最大值和最后更新时间 objTagMax.Read Dim maxTemp maxTemp = objTagMax.Value objTagTime.Read Dim lastTime lastTime = objTagTime.Value ' 初始化处理 If IsEmpty(maxTemp) Then maxTemp = currentTemp lastTime = Now objTagMax.Write maxTemp objTagTime.Write lastTime End If If currentTemp > maxTemp Then ' 更新最大值和时间 maxTemp = currentTemp lastTime = Now objTagMax.Write maxTemp objTagTime.Write lastTime ' 清除提示 objTagAlert.Write False Else ' 计算时间差 Dim diffMinutes diffMinutes = DateDiff("n", lastTime, Now) If diffMinutes >=5 Then objTagAlert.Write True Else objTagAlert.Write False End If End If 但需要注意,WinCC的VBS脚本中,变量的读写可能需要处理数据类型和空值的情况。例如,初始时LastUpdateTime可能为空,需要初始化。 此外,还需要确保脚本的触发条件正确,比如当温度变量变化时执行该脚本。可以在温度变量的属性中设置“数据更改”时触发该脚本。 关于提示的方式,可以使用TemperatureAlert变量来控制,例如在画面中显示一个报警指示灯,或者触发消息框等。 最后,测试时需要考虑各种情况,比如温度持续低于最大值超过5分钟,是否触发提示;当温度更新最大值后,提示是否清除;以及脚本的执行频率是否足够等。 总结步骤: 1. 创建三个内部变量:MaxTemperature(浮点)、LastUpdateTime(日期时间)、TemperatureAlert(布尔)。 2. 编写VBS脚本,由温度变量变化触发。 3. 脚本逻辑:比较当前温度与最大值,更新或检查时间差,设置提示变量。 4. 在画面中使用提示变量显示报警状态。 可能还需要处理脚本的错误,比如变量未初始化,或者时间计算错误等。同时,确保WinCC的项目设置中,VBS脚本的权限和触发条件正确。</think>在WinCC中使用VBS实现温度最大值监控及超时提示功能,可按照以下步骤实现: ### 一、变量准备 1. 创建3个内部变量: - `TempValue`(浮点型):实时温度值(需与PLC采集的物理变量绑定) - `MaxTemp`(浮点型):记录历史最大值 - `LastUpdateTime`(时间型):记录最后更新时间 - `AlertActive`(布尔型):报警触发状态 ### 二、VBS脚本实现 ```vbscript Sub CheckMaxTemperature() Dim objTemp, objMax, objTime, objAlert Set objTemp = HMIRuntime.Tags("TempValue") Set objMax = HMIRuntime.Tags("MaxTemp") Set objTime = HMIRuntime.Tags("LastUpdateTime") Set objAlert = HMIRuntime.Tags("AlertActive") ' 读取当前温度值 objTemp.Read Dim currentTemp : currentTemp = objTemp.Value ' 初始化处理(首次运行) If IsEmpty(objMax.Value) Then objMax.Write currentTemp objTime.Write Now objAlert.Write False Exit Sub End If ' 主逻辑判断 If currentTemp > objMax.Value Then ' 更新最大值和时间戳 objMax.Write currentTemp objTime.Write Now objAlert.Write False ' 清除报警 Else ' 计算时间差(分钟) Dim diffMinutes : diffMinutes = DateDiff("n", objTime.Value, Now) If diffMinutes >= 5 Then objAlert.Write True ' 触发报警 Else objAlert.Write False ' 保持状态 End If End If End Sub ``` ### 三、脚本触发配置 1. **设置触发器**: - 在`TempValue`变量的属性中,勾选**数据更改**事件触发器 - 绑定到上述`CheckMaxTemperature`脚本 ### 四、报警提示实现 1. 在WinCC画面中添加以下组件: - **报警指示灯**:绑定到`AlertActive`变量 - **文本显示**:绑定`MaxTemp`和`LastUpdateTime`变量用于调试 ### 五、逻辑流程图解 $$ \begin{aligned} &\text{温度更新} \rightarrow \text{读取当前值} \\ &\downarrow \\ &\text{当前值 > 最大值?} \rightarrow \begin{cases} \text{是} & \rightarrow \text{更新最大值/时间,清除报警} \\ \text{否} & \rightarrow \text{检查时间差} \rightarrow \begin{cases} \geq5\text{分钟} & \rightarrow \text{触发报警} \\ <5\text{分钟} & \rightarrow \text{保持状态} \end{cases} \end{cases} \end{aligned} $$ ### 六、注意事项 1. **时间精度**:使用`DateDiff("n", ...)`计算分钟差,确保时区与系统一致 2. **变量初始化**:首次运行时自动将当前温度设为最大值 3. **报警复位**:当温度突破历史最大值时自动清除报警 4. **执行频率**:确保温度变量采集周期与脚本触发频率匹配 ### 七、扩展优化建议 1. 增加**手动复位按钮**:绑定`AlertActive.Write False` 2. 添加**报警延时**:通过`DateAdd("n",5,LastUpdateTime)`预计算超时时间 3. 记录**报警事件**:通过`HMIRuntime.Trace`写入报警日志 完整方案通过动态跟踪最大值和时间戳,实现了精确的5分钟无变化报警逻辑,满足工业场景下的稳定性要求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

永远的麦田

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值