Java如何 根据指定的时间段获取时间段内的所有年、季度、月、周。
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java如何 根据指定的时间段获取时间段内的所有年、季度、月、周。相关的知识,希望对你有一定的参考价值。
你的意思是给一个时间跨度好比2010/3/2-2015/05/06
然后输出 2010 2011 2012 2013 2014 2015 其他类似,是这个意思吗?
String format=new Format("yyyy"),format(new Data());
这样可以获得数字类型的年
Integer int =Integer.parsreInteger(format);
这样可以获得整形的年
之后就是进行循环读取即可。 参考技术A 不太明白意思。
周是指年的第几周吗。
季度是固定的判断。
年哪年就是哪年了。
请参考 java.util.Calendar本回答被提问者采纳 参考技术B 有一个类叫做Calendar
如何获取不在给定 IP 地址范围内的所有 IP 地址
【中文标题】如何获取不在给定 IP 地址范围内的所有 IP 地址【英文标题】:How to get all IP addresses that are not in a given range of IP addresses 【发布时间】:2018-10-08 01:16:51 【问题描述】:我需要能够输出不在给定 IP 地址范围列表中的所有 IP 地址范围。
有某种算法可以用于这种任务,我可以将其转换为工作代码?
基本上我将使用 Salesforce Apex 代码,因此如果给定示例可能,任何类似 JAVA 的语言都可以。【问题讨论】:
如何指定范围? X.X.X.X/Y? @DavidEisenstat - X.X.X.X 到 Y.Y.Y.Y @GoldenAxe 您的任务仅与 IPv4 有关吗? (意味着没有 IPv6 地址) 您要解决的更广泛的问题是什么?平台本身可能会根据您的尝试为您提供帮助。 有趣的问题 【参考方案1】:我认为一个简单解决方案的关键是记住 IP 地址可以被视为长类型的数字,因此可以对其进行排序。
我假设排除的范围以“很好”的方式给出,这意味着没有重叠,没有与全局范围的部分重叠等等。您当然可以稍后添加此类输入检查。
在本例中,我将所有网络范围(全局、包含、排除)作为 NetworkRange
类的实例。
以下是NetworkRange
的实现。注意splitByExcludedRange
和includes
这两个方法。
public class NetworkRange
private long startAddress;
private long endAddress;
public NetworkRange(String start, String end)
startAddress = addressRepresentationToAddress(start);
endAddress = addressRepresentationToAddress(end);
public NetworkRange(long start, long end)
startAddress = start;
endAddress = end;
public String getStartAddress()
return addressToAddressRepresentation(startAddress);
public String getEndAddress()
return addressToAddressRepresentation(endAddress);
static String addressToAddressRepresentation(long address)
String result = String.valueOf(address % 256);
for (int i = 1; i < 4; i++)
address = address / 256;
result = String.valueOf(address % 256) + "." + result;
return result;
static long addressRepresentationToAddress(String addressRep)
long result = 0L;
String[] tokens = addressRep.split("\\.");
for (int i = 0; i < 4; i++)
result += Math.pow(256, i) * Long.parseLong(tokens[3-i]);
return result;
public List<NetworkRange> splitByExcludedRange(NetworkRange excludedRange)
if (this.startAddress == excludedRange.startAddress && this.endAddress == excludedRange.endAddress)
return Arrays.asList();
if (this.startAddress == excludedRange.startAddress)
return Arrays.asList(new NetworkRange(excludedRange.endAddress+1, this.endAddress));
if (this.endAddress == excludedRange.endAddress)
return Arrays.asList(new NetworkRange(this.startAddress, excludedRange.startAddress-1));
return Arrays.asList(new NetworkRange(this.startAddress, excludedRange.startAddress-1),
new NetworkRange(excludedRange.endAddress+1, this.endAddress));
public boolean includes(NetworkRange excludedRange)
return this.startAddress <= excludedRange.startAddress && this.endAddress >= excludedRange.endAddress;
public String toString()
return "[" + getStartAddress() + "-" + getEndAddress() + "]";
现在是计算剩下的网络范围的类。它在构造函数中接受一个全局范围。
public class RangeProducer
private NetworkRange global;
public RangeProducer(NetworkRange global)
this.global = global;
public List<NetworkRange> computeEffectiveRanges(List<NetworkRange> excludedRanges)
List<NetworkRange> effectiveRanges = new ArrayList<>();
effectiveRanges.add(global);
List<NetworkRange> effectiveRangesSplitted = new ArrayList<>();
for (NetworkRange excludedRange : excludedRanges)
for (NetworkRange effectiveRange : effectiveRanges)
if (effectiveRange.includes(excludedRange))
effectiveRangesSplitted.addAll(effectiveRange.splitByExcludedRange(excludedRange));
else
effectiveRangesSplitted.add(effectiveRange);
effectiveRanges = effectiveRangesSplitted;
effectiveRangesSplitted = new ArrayList<>();
return effectiveRanges;
您可以运行以下示例:
public static void main(String[] args)
NetworkRange global = new NetworkRange("10.0.0.0", "10.255.255.255");
NetworkRange ex1 = new NetworkRange("10.0.0.0", "10.0.1.255");
NetworkRange ex2 = new NetworkRange("10.1.0.0", "10.1.1.255");
NetworkRange ex3 = new NetworkRange("10.6.1.0", "10.6.2.255");
List<NetworkRange> excluded = Arrays.asList(ex1, ex2, ex3);
RangeProducer producer = new RangeProducer(global);
for (NetworkRange effective : producer.computeEffectiveRanges(excluded))
System.out.println(effective);
输出应该是:
[10.0.2.0-10.0.255.255]
[10.1.2.0-10.6.0.255]
[10.6.3.0-10.255.255.255]
【讨论】:
【参考方案2】:首先,我假设您的意思是您获得一个或多个不相交的 CIDR 范围作为输入,并且需要生成所有 CIDR 范围的列表,其中不包括作为输入给出的任何 CIDR 范围。为方便起见,让我们进一步假设输入不包括整个 IP 地址空间:即0.0.0.0/0
。 (这可以通过一个特殊情况来解决,但没有太大意义。)
我以前写过类似的代码,虽然我不能随意分享代码,但我可以描述方法。它本质上是一种二分搜索算法,在该算法中,您重复地平分整个地址空间,直到您隔离出您感兴趣的一个范围。
将 IP 地址空间视为二叉树:根是完整的 IPv4 地址空间0.0.0.0/0
。它的子代分别代表地址空间的一半:0.0.0.0/1
和 128.0.0.0/1.
这些子代又可以细分为分别创建子代0.0.0.0/2
/ 64.0.0.0/2
和128.0.0.0/2
/ 192.0.0.0/2,
。一直继续下去,你会得到2**32
叶子,每个叶子代表一个/32
(即一个地址)。
现在,将这棵树视为从输入列表中排除的地址空间部分。所以你的任务是遍历这棵树,从树中的输入列表中找到每个范围,并剪掉你输入中树的所有部分,留下地址空间的剩余部分。
幸运的是,您实际上不需要创建所有 2**32
叶子。如果没有为其创建子节点,则可以假设 CIDR N
的每个节点包括 CIDR N+1
及以上的所有节点(您需要一个标志来记住它已经被细分 - ie 不再是一片叶子——原因见下文)。
因此,首先,整个地址空间都存在于树中,但都可以由单个叶节点表示。调用树excluded,
并用单个节点0.0.0.0/0.
初始化它
现在,考虑第一个输入范围——我们将其称为trial
(我将使用14.27.34.0/24
作为初始trial
值,只是为了提供一个具体的值用于演示)。任务是从excluded
中删除trial
,留下剩余的地址空间。
从 current
节点指针设置为 excluded
根节点开始。
开始:
将trial
CIDR 与current
进行比较。如果它是相同的,那么你就完成了(但如果你的输入范围不相交并且你已经从输入中排除了0.0.0.0/0
,这永远不会发生)。
否则,如果current
是一个叶子节点(还没有被细分,意味着它代表了这个CIDR级别及以下的整个地址空间),设置它的细分标志,并为其创建两个子节点:一个@ 987654347@ 指向其地址空间的前半部分,right
指向后半部分。适当地标记其中的每一个(对于根节点的子节点,将是0.0.0.0/1
和128.0.0.0/1
)。
确定trial
CIDR 是在current
的左侧还是右侧。对于我们最初的trial
值,它位于左侧。现在,如果那一侧的指针已经是NULL
,那么你就完成了(尽管如果你的输入范围不相交,那“不可能发生”)。
如果trial
CIDR 完全等同于该节点中的 CIDR,则只需释放该节点(以及它可能拥有的任何子节点,如果有,则应该没有只有不相交的输入),将指针设置到那一侧NULL
,你就完成了。您刚刚通过从树上剪下那片叶子来排除整个范围。
如果试验值与该侧节点中的CIDR不完全相等,则将current
设置为该侧并重新开始(即跳转到上面的开始标签)。
因此,初始输入范围为14.27.34.0/24
,您将首先将0.0.0.0/0
拆分为0.0.0.0/1
和128.0.0.0/1
。然后,您将在左侧下拉并将0.0.0.0/1
拆分为0.0.0.0/2
和64.0.0.0/2.
然后您将再次下拉到左侧以创建0.0.0.0/3
和32.0.0.0/3.
等等,直到经过23 次拆分,您然后将14.27.34.0/23
拆分为14.27.34.0/24
和14.27.35.0/24.
然后删除左侧的14.27.34.0/24
子节点并将其指针设置为NULL
,留下另一个。
这将为您留下一棵包含 24 个叶节点的稀疏树(在您删除目标节点之后)。剩下的叶子节点用*标记:
(ROOT)
0.0.0.0/0
/ \
0.0.0.0/1 128.0.0.0/1*
/ \
0.0.0.0/2 64.0.0.0/2*
/ \
0.0.0.0/3 32.0.0.0.0/3*
/ \
0.0.0.0/4 16.0.0.0/4*
/ \
*0.0.0.0/5 8.0.0.0/5
/ \
*8.0.0.0/6 12.0.0.0/6
/ \
*12.0.0.0/7 14.0.0.0/7
/ \
14.0.0.0/8 15.0.0.0/8*
/ \
...
/ \
*14.27.32.0/23 14.27.34.0/23
/ \
(null) 14.27.35.0/24*
(14.27.34.0/24)
对于每个剩余的输入范围,您将再次遍历树,必要时将叶节点一分为二,通常会产生更多叶,但总是会切掉地址空间的一部分。
最后,您只需按照方便的顺序遍历生成的树,收集剩余叶子的 CIDR。请注意,在此阶段您必须排除之前已细分的那些。例如,在上面的树中,如果您接下来处理输入范围14.27.35.0/24
,您将留下没有子级的14.27.34.0/23
,但它的两半都被分别切掉,不应包含在输出中。 (如果有一些额外的复杂情况,您当然也可以折叠其上方的节点以适应这种情况,但在每个节点中保留一个标志会更容易。)
【讨论】:
如前所述,格式为 X.X.X.X 到 Y.Y.Y.Y,您可以将其视为 IP 范围对象的列表,列表中的每个项目都包含 Start-IP 和 End-IP。我正在考虑按升序对列表进行排序,在其上循环,然后创建一个新列表,其范围介于两者之间。列表开头和列表结尾的特殊情况。这个解决方案有效吗? * 假设我们没有重叠。 此解决方案适用于任何组范围,因为任何范围都可以分解为有效 CIDR 格式范围的列表——尽管列表中的个别成员可能最终是/32(即单主机)。【参考方案3】:首先,您所描述的可以简化为:
您的区间格式为 x.x.x.x - y.y.y.y 您想要输出尚未在此范围内“采用”的间隔。 您希望能够有效地添加或删除间隔我建议使用interval tree,其中每个节点存储一个区间,您可以高效地插入和删除节点;并查询给定点(= IP 地址)的重叠。
如果您可以保证不会有重叠,您可以改用简单的TreeSet<String>
,但是您必须保证(为了正确排序)所有字符串都使用xxx.xxx.xxx.xxx-yyy.yyy.yyy.yyy
零填充格式。
一旦您的区间位于树中,您就可以生成所需的输出,假设没有区间重叠,方法是对树执行深度优先的前序遍历,并将每个访问节点的开始和结束存储在一个列表。鉴于此列表,
在开头预置 0.0.0.0 在末尾追加 255.255.255.255 删除所有重复的 ip(它们将在列表中强制相邻) 成对使用(数量始终为偶数),您就有了免费 IP 的间隔,完全排序。请注意,0.0.0.0 和 255.255.255.255 实际上不是有效的可路由 IP。如果你真的需要输出真实世界感知的 IP,你应该阅读相关的 RFC。
【讨论】:
以上是关于Java如何 根据指定的时间段获取时间段内的所有年、季度、月、周。的主要内容,如果未能解决你的问题,请参考以下文章