Date 基于时间的增量日期
我需要根据时间将日期增加+1d。这似乎有点让我不知所措,但我怀疑它可以通过perl甚至awk来完成。对于每个带有0000的时间戳,我需要将天增加+1 输入:Date 基于时间的增量日期,date,awk,sed,Date,Awk,Sed,我需要根据时间将日期增加+1d。这似乎有点让我不知所措,但我怀疑它可以通过perl甚至awk来完成。对于每个带有0000的时间戳,我需要将天增加+1 输入: 15,07/31/2020 1600,1048,31,0 15,07/31/2020 1700,1086,45,0 15,07/31/2020 1800,1092,42,0 15,07/31/2020 1900,1017,20,1 15,07/31/2020 2000,945,0,28 15,07/31/2020 2100,897,0,43
15,07/31/2020 1600,1048,31,0
15,07/31/2020 1700,1086,45,0
15,07/31/2020 1800,1092,42,0
15,07/31/2020 1900,1017,20,1
15,07/31/2020 2000,945,0,28
15,07/31/2020 2100,897,0,43
15,07/31/2020 2200,869,0,55
15,07/31/2020 2300,812,0,72
15,07/31/2020 0000,778,0,82
预期产出:
15,07/31/2020 1600,1048,31,0
15,07/31/2020 1700,1086,45,0
15,07/31/2020 1800,1092,42,0
15,07/31/2020 1900,1017,20,1
15,07/31/2020 2000,945,0,28
15,07/31/2020 2100,897,0,43
15,07/31/2020 2200,869,0,55
15,07/31/2020 2300,812,0,72
15,08/01/2020 0000,778,0,82
看起来awk可以增加日期,但我的问题是,如何在不改变其余行的情况下,只增加0000行的日期?使用GNU awk:
awk '$5=="0000"{
# convert columns to unixtime
unixtime=mktime($4 " " $2 " " $3 " " "00 00 00")
# add one day to unixtime and convert back to month/day/year
nextday=strftime("%m/%d/%Y",unixtime+60*60*24)
# rebuild current row
$0=$1 OFS nextday " " $5 OFS $6 OFS $7 OFS $8
}
{print}' FS='[,/ ]' OFS=',' file
作为一行:
awk '$5=="0000"{unixtime=mktime($4 " " $2 " " $3 " " "00 00 00"); nextday=strftime("%m/%d/%Y",unixtime+60*60*24); print $1,nextday " " $5,$6,$7,$8; next}{print}' FS='[,/ ]' OFS=',' file
输出:
15,07/31/2020 1600,1048,31,0
15,07/31/2020 1700,1086,45,0
15,07/31/2020 1800,1092,42,0
15,07/31/2020 1900,1017,20,1
15,07/31/2020 2000,945,0,28
15,07/31/2020 2100,897,0,43
15,07/31/2020 2200,869,0,55
15,07/31/2020 2300,812,0,72
15,08/01/2020 0000,778,0,82
15,07/31/2020 1600,1048,31,0
15,07/31/2020 1700,1086,45,0
15,07/31/2020 1800,1092,42,0
15,07/31/2020 1900,1017,20,1
15,07/31/2020 2000,945,0,28
15,07/31/2020 2100,897,0,43
15,07/31/2020 2200,869,0,55
15,07/31/2020 2300,812,0,72
15,08/01/2020 0000,778,0,82
请参阅:此Perl解决方案使用Time::Piece(包含在标准发行版中) 注:这是我的第一条评论。因为这个问题已经重新打开,我可以在这里发布答案
为了增加日数,我们还需要在必要时滚动月数 为此,我们需要知道一个月的天数 要知道这一点,我们还需要知道当前年份是否为闰年(即二月有28天或29天)。该公式可通过网络搜索轻松获得 我不确定您输入的格式:
15,07/31/2020 0000,778,0,82
什么是15
?我想你只是通过了
什么是0000778,0,82
?我假设您可以将第一个数字[作为文本]与0000
进行比较
下面是
perl
中的代码。我编写了整个算法,不依赖于安装额外的perl软件包或使用函数,如mktime
,等等。我尝试尽可能多地对其进行注释:
#!/usr/bin/perl
# code to increment day
master(@ARGV);
exit(0);
sub master
{
my(@days_in_month) = (31,28,31,30,31,30,31,31,30,31,30,31);
# input format:
# 15,07/31/2020 0000,778,0,82
while ($buf = <STDIN>) {
chomp($buf);
# split off date and time
my($date,$time) = split(" ",$buf);
# split up date
my($pre,$mon,$day,$year) = split(m%[,/]%,$date);
# decide if current year is leap year
my($isleap) = 0;
{
# year must be divisible by 4
last if (($year % 4) != 0);
# if year is divisible by 100, it is _not_ a leap year unless ...
if (($year % 100) == 0) {
# ... it is also divisible by 400
last if (($year % 400) != 0);
}
$isleap = 1;
}
# get number of days in february
if ($isleap) {
$days_in_month[1] = 29;
}
else {
$days_in_month[1] = 28;
}
# change only if time is 0000
if ($time =~ /^0000,/) {
# increment day
$day += 1;
# advance month if necessary
if ($day > $days_in_month[$mon - 1]) {
$day = 1;
$mon += 1;
}
# advance year if necessary
if ($mon > 12) {
$mon = 1;
$year += 1;
}
}
$date = sprintf("%2.2d,%2.2d/%2.2d/%4.4d",$pre,$mon,$day,$year);
printf("%s %s\n",$date,$time);
}
}
#/usr/bin/perl
#代码到增量日
船长(@ARGV);
出口(0);
副船长
{
my(@days_in_month)=(31,28,31,30,31,30,31,31,30,31);
#输入格式:
# 15,07/31/2020 0000,778,0,82
而($buf=){
chomp($buf);
#分开日期和时间
我的($date,$time)=分割(“,$buf);
#分手日期
我的($pre,$mon,$day,$year)=分割(m%[,/]%,$date);
#决定当前年份是否为闰年
我的($isleap)=0;
{
#年份必须可以被4整除
如果($year%4)!=0,则为最后一次;
#如果一年可以被100整除,那就不是闰年,除非。。。
如果(($year%100)==0){
#…它也可以被400整除
如果($year%400)!=0,则为最后一次;
}
$isleap=1;
}
#获取二月的天数
如果($isleap){
$days_in_月[1]=29;
}
否则{
$days_in_月[1]=28;
}
#仅当时间为0000时更改
如果($time=~/^0000,/){
#增量日
$day+=1;
#如有必要,提前一个月
如果($day>$days\u in\u月[$mon-1]){
$day=1;
$mon+=1;
}
#如有必要,提前一年
如果($mon>12){
$mon=1;
$year+=1;
}
}
$date=sprintf(“%2.2d、%2.2d/%2.2d/%4.4d”、$pre、$mon、$day、$year);
printf(“%s%s\n”,$date,$time);
}
}
现在我正在与sed合作sed-i'/0000/s/07/08/g'file.csv>newfile.csv
这将查找字符串并替换月份。然而,我不确定如何让它动态检测日期并添加一天。我还研究了awk,它的挑战似乎是它不分青红皂白地影响所有日期。为了增加日期,您还需要在必要时滚动一个月。为此,您需要知道一个月的天数。要知道这一点,您还需要知道当前年份是否为闰年(即二月有28天或29天)。该公式可通过网络搜索轻松获得。我不确定您输入的格式:15,07/31/2020 0000778,0,82
什么是15
?我想你只是通过了。什么是0000778,0,82
?我假设您可以将第一个数字[作为文本]与0000
进行比较。请看:这非常有用,感谢您指出闰年警告。虽然我最终使用了下面较短的脚本,但由于布局良好的格式和清晰/有用的注释,我也将此脚本存档。我希望我也能给你一个答案。不管怎样,非常感谢你的帮助!!!不客气!正如我所提到的,我故意避免使用固定的助手函数来演示如何手动操作。特别是因为其他人正在使用它们。别担心。你应该[总是]接受最好的答案。但是,(如果你还没有这样做的话),你可以投多个好的答案。
15,07/31/2020 0000,778,0,82
#!/usr/bin/perl
# code to increment day
master(@ARGV);
exit(0);
sub master
{
my(@days_in_month) = (31,28,31,30,31,30,31,31,30,31,30,31);
# input format:
# 15,07/31/2020 0000,778,0,82
while ($buf = <STDIN>) {
chomp($buf);
# split off date and time
my($date,$time) = split(" ",$buf);
# split up date
my($pre,$mon,$day,$year) = split(m%[,/]%,$date);
# decide if current year is leap year
my($isleap) = 0;
{
# year must be divisible by 4
last if (($year % 4) != 0);
# if year is divisible by 100, it is _not_ a leap year unless ...
if (($year % 100) == 0) {
# ... it is also divisible by 400
last if (($year % 400) != 0);
}
$isleap = 1;
}
# get number of days in february
if ($isleap) {
$days_in_month[1] = 29;
}
else {
$days_in_month[1] = 28;
}
# change only if time is 0000
if ($time =~ /^0000,/) {
# increment day
$day += 1;
# advance month if necessary
if ($day > $days_in_month[$mon - 1]) {
$day = 1;
$mon += 1;
}
# advance year if necessary
if ($mon > 12) {
$mon = 1;
$year += 1;
}
}
$date = sprintf("%2.2d,%2.2d/%2.2d/%4.4d",$pre,$mon,$day,$year);
printf("%s %s\n",$date,$time);
}
}