草庐IT

java - 如何将 Julian Day Numbers 与 Java Calendar API 一起使用?

coder 2024-03-21 原文

儒略日数是一种将时间戳记表示为自公元前 4713 年 1 月 1 日中午 UTC 以来的连续天数(和小数天数)的一种方式。 Java 7 SE API 不包含对这种格式的支持。使用过 SQLite 数据库的开发人员可能已经使用过 strftime() 函数提供的 native 儒略日支持。

将时间戳表示为儒略日数的优点包括:

  • 日期和时间可以用原始数据类型( double )表示为毫秒精度
  • 一年中的几天比一天中的几秒钟更具体
  • 如果这种精度不重要,则可以避免“闰秒”的问题
  • 计算日期之间的天数是微不足道的;排序优先级很容易确定
  • 非常轻便

缺点

  • Java 日期/时间 API 没有对 JDN 的内置支持
  • 不适合非常精确的时间测量
  • 仅为 UTC 定义并且必须从 UTC 映射到本地时间
  • 不适合向最终用户展示;必须在显示前转换/格式化

儒略日数常用于天文计算,其定义已高度标准化并广为接受。同样,修改后的儒略日数字(从 1858 年 11 月 17 日午夜 UTC 开始计算)在航空航天应用中被标准定义和使用(参见 http://tycho.usno.navy.mil/mjd.html )。

对于广泛使用日期/时间算术或时间排序的应用程序(或者如果持久化轻量级原语比持久化时间戳更有吸引力),在内部将日期和时间表示为 JDN 或 MJD 可能对您有意义。

以下代码定义的函数有助于将 Julian Day Numbers 或 Modified Julian Day Numbers 与 Java Date/Time/Calendar API 结合使用。该代码基于 Jean Meeus 的“天文算法”,第 1 版,1991 年发表的算法。

public class JulianDay {

    private static final int YEAR = 0;
    private static final int MONTH = 1;
    private static final int DAY = 2;
    private static final int HOURS = 3;
    private static final int MINUTES = 4;
    private static final int SECONDS = 5;
    private static final int MILLIS = 6;

    :
    :

    // Converts a timestamp presented as an array of integers in the following
    // order (from index 0 to 6): year,month,day,hours,minutes,seconds,millis
    // month (1-12), day (1-28 or 29), hours (0-23), min/sec (0-59) to a
    // Modified Julian Day Number.
    // For clarity and simplicity, the input values are assumed to be well-formed;
    // error checking is not implemented in the snippet.

    public static double toMJD(int[] ymd_hms) {

        int y = ymd_hms[YEAR];
        int m = ymd_hms[MONTH];
        double d = (double) ymd_hms[DAY];

        d = d + ((ymd_hms[HOURS] / 24.0) +
                 (ymd_hms[MINUTES] / 1440.0) +
                 (ymd_hms[SECONDS] / 86400.0) +
                 (ymd_hms[MILLIS] / 86400000.0));

        if (m == 1 || m == 2) {
            y--;
            m = m + 12;
        }

        double a = Math.floor(y / 100);
        double b = 2 - a + Math.floor(a / 4);

        return (Math.floor(365.25 * (y + 4716.0)) +
               Math.floor(30.6001 * (m + 1)) +
               d + b - 1524.5) - 2400000.5;  // for Julian Day omit the 2400000.5 term
    }

    // Converts an Modified Julian Day Number (double) to an integer array representing
    // a timestamp (year,month,day,hours,mins,secs,millis). Works for all positive JDN

    public static int[] toTimestamp(double mjd) {

        int ymd_hms[] = { -1, -1, -1, -1, -1, -1, -1 };
        int a, b, c, d, e, z;

        double jd = mjd + 2400000.5 + 0.5;  // if a JDN is passed as argument,
                                            // omit the 2400000.5 term
        double f, x;

        z = (int) Math.floor(jd);
        f = jd - z;

        if (z >= 2299161) {
            int alpha = (int) Math.floor((z - 1867216.25) / 36524.25);
            a = z + 1 + alpha - (int) Math.floor(alpha / 4);
        } else {
            a = z;
        }

        b = a + 1524;
        c = (int) Math.floor((b - 122.1) / 365.25);
        d = (int) Math.floor(365.25 * c);
        e = (int) Math.floor((b - d) / 30.6001);

        ymd_hms[DAY] = b - d - (int) Math.floor(30.6001 * e);
        ymd_hms[MONTH] = (e < 14)
                ? (e - 1)
                : (e - 13);
        ymd_hms[YEAR] = (ymd_hms[MONTH] > 2)
                ? (c - 4716)
                : (c - 4715);

        for (int i = HOURS; i <= MILLIS; i++) {
            switch(i) {
                case HOURS:
                    f = f * 24.0;
                    break;
                case MINUTES: case SECONDS:
                    f = f * 60.0;
                    break;
                case MILLIS:
                    f = f * 1000.0;
                    break;  
            }
            x = Math.floor(f);
            ymd_hms[i] = (int) x;
            f = f - x;
        }   

        return ymd_hms;
    }
}

这里也提供了这个答案:How can I convert between a Java Date and Julian day number? .在当前帖子中,提供了该算法的引用资料以及更多讨论。上述算法的实现也不包含任何 Java API 依赖项(数学函数除外)。

最佳答案

java.time

Java 8 和更高版本中内置的 java.time 框架取代了与最早版本的 Java 捆绑在一起的旧日期时间类。参见 Oracle Tutorial .许多功能已在 ThreeTen-Backport 中反向移植到 Java 6 和 7并在 ThreeTenABP 中进一步适配 Android .

java.time 类包括 java.time.temporal.JulianFields .此类提供了三种实现 TemporalField为仅 Julian 日期值(无时间)提供有限支持。所以你可以获得整数天数,而不是问题中请求的 double 。仔细阅读该类文档以确保它符合您的期望。请注意,与大多数其他 java.time 类不同,这些 Julian 类忽略任何与 UTC 的偏移量或时区信息(始终被视为本地日期)。

  • JULIAN_DAY → 自第 0 天以来的所有天数,即儒略历公元前 4713 年 1 月 1 日 (-4713-11-24 Gregorian)。
  • MODIFIED_JULIAN_DAY → 与 JULIAN_DAY 类似,但减去 2_400_000.5(基本上删除 Julian 日期数字的前两位)。请注意,此处的结果比上述项目的儒略日期数少一 (-1)
  • RATA_DIE → 与上面两项类似,它是从一个纪元开始的天数。但这里的纪元是 ISO 8601 0001-01-01 的日期。

在此示例中,我们从 1970-01-01 的 ISO 8601 日期开始。

LocalDate localDate = LocalDate.of ( 1970 , 1 , 1 );
long julianDate = JulianFields.JULIAN_DAY.getFrom ( localDate );
long modifiedJulianDate = JulianFields.MODIFIED_JULIAN_DAY.getFrom ( localDate );
long rataDie = JulianFields.RATA_DIE.getFrom ( localDate );

localDate: 1970-01-01 | julianDate: 2440588 | modifiedJulianDate: 40587 | rataDie: 719163

三十加分

ThreeTen-Extra项目是 future 可能添加到 java.time 的实验性试验场。名称来自JSR 310定义 java.time。

此库在其 Julian calendar system 中包含对 Julian 日期的额外支持(Chronology)。与 Java 8 中的支持一样,此库仅限于日期值(没有部分日期或时间)。

使用这个库你可以实例化JulianDate对象。

许多方法和功能供您在那里检查。

关于java - 如何将 Julian Day Numbers 与 Java Calendar API 一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14988459/

有关java - 如何将 Julian Day Numbers 与 Java Calendar API 一起使用?的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  4. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  5. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  6. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  7. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  8. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  9. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  10. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

随机推荐