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的实现。注意splitByExcludedRangeincludes这两个方法。

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/1128.0.0.0/1. 这些子代又可以细分为分别创建子代0.0.0.0/2 / 64.0.0.0/2128.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/1128.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/1128.0.0.0/1。然后,您将在左侧下拉并将0.0.0.0/1 拆分为0.0.0.0/264.0.0.0/2. 然后您将再次下拉到左侧以创建0.0.0.0/332.0.0.0/3. 等等,直到经过23 次拆分,您然后将14.27.34.0/23 拆分为14.27.34.0/2414.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&lt;String&gt;,但是您必须保证(为了正确排序)所有字符串都使用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如何 根据指定的时间段获取时间段内的所有年、季度、月、周。的主要内容,如果未能解决你的问题,请参考以下文章

java 根据文件获取文件名及路径的方法

当时间范围在两天之间时如何获取特定时间范围内的记录

Mongo 获取指定位置 10 英里内的所有文件

PHP:根据给定日期获取周内的所有日期

C语言:如何得到指定地址的文件夹中所有文件的文件名和其修改时间 包括子文件内的

java如何取得文件夹下所有的子目录