您可以使用datenum 并输入您提供的示例中的确切日期格式字符串之一。如果您有半小时的时间间隔,那么连续的datenum 调用之间的差异应该产生相同的差异。例如,让我们将日期放入一个单元格数组中,如下所示:
C = {'1/01/2011 12:30 AM',
'1/01/2011 1:00 AM',
'1/01/2011 1:30 AM',
'1/01/2011 2:00 AM',
'1/01/2011 2:30 AM'};
我们可以使用diff 来计算连续元素之间的差异。 diff 是如何工作的,给定数组中的第 ith 个元素,在给定输入值 x_i 的情况下,y_i 处的向量的输出是:
y_i = x_{i+1} - x_i
因此,这将返回一个长度比原始向量小一的向量。我们基本上是在考虑从你们日期的第二个元素开始的元素。因此,将diff 应用于此元胞数组中的每个元素datenum,我们得到:
format long
diffs = diff(datenum(C))
diffs =
0.020833333255723
0.020833333372138
0.020833333372138
0.020833333255723
前 7 个有效数字左右很重要。其余的数字是由于一些精度差异造成的,但我们暂时搁置它。因此,您需要检查差异中的每个元素是否大约为0.0208333。如果不是,那么你错过了一个间隔。让我们试着捏造几次:
C = {'1/01/2011 12:30 AM',
'1/01/2011 1:30 AM',
'1/01/2011 2:30 AM',
'1/01/2011 3:00 AM',
'1/01/2011 4:30 AM'};
format long
diffs = diff(datenum(C))
diffs =
0.041666666627862
0.041666666627862
0.020833333372138
0.062500000000000
因此,对于C 的第二个、第三个和最后一个元素,我们缺少半小时间隔的测量值。具体来说,我假设您的单位是半小时。因此,缺失测量值之间的最小可能跳跃是一个小时,这是0.0208 和0.0416 之间的跳跃,所以这大约是0.02 的差异。因此,我们需要在这个数组中找到大于0.0416 的位置。为了安全起见,我们将其设置为0.03。因此,如果您想以编程方式执行此操作,您可以这样做:
diffs = diff(datenum(C));
locs = find(diffs > 0.03) + 1;
find 找出满足特定布尔条件的矩阵/数组中的位置。在这种情况下,我们希望找到差异为> 0.03 的位置。我们还抵消了1,因为我们正在查看我们之前讨论过的第二个元素。通过使用我们修改后的C 数组,我们得到:
locs =
2
3
5
这告诉我们,在我们修改后的日期数组 (C) 的位置 2、3 和 5 处,我们缺少半小时标记处的测量值。
为了仔细检查我们的第一个示例,如果我们在没有跳过的情况下将其应用于第一个示例,我们会按预期得到空数组:
locs =
[]
作为一个小奖励,我们可以显示在哪些位置缺少间隔。具体来说:
missingTimes = C(locs)
对于我们捏造的时间示例,我们得到:
missingTimes =
'1/01/2011 1:30 AM'
'1/01/2011 2:30 AM'
'1/01/2011 4:30 AM'
编辑
从我们在 cmets 回来的谈话中,只要你有一个没有时间和只有日期的约会,这就搞砸了。具体来说,当您调用 datenum 并在单元格数组中至少包含其中一个时,我们将不再获得浮点精度。我们只会得到整数(出于某种奇怪的原因......我不知道为什么。我可能应该为此发表一篇 StackOverflow 帖子)。换句话说,如果我们这样做了:
C = {'1/01/2011',
'1/01/2011 12:30 AM',
'1/01/2011 1:30 AM',
'1/01/2011 2:30 AM',
'1/01/2011 3:00 AM',
'1/01/2011 4:30 AM'};
如果我们这样做了:
diff(datenum(C))
我们得到:
ans =
0
0
0
0
0
为了解决这个问题,我必须实现我自己的diff 版本,并单独访问日期数组中的元素。因此,改为这样做:
format long;
diffs = arrayfun(@(x) datenum(C{x}) - datenum(C{x-1}), (2:numel(C)).');
我使用了arrayfun,并指定了一个输入数组,该数组的元素数从 2 到 C 中的元素数。对于我们输出中的每个元素,我们采用i+1th 元素的datenum 表示并从我们的ith 元素中减去它。这实质上是手动实现diff 操作,并在您包含一个没有时间的日期时避开这个小错误。老实说,我不知道为什么整数后的所有小数点都被删除了....但这暂时有效。
无论如何,我们得到:
diffs =
0.020833333372138
0.041666666627862
0.041666666627862
0.020833333372138
0.062500000000000
编辑#2
看来你还是遇到了麻烦。我会提出的另一个建议是找到那些缺少12:00 AM 时间戳的时间。然后我们会找到这些条目并手动放置12:00 AM 时间戳。因此,我们可以通过regexp 使用正则表达式来做到这一点。正则表达式尝试查找模式在字符串中出现的位置。因此,我们要做的是找到那些不在末尾包含时间戳的模式,然后使用一些额外的代码插入这个时间戳。让我们考虑一个玩具示例:
C = {'1/01/2011',
'1/01/2011 12:30 AM',
'1/01/2011 1:30 AM',
'1/01/2011 2:30 AM',
'1/01/2011 3:00 AM',
'1/01/2011 4:30 AM',
'1/02/2011',
'1/02/2011 12:30 AM',
'1/02/2011 1:30 AM',
'1/02/2011 2:30 AM',
'1/02/2011 3:00 AM',
'1/02/2011 4:30 AM',
'1/03/2011',
'1/03/2011 12:30 AM',
'1/03/2011 1:30 AM',
'1/03/2011 2:30 AM',
'1/03/2011 3:00 AM',
'1/03/2011 4:30 AM'};
这里有不同的日期和时间,有些缺少12:00 AM 时间戳。因此,这就是我将如何插入时间戳:
missingTimeStampsLocs = cellfun(@(x) isempty(regexp(x,'[0-9]{1,2}\/[0-9]{2}\/[0-9]{4} [0-9]{1,2}:[0-9]{2} [AaPp][Mm]')), C);
missingTimeStamps = C(missingTimeStampsLocs);
filledInTimeStamps = cellfun(@(x) [x ' 12:00 AM'], missingTimeStamps, 'uni', 0);
C(missingTimeStampsLocs) = filledInTimeStamps;
这看起来像是一段令人生畏的代码,但肯定可以解释。让我们从第一行代码开始。首先,我们调用regexp,它接收一个我们想要查看的字符串,然后第二个参数用于描述您正在寻找的pattern。我必须在这里做的是我要查找以下格式的所有日期:
#/##/#### ##:## xx
OR
##/##/#### ##:## xx
# 表示数字,x 表示字符。我们将搜索所有遵循这种exact格式的日期。我们将标记任何不遵循这种格式的日期,这意味着它们缺少时间戳。看看这句话:
regexp(x,'[0-9]{1,2}\/[0-9]{2}\/[0-9]{4} [0-9]{1,2}:[0-9]{2} [AaPp][Mm]')
这就是说,对于一个字符串x,我们将寻找一个以1或2个数字开头的字符串,然后是/,然后正好是2个数字,然后是@987654382 @,后跟正好 4 个数字,后跟一个空格,然后我们将查找 1 个或 2 个数字,然后是 :,然后正好是 2 个数字,后跟一个空格,然后是 AM 或 PM并且不区分大小写。这意味着AM 或PM 可以是大写或小写。
regexp 将返回的是您的字符串中找到此字符串的位置。在我们的例子中,它要么返回1,表示我们在它的开始处找到了这个字符串,要么返回empty,表示我们没有找到这样的字符串.如果regexp 返回空,则此日期缺少时间戳。这就是为什么我用isempty 包装这个调用来检查regexp 是否返回空。然后我使用cellfun 包装这个调用,以便我们可以迭代我们的日期单元格数组中的所有元素。输出(存储在missingTimeStampsLocs)将包含一个布尔数组,其中1 表示缺少时间戳,0 表示没有丢失。
下一行代码然后从原始元胞数组中提取那些缺少日期的日期。然后我再运行一次cellfun 来遍历这些单元格,然后我们将12:00 AM 时间戳连接到这个提取的单元格数组中每个字符串的末尾。请注意,我还指定了两个附加参数('uni' 和 0),因为输出不再是单个值,而是一个字符串。这些字符串将被放置在一个元胞数组中,这是完美的,因为它们无论如何都是从一个元胞数组中提取的。我们不必在第一个 cellfun 调用中指定它,因为输出是单个值 - 在这种情况下,它是 0 或 1 的布尔值。完成后,我们将那些缺少时间戳的日期替换为我们刚刚用12:00 AM 时间戳填写的日期。这将被覆盖到C。因此,通过使用我们的C 运行上述代码,我们得到了:
C =
'1/01/2011 12:00 AM'
'1/01/2011 12:30 AM'
'1/01/2011 1:30 AM'
'1/01/2011 2:30 AM'
'1/01/2011 3:00 AM'
'1/01/2011 4:30 AM'
'1/02/2011 12:00 AM'
'1/02/2011 12:30 AM'
'1/02/2011 1:30 AM'
'1/02/2011 2:30 AM'
'1/02/2011 3:00 AM'
'1/02/2011 4:30 AM'
'1/03/2011 12:00 AM'
'1/03/2011 12:30 AM'
'1/03/2011 1:30 AM'
'1/03/2011 2:30 AM'
'1/03/2011 3:00 AM'
'1/03/2011 4:30 AM'
然后我们可以通过我们的检测代码运行它,看看哪些日期跳跃了半小时。
diffs = diff(datenum(C));
locs = find(diffs > 0.03) + 1;
missingTimes = C(locs)
因此我们得到:
missingTimes =
'1/01/2011 1:30 AM'
'1/01/2011 2:30 AM'
'1/01/2011 4:30 AM'
'1/02/2011 12:00 AM'
'1/02/2011 1:30 AM'
'1/02/2011 2:30 AM'
'1/02/2011 4:30 AM'
'1/03/2011 12:00 AM'
'1/03/2011 1:30 AM'
'1/03/2011 2:30 AM'
'1/03/2011 4:30 AM'
我真的希望这是我最后一次解决这个问题 (LOL),因为我很确定我已经涵盖了所有意外情况。我还假设您的日期以特定方式格式化,我希望这能解决您的问题。我们也不需要使用我们编写的自定义 diff 函数,因为我现在正在完成您的日期以在其上添加 12:00 AM 时间戳。
祝你好运!