Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit eba95ea6 authored by Ricki Hirner's avatar Ricki Hirner Committed by GitHub
Browse files

Use Java 8 Time API for dates and times (#23)

* Use Java 8 Time API for dates and times

* Use Instant as input for formatting HTTP dates

* Optimize imports [skip ci]
parent 2dafc3b3
Loading
Loading
Loading
Loading

run-tests.sh

deleted100755 → 0
+0 −16
Original line number Diff line number Diff line
#!/bin/sh

./gradlew -i check

echo
echo View lint report:
echo -n file://
realpath build/outputs/lint-results-debug.html

echo
echo View local unit test reports:
echo -n file://
realpath build/reports/tests/debug/index.html
echo -n file://
realpath build/reports/tests/release/index.html
+10 −2
Original line number Diff line number Diff line
@@ -6,12 +6,20 @@

package at.bitfire.dav4jvm

import okhttp3.*
import okhttp3.Authenticator
import okhttp3.Challenge
import okhttp3.Credentials
import okhttp3.Interceptor
import okhttp3.Request
import okhttp3.RequestBody
import okhttp3.Response
import okhttp3.Route
import okio.Buffer
import okio.ByteString.Companion.toByteString
import java.io.IOException
import java.util.*
import java.util.LinkedList
import java.util.Locale
import java.util.UUID
import java.util.concurrent.atomic.AtomicInteger

/**
+13 −9
Original line number Diff line number Diff line
@@ -20,8 +20,11 @@ import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import java.io.IOException
import java.io.StringWriter
import java.text.SimpleDateFormat
import java.util.*
import java.time.Instant
import java.time.ZoneOffset
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.util.Locale
import java.util.logging.Logger

class DavCalendar @JvmOverloads constructor(
@@ -44,10 +47,7 @@ class DavCalendar @JvmOverloads constructor(
        const val TIME_RANGE_START = "start"
        const val TIME_RANGE_END = "end"

        private val timeFormatUTC = SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'", Locale.ROOT)
        init {
            timeFormatUTC.timeZone = TimeZone.getTimeZone("Etc/UTC")
        }
        private val timeFormatUTC = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmssVV", Locale.US)
    }


@@ -66,7 +66,7 @@ class DavCalendar @JvmOverloads constructor(
     * @throws HttpException on HTTP error
     * @throws DavException on WebDAV error
     */
    fun calendarQuery(component: String, start: Date?, end: Date?, callback: MultiResponseCallback): List<Property> {
    fun calendarQuery(component: String, start: Instant?, end: Instant?, callback: MultiResponseCallback): List<Property> {
        /* <!ELEMENT calendar-query ((DAV:allprop |
                                      DAV:propname |
                                      DAV:prop)?, filter, timezone?)>
@@ -96,9 +96,13 @@ class DavCalendar @JvmOverloads constructor(
                        if (start != null || end != null) {
                            insertTag(TIME_RANGE) {
                                if (start != null)
                                    attribute(null, TIME_RANGE_START, timeFormatUTC.format(start))
                                    attribute(null, TIME_RANGE_START, timeFormatUTC.format(
                                        ZonedDateTime.ofInstant(start, ZoneOffset.UTC)
                                    ))
                                if (end != null)
                                    attribute(null, TIME_RANGE_END, timeFormatUTC.format(end))
                                    attribute(null, TIME_RANGE_END, timeFormatUTC.format(
                                        ZonedDateTime.ofInstant(end, ZoneOffset.UTC)
                                    ))
                            }
                        }
                    }
+47 −34
Original line number Diff line number Diff line
@@ -8,16 +8,21 @@ package at.bitfire.dav4jvm

import okhttp3.HttpUrl
import okhttp3.Response
import org.apache.commons.lang3.time.DateUtils
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.*

import java.time.Instant
import java.time.LocalDateTime
import java.time.ZoneOffset
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.time.format.DateTimeParseException
import java.util.Locale

object HttpUtils {

    private const val httpDateFormatStr = "EEE, dd MMM yyyy HH:mm:ss zzz"
    private val httpDateFormat = SimpleDateFormat(httpDateFormatStr, Locale.ROOT)
    /**
     * Preferred HTTP date/time format, see RFC 7231 7.1.1.1 IMF-fixdate
     */
    private const val httpDateFormatStr = "EEE, dd MMM yyyy HH:mm:ss ZZZZ"
    private val httpDateFormat = DateTimeFormatter.ofPattern(httpDateFormatStr, Locale.US)

    /**
     * Gets the resource name (the last segment of the path) from an URL.
@@ -44,42 +49,50 @@ object HttpUtils {
     * Formats a date for use in HTTP headers using [httpDateFormat].
     *
     * @param date date to be formatted
     *
     * @return date in HTTP-date format
     */
    fun formatDate(date: Date): String = httpDateFormat.format(date)
    fun formatDate(date: Instant): String =
        ZonedDateTime.ofInstant(date, ZoneOffset.UTC).format(httpDateFormat)

    /**
     * Parses a HTTP-date.
     * Parses a HTTP-date according to RFC 7231 section 7.1.1.1.
     *
     * @param dateStr date formatted in one of the three accepted formats:
     *
     * @param dateStr date with format specified by RFC 7231 section 7.1.1.1
     * or in one of the obsolete formats (copied from okhttp internal date-parsing class)
     *   - preferred format (`IMF-fixdate`)
     *   - obsolete RFC 850 format
     *   - ANSI C's `asctime()` format
     *
     * @return date, or null if date could not be parsed
     */
    fun parseDate(dateStr: String) = try {
        DateUtils.parseDate(dateStr, Locale.US,
                httpDateFormatStr,               // RFC 822, updated by RFC 1123 with any TZ
                "EEE, dd MMM yyyy HH:mm:ss zzz",
                "EEEE, dd-MMM-yy HH:mm:ss zzz",  // RFC 850, obsoleted by RFC 1036 with any TZ.
                "EEE MMM d HH:mm:ss yyyy",       // ANSI C's asctime() format
                // Alternative formats.
                "EEE, dd-MMM-yyyy HH:mm:ss z",
                "EEE, dd-MMM-yyyy HH-mm-ss z",
                "EEE, dd MMM yy HH:mm:ss z",
                "EEE dd-MMM-yyyy HH:mm:ss z",
                "EEE dd MMM yyyy HH:mm:ss z",
                "EEE dd-MMM-yyyy HH-mm-ss z",
                "EEE dd-MMM-yy HH:mm:ss z",
                "EEE dd MMM yy HH:mm:ss z",
                "EEE,dd-MMM-yy HH:mm:ss z",
                "EEE,dd-MMM-yyyy HH:mm:ss z",
                "EEE, dd-MM-yyyy HH:mm:ss z",
                /* RI bug 6641315 claims a cookie of this format was once served by www.yahoo.com */
                "EEE MMM d yyyy HH:mm:ss z"
    fun parseDate(dateStr: String): ZonedDateTime? {
        val zonedFormats = arrayOf(
            // preferred format
            httpDateFormat,

            // obsolete RFC 850 format
            DateTimeFormatter.ofPattern("EEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US),
        )
    } catch (e: ParseException) {
        Dav4jvm.log.warning("Couldn't parse date: $dateStr, ignoring")
        null

        // try the two formats with zone info
        for (format in zonedFormats)
            try {
                return ZonedDateTime.parse(dateStr, format)
            } catch (ignored: DateTimeParseException) {
            }

        // try ANSI C's asctime() format
        try {
            val formatC = DateTimeFormatter.ofPattern("EEE MMM ppd HH:mm:ss yyyy", Locale.US)
            val local = LocalDateTime.parse(dateStr, formatC)
            return local.atZone(ZoneOffset.UTC)
        } catch (ignored: DateTimeParseException) {
        }

        // no success in parsing
        Dav4jvm.log.warning("Couldn't parse HTTP date: $dateStr, ignoring")
        return null
    }

}
 No newline at end of file
+1 −1
Original line number Diff line number Diff line
@@ -14,7 +14,7 @@ import okhttp3.Protocol
import okhttp3.internal.http.StatusLine
import org.xmlpull.v1.XmlPullParser
import java.net.ProtocolException
import java.util.*
import java.util.LinkedList

/**
 * Represents a WebDAV propstat XML element.
Loading